From 2a440efa01c631dc8e70dec50d0fe1917bad2017 Mon Sep 17 00:00:00 2001 From: bitcoinz Date: Wed, 20 Sep 2017 00:49:38 -0700 Subject: [PATCH] zcash v1.0.11 merge --- .gitignore | 3 + .travis.yml | 4 +- COPYING | 3 +- configure.ac | 55 +------ contrib/ci-workers/README.md | 62 +++++++ contrib/ci-workers/ansible.cfg | 2 + contrib/ci-workers/tasks/install-pip.yml | 8 + .../templates/buildbot-worker.service.j2 | 17 ++ contrib/ci-workers/templates/host.ec2.j2 | 1 + contrib/ci-workers/templates/host.j2 | 3 + contrib/ci-workers/unix.yml | 152 ++++++++++++++++++ contrib/ci-workers/vars/Archlinux.yml | 7 + contrib/ci-workers/vars/CentOS.yml | 13 ++ contrib/ci-workers/vars/Debian.yml | 6 + contrib/ci-workers/vars/Fedora.yml | 10 ++ contrib/ci-workers/vars/FreeBSD.yml | 9 ++ contrib/ci-workers/vars/Ubuntu.yml | 5 + contrib/ci-workers/vars/buildbot.yml | 5 + contrib/ci-workers/vars/default.yml | 44 +++++ contrib/debian/changelog | 12 ++ contrib/debian/copyright | 4 - contrib/gitian-descriptors/gitian-linux.yml | 2 +- depends/README.md | 1 - depends/config.site.in | 4 - depends/packages/miniupnpc.mk | 32 ---- depends/packages/packages.mk | 2 - .../miniupnpc/fix-solaris-compilation.patch | 42 ----- .../miniupnpc/patch-strlen-patch.patch | 22 --- .../miniupnpc/strlen-before-memcmp.patch | 23 --- doc/authors.md | 10 +- doc/hotfix-process.md | 74 +++++++++ doc/man/zcash-cli.1 | 8 +- doc/man/zcash-tx.1 | 8 +- doc/man/zcashd.1 | 16 +- doc/payment-api.md | 5 +- doc/release-notes/release-notes-1.0.11-rc1.md | 44 +++++ doc/release-notes/release-notes-1.0.11.md | 7 + doc/release-process.md | 39 ++++- qa/rpc-tests/decodescript.py | 4 +- qa/rpc-tests/disablewallet.py | 3 +- qa/rpc-tests/forknotify.py | 6 +- qa/rpc-tests/fundrawtransaction.py | 9 +- qa/rpc-tests/getblocktemplate.py | 3 +- qa/rpc-tests/getblocktemplate_longpoll.py | 4 +- qa/rpc-tests/getblocktemplate_proposals.py | 2 +- qa/rpc-tests/hardforkdetection.py | 7 +- qa/rpc-tests/httpbasics.py | 47 +++--- qa/rpc-tests/invalidateblock.py | 13 +- qa/rpc-tests/invalidblockrequest.py | 10 +- qa/rpc-tests/keypool.py | 11 +- qa/rpc-tests/listtransactions.py | 2 +- qa/rpc-tests/maxblocksinflight.py | 15 +- qa/rpc-tests/mempool_coinbase_spends.py | 8 +- qa/rpc-tests/mempool_resurrect_test.py | 5 +- qa/rpc-tests/mempool_spendcoinbase.py | 7 +- qa/rpc-tests/mempool_tx_input_limit.py | 17 +- qa/rpc-tests/merkle_blocks.py | 7 +- qa/rpc-tests/nodehandling.py | 9 +- qa/rpc-tests/p2p-acceptblock.py | 11 +- qa/rpc-tests/prioritisetransaction.py | 9 +- qa/rpc-tests/proton_test.py | 16 +- qa/rpc-tests/proxy_test.py | 10 +- qa/rpc-tests/pruning.py | 10 +- qa/rpc-tests/rawtransactions.py | 22 +-- qa/rpc-tests/receivedby.py | 45 +++--- qa/rpc-tests/reindex.py | 6 +- qa/rpc-tests/rest.py | 77 ++++----- qa/rpc-tests/rpcbind_test.py | 16 +- qa/rpc-tests/script_test.py | 11 +- qa/rpc-tests/signrawtransactions.py | 3 +- qa/rpc-tests/smartfees.py | 6 +- qa/rpc-tests/test_framework/blockstore.py | 7 +- qa/rpc-tests/test_framework/blocktools.py | 3 +- qa/rpc-tests/test_framework/comptool.py | 7 +- qa/rpc-tests/test_framework/script.py | 4 +- qa/rpc-tests/test_framework/test_framework.py | 7 +- qa/rpc-tests/test_framework/util.py | 5 +- qa/rpc-tests/txn_doublespend.py | 9 +- qa/rpc-tests/wallet.py | 37 +++-- qa/rpc-tests/wallet_1941.py | 10 +- qa/rpc-tests/wallet_nullifiers.py | 16 +- qa/rpc-tests/wallet_protectcoinbase.py | 13 +- qa/rpc-tests/wallet_treestate.py | 11 +- qa/rpc-tests/walletbackup.py | 9 +- qa/rpc-tests/zapwallettxes.py | 50 +++--- qa/rpc-tests/zcjoinsplit.py | 8 +- qa/rpc-tests/zcjoinsplitdoublespend.py | 9 +- qa/rpc-tests/zmq_test.py | 18 +-- qa/zcash/create_wallet_200k_utxos.py | 60 +++++++ qa/zcash/performance-measurements.sh | 85 ++++++++-- src/Makefile.am | 3 +- src/Makefile.gtest.include | 3 +- src/Makefile.test.include | 2 +- src/amount.cpp | 4 +- src/amount.h | 4 +- src/clientversion.h | 4 +- src/deprecation.h | 6 +- src/gtest/test_httprpc.cpp | 62 +++++++ src/gtest/test_metrics.cpp | 41 +++++ src/httprpc.cpp | 5 + src/httpserver.h | 15 +- src/init.cpp | 31 ++-- src/leveldbwrapper.cpp | 4 +- src/leveldbwrapper.h | 14 +- src/metrics.cpp | 41 ++++- src/metrics.h | 3 + src/net.cpp | 136 ---------------- src/net.h | 9 +- src/rpcblockchain.cpp | 7 +- src/rpcmining.cpp | 4 +- src/rpcmisc.cpp | 4 +- src/rpcnet.cpp | 2 +- src/rpcrawtransaction.cpp | 14 +- src/sendalert.cpp | 16 +- src/test/rpc_wallet_tests.cpp | 12 ++ src/torcontrol.cpp | 4 +- src/util.cpp | 2 +- src/wallet/asyncrpcoperation_sendmany.cpp | 8 + src/wallet/rpcwallet.cpp | 68 ++++---- src/zcbenchmarks.cpp | 60 +++++++ src/zcbenchmarks.h | 2 + zcutil/build.sh | 2 +- zcutil/make-release.py | 100 +++++++++++- zcutil/release-notes.py | 28 ++++ 124 files changed, 1507 insertions(+), 776 deletions(-) create mode 100644 contrib/ci-workers/README.md create mode 100644 contrib/ci-workers/ansible.cfg create mode 100644 contrib/ci-workers/tasks/install-pip.yml create mode 100644 contrib/ci-workers/templates/buildbot-worker.service.j2 create mode 100644 contrib/ci-workers/templates/host.ec2.j2 create mode 100644 contrib/ci-workers/templates/host.j2 create mode 100644 contrib/ci-workers/unix.yml create mode 100644 contrib/ci-workers/vars/Archlinux.yml create mode 100644 contrib/ci-workers/vars/CentOS.yml create mode 100644 contrib/ci-workers/vars/Debian.yml create mode 100644 contrib/ci-workers/vars/Fedora.yml create mode 100644 contrib/ci-workers/vars/FreeBSD.yml create mode 100644 contrib/ci-workers/vars/Ubuntu.yml create mode 100644 contrib/ci-workers/vars/buildbot.yml create mode 100644 contrib/ci-workers/vars/default.yml delete mode 100644 depends/packages/miniupnpc.mk delete mode 100644 depends/patches/miniupnpc/fix-solaris-compilation.patch delete mode 100644 depends/patches/miniupnpc/patch-strlen-patch.patch delete mode 100644 depends/patches/miniupnpc/strlen-before-memcmp.patch create mode 100644 doc/hotfix-process.md create mode 100644 doc/release-notes/release-notes-1.0.11-rc1.md create mode 100644 doc/release-notes/release-notes-1.0.11.md create mode 100755 qa/zcash/create_wallet_200k_utxos.py create mode 100644 src/gtest/test_httprpc.cpp diff --git a/.gitignore b/.gitignore index e75e41810..c87eaed1b 100644 --- a/.gitignore +++ b/.gitignore @@ -112,3 +112,6 @@ libzcashconsensus.pc contrib/debian/files contrib/debian/substvars + +.idea/ +*.iml diff --git a/.travis.yml b/.travis.yml index 662ac5681..b2cc7b02b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ matrix: fast_finish: true include: - compiler: ": ARM" - env: HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" + env: HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="" GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" - compiler: ": Win32" env: HOST=i686-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-i686 g++-mingw-w64-i686 binutils-mingw-w64-i686 mingw-w64-dev wine bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-reduce-exports" MAKEJOBS="-j2" - compiler: ": 32-bit + dash" @@ -37,7 +37,7 @@ matrix: - compiler: ": Win64" env: HOST=x86_64-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64 mingw-w64-dev wine bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--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" PPA="ppa:chris-lea/zeromq" DEP_OPTS="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" diff --git a/COPYING b/COPYING index 67a092a04..c84bfb7aa 100644 --- a/COPYING +++ b/COPYING @@ -28,8 +28,7 @@ open-source licenses. For further details see 'contrib/debian/copyright'. 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), -and UPnP software written by Thomas Bernard. +software written by Eric Young (eay@cryptsoft.com). Although almost all of the Zcash code is licensed under "permissive" open source diff --git a/configure.ac b/configure.ac index 7ce256781..4802aa03a 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,8 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 1) define(_CLIENT_VERSION_MINOR, 0) -define(_CLIENT_VERSION_REVISION, 10) -define(_CLIENT_VERSION_BUILD, 51) +define(_CLIENT_VERSION_REVISION, 11) +define(_CLIENT_VERSION_BUILD, 50) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) @@ -94,18 +94,6 @@ AC_ARG_ENABLE([rust], [enable_rust=$enableval], [enable_rust=yes]) -AC_ARG_WITH([miniupnpc], - [AS_HELP_STRING([--with-miniupnpc], - [enable UPNP (default is yes if libminiupnpc is found)])], - [use_upnp=$withval], - [use_upnp=auto]) - -AC_ARG_ENABLE([upnp-default], - [AS_HELP_STRING([--enable-upnp-default], - [if UPNP is enabled, turn it on at startup (default is no)])], - [use_upnp_default=$enableval], - [use_upnp_default=no]) - AC_ARG_ENABLE([proton], [AS_HELP_STRING([--disable-proton], [disable Proton (AMQP messaging)])], @@ -556,15 +544,6 @@ else AC_DEFINE(ENABLE_PROTON, 0, [Define to 1 to enable Proton functions]) fi -dnl Check for libminiupnpc (optional) -if test x$use_upnp != xno; then - AC_CHECK_HEADERS( - [miniupnpc/miniwget.h miniupnpc/miniupnpc.h miniupnpc/upnpcommands.h miniupnpc/upnperrors.h], - [AC_CHECK_LIB([miniupnpc], [main],[MINIUPNPC_LIBS=-lminiupnpc], [have_miniupnpc=no])], - [have_miniupnpc=no] - ) -fi - if test x$build_bitcoin_utils$build_bitcoind$use_tests = xnonono; then use_boost=no else @@ -876,33 +855,6 @@ else AC_MSG_RESULT(no) fi -dnl enable upnp support -AC_MSG_CHECKING([whether to build with support for UPnP]) -if test x$have_miniupnpc = xno; then - if test x$use_upnp = xyes; then - AC_MSG_ERROR("UPnP requested but cannot be built. use --without-miniupnpc") - fi - AC_MSG_RESULT(no) -else - if test x$use_upnp != xno; then - AC_MSG_RESULT(yes) - AC_MSG_CHECKING([whether to build with UPnP enabled by default]) - use_upnp=yes - upnp_setting=0 - if test x$use_upnp_default != xno; then - use_upnp_default=yes - upnp_setting=1 - fi - AC_MSG_RESULT($use_upnp_default) - AC_DEFINE_UNQUOTED([USE_UPNP],[$upnp_setting],[UPnP support not compiled if undefined, otherwise value (0 or 1) determines default state]) - if test x$TARGET_OS = xwindows; then - MINIUPNPC_CPPFLAGS="-DSTATICLIB -DMINIUPNP_STATICLIB" - fi - else - AC_MSG_RESULT(no) - fi -fi - AM_CONDITIONAL([ENABLE_ZMQ], [test "x$use_zmq" = "xyes"]) AM_CONDITIONAL([ENABLE_PROTON], [test "x$use_proton" = "xyes"]) @@ -955,12 +907,9 @@ AC_SUBST(COPYRIGHT_YEAR, _COPYRIGHT_YEAR) AC_SUBST(RELDFLAGS) AC_SUBST(LIBTOOL_APP_LDFLAGS) -AC_SUBST(USE_UPNP) AC_SUBST(BOOST_LIBS) AC_SUBST(TESTDEFS) AC_SUBST(LEVELDB_TARGET_FLAGS) -AC_SUBST(MINIUPNPC_CPPFLAGS) -AC_SUBST(MINIUPNPC_LIBS) AC_SUBST(GMP_LIBS) AC_SUBST(GMPXX_LIBS) AC_SUBST(LIBSNARK_LIBS) diff --git a/contrib/ci-workers/README.md b/contrib/ci-workers/README.md new file mode 100644 index 000000000..37f7ad833 --- /dev/null +++ b/contrib/ci-workers/README.md @@ -0,0 +1,62 @@ +# Zcash CI workers + +This folder contains the Ansible playbooks for configuring a fresh OS +installation for use as a Buildbot worker in Zcash's CI. + +# Criteria for Adding Workers + +a. Don't add workers until users complain about a problem on a platform + that doesn't yet have workers or if we anticipate many users will use + a platform, we may pre-emptively add an unsupported worker for it. + +b. Prioritize the platforms that seem to have the most users. + +c. When adding workers start by adding workers for the "most common" + variant of any distro, then if users later encounter problems with a + sub-variant, we can consider adding new workers at that point. + Example: add Ubuntu Desktop before Xubuntu, on the assumption the + former has a larger population base. + +# Setting up a latent worker on Amazon EC2 + +- Add a regular (non-latent) worker to the master.cfg for dev-ci.z.cash, and + deploy the changes. + - This enables the Ansible playbook to run to completion, ending in the worker + connecting to the master. + +- Start a basic EC2 instance using the template AMI for the target OS. + - Choose the smallest instance size, it won't be used for building Zcash. + +- Figure out which user to log into the instance with. + - E.g. for the Ubuntu template, use "ubuntu" instead of "root" + - If you get an Ansible error later with a message like "Failed to connect to + the host via ssh: Received message too long 1349281121\r\n", that means the + instance is sending a text string in response to the SSH connection, and the + Ansible protocol is balking. Try manually logging in with the same + credentials to diagnose. + +- Create `inventory/hosts` containing the following: + + [zcash-ci-worker-unix] + some-name ansible_host= ansible_ssh_user= + +- Run `ansible-playbook -e buildbot_worker_host_template=templates/host.ec2.j2 -i inventory/hosts unix.yml`, + passing in the worker's Buildbot name and password. + - After a successful run, the worker should be connected to dev-ci.z.cash and + visible in its worker list. + +- Create an AMI from the instance. This is the worker AMI to put into the + master.cfg for dev-ci.z.cash. + - 16 GB of storage should be sufficient. + +- SSH into the instance, and edit the worker config to connect to ci.z.cash. + +- Create an AMI from the instance. This is the worker AMI to put into the + master.cfg for ci.z.cash. + - 16 GB of storage should be sufficient. + +- Delete the instance (it is no longer needed). + +- Edit the master.cfg to turn the new worker into a latent (using the new AMI + IDs), add it to the appropriate worker groups, set up new builders etc. + - Deploy this via the normal PR review process. diff --git a/contrib/ci-workers/ansible.cfg b/contrib/ci-workers/ansible.cfg new file mode 100644 index 000000000..c58fea3c0 --- /dev/null +++ b/contrib/ci-workers/ansible.cfg @@ -0,0 +1,2 @@ +[ssh_connection] +pipelining = True diff --git a/contrib/ci-workers/tasks/install-pip.yml b/contrib/ci-workers/tasks/install-pip.yml new file mode 100644 index 000000000..8beff50ef --- /dev/null +++ b/contrib/ci-workers/tasks/install-pip.yml @@ -0,0 +1,8 @@ +--- +- name: Fetch pip installer + get_url: + url: https://bootstrap.pypa.io/get-pip.py + dest: /tmp/get-pip.py + +- name: Install pip + command: "{{ ansible_python.executable }} /tmp/get-pip.py" diff --git a/contrib/ci-workers/templates/buildbot-worker.service.j2 b/contrib/ci-workers/templates/buildbot-worker.service.j2 new file mode 100644 index 000000000..ffe497bcf --- /dev/null +++ b/contrib/ci-workers/templates/buildbot-worker.service.j2 @@ -0,0 +1,17 @@ +[Unit] +Description=Buildbot worker +Wants=network.target +After=network.target + +[Service] +Type=forking +PIDFile=/home/{{ buildbot_worker_user }}/{{ buildbot_worker_name }}/twistd.pid +WorkingDirectory=/home/{{ buildbot_worker_user }} +ExecStart={{ pip_bin_dir }}/buildbot-worker start {{ buildbot_worker_name }} +ExecReload={{ pip_bin_dir }}/buildbot-worker restart {{ buildbot_worker_name }} +ExecStop={{ pip_bin_dir }}/buildbot-worker stop {{ buildbot_worker_name }} +Restart=always +User={{ buildbot_worker_user }} + +[Install] +WantedBy=multi-user.target diff --git a/contrib/ci-workers/templates/host.ec2.j2 b/contrib/ci-workers/templates/host.ec2.j2 new file mode 100644 index 000000000..dee692e02 --- /dev/null +++ b/contrib/ci-workers/templates/host.ec2.j2 @@ -0,0 +1 @@ +OS: {{ ansible_distribution }} {{ ansible_distribution_version }} diff --git a/contrib/ci-workers/templates/host.j2 b/contrib/ci-workers/templates/host.j2 new file mode 100644 index 000000000..3a5abb0c2 --- /dev/null +++ b/contrib/ci-workers/templates/host.j2 @@ -0,0 +1,3 @@ +OS: {{ ansible_distribution }} {{ ansible_distribution_version }} +Memory: {{ ansible_memtotal_mb }} MB +CPU: {{ ansible_processor[1] }} diff --git a/contrib/ci-workers/unix.yml b/contrib/ci-workers/unix.yml new file mode 100644 index 000000000..6e6cc49c4 --- /dev/null +++ b/contrib/ci-workers/unix.yml @@ -0,0 +1,152 @@ +--- +- name: Configure a Buildbot worker for Zcash CI + hosts: zcash-ci-worker-unix + become: true + gather_facts: False + + vars_files: + - vars/default.yml + - vars/buildbot.yml + + vars_prompt: + - name: "buildbot_worker_admin" + prompt: "Admin details" + default: "Zcash " + - name: "buildbot_worker_name" + prompt: "Buildbot worker name (provided by ZECC)" + private: no + - name: "buildbot_worker_password" + prompt: "Buildbot worker password (provided by ZECC)" + + pre_tasks: + - name: Install Python 2.7 for Ansible and Buildbot + raw: test -e /usr/bin/python || test -e /usr/bin/python2 || test -e /usr/bin/python2.7 || test -e /usr/local/bin/python2.7 || (test -e /usr/bin/apt && apt -qqy update && apt install -qqy python) || (test -e /usr/bin/dnf && dnf install -qqy python2) || (test -e /usr/sbin/pkg && pkg install -qqy python2) + register: output + changed_when: + - output.stdout != "" + - output.stdout != "\r\n" + + - name: Check if Python is in the configured location + raw: test -e {{ ansible_python_interpreter }} + ignore_errors: true + register: python_check + when: ansible_python_interpreter is defined + + - name: Fail if configured Python is unavailable + fail: + msg: "Python is not accessible at {{ ansible_python_interpreter }} on this host! Please set the inventory variable 'ansible_python_interpreter' to the location of the Python 2.7 binary." + when: ansible_python_interpreter is defined and python_check.rc == 1 + + - name: Check if Python is in the default location + raw: test -e /usr/bin/python + ignore_errors: true + register: python_check + when: ansible_python_interpreter is undefined + + - name: Fail if default Python is unavailable + fail: + msg: Python is not accessible at /usr/bin/python on this host! Please set the inventory variable 'ansible_python_interpreter' to the location of the Python 2.7 binary. + when: ansible_python_interpreter is undefined and python_check.rc == 1 + + - name: Gathering Facts + setup: + + - name: Fail if Python is the wrong version + fail: + msg: "The Python binary at {{ ansible_python.executable }} is version {{ ansible_python_version }}! Please set the inventory variable 'ansible_python_interpreter' to the location of the Python 2.7 binary." + when: ansible_python.version.major != 2 or ansible_python.version.minor != 7 + + tasks: + - name: Get dependencies for distribution + include_vars: "{{ item }}" + with_first_found: + - files: + - "vars/{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml" + - "vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version | int }}.yml" + - "vars/{{ ansible_distribution }}.yml" + - "vars/{{ ansible_os_family }}.yml" + skip: true + + - name: Collate dependencies + set_fact: + package_deps: "{{ buildbot_deps + fetch_deps + conf_deps + build_deps + link_deps + dist_deps }}" + python_modules: "{{ buildbot_modules + rpc_test_modules }}" + + - name: Update rolling release [Arch Linux] + pacman: + update_cache: yes + upgrade: yes + when: ansible_distribution == 'Archlinux' + + - name: Install required packages + package: + name: "{{ item }}" + state: present + with_items: "{{ package_deps }}" + + - name: Install pip [CentOS] + include: tasks/install-pip.yml + when: ansible_distribution == 'CentOS' + + - name: Install required Python modules + pip: + name: "{{ item }}" + state: latest + with_items: "{{ python_modules }}" + notify: restart buildbot-worker + + - name: Set up the Buildbot worker user + user: + name: "{{ buildbot_worker_user }}" + comment: Buildbot worker + shell: /bin/bash + state: present + + - name: Create Buildbot worker + command: > + buildbot-worker create-worker ~/{{ buildbot_worker_name }} + {{ buildbot_master_host }}:{{ buildbot_master_port }} + {{ buildbot_worker_name|quote }} {{ buildbot_worker_password|quote }} + args: + creates: "~/{{ buildbot_worker_name }}/buildbot.tac" + become_user: "{{ buildbot_worker_user }}" + + - name: Set admin details for Buildbot worker + copy: + content: "{{ buildbot_worker_admin }}" + dest: "~{{ buildbot_worker_user }}/{{ buildbot_worker_name }}/info/admin" + owner: "{{ buildbot_worker_user }}" + group: "{{ buildbot_worker_user }}" + mode: "0644" + + - name: Set host details for Buildbot worker + template: + src: "{{ buildbot_worker_host_template }}" + dest: "~{{ buildbot_worker_user }}/{{ buildbot_worker_name }}/info/host" + owner: "{{ buildbot_worker_user }}" + group: "{{ buildbot_worker_user }}" + mode: "0644" + + - name: Copy Buildbot worker systemd service unit + template: + src: templates/buildbot-worker.service.j2 + dest: "/etc/systemd/system/buildbot-worker.service" + owner: root + group: root + mode: "0644" + notify: reload systemd + + - name: Start Buildbot worker. + service: + name: buildbot-worker + state: started + enabled: yes + + handlers: + - name: restart buildbot-worker + service: + name: buildbot-worker + state: restarted + + - name: reload systemd + command: /bin/systemctl daemon-reload diff --git a/contrib/ci-workers/vars/Archlinux.yml b/contrib/ci-workers/vars/Archlinux.yml new file mode 100644 index 000000000..ac4a44e5b --- /dev/null +++ b/contrib/ci-workers/vars/Archlinux.yml @@ -0,0 +1,7 @@ +--- +buildbot_deps: + - python2-pip +build_deps: + - multilib/gcc + - make +pip_bin_dir: /usr/bin diff --git a/contrib/ci-workers/vars/CentOS.yml b/contrib/ci-workers/vars/CentOS.yml new file mode 100644 index 000000000..7e09b0717 --- /dev/null +++ b/contrib/ci-workers/vars/CentOS.yml @@ -0,0 +1,13 @@ +--- +buildbot_deps: [] # Empty to remove python-pip +build_deps: + - bzip2 + - gcc + - gcc-c++ + - make + - patch +dist_deps: + - pkgconfig # Required until b556beda264308e040f8d88aca4f2f386a0183d9 is pulled in + - python-devel + - redhat-rpm-config +pip_bin_dir: /usr/bin diff --git a/contrib/ci-workers/vars/Debian.yml b/contrib/ci-workers/vars/Debian.yml new file mode 100644 index 000000000..992224721 --- /dev/null +++ b/contrib/ci-workers/vars/Debian.yml @@ -0,0 +1,6 @@ +--- +build_deps: + - build-essential # Depends on g++, libc6-dev, make +dist_deps: + - pkg-config # Required until b556beda264308e040f8d88aca4f2f386a0183d9 is pulled in + - python-dev diff --git a/contrib/ci-workers/vars/Fedora.yml b/contrib/ci-workers/vars/Fedora.yml new file mode 100644 index 000000000..1c6b0e0f3 --- /dev/null +++ b/contrib/ci-workers/vars/Fedora.yml @@ -0,0 +1,10 @@ +--- +build_deps: + - gcc + - gcc-c++ + - make + - patch +dist_deps: + - pkgconfig # Required until b556beda264308e040f8d88aca4f2f386a0183d9 is pulled in + - python-devel + - redhat-rpm-config diff --git a/contrib/ci-workers/vars/FreeBSD.yml b/contrib/ci-workers/vars/FreeBSD.yml new file mode 100644 index 000000000..65909d71d --- /dev/null +++ b/contrib/ci-workers/vars/FreeBSD.yml @@ -0,0 +1,9 @@ +--- +buildbot_deps: + - py27-pip +build_deps: + - gcc + - gmake +dist_deps: + - bash + - pkgconf # Required until b556beda264308e040f8d88aca4f2f386a0183d9 is pulled in diff --git a/contrib/ci-workers/vars/Ubuntu.yml b/contrib/ci-workers/vars/Ubuntu.yml new file mode 100644 index 000000000..4acca499b --- /dev/null +++ b/contrib/ci-workers/vars/Ubuntu.yml @@ -0,0 +1,5 @@ +--- +build_deps: + - build-essential # Depends on g++, libc6-dev, make +dist_deps: + - pkg-config # Required until b556beda264308e040f8d88aca4f2f386a0183d9 is pulled in diff --git a/contrib/ci-workers/vars/buildbot.yml b/contrib/ci-workers/vars/buildbot.yml new file mode 100644 index 000000000..38e3fd25a --- /dev/null +++ b/contrib/ci-workers/vars/buildbot.yml @@ -0,0 +1,5 @@ +--- +buildbot_worker_user: zcbbworker +buildbot_master_host: dev-ci.z.cash +buildbot_master_port: 9899 +buildbot_worker_host_template: templates/host.j2 diff --git a/contrib/ci-workers/vars/default.yml b/contrib/ci-workers/vars/default.yml new file mode 100644 index 000000000..67da0e51d --- /dev/null +++ b/contrib/ci-workers/vars/default.yml @@ -0,0 +1,44 @@ +--- +# These variables can be overridden in distribution files. + +# Dependencies required to install Buildbot +buildbot_deps: + - python-pip # So we can install Python modules + +# Dependencies required to download files +fetch_deps: + - git + - wget # For zcutil/fetch-params.sh + +# Dependencies required to configure Zcash +conf_deps: + - autoconf + - automake + - m4 + +# Dependencies required to compile Zcash +build_deps: + - g++ + - gcc + - make + +# Dependencies required to link Zcash +link_deps: + - libtool + +# Additional distribution-specific dependencies +dist_deps: [] + +# Python modules required for a Zcash Buildbot worker +buildbot_modules: + - pip # Needs to be updated first so Buildbot installs + - buildbot-worker + - pyflakes + +# Python modules required to run the Zcash RPC test suite +rpc_test_modules: + - pyblake2 + - pyzmq + +# Environment variables +pip_bin_dir: /usr/local/bin diff --git a/contrib/debian/changelog b/contrib/debian/changelog index e2cbaab82..1da00f690 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,15 @@ +zcash (1.0.11) stable; urgency=medium + + * 1.0.11 release. + + -- Zcash Company Tue, 15 Aug 2017 10:06:25 +0100 + +zcash (1.0.11~rc1) stable; urgency=medium + + * 1.0.11-rc1 release. + + -- Zcash Company Tue, 01 Aug 2017 17:12:52 +0200 + zcash (1.0.10+1) stable; urgency=medium * 1.0.10-1 release. diff --git a/contrib/debian/copyright b/contrib/debian/copyright index 5eb71ebb2..3fbaa848b 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -38,10 +38,6 @@ Files: depends/sources/openssl-*.tar.gz Copyright: 1998-2016 The OpenSSL Project and 1995-1998 Eric Young License: OpenSSL+SSLeay -Files: depends/sources/miniupnpc-*.tar.gz -Copyright: 2005-2016 Thomas BERNARD -License: BSD-3clause - Files: depends/sources/zeromq-*.tar.gz Copyright: 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index cc3dcd701..892de5287 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-1.0.10-1" +name: "zcash-1.0.11" enable_cache: true distro: "debian" suites: diff --git a/depends/README.md b/depends/README.md index 09296cc47..41898de1a 100644 --- a/depends/README.md +++ b/depends/README.md @@ -35,7 +35,6 @@ The following can be set when running make: make FOO=bar SDK_PATH: Path where sdk's can be found (used by OSX) PRIORITY_DOWNLOAD_PATH: Try fetching source files from here before using their own URLs 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 If some packages are not built, for example `make NO_WALLET=1`, the appropriate diff --git a/depends/config.site.in b/depends/config.site.in index 153330360..103486332 100644 --- a/depends/config.site.in +++ b/depends/config.site.in @@ -17,10 +17,6 @@ if test -z $enable_wallet && test -n "@no_wallet@"; then enable_wallet=no fi -if test -z $with_miniupnpc && test -n "@no_upnp@"; then - with_miniupnpc=no -fi - if test x@host_os@ = xdarwin; then BREW=no PORT=no diff --git a/depends/packages/miniupnpc.mk b/depends/packages/miniupnpc.mk deleted file mode 100644 index 0d8efbc3f..000000000 --- a/depends/packages/miniupnpc.mk +++ /dev/null @@ -1,32 +0,0 @@ -package=miniupnpc -$(package)_version=2.0 -$(package)_download_path=http://miniupnp.free.fr/files -$(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=d434ceb8986efbe199c5ca53f90ed53eab290b1e6d0530b717eb6fa49d61f93b -$(package)_patches=fix-solaris-compilation.patch strlen-before-memcmp.patch patch-strlen-patch.patch - -define $(package)_set_vars -$(package)_build_opts=CC="$($(package)_cc)" -$(package)_build_opts_darwin=OS=Darwin -$(package)_build_opts_mingw32=-f Makefile.mingw -$(package)_build_env+=CFLAGS="$($(package)_cflags) $($(package)_cppflags)" AR="$($(package)_ar)" -endef - -define $(package)_preprocess_cmds - mkdir dll && \ - sed -e 's|MINIUPNPC_VERSION_STRING \"version\"|MINIUPNPC_VERSION_STRING \"$($(package)_version)\"|' -e 's|OS/version|$(host)|' miniupnpcstrings.h.in > miniupnpcstrings.h && \ - sed -i.old "s|miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings|miniupnpcstrings.h: miniupnpcstrings.h.in|" Makefile.mingw && \ - patch -p2 < $($(package)_patch_dir)/fix-solaris-compilation.patch && \ - patch -p2 < $($(package)_patch_dir)/strlen-before-memcmp.patch && \ - patch -p2 < $($(package)_patch_dir)/patch-strlen-patch.patch -endef - -define $(package)_build_cmds - $(MAKE) libminiupnpc.a $($(package)_build_opts) -endef - -define $(package)_stage_cmds - mkdir -p $($(package)_staging_prefix_dir)/include/miniupnpc $($(package)_staging_prefix_dir)/lib &&\ - install *.h $($(package)_staging_prefix_dir)/include/miniupnpc &&\ - install libminiupnpc.a $($(package)_staging_prefix_dir)/lib -endef diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 5e45dbe98..91873bf9f 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -5,5 +5,3 @@ packages := boost openssl libevent zeromq $(zcash_packages) googletest googlemoc native_packages := native_ccache wallet_packages=bdb - -upnp_packages=miniupnpc diff --git a/depends/patches/miniupnpc/fix-solaris-compilation.patch b/depends/patches/miniupnpc/fix-solaris-compilation.patch deleted file mode 100644 index 30eb3b106..000000000 --- a/depends/patches/miniupnpc/fix-solaris-compilation.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 71ce1d6dfa5424f8fe8633e23494c7638ea2c79e Mon Sep 17 00:00:00 2001 -From: Thomas Bernard -Date: Thu, 10 Nov 2016 21:55:33 +0100 -Subject: [PATCH] fix for Solaris 11 compilation - -see #216 ---- - miniupnpc/Makefile | 2 ++ - miniupnpc/minissdpc.c | 3 +++ - 2 files changed, 5 insertions(+) - -diff --git a/miniupnpc/Makefile b/miniupnpc/Makefile -index 5c23000..72cdc0f 100644 ---- a/miniupnpc/Makefile -+++ b/miniupnpc/Makefile -@@ -43,10 +43,12 @@ CFLAGS += -D_NETBSD_SOURCE - endif - ifneq ($(OS), FreeBSD) - ifneq ($(OS), Darwin) -+ifneq ($(OS), SunOS) - #CFLAGS += -D_POSIX_C_SOURCE=200112L - CFLAGS += -D_XOPEN_SOURCE=600 - endif - endif -+endif - #CFLAGS += -ansi - # -DNO_GETADDRINFO - INSTALL = install -diff --git a/miniupnpc/minissdpc.c b/miniupnpc/minissdpc.c -index f200f07..263160e 100644 ---- a/miniupnpc/minissdpc.c -+++ b/miniupnpc/minissdpc.c -@@ -73,6 +73,9 @@ struct sockaddr_un { - - #if !defined(HAS_IP_MREQN) && !defined(_WIN32) - #include -+#if defined(__sun) -+#include -+#endif - #endif - - #if defined(HAS_IP_MREQN) && defined(NEED_STRUCT_IP_MREQN) diff --git a/depends/patches/miniupnpc/patch-strlen-patch.patch b/depends/patches/miniupnpc/patch-strlen-patch.patch deleted file mode 100644 index df7140234..000000000 --- a/depends/patches/miniupnpc/patch-strlen-patch.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0aa7c46227acd8ddb135c577674ad454bf2fba86 Mon Sep 17 00:00:00 2001 -From: Thomas Bernard -Date: Fri, 11 Nov 2016 17:53:21 +0100 -Subject: [PATCH] remove unsigned/signed comparison - ---- - miniupnpc/portlistingparse.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/miniupnpc/portlistingparse.c b/miniupnpc/portlistingparse.c -index 1bed763..07f3f87 100644 ---- a/miniupnpc/portlistingparse.c -+++ b/miniupnpc/portlistingparse.c -@@ -55,7 +55,7 @@ startelt(void * d, const char * name, int l) - pdata->curelt = PortMappingEltNone; - for(i = 0; elements[i].str; i++) - { -- if(strlen(elements[i].str) == l && memcmp(name, elements[i].str, l) == 0) -+ if(strlen(elements[i].str) == (size_t)l && memcmp(name, elements[i].str, l) == 0) - { - pdata->curelt = elements[i].code; - break; diff --git a/depends/patches/miniupnpc/strlen-before-memcmp.patch b/depends/patches/miniupnpc/strlen-before-memcmp.patch deleted file mode 100644 index 8e1f2005e..000000000 --- a/depends/patches/miniupnpc/strlen-before-memcmp.patch +++ /dev/null @@ -1,23 +0,0 @@ -From ec1c49bb0cd5e448e6f0adee7de3a831c4869bdd Mon Sep 17 00:00:00 2001 -From: Thomas Bernard -Date: Fri, 11 Nov 2016 17:24:39 +0100 -Subject: [PATCH] check strlen before memcmp - -1st try to fix #220 ---- - miniupnpc/portlistingparse.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/miniupnpc/portlistingparse.c b/miniupnpc/portlistingparse.c -index 0e09278..1bed763 100644 ---- a/miniupnpc/portlistingparse.c -+++ b/miniupnpc/portlistingparse.c -@@ -55,7 +55,7 @@ startelt(void * d, const char * name, int l) - pdata->curelt = PortMappingEltNone; - for(i = 0; elements[i].str; i++) - { -- if(memcmp(name, elements[i].str, l) == 0) -+ if(strlen(elements[i].str) == l && memcmp(name, elements[i].str, l) == 0) - { - pdata->curelt = elements[i].code; - break; diff --git a/doc/authors.md b/doc/authors.md index b1e6c924d..8d3010dc6 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -1,12 +1,12 @@ Zcash Contributors ================== -Jack Grigg (428) -Simon Liu (266) +Jack Grigg (445) +Simon Liu (269) Sean Bowe (188) -Daira Hopwood (95) +Daira Hopwood (102) Taylor Hornby (65) -Wladimir J. van der Laan (60) +Wladimir J. van der Laan (61) Nathan Wilcox (51) Jay Graber (49) Jonas Schnelli (48) @@ -42,9 +42,11 @@ Joe Turgeon (2) Jack Gavigan (2) ITH4Coinomia (2) Gavin Andresen (2) +Ariel Gabizon (2) Amgad Abdelhafez (2) zathras-crypto (1) unsystemizer (1) +practicalswift (1) mruddy (1) mrbandrews (1) kazcw (1) diff --git a/doc/hotfix-process.md b/doc/hotfix-process.md new file mode 100644 index 000000000..e6ce8a7a2 --- /dev/null +++ b/doc/hotfix-process.md @@ -0,0 +1,74 @@ +Hotfix Release Process +====================== + +Hotfix releases are versioned by incrementing the build number of the latest +release. For example: + + First hotfix: v1.0.11 -> v1.0.11-1 + Second hotfix: v1.0.11-1 -> v1.0.11-2 + +In the commands below, and are prefixed with a v, ie. +v1.0.11 (not 1.0.11). + +## Create a hotfix branch + +Create a hotfix branch from the previous release tag, and push it to the main +repository: + + $ git branch hotfix- + $ git push 'git@github.com:zcash/zcash' hotfix- + +## Implement hotfix changes + +Hotfix changes are implemented the same way as regular changes (developers work +in separate branches per change, and push the branches to their own repositories), +except that the branches are based on the hotfix branch instead of master: + + $ git checkout hotfix- + $ git checkout -b + +## Merge hotfix PRs + +Hotfix PRs are created like regular PRs, except using the hotfix branch as the +base instead of master. Each PR should be reviewed as normal, and then the +following process should be used to merge: + +- A CI merge build is manually run by logging into the CI server, going to the + pr-merge builder, clicking the "force" button, and entering the following + values: + + - Repository: https://github.com//zcash + - must be in the set of "safe" users as-specified in the CI + config. + - Branch: name of the hotfix PR branch (not the hotfix release branch). + +- A link to the build and its result is manually added to the PR as a comment. + +- If the build was successful, the PR is merged via the GitHub button. + +## Release process + +The majority of this process is identical to the standard release process. +However, there are a few notable differences: + +- When running the release script, use the `--hotfix` flag: + + $ ./zcutil/make-release.py --hotfix + +- To review the automated changes in git: + + $ git log hotfix-..HEAD + +- After the standard review process, use the hotfix merge process outlined above + instead of the regular merge process. + +- When making the tag, check out the hotfix branch instead of master. + +## Post-release + +Once the hotfix release has been created, a new PR should be opened for merging +the hotfix release branch into master. This may require fixing merge conflicts +(e.g. changing the version number in the hotfix branch to match master, if +master is ahead). Such conflicts **MUST** be addressed with additional commits +to the hotfix branch; specifically, the branch **MUST NOT** be rebased on +master. diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index bb0c98c66..7e56ac742 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.3. -.TH ZCASH-CLI "1" "June 2017" "zcash-cli v1.0.10-1" "User Commands" +.TH ZCASH-CLI "1" "August 2017" "zcash-cli v1.0.11" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v1.0.10-1 +zcash-cli \- manual page for zcash-cli v1.0.11 .SH DESCRIPTION -Zcash RPC client version v1.0.10\-1 +Zcash RPC client version v1.0.11 .PP In order to ensure you are adequately protecting your privacy when using BitcoinZ, please see . @@ -81,4 +81,4 @@ 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. +by Eric Young. diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index 735c8385a..f40e4a345 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.3. -.TH ZCASH-TX "1" "June 2017" "zcash-tx v1.0.10-1" "User Commands" +.TH ZCASH-TX "1" "August 2017" "zcash-tx v1.0.11" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v1.0.10-1 +zcash-tx \- manual page for zcash-tx v1.0.11 .SH DESCRIPTION -Zcash zcash\-tx utility version v1.0.10\-1 +Zcash zcash\-tx utility version v1.0.11 .SS "Usage:" .TP zcash\-tx [options] [commands] @@ -98,4 +98,4 @@ 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. +by Eric Young. diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index a6d99befb..9f3b37816 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.3. -.TH ZCASHD "1" "June 2017" "zcashd v1.0.10-1" "User Commands" +.TH ZCASHD "1" "August 2017" "zcashd v1.0.11" "User Commands" .SH NAME -zcashd \- manual page for zcashd v1.0.10-1 +zcashd \- manual page for zcashd v1.0.11 .SH DESCRIPTION -Zcash Daemon version v1.0.10\-1 +Zcash Daemon version v1.0.11 .PP In order to ensure you are adequately protecting your privacy when using BitcoinZ, please see . @@ -54,7 +54,7 @@ Specify data directory \fB\-disabledeprecation=\fR .IP Disable block\-height node deprecation and automatic shutdown (example: -\fB\-disabledeprecation\fR=\fI\,1\/\fR.0.10\-1) +\fB\-disabledeprecation\fR=\fI\,1\/\fR.0.11) .HP \fB\-exportdir=\fR .IP @@ -79,7 +79,7 @@ mempool will accept (default: 0 = no limit applied) .HP \fB\-par=\fR .IP -Set the number of script verification threads (\fB\-4\fR to 16, 0 = auto, <0 = +Set the number of script verification threads (\fB\-2\fR to 16, 0 = auto, <0 = leave that many cores free, default: 0) .HP \fB\-pid=\fR @@ -217,10 +217,6 @@ Tor control port to use if onion listening enabled (default: .IP Tor control port password (default: empty) .HP -\fB\-upnp\fR -.IP -Use UPnP to map the listening port (default: 0) -.HP \fB\-whitebind=\fR .IP Bind to given address and whitelist peers connecting to it. Use @@ -484,4 +480,4 @@ 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. +by Eric Young. diff --git a/doc/payment-api.md b/doc/payment-api.md index 5dc0eb907..6812cf6b4 100644 --- a/doc/payment-api.md +++ b/doc/payment-api.md @@ -71,7 +71,7 @@ z_importwallet | filename | _Requires an unlocked wallet or an unencrypted walle Command | Parameters | Description --- | --- | --- z_listreceivedbyaddress
| zaddr [minconf=1] | Return a list of amounts received by a zaddr belonging to the node’s wallet.

Optionally set the minimum number of confirmations which a received amount must have in order to be included in the result. Use 0 to count unconfirmed transactions.

Output:
[{
“txid”: “4a0f…”,
“amount”: 0.54,
“memo”:”F0FF…”,}, {...}, {...}
] -z_sendmany
| fromaddress amounts [minconf=1] [fee=0.0001] | _This is an Asynchronous RPC call_

Send funds from an address to multiple outputs. The address can be either a taddr or a zaddr.

Amounts is a list containing key/value pairs corresponding to the addresses and amount to pay. Each output address can be in taddr or zaddr format.

When sending to a zaddr, you also have the option of attaching a memo in hexadecimal format.

**NOTE:**When sending coinbase funds to a zaddr, the node's wallet does not allow any change. Put another way, spending a partial amount of a coinbase utxo is not allowed. This is not a consensus rule but a local wallet rule due to the current implementation of z_sendmany. In future, this rule may be removed.

Example of Outputs parameter:
[{“address”:”t123…”, “amount”:0.005},
,{“address”:”z010…”,”amount”:0.03, “memo”:”f508af…”}]

Optionally set the minimum number of confirmations which a private or transparent transaction must have in order to be used as an input.

Optionally set a transaction fee, which by default is 0.0001 ZEC.

Any transparent change will be sent to a new transparent address. Any private change will be sent back to the zaddr being used as the source of funds.

Returns an operationid. You use the operationid value with z_getoperationstatus and z_getoperationresult to obtain the result of sending funds, which if successful, will be a txid. +z_sendmany
| fromaddress amounts [minconf=1] [fee=0.0001] | _This is an Asynchronous RPC call_

Send funds from an address to multiple outputs. The address can be either a taddr or a zaddr.

Amounts is a list containing key/value pairs corresponding to the addresses and amount to pay. Each output address can be in taddr or zaddr format.

When sending to a zaddr, you also have the option of attaching a memo in hexadecimal format.

**NOTE:**When sending coinbase funds to a zaddr, the node's wallet does not allow any change. Put another way, spending a partial amount of a coinbase utxo is not allowed. This is not a consensus rule but a local wallet rule due to the current implementation of z_sendmany. In future, this rule may be removed.

Example of Outputs parameter:
[{“address”:”t123…”, “amount”:0.005},
,{“address”:”z010…”,”amount”:0.03, “memo”:”f508af…”}]

Optionally set the minimum number of confirmations which a private or transparent transaction must have in order to be used as an input. When sending from a zaddr, minconf must be greater than zero.

Optionally set a transaction fee, which by default is 0.0001 ZEC.

Any transparent change will be sent to a new transparent address. Any private change will be sent back to the zaddr being used as the source of funds.

Returns an operationid. You use the operationid value with z_getoperationstatus and z_getoperationresult to obtain the result of sending funds, which if successful, will be a txid. ### Operations @@ -100,7 +100,7 @@ It is currently not possible to cancel operations. Command | Parameters | Description --- | --- | --- -z_getoperationresult
| [operationids] | Return OperationStatus JSON objects for all completed operations the node is currently aware of, and then remove the operation from memory.

Operationids is an optional array to filter which operations you want to receive status objects for.

Output is a list of operation status objects, where the status is either "failed", "cancelled" or "success".
[
{“operationid”: “opid-11ee…”,
“status”: “cancelled”},
{“operationid”: “opid-9876”, “status”: ”failed”},
{“operationid”: “opid-0e0e”,
“status”:”success”,
“execution_time”:”25”,
“result”: {“txid”:”af3887654…”,...}
},
] +z_getoperationresult
| [operationids] | Return OperationStatus JSON objects for all completed operations the node is currently aware of, and then remove the operation from memory.

Operationids is an optional array to filter which operations you want to receive status objects for.

Output is a list of operation status objects, where the status is either "failed", "cancelled" or "success".
[
{“operationid”: “opid-11ee…”,
“status”: “cancelled”},
{“operationid”: “opid-9876”, “status”: ”failed”},
{“operationid”: “opid-0e0e”,
“status”:”success”,
“execution_time”:”25”,
“result”: {“txid”:”af3887654…”,...}
},
]

Examples:
zcash-cli z_getoperationresult '["opid-8120fa20-5ee7-4587-957b-f2579c2d882b"]'
zcash-cli z_getoperationresult z_getoperationstatus
| [operationids] | Return OperationStatus JSON objects for all operations the node is currently aware of.

Operationids is an optional array to filter which operations you want to receive status objects for.

Output is a list of operation status objects.
[
{“operationid”: “opid-12ee…”,
“status”: “queued”},
{“operationid”: “opd-098a…”, “status”: ”executing”},
{“operationid”: “opid-9876”, “status”: ”failed”}
]

When the operation succeeds, the status object will also include the result.

{“operationid”: “opid-0e0e”,
“status”:”success”,
“execution_time”:”25”,
“result”: {“txid”:”af3887654…”,...}
} z_listoperationids
| [state] | Return a list of operationids for all operations which the node is currently aware of.

State is an optional string parameter to filter the operations you want listed by their state. Acceptable parameter values are ‘queued’, ‘executing’, ‘success’, ‘failed’, ‘cancelled’.

[“opid-0e0e…”, “opid-1af4…”, … ] @@ -112,6 +112,7 @@ Zcash error codes are defined in https://github.com/zcash/zcash/blob/master/src/ RPC_INVALID_PARAMETER (-8) | _Invalid, missing or duplicate parameter_ ---------------------------| ------------------------------------------------- +"Minconf cannot be zero when sending from zaddr" | Cannot accept minimum confirmation value of zero when sending from zaddr. "Minconf cannot be negative" | Cannot accept negative minimum confirmation number. "Minimum number of confirmations cannot be less than 0" | Cannot accept negative minimum confirmation number. "From address parameter missing" | Missing an address to send funds from. diff --git a/doc/release-notes/release-notes-1.0.11-rc1.md b/doc/release-notes/release-notes-1.0.11-rc1.md new file mode 100644 index 000000000..4542a448c --- /dev/null +++ b/doc/release-notes/release-notes-1.0.11-rc1.md @@ -0,0 +1,44 @@ +Changelog +========= + +Ariel Gabizon (2): + make-release.py: Versioning changes for 1.0.11-rc1. + make-release.py: Updated manpages for 1.0.11-rc1. + +Daira Hopwood (7): + Clean up imports to be pyflakes-checkable. fixes #2450 + For unused variables reported by pyflakes, either remove the variable, suppress the warning, or fix a bug (if the wrong variable was used). refs #2450 + Cosmetics (trailing whitespace, comment conventions, etc.) + Alert 1004 (version 1.0.10 only) + Remove UPnP support. fixes #2500 + Change wording in Security Warnings section of README.md. + Document our criteria for adding CI workers. closes #2499 + +Jack Grigg (15): + Pull in temporary release notes during the release process + Ansible playbook for installing Zcash dependencies and Buildbot worker + Variable overrides for Debian, Ubuntu and Fedora + Variable overrides for FreeBSD + Simplify Python installation, inform user if they need to manually configure + Add test for issue #2444 + Add Buildbot worker setup to Ansible playbook + Add steps for setting up a latent worker on Amazon EC2 + Add pyblake2 to required Python modules + Remove Buildbot version from host file + Add a separate Buildbot host info template for EC2 + Add pyflakes to required Python modules + Add block download progress to metrics UI + Correct and extend EstimateNetHeightInner tests + Improve network height estimation + +Simon Liu (3): + Closes #2446 by adding generated field to listunspent. + Fixes #2519. When sending from a zaddr, minconf cannot be zero. + Fixes #2480. Null entry in map was dereferenced leading to a segfault. + +Wladimir J. van der Laan (1): + rpc: Add WWW-Authenticate header to 401 response + +practicalswift (1): + Net: Fix resource leak in ReadBinaryFile(...) + diff --git a/doc/release-notes/release-notes-1.0.11.md b/doc/release-notes/release-notes-1.0.11.md new file mode 100644 index 000000000..7a36c0be6 --- /dev/null +++ b/doc/release-notes/release-notes-1.0.11.md @@ -0,0 +1,7 @@ +Changelog +========= + +Jack Grigg (2): + make-release.py: Versioning changes for 1.0.11. + make-release.py: Updated manpages for 1.0.11. + diff --git a/doc/release-process.md b/doc/release-process.md index d6090dfcd..bcbab4946 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -2,6 +2,8 @@ Release Process ==================== Meta: There should always be a single release engineer to disambiguate responsibility. +If this is a hotfix release, please see `./hotfix-process.md` before proceeding. + ## Pre-release ### Github Milestone @@ -38,8 +40,23 @@ process. If these were not anticipated correctly, this could block the release, so if you suspect this is necessary, double check with the whole engineering team. +## Release dependencies + +The release script has the following dependencies: + +- `help2man` +- `debchange` (part of the devscripts Debian package) + +You can optionally install the `progressbar2` Python module with pip to have a +progress bar displayed during the build process. + ## Release process +In the commands below, and are prefixed with a v, ie. +v1.0.9 (not 1.0.9). + +### Create the release branch + Run the release script, which will verify you are on the latest clean checkout of master, create a branch, then commit standard automated changes to that branch locally: @@ -91,6 +108,22 @@ signed. **CAUTION:** Remember the `v` at the beginning here: - If all is well, the DevOps engineer will build the Debian packages and update the [apt.z.cash package repository](https://apt.z.cash). +## Add release notes to GitHub + +- Go to the [GitHub tags page](https://github.com/zcash/zcash/tags). +- Click "Add release notes" beside the tag for this release. +- Copy the release blog post into the release description, and edit to suit + publication on GitHub. See previous release notes for examples. +- Click "Publish release" if publishing the release blog post now, or + "Save draft" to store the notes internally (and then return later to publish + once the blog post is up). + +Note that some GitHub releases are marked as "Verified", and others as +"Unverified". This is related to the GPG signature on the release tag - in +particular, GitHub needs the corresponding public key to be uploaded to a +corresponding GitHub account. If this release is marked as "Unverified", click +the marking to see what GitHub wants to be done. + ## Post Release Task List ### Deploy testnet @@ -106,6 +139,10 @@ Then, verify that nodes can connect to the testnet server, and update the guide ### Update the 1.0 User Guide -### Publish the release announcement (blog, zcash-dev, slack) +This also means updating [the translations](https://github.com/zcash/zcash-docs). +Coordinate with the translation team for now. Suggestions for improving this +part of the process should be added to #2596. + +### Publish the release announcement (blog, github, zcash-dev, slack) ## Celebrate diff --git a/qa/rpc-tests/decodescript.py b/qa/rpc-tests/decodescript.py index ce3bc94ef..89364a840 100755 --- a/qa/rpc-tests/decodescript.py +++ b/qa/rpc-tests/decodescript.py @@ -4,7 +4,9 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.util import assert_equal, initialize_chain_clean, \ + start_nodes + class DecodeScriptTest(BitcoinTestFramework): """Tests decoding scripts via RPC command "decodescript".""" diff --git a/qa/rpc-tests/disablewallet.py b/qa/rpc-tests/disablewallet.py index 67acdcea1..339c6a8f6 100755 --- a/qa/rpc-tests/disablewallet.py +++ b/qa/rpc-tests/disablewallet.py @@ -8,7 +8,8 @@ # from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.util import initialize_chain_clean, start_nodes + class DisableWalletTest (BitcoinTestFramework): diff --git a/qa/rpc-tests/forknotify.py b/qa/rpc-tests/forknotify.py index 0acef8e30..1be750a64 100755 --- a/qa/rpc-tests/forknotify.py +++ b/qa/rpc-tests/forknotify.py @@ -8,9 +8,9 @@ # from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.util import start_node, connect_nodes + import os -import shutil class ForkNotifyTest(BitcoinTestFramework): @@ -19,7 +19,7 @@ class ForkNotifyTest(BitcoinTestFramework): 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'): 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 + "\""])) diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 1d15fd132..42896be4f 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -4,9 +4,12 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -from pprint import pprint -from time import sleep +from test_framework.authproxy import JSONRPCException +from test_framework.util import assert_equal, assert_greater_than, \ + initialize_chain_clean, start_nodes, connect_nodes_bi, stop_nodes, \ + wait_bitcoinds + +from decimal import Decimal # Create one-input, one-output, no-fee transaction: class RawTransactionsTest(BitcoinTestFramework): diff --git a/qa/rpc-tests/getblocktemplate.py b/qa/rpc-tests/getblocktemplate.py index c9777c0c7..82082afa9 100755 --- a/qa/rpc-tests/getblocktemplate.py +++ b/qa/rpc-tests/getblocktemplate.py @@ -4,7 +4,8 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.util import initialize_chain_clean, start_nodes, \ + connect_nodes_bi class GetBlockTemplateTest(BitcoinTestFramework): diff --git a/qa/rpc-tests/getblocktemplate_longpoll.py b/qa/rpc-tests/getblocktemplate_longpoll.py index aab456242..37a40384b 100755 --- a/qa/rpc-tests/getblocktemplate_longpoll.py +++ b/qa/rpc-tests/getblocktemplate_longpoll.py @@ -4,8 +4,10 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.authproxy import AuthServiceProxy +from test_framework.util import random_transaction +from decimal import Decimal def check_array_result(object_array, to_match, expected): """ diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py index 0c9e7e4cc..16b2e9b94 100755 --- a/qa/rpc-tests/getblocktemplate_proposals.py +++ b/qa/rpc-tests/getblocktemplate_proposals.py @@ -4,7 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.authproxy import JSONRPCException from binascii import a2b_hex, b2a_hex from hashlib import sha256 diff --git a/qa/rpc-tests/hardforkdetection.py b/qa/rpc-tests/hardforkdetection.py index d399dc964..dbfb5cd34 100755 --- a/qa/rpc-tests/hardforkdetection.py +++ b/qa/rpc-tests/hardforkdetection.py @@ -5,9 +5,10 @@ # from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.authproxy import JSONRPCException +from test_framework.util import assert_equal, start_node + import os -import shutil class HardForkDetectionTest(BitcoinTestFramework): @@ -16,7 +17,7 @@ class HardForkDetectionTest(BitcoinTestFramework): 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'): 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 + "\""])) diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py index b66533543..b1a4623bd 100755 --- a/qa/rpc-tests/httpbasics.py +++ b/qa/rpc-tests/httpbasics.py @@ -8,7 +8,8 @@ # from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.util import assert_equal, start_nodes + import base64 try: @@ -36,45 +37,45 @@ def run_test(self): conn = httplib.HTTPConnection(url.hostname, url.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) - out1 = conn.getresponse().read(); + 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_equal(conn.sock!=None, True) # according to http/1.1 connection must still be open! - #send 2nd request without closing connection + # 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! + out2 = conn.getresponse().read() + assert_equal('"error":null' in out2, 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! conn.close() - #same should be if we add keep-alive because this should be the std. behaviour + # same should be if we add keep-alive because this should be the std. behaviour headers = {"Authorization": "Basic " + base64.b64encode(authpair), "Connection": "keep-alive"} conn = httplib.HTTPConnection(url.hostname, url.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) - out1 = conn.getresponse().read(); + 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_equal(conn.sock!=None, True) # according to http/1.1 connection must still be open! - #send 2nd request without closing connection + # 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! + out2 = conn.getresponse().read() + assert_equal('"error":null' in out2, 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! conn.close() - #now do the same with "Connection: close" + # now do the same with "Connection: close" headers = {"Authorization": "Basic " + base64.b64encode(authpair), "Connection":"close"} conn = httplib.HTTPConnection(url.hostname, url.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) - out1 = conn.getresponse().read(); + 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_equal(conn.sock!=None, False) # now the connection must be closed after the response - #node1 (2nd node) is running with disabled keep-alive option + # 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)} @@ -82,10 +83,10 @@ def run_test(self): conn = httplib.HTTPConnection(urlNode1.hostname, urlNode1.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) - out1 = conn.getresponse().read(); + out1 = conn.getresponse().read() assert_equal('"error":null' in out1, True) - #node2 (third node) is running with standard keep-alive parameters which means keep-alive is on + # 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)} @@ -93,9 +94,9 @@ def run_test(self): conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) - out1 = conn.getresponse().read(); + 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_equal(conn.sock!=None, True) # connection must be closed because bitcoind should use keep-alive by default if __name__ == '__main__': - HTTPBasicsTest ().main () + HTTPBasicsTest().main() diff --git a/qa/rpc-tests/invalidateblock.py b/qa/rpc-tests/invalidateblock.py index 2b9c8154e..5cbd1ea98 100755 --- a/qa/rpc-tests/invalidateblock.py +++ b/qa/rpc-tests/invalidateblock.py @@ -8,22 +8,23 @@ # from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.util import initialize_chain_clean, start_node, \ + connect_nodes_bi, sync_blocks + +import time class InvalidateTest(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.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 "Make sure we repopulate setBlockIndexCandidates after InvalidateBlock:" print "Mine 4 blocks on Node 0" diff --git a/qa/rpc-tests/invalidblockrequest.py b/qa/rpc-tests/invalidblockrequest.py index 272cc08f9..05b33d772 100755 --- a/qa/rpc-tests/invalidblockrequest.py +++ b/qa/rpc-tests/invalidblockrequest.py @@ -5,11 +5,11 @@ # from test_framework.test_framework import ComparisonTestFramework -from test_framework.util import * +from test_framework.util import assert_equal from test_framework.comptool import TestManager, TestInstance -from test_framework.mininode import * -from test_framework.blocktools import * -import logging +from test_framework.mininode import NetworkThread +from test_framework.blocktools import create_block, create_coinbase, create_transaction + import copy import time @@ -25,7 +25,7 @@ # Use the ComparisonTestFramework with 1 node: only use --testbinary. class InvalidBlockRequestTest(ComparisonTestFramework): - ''' Can either run this test as 1 node with expected answers, or two and compare them. + ''' 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): self.num_nodes = 1 diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py index 38d6874dc..a7b32e13f 100755 --- a/qa/rpc-tests/keypool.py +++ b/qa/rpc-tests/keypool.py @@ -6,18 +6,17 @@ # Exercise the wallet keypool, and interaction with wallet encryption/locking # Add python-bitcoinrpc to module search path: + +from test_framework.authproxy import JSONRPCException +from test_framework.util import check_json_precision, initialize_chain, \ + start_nodes, start_node, stop_nodes, wait_bitcoinds, bitcoind_processes + import os import sys - -import json import shutil -import subprocess import tempfile import traceback -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 diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py index 4df8d795d..a735f41ab 100755 --- a/qa/rpc-tests/listtransactions.py +++ b/qa/rpc-tests/listtransactions.py @@ -6,8 +6,8 @@ # Exercise the listtransactions API from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from decimal import Decimal def check_array_result(object_array, to_match, expected): """ diff --git a/qa/rpc-tests/maxblocksinflight.py b/qa/rpc-tests/maxblocksinflight.py index a601147ce..beef3d2ea 100755 --- a/qa/rpc-tests/maxblocksinflight.py +++ b/qa/rpc-tests/maxblocksinflight.py @@ -4,9 +4,15 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. # -from test_framework.mininode import * +from test_framework.mininode import NodeConn, NodeConnCB, NetworkThread, \ + EarlyDisconnectError, CInv, msg_inv, mininode_lock from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.util import initialize_chain_clean, start_nodes, \ + p2p_port + +import os +import time +import random import logging ''' @@ -43,7 +49,6 @@ def add_new_connection(self, connection): def run(self): try: - fail = False self.connection.rpc.generate(1) # Leave IBD numBlocksToGenerate = [ 8, 16, 128, 1024 ] @@ -56,7 +61,7 @@ def run(self): 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) @@ -75,7 +80,7 @@ def run(self): self.disconnectOkay = True self.connection.disconnect_node() - + class MaxBlocksInFlightTest(BitcoinTestFramework): def add_options(self, parser): parser.add_option("--testbinary", dest="testbinary", diff --git a/qa/rpc-tests/mempool_coinbase_spends.py b/qa/rpc-tests/mempool_coinbase_spends.py index 578ddb1fb..041de831b 100755 --- a/qa/rpc-tests/mempool_coinbase_spends.py +++ b/qa/rpc-tests/mempool_coinbase_spends.py @@ -9,9 +9,8 @@ # from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -import os -import shutil +from test_framework.util import assert_equal, start_node, connect_nodes + # Create one-input, one-output, no-fee transaction: class MempoolCoinbaseTest(BitcoinTestFramework): @@ -36,8 +35,6 @@ def create_tx(self, from_txid, to_address, amount): return signresult["hex"] def run_test(self): - start_count = self.nodes[0].getblockcount() - # Mine three blocks. After this, nodes[0] blocks # 101, 102, and 103 are spend-able. new_blocks = self.nodes[1].generate(4) @@ -69,6 +66,7 @@ def run_test(self): # Broadcast and mine 103_1: spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw) + [spend_103_1_id] # hush pyflakes self.nodes[0].generate(1) # ... now put spend_101 and spend_102_1 in memory pools: diff --git a/qa/rpc-tests/mempool_resurrect_test.py b/qa/rpc-tests/mempool_resurrect_test.py index dd3f0486f..1cbbd2cd5 100755 --- a/qa/rpc-tests/mempool_resurrect_test.py +++ b/qa/rpc-tests/mempool_resurrect_test.py @@ -9,9 +9,8 @@ # from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -import os -import shutil +from test_framework.util import assert_equal, start_node + # Create one-input, one-output, no-fee transaction: class MempoolCoinbaseTest(BitcoinTestFramework): diff --git a/qa/rpc-tests/mempool_spendcoinbase.py b/qa/rpc-tests/mempool_spendcoinbase.py index b2ec6937b..5366fb955 100755 --- a/qa/rpc-tests/mempool_spendcoinbase.py +++ b/qa/rpc-tests/mempool_spendcoinbase.py @@ -14,9 +14,10 @@ # from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -import os -import shutil +from test_framework.authproxy import JSONRPCException +from test_framework.util import assert_equal, assert_greater_than, assert_raises, \ + start_node + # Create one-input, one-output, no-fee transaction: class MempoolSpendCoinbaseTest(BitcoinTestFramework): diff --git a/qa/rpc-tests/mempool_tx_input_limit.py b/qa/rpc-tests/mempool_tx_input_limit.py index 89a96a0ca..538122671 100755 --- a/qa/rpc-tests/mempool_tx_input_limit.py +++ b/qa/rpc-tests/mempool_tx_input_limit.py @@ -4,10 +4,12 @@ # 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 time import sleep +from test_framework.authproxy import JSONRPCException +from test_framework.util import assert_equal, initialize_chain_clean, \ + start_node, connect_nodes + +import time +from decimal import Decimal # Test -mempooltxinputlimit class MempoolTxInputLimitTest(BitcoinTestFramework): @@ -44,7 +46,7 @@ def wait_and_assert_operationid_status(self, myopid, in_status='success', in_err for x in xrange(1, timeout): results = self.nodes[0].z_getoperationresult(opids) if len(results)==0: - sleep(1) + time.sleep(1) else: status = results[0]["status"] if status == "failed": @@ -61,8 +63,6 @@ def wait_and_assert_operationid_status(self, myopid, in_status='success', in_err return txid def run_test(self): - start_count = self.nodes[0].getblockcount() - self.nodes[0].generate(100) self.sync_all() # Mine three blocks. After this, nodes[0] blocks @@ -90,7 +90,7 @@ def run_test(self): for x in xrange(1, timeout): results = self.nodes[0].z_getoperationresult(opids) if len(results)==0: - sleep(1) + time.sleep(1) else: status = results[0]["status"] msg = results[0]["error"]["message"] @@ -116,7 +116,6 @@ def run_test(self): assert_equal(set(self.nodes[0].getrawmempool()), set()) # Check 2: sendfrom is limited by -mempooltxinputlimit - node1_taddr = self.nodes[1].getnewaddress(); recipients = [] spend_taddr_amount = spend_zaddr_amount - Decimal('0.0001') spend_taddr_output = Decimal('8') diff --git a/qa/rpc-tests/merkle_blocks.py b/qa/rpc-tests/merkle_blocks.py index 5c333124f..2c0fcd203 100755 --- a/qa/rpc-tests/merkle_blocks.py +++ b/qa/rpc-tests/merkle_blocks.py @@ -8,9 +8,10 @@ # from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -import os -import shutil +from test_framework.authproxy import JSONRPCException +from test_framework.util import assert_equal, assert_raises, \ + initialize_chain_clean, start_node, connect_nodes + class MerkleBlockTest(BitcoinTestFramework): diff --git a/qa/rpc-tests/nodehandling.py b/qa/rpc-tests/nodehandling.py index 9a77bd97e..391a935d0 100755 --- a/qa/rpc-tests/nodehandling.py +++ b/qa/rpc-tests/nodehandling.py @@ -8,13 +8,10 @@ # from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -import base64 +from test_framework.util import assert_equal, connect_nodes_bi, p2p_port + +import time -try: - import http.client as httplib -except ImportError: - import httplib try: import urllib.parse as urlparse except ImportError: diff --git a/qa/rpc-tests/p2p-acceptblock.py b/qa/rpc-tests/p2p-acceptblock.py index 83c03eeb7..25221fbed 100755 --- a/qa/rpc-tests/p2p-acceptblock.py +++ b/qa/rpc-tests/p2p-acceptblock.py @@ -4,12 +4,17 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. # -from test_framework.mininode import * +from test_framework.mininode import CBlockHeader, CInv, NodeConn, NodeConnCB, \ + NetworkThread, msg_block, msg_headers, msg_inv, msg_ping, msg_pong, \ + mininode_lock from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -import time +from test_framework.util import assert_equal, initialize_chain_clean, \ + start_node, p2p_port from test_framework.blocktools import create_block, create_coinbase +import os +import time + ''' AcceptBlockTest -- test processing of unrequested blocks. diff --git a/qa/rpc-tests/prioritisetransaction.py b/qa/rpc-tests/prioritisetransaction.py index 19697fc4a..9eeb72e8c 100755 --- a/qa/rpc-tests/prioritisetransaction.py +++ b/qa/rpc-tests/prioritisetransaction.py @@ -4,9 +4,10 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -from time import * +from test_framework.util import assert_equal, initialize_chain_clean, \ + start_node, connect_nodes from test_framework.mininode import COIN + import time @@ -37,7 +38,7 @@ def wait_and_assert_operationid_status(self, myopid, in_status='success', in_err for x in xrange(1, timeout): results = self.nodes[0].z_getoperationresult(opids) if len(results)==0: - sleep(1) + time.sleep(1) else: status = results[0]["status"] if status == "failed": @@ -120,7 +121,7 @@ def run_test (self): break if time.time() - start > 30: raise AssertionError("Test timed out because prioritised transaction was not returned by getblocktemplate within 30 seconds.") - sleep(1) + time.sleep(1) block_template = self.nodes[0].getblocktemplate() assert(in_block_template) diff --git a/qa/rpc-tests/proton_test.py b/qa/rpc-tests/proton_test.py index b895c087f..d9fb27bd3 100755 --- a/qa/rpc-tests/proton_test.py +++ b/qa/rpc-tests/proton_test.py @@ -14,21 +14,13 @@ # from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.util import assert_equal, bytes_to_hex_str, \ + start_nodes + from proton.handlers import MessagingHandler from proton.reactor import Container -import binascii -import struct -import threading -try: - import http.client as httplib -except ImportError: - import httplib -try: - import urllib.parse as urlparse -except ImportError: - import urlparse +import threading class Server(MessagingHandler): diff --git a/qa/rpc-tests/proxy_test.py b/qa/rpc-tests/proxy_test.py index 3623c1616..e4fb48820 100755 --- a/qa/rpc-tests/proxy_test.py +++ b/qa/rpc-tests/proxy_test.py @@ -2,14 +2,14 @@ # 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. -import socket -import traceback, sys -from binascii import hexlify -import time, os from test_framework.socks5 import Socks5Configuration, Socks5Command, Socks5Server, AddressType from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.util import assert_equal, start_nodes + +import socket +import os + ''' Test plan: - Start bitcoind's with different proxy configurations diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py index 21f8d6938..2639060fa 100755 --- a/qa/rpc-tests/pruning.py +++ b/qa/rpc-tests/pruning.py @@ -12,8 +12,12 @@ # ******** from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.authproxy import JSONRPCException +from test_framework.util import initialize_chain_clean, start_node, \ + connect_nodes, stop_node, sync_blocks + import os.path +import time 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) @@ -190,7 +194,7 @@ def reorg_back(self): try: self.nodes[2].getblock(self.forkhash) raise AssertionError("Old block wasn't pruned so can't test redownload") - except JSONRPCException as e: + except JSONRPCException: print "Will need to redownload block",self.forkheight # Verify that we have enough history to reorg back to the fork point @@ -253,7 +257,7 @@ def mine_full_block(self, node, address): newtx = newtx + rawtx[94:] # Appears to be ever so slightly faster to sign with SIGHASH_NONE signresult = node.signrawtransaction(newtx,None,None,"NONE") - txid = node.sendrawtransaction(signresult["hex"], True) + node.sendrawtransaction(signresult["hex"], True) # Mine a full sized block which will be these transactions we just created node.generate(1) diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py index 45517d3fd..dc919f028 100755 --- a/qa/rpc-tests/rawtransactions.py +++ b/qa/rpc-tests/rawtransactions.py @@ -9,9 +9,11 @@ # from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -from pprint import pprint -from time import sleep +from test_framework.authproxy import JSONRPCException +from test_framework.util import assert_equal, initialize_chain_clean, \ + start_nodes, connect_nodes_bi + +from decimal import Decimal # Create one-input, one-output, no-fee transaction: class RawTransactionsTest(BitcoinTestFramework): @@ -104,18 +106,20 @@ def run_test(self): mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']]) mSigObjValid = self.nodes[2].validateaddress(mSigObj) + assert_equal(mSigObjValid['isvalid'], True) txId = self.nodes[0].sendtoaddress(mSigObj, 2.2); decTx = self.nodes[0].gettransaction(txId) rawTx = self.nodes[0].decoderawtransaction(decTx['hex']) sPK = rawTx['vout'][0]['scriptPubKey']['hex'] + [sPK] # hush pyflakes self.sync_all() self.nodes[0].generate(1) self.sync_all() - #THIS IS A INCOMPLETE FEATURE - #NODE2 HAS TWO OF THREE KEY AND THE FUNDS SHOULD BE SPENDABLE AND COUNT AT BALANCE CALCULATION - assert_equal(self.nodes[2].getbalance(), bal) #for now, assume the funds of a 2of3 multisig tx are not marked as spendable + # THIS IS A INCOMPLETE FEATURE + # NODE2 HAS TWO OF THREE KEY AND THE FUNDS SHOULD BE SPENDABLE AND COUNT AT BALANCE CALCULATION + assert_equal(self.nodes[2].getbalance(), bal) # for now, assume the funds of a 2of3 multisig tx are not marked as spendable txDetails = self.nodes[0].gettransaction(txId, True) rawTx = self.nodes[0].decoderawtransaction(txDetails['hex']) @@ -130,10 +134,10 @@ def run_test(self): outputs = { self.nodes[0].getnewaddress() : 2.199 } rawTx = self.nodes[2].createrawtransaction(inputs, outputs) rawTxPartialSigned = self.nodes[1].signrawtransaction(rawTx, inputs) - assert_equal(rawTxPartialSigned['complete'], False) #node1 only has one key, can't comp. sign the tx - + assert_equal(rawTxPartialSigned['complete'], False) # node1 only has one key, can't comp. sign the tx + rawTxSigned = self.nodes[2].signrawtransaction(rawTx, inputs) - assert_equal(rawTxSigned['complete'], True) #node2 can sign the tx compl., own two of three keys + assert_equal(rawTxSigned['complete'], True) # node2 can sign the tx compl., own two of three keys self.nodes[2].sendrawtransaction(rawTxSigned['hex']) rawTx = self.nodes[0].decoderawtransaction(rawTxSigned['hex']) self.sync_all() diff --git a/qa/rpc-tests/receivedby.py b/qa/rpc-tests/receivedby.py index 16d6bd4cf..59f7bf258 100755 --- a/qa/rpc-tests/receivedby.py +++ b/qa/rpc-tests/receivedby.py @@ -6,15 +6,14 @@ # Exercise the listreceivedbyaddress API from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from decimal import Decimal def get_sub_array_from_array(object_array, to_match): ''' - Finds and returns a sub array from an array of arrays. - to_match should be a unique idetifier of a sub array + Finds and returns a sub array from an array of arrays. + to_match should be a unique idetifier of a sub array ''' - num_matched = 0 for item in object_array: all_match = True for key,value in to_match.items(): @@ -26,12 +25,12 @@ def get_sub_array_from_array(object_array, to_match): 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 - """ + ''' + 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 @@ -62,49 +61,49 @@ def run_test(self): txid = self.nodes[0].sendtoaddress(addr, 0.1) self.sync_all() - #Check not listed in listreceivedbyaddress because has 0 confirmations + # Check not listed in listreceivedbyaddress because has 0 confirmations check_array_result(self.nodes[1].listreceivedbyaddress(), {"address":addr}, { }, True) - #Bury Tx under 10 block so it will be returned by listreceivedbyaddress + # 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(), {"address":addr}, {"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]}) - #With min confidence < 10 + # With min confidence < 10 check_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 + # With min confidence > 10, should not find Tx check_array_result(self.nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True) - #Empty Tx + # Empty Tx addr = self.nodes[1].getnewaddress() check_array_result(self.nodes[1].listreceivedbyaddress(0,True), {"address":addr}, {"address":addr, "account":"", "amount":0, "confirmations":0, "txids":[]}) ''' - getreceivedbyaddress Test + getreceivedbyaddress Test ''' # Send from node 0 to 1 addr = self.nodes[1].getnewaddress() txid = self.nodes[0].sendtoaddress(addr, 0.1) self.sync_all() - #Check balance is 0 because of 0 confirmations + # Check balance is 0 because of 0 confirmations balance = self.nodes[1].getreceivedbyaddress(addr) if balance != Decimal("0.0"): raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance)) - #Check balance is 0.1 + # Check balance is 0.1 balance = self.nodes[1].getreceivedbyaddress(addr,0) if balance != Decimal("0.1"): raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance)) - #Bury Tx under 10 block so it will be returned by the default getreceivedbyaddress + # Bury Tx under 10 block so it will be returned by the default getreceivedbyaddress self.nodes[1].generate(10) self.sync_all() balance = self.nodes[1].getreceivedbyaddress(addr) @@ -112,15 +111,15 @@ def run_test(self): raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance)) ''' - listreceivedbyaccount + getreceivedbyaccount Test + listreceivedbyaccount + getreceivedbyaccount Test ''' - #set pre-state + # set pre-state addrArr = self.nodes[1].getnewaddress() account = self.nodes[1].getaccount(addrArr) received_by_account_json = get_sub_array_from_array(self.nodes[1].listreceivedbyaccount(),{"account":account}) if len(received_by_account_json) == 0: raise AssertionError("No accounts found in node") - balance_by_account = rec_by_accountArr = self.nodes[1].getreceivedbyaccount(account) + balance_by_account = self.nodes[1].getreceivedbyaccount(account) txid = self.nodes[0].sendtoaddress(addr, 0.1) self.sync_all() @@ -147,7 +146,7 @@ def run_test(self): if balance != balance_by_account + Decimal("0.1"): raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance)) - #Create a new account named "mynewaccount" that has a 0 balance + # Create a new account named "mynewaccount" that has a 0 balance self.nodes[1].getaccountaddress("mynewaccount") received_by_account_json = get_sub_array_from_array(self.nodes[1].listreceivedbyaccount(0,True),{"account":"mynewaccount"}) if len(received_by_account_json) == 0: diff --git a/qa/rpc-tests/reindex.py b/qa/rpc-tests/reindex.py index f2e3f248e..ae7563192 100755 --- a/qa/rpc-tests/reindex.py +++ b/qa/rpc-tests/reindex.py @@ -6,9 +6,11 @@ # # Test -reindex with CheckBlockIndex # + from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -import os.path +from test_framework.util import assert_equal, initialize_chain_clean, \ + start_node, stop_node, wait_bitcoinds + class ReindexTest(BitcoinTestFramework): diff --git a/qa/rpc-tests/rest.py b/qa/rpc-tests/rest.py index d315c66d3..b14ec765d 100755 --- a/qa/rpc-tests/rest.py +++ b/qa/rpc-tests/rest.py @@ -7,14 +7,15 @@ # Test REST interface # - from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -from struct import * +from test_framework.util import assert_equal, assert_greater_than, \ + initialize_chain_clean, start_nodes, connect_nodes_bi + +import struct import binascii import json import StringIO -import decimal +from decimal import Decimal try: import http.client as httplib @@ -28,11 +29,11 @@ def deser_uint256(f): r = 0 for i in range(8): - t = unpack(b" /dev/null } +function extract_benchmark_datadir { + if [ -f "$1.tar.xz" ]; then + # Check the hash of the archive: + "$SHA256CMD" $SHA256ARGS -c < 0) @@ -27,5 +29,5 @@ CAmount CFeeRate::GetFee(size_t nSize) const std::string CFeeRate::ToString() const { - return strprintf("%d.%08d BTC/kB", nSatoshisPerK / COIN, nSatoshisPerK % COIN); + return strprintf("%d.%08d %s/kB", nSatoshisPerK / COIN, nSatoshisPerK % COIN, CURRENCY_UNIT); } diff --git a/src/amount.h b/src/amount.h index 7dc62edac..b224c2c7d 100644 --- a/src/amount.h +++ b/src/amount.h @@ -16,6 +16,8 @@ typedef int64_t CAmount; static const CAmount COIN = 100000000; static const CAmount CENT = 1000000; +extern const std::string CURRENCY_UNIT; + /** No amount larger than this (in satoshi) is valid. * * Note that this constant is *not* the total money supply, which in Bitcoin @@ -25,7 +27,7 @@ static const CAmount CENT = 1000000; * critical; in unusual circumstances like a(nother) overflow bug that allowed * for the creation of coins out of thin air modification could lead to a fork. * */ -static const CAmount MAX_MONEY = 21000000 * COIN; +static const CAmount MAX_MONEY = 21000000000 * COIN; inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } /** Type-safe wrapper class to for fee rates diff --git a/src/clientversion.h b/src/clientversion.h index f2bc38e4d..61813106f 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -17,8 +17,8 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 1 #define CLIENT_VERSION_MINOR 0 -#define CLIENT_VERSION_REVISION 10 -#define CLIENT_VERSION_BUILD 51 +#define CLIENT_VERSION_REVISION 11 +#define CLIENT_VERSION_BUILD 50 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index bfc70e72c..78e15380e 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -5,8 +5,10 @@ #ifndef ZCASH_DEPRECATION_H #define ZCASH_DEPRECATION_H -// Deprecation policy is 4th third-Tuesday after a release -static const int APPROX_RELEASE_HEIGHT = 137236; +// Deprecation policy: +// * Shut down 18 weeks' worth of blocks after the estimated release block height. +// * A warning is shown during the 2 weeks' worth of blocks prior to shut down. +static const int APPROX_RELEASE_HEIGHT = 167200; static const int WEEKS_UNTIL_DEPRECATION = 18; static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); diff --git a/src/gtest/test_httprpc.cpp b/src/gtest/test_httprpc.cpp new file mode 100644 index 000000000..c630973fb --- /dev/null +++ b/src/gtest/test_httprpc.cpp @@ -0,0 +1,62 @@ +#include +#include + +#include "httprpc.cpp" +#include "httpserver.h" + +using ::testing::Return; + +class MockHTTPRequest : public HTTPRequest { +public: + MOCK_METHOD0(GetPeer, CService()); + MOCK_METHOD0(GetRequestMethod, HTTPRequest::RequestMethod()); + MOCK_METHOD1(GetHeader, std::pair(const std::string& hdr)); + MOCK_METHOD2(WriteHeader, void(const std::string& hdr, const std::string& value)); + MOCK_METHOD2(WriteReply, void(int nStatus, const std::string& strReply)); + + MockHTTPRequest() : HTTPRequest(nullptr) {} + void CleanUp() { + // So the parent destructor doesn't try to send a reply + replySent = true; + } +}; + +TEST(HTTPRPC, FailsOnGET) { + MockHTTPRequest req; + EXPECT_CALL(req, GetRequestMethod()) + .WillRepeatedly(Return(HTTPRequest::GET)); + EXPECT_CALL(req, WriteReply(HTTP_BAD_METHOD, "JSONRPC server handles only POST requests")) + .Times(1); + EXPECT_FALSE(HTTPReq_JSONRPC(&req, "")); + req.CleanUp(); +} + +TEST(HTTPRPC, FailsWithoutAuthHeader) { + MockHTTPRequest req; + EXPECT_CALL(req, GetRequestMethod()) + .WillRepeatedly(Return(HTTPRequest::POST)); + EXPECT_CALL(req, GetHeader("authorization")) + .WillRepeatedly(Return(std::make_pair(false, ""))); + EXPECT_CALL(req, WriteHeader("WWW-Authenticate", "Basic realm=\"jsonrpc\"")) + .Times(1); + EXPECT_CALL(req, WriteReply(HTTP_UNAUTHORIZED, "")) + .Times(1); + EXPECT_FALSE(HTTPReq_JSONRPC(&req, "")); + req.CleanUp(); +} + +TEST(HTTPRPC, FailsWithBadAuth) { + MockHTTPRequest req; + EXPECT_CALL(req, GetRequestMethod()) + .WillRepeatedly(Return(HTTPRequest::POST)); + EXPECT_CALL(req, GetHeader("authorization")) + .WillRepeatedly(Return(std::make_pair(true, "Basic spam:eggs"))); + EXPECT_CALL(req, GetPeer()) + .WillRepeatedly(Return(CService("127.0.0.1:1337"))); + EXPECT_CALL(req, WriteHeader("WWW-Authenticate", "Basic realm=\"jsonrpc\"")) + .Times(1); + EXPECT_CALL(req, WriteReply(HTTP_UNAUTHORIZED, "")) + .Times(1); + EXPECT_FALSE(HTTPReq_JSONRPC(&req, "")); + req.CleanUp(); +} diff --git a/src/gtest/test_metrics.cpp b/src/gtest/test_metrics.cpp index c199b323e..143fe46d6 100644 --- a/src/gtest/test_metrics.cpp +++ b/src/gtest/test_metrics.cpp @@ -92,3 +92,44 @@ TEST(Metrics, GetLocalSolPS) { SetMockTime(104); EXPECT_EQ(1, GetLocalSolPS()); } + +TEST(Metrics, EstimateNetHeightInner) { + // Ensure that the (rounded) current height is returned if the tip is current + SetMockTime(15000); + EXPECT_EQ(100, EstimateNetHeightInner(100, 14100, 50, 7500, 0, 150)); + SetMockTime(15150); + EXPECT_EQ(100, EstimateNetHeightInner(101, 14250, 50, 7500, 0, 150)); + + // Ensure that correct estimates are returned if the tip is in the past + SetMockTime(15300); // Tip is 2 blocks behind + EXPECT_EQ(100, EstimateNetHeightInner(100, 14100, 50, 7500, 0, 150)); + SetMockTime(15900); // Tip is 6 blocks behind + EXPECT_EQ(110, EstimateNetHeightInner(100, 14100, 50, 7500, 0, 150)); + + // Check estimates during resync + SetMockTime(15000); + EXPECT_EQ(100, EstimateNetHeightInner( 0, 0, 50, 7500, 0, 150)); + EXPECT_EQ(100, EstimateNetHeightInner( 7, 600, 50, 7500, 0, 150)); + EXPECT_EQ(100, EstimateNetHeightInner( 8, 600, 50, 7500, 0, 150)); + EXPECT_EQ(100, EstimateNetHeightInner(10, 750, 50, 7500, 0, 150)); + EXPECT_EQ(100, EstimateNetHeightInner(11, 900, 50, 7500, 0, 150)); + EXPECT_EQ(100, EstimateNetHeightInner(20, 2100, 50, 7500, 0, 150)); + EXPECT_EQ(100, EstimateNetHeightInner(49, 6450, 50, 7500, 0, 150)); + EXPECT_EQ(100, EstimateNetHeightInner(50, 6600, 50, 7500, 0, 150)); + EXPECT_EQ(100, EstimateNetHeightInner(51, 6750, 50, 7500, 0, 150)); + EXPECT_EQ(100, EstimateNetHeightInner(55, 7350, 50, 7500, 0, 150)); + EXPECT_EQ(100, EstimateNetHeightInner(56, 7500, 50, 7500, 0, 150)); + EXPECT_EQ(100, EstimateNetHeightInner(57, 7650, 50, 7500, 0, 150)); + EXPECT_EQ(100, EstimateNetHeightInner(75, 10350, 50, 7500, 0, 150)); + + // More complex calculations: + SetMockTime(20000); + // - Checkpoint spacing: 200 + // -> Average spacing: 175 + // -> estimated height: 127 -> 130 + EXPECT_EQ(130, EstimateNetHeightInner(100, 14100, 50, 5250, 0, 150)); + // - Checkpoint spacing: 50 + // -> Average spacing: 100 + // -> estimated height: 153 -> 150 + EXPECT_EQ(150, EstimateNetHeightInner(100, 14100, 50, 12000, 0, 150)); +} diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 98ac750bb..cdce110c5 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -13,6 +13,9 @@ #include // boost::trim +/** WWW-Authenticate to present with 401 Unauthorized response */ +static const char* WWW_AUTH_HEADER_DATA = "Basic realm=\"jsonrpc\""; + /** Simple one-shot callback timer to be used by the RPC mechanism to e.g. * re-lock the wellet. */ @@ -94,6 +97,7 @@ static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &) // Check authorization std::pair authHeader = req->GetHeader("authorization"); if (!authHeader.first) { + req->WriteHeader("WWW-Authenticate", WWW_AUTH_HEADER_DATA); req->WriteReply(HTTP_UNAUTHORIZED); return false; } @@ -106,6 +110,7 @@ static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &) shouldn't have their RPC port exposed. */ MilliSleep(250); + req->WriteHeader("WWW-Authenticate", WWW_AUTH_HEADER_DATA); req->WriteReply(HTTP_UNAUTHORIZED); return false; } diff --git a/src/httpserver.h b/src/httpserver.h index b377dc19f..347e7c3ab 100644 --- a/src/httpserver.h +++ b/src/httpserver.h @@ -56,11 +56,14 @@ class HTTPRequest { private: struct evhttp_request* req; + + // For test access +protected: bool replySent; public: HTTPRequest(struct evhttp_request* req); - ~HTTPRequest(); + virtual ~HTTPRequest(); enum RequestMethod { UNKNOWN, @@ -76,17 +79,17 @@ class HTTPRequest /** Get CService (address:ip) for the origin of the http request. */ - CService GetPeer(); + virtual CService GetPeer(); /** Get request method. */ - RequestMethod GetRequestMethod(); + virtual RequestMethod GetRequestMethod(); /** * Get the request header specified by hdr, or an empty string. * Return an pair (isPresent,string). */ - std::pair GetHeader(const std::string& hdr); + virtual std::pair GetHeader(const std::string& hdr); /** * Read request body. @@ -101,7 +104,7 @@ class HTTPRequest * * @note call this before calling WriteErrorReply or Reply. */ - void WriteHeader(const std::string& hdr, const std::string& value); + virtual void WriteHeader(const std::string& hdr, const std::string& value); /** * Write HTTP reply. @@ -111,7 +114,7 @@ class HTTPRequest * @note Can be called only once. As this will give the request back to the * main thread, do not call any other HTTPRequest methods after calling this. */ - void WriteReply(int nStatus, const std::string& strReply = ""); + virtual void WriteReply(int nStatus, const std::string& strReply = ""); }; /** Event handler closure. diff --git a/src/init.cpp b/src/init.cpp index 2c3487320..ccc6eb3ea 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -393,13 +393,6 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-timeout=", strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT)); strUsage += HelpMessageOpt("-torcontrol=:", strprintf(_("Tor control port to use if onion listening enabled (default: %s)"), DEFAULT_TOR_CONTROL)); strUsage += HelpMessageOpt("-torpassword=", _("Tor control port password (default: empty)")); -#ifdef USE_UPNP -#if USE_UPNP - strUsage += HelpMessageOpt("-upnp", _("Use UPnP to map the listening port (default: 1 when listening and no -proxy)")); -#else - strUsage += HelpMessageOpt("-upnp", strprintf(_("Use UPnP to map the listening port (default: %u)"), 0)); -#endif -#endif strUsage += HelpMessageOpt("-whitebind=", _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6")); 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")); @@ -409,16 +402,17 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls")); strUsage += HelpMessageOpt("-keypool=", strprintf(_("Set key pool size to (default: %u)"), 100)); if (showDebug) - strUsage += HelpMessageOpt("-mintxfee=", strprintf("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)", - FormatMoney(CWallet::minTxFee.GetFeePerK()))); - strUsage += HelpMessageOpt("-paytxfee=", strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK()))); - strUsage += HelpMessageOpt("-rescan", _("Rescan the blockchain for missing wallet transactions") + " " + _("on startup")); + strUsage += HelpMessageOpt("-mintxfee=", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)", + CURRENCY_UNIT, FormatMoney(CWallet::minTxFee.GetFeePerK()))); + strUsage += HelpMessageOpt("-paytxfee=", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"), + CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK()))); + strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions") + " " + _("on startup")); strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup")); strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0)); strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1)); 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("-maxtxfee=", strprintf(_("Maximum total fees to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)"), - FormatMoney(maxTxFee))); + strUsage += HelpMessageOpt("-maxtxfee=", strprintf(_("Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)"), + CURRENCY_UNIT, FormatMoney(maxTxFee))); strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format") + " " + _("on startup")); strUsage += HelpMessageOpt("-wallet=", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), "wallet.dat")); strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), true)); @@ -469,7 +463,8 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-relaypriority", strprintf("Require high priority for relaying free or low-fee transactions (default: %u)", 0)); strUsage += HelpMessageOpt("-maxsigcachesize=", strprintf("Limit size of signature cache to entries (default: %u)", 50000)); } - strUsage += HelpMessageOpt("-minrelaytxfee=", strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK()))); + strUsage += HelpMessageOpt("-minrelaytxfee=", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for relaying (default: %s)"), + CURRENCY_UNIT, FormatMoney(::minRelayTxFee.GetFeePerK()))); strUsage += HelpMessageOpt("-printtoconsole", _("Send trace/debug info to console instead of debug.log file")); if (showDebug) { @@ -829,19 +824,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // to protect privacy, do not listen by default if a default proxy server is specified if (SoftSetBoolArg("-listen", false)) LogPrintf("%s: parameter interaction: -proxy set -> setting -listen=0\n", __func__); - // to protect privacy, do not use UPNP when a proxy is set. The user may still specify -listen=1 - // to listen locally, so don't rely on this happening through -listen below. - if (SoftSetBoolArg("-upnp", false)) - LogPrintf("%s: parameter interaction: -proxy set -> setting -upnp=0\n", __func__); // to protect privacy, do not discover addresses by default if (SoftSetBoolArg("-discover", false)) LogPrintf("%s: parameter interaction: -proxy set -> setting -discover=0\n", __func__); } if (!GetBoolArg("-listen", DEFAULT_LISTEN)) { - // do not map ports or try to retrieve public IP when not listening (pointless) - if (SoftSetBoolArg("-upnp", false)) - LogPrintf("%s: parameter interaction: -listen=0 -> setting -upnp=0\n", __func__); + // do not try to retrieve public IP when not listening (pointless) if (SoftSetBoolArg("-discover", false)) LogPrintf("%s: parameter interaction: -listen=0 -> setting -discover=0\n", __func__); if (SoftSetBoolArg("-listenonion", false)) diff --git a/src/leveldbwrapper.cpp b/src/leveldbwrapper.cpp index 26cacf95a..b5d024abb 100644 --- a/src/leveldbwrapper.cpp +++ b/src/leveldbwrapper.cpp @@ -13,7 +13,7 @@ #include #include -void HandleError(const leveldb::Status& status) throw(leveldb_error) +void HandleError(const leveldb::Status& status) { if (status.ok()) return; @@ -81,7 +81,7 @@ CLevelDBWrapper::~CLevelDBWrapper() options.env = NULL; } -bool CLevelDBWrapper::WriteBatch(CLevelDBBatch& batch, bool fSync) throw(leveldb_error) +bool CLevelDBWrapper::WriteBatch(CLevelDBBatch& batch, bool fSync) { leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch); HandleError(status); diff --git a/src/leveldbwrapper.h b/src/leveldbwrapper.h index c65e84270..639f736a5 100644 --- a/src/leveldbwrapper.h +++ b/src/leveldbwrapper.h @@ -22,7 +22,7 @@ class leveldb_error : public std::runtime_error leveldb_error(const std::string& msg) : std::runtime_error(msg) {} }; -void HandleError(const leveldb::Status& status) throw(leveldb_error); +void HandleError(const leveldb::Status& status); /** Batch of changes queued to be written to a CLevelDBWrapper */ class CLevelDBBatch @@ -90,7 +90,7 @@ class CLevelDBWrapper ~CLevelDBWrapper(); template - bool Read(const K& key, V& value) const throw(leveldb_error) + bool Read(const K& key, V& value) const { CDataStream ssKey(SER_DISK, CLIENT_VERSION); ssKey.reserve(ssKey.GetSerializeSize(key)); @@ -115,7 +115,7 @@ class CLevelDBWrapper } template - bool Write(const K& key, const V& value, bool fSync = false) throw(leveldb_error) + bool Write(const K& key, const V& value, bool fSync = false) { CLevelDBBatch batch; batch.Write(key, value); @@ -123,7 +123,7 @@ class CLevelDBWrapper } template - bool Exists(const K& key) const throw(leveldb_error) + bool Exists(const K& key) const { CDataStream ssKey(SER_DISK, CLIENT_VERSION); ssKey.reserve(ssKey.GetSerializeSize(key)); @@ -142,14 +142,14 @@ class CLevelDBWrapper } template - bool Erase(const K& key, bool fSync = false) throw(leveldb_error) + bool Erase(const K& key, bool fSync = false) { CLevelDBBatch batch; batch.Erase(key); return WriteBatch(batch, fSync); } - bool WriteBatch(CLevelDBBatch& batch, bool fSync = false) throw(leveldb_error); + bool WriteBatch(CLevelDBBatch& batch, bool fSync = false); // not available for LevelDB; provide for compatibility with BDB bool Flush() @@ -157,7 +157,7 @@ class CLevelDBWrapper return true; } - bool Sync() throw(leveldb_error) + bool Sync() { CLevelDBBatch batch; return WriteBatch(batch, true); diff --git a/src/metrics.cpp b/src/metrics.cpp index eb35b2448..0b3508a09 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -5,6 +5,7 @@ #include "metrics.h" #include "chainparams.h" +#include "checkpoints.h" #include "main.h" #include "ui_interface.h" #include "util.h" @@ -110,6 +111,36 @@ double GetLocalSolPS() return miningTimer.rate(solutionTargetChecks); } +int EstimateNetHeightInner(int height, int64_t tipmediantime, + int heightLastCheckpoint, int64_t timeLastCheckpoint, + int64_t genesisTime, int64_t targetSpacing) +{ + // We average the target spacing with the observed spacing to the last + // checkpoint (either from below or above depending on the current height), + // and use that to estimate the current network height. + int medianHeight = height > CBlockIndex::nMedianTimeSpan ? + height - (1 + ((CBlockIndex::nMedianTimeSpan - 1) / 2)) : + height / 2; + double checkpointSpacing = medianHeight > heightLastCheckpoint ? + (double (tipmediantime - timeLastCheckpoint)) / (medianHeight - heightLastCheckpoint) : + (double (timeLastCheckpoint - genesisTime)) / heightLastCheckpoint; + double averageSpacing = (targetSpacing + checkpointSpacing) / 2; + int netheight = medianHeight + ((GetTime() - tipmediantime) / averageSpacing); + // Round to nearest ten to reduce noise + return ((netheight + 5) / 10) * 10; +} + +int EstimateNetHeight(int height, int64_t tipmediantime, CChainParams chainParams) +{ + auto checkpointData = chainParams.Checkpoints(); + return EstimateNetHeightInner( + height, tipmediantime, + Checkpoints::GetTotalBlocksEstimate(checkpointData), + checkpointData.nTimeLastCheckpoint, + chainParams.GenesisBlock().nTime, + chainParams.GetConsensus().nPowTargetSpacing); +} + void TriggerRefresh() { *nNextRefresh = GetTime(); @@ -176,17 +207,25 @@ int printStats(bool mining) int lines = 4; int height; + int64_t tipmediantime; size_t connections; int64_t netsolps; { LOCK2(cs_main, cs_vNodes); height = chainActive.Height(); + tipmediantime = chainActive.Tip()->GetMedianTimePast(); connections = vNodes.size(); netsolps = GetNetworkHashPS(120, -1); } auto localsolps = GetLocalSolPS(); - std::cout << " " << _("Block height") << " | " << height << std::endl; + if (IsInitialBlockDownload()) { + int netheight = EstimateNetHeight(height, tipmediantime, Params()); + int downloadPercent = height * 100 / netheight; + std::cout << " " << _("Downloading blocks") << " | " << height << " / ~" << netheight << " (" << downloadPercent << "%)" << std::endl; + } else { + std::cout << " " << _("Block height") << " | " << height << std::endl; + } std::cout << " " << _("Connections") << " | " << connections << std::endl; std::cout << " " << _("Network solution rate") << " | " << netsolps << " Sol/s" << std::endl; if (mining && miningTimer.running()) { diff --git a/src/metrics.h b/src/metrics.h index ceb7201d9..a60bf19ce 100644 --- a/src/metrics.h +++ b/src/metrics.h @@ -63,6 +63,9 @@ void TrackMinedBlock(uint256 hash); void MarkStartTime(); double GetLocalSolPS(); +int EstimateNetHeightInner(int height, int64_t tipmediantime, + int heightLastCheckpoint, int64_t timeLastCheckpoint, + int64_t genesisTime, int64_t targetSpacing); void TriggerRefresh(); diff --git a/src/net.cpp b/src/net.cpp index de624c72a..7a40d97d6 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -23,13 +23,6 @@ #include #endif -#ifdef USE_UPNP -#include -#include -#include -#include -#endif - #include #include @@ -1215,131 +1208,6 @@ void ThreadSocketHandler() } - - - - - - - -#ifdef USE_UPNP -void ThreadMapPort() -{ - std::string port = strprintf("%u", GetListenPort()); - const char * multicastif = 0; - const char * minissdpdpath = 0; - struct UPNPDev * devlist = 0; - char lanaddr[64]; - -#ifndef UPNPDISCOVER_SUCCESS - /* miniupnpc 1.5 */ - devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0); -#elif MINIUPNPC_API_VERSION < 14 - /* miniupnpc 1.6 */ - int error = 0; - devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error); -#else - /* miniupnpc 1.9.20150730 */ - int error = 0; - devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error); -#endif - - struct UPNPUrls urls; - struct IGDdatas data; - int r; - - r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); - if (r == 1) - { - if (fDiscover) { - char externalIPAddress[40]; - r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress); - if(r != UPNPCOMMAND_SUCCESS) - LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r); - else - { - if(externalIPAddress[0]) - { - LogPrintf("UPnP: ExternalIPAddress = %s\n", externalIPAddress); - AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP); - } - else - LogPrintf("UPnP: GetExternalIPAddress failed.\n"); - } - } - - string strDesc = "Bitcoin " + FormatFullVersion(); - - try { - while (true) { -#ifndef UPNPDISCOVER_SUCCESS - /* miniupnpc 1.5 */ - r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, - port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0); -#else - /* miniupnpc 1.6 */ - r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, - port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0"); -#endif - - if(r!=UPNPCOMMAND_SUCCESS) - LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", - port, port, lanaddr, r, strupnperror(r)); - else - LogPrintf("UPnP Port Mapping successful.\n");; - - MilliSleep(20*60*1000); // Refresh every 20 minutes - } - } - catch (const boost::thread_interrupted&) - { - r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); - LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r); - freeUPNPDevlist(devlist); devlist = 0; - FreeUPNPUrls(&urls); - throw; - } - } else { - LogPrintf("No valid UPnP IGDs found\n"); - freeUPNPDevlist(devlist); devlist = 0; - if (r != 0) - FreeUPNPUrls(&urls); - } -} - -void MapPort(bool fUseUPnP) -{ - static boost::thread* upnp_thread = NULL; - - if (fUseUPnP) - { - if (upnp_thread) { - upnp_thread->interrupt(); - upnp_thread->join(); - delete upnp_thread; - } - upnp_thread = new boost::thread(boost::bind(&TraceThread, "upnp", &ThreadMapPort)); - } - else if (upnp_thread) { - upnp_thread->interrupt(); - upnp_thread->join(); - delete upnp_thread; - upnp_thread = NULL; - } -} - -#else -void MapPort(bool) -{ - // Intentionally left blank. -} -#endif - - - - - - void ThreadDNSAddressSeed() { // goal: only query DNS seeds if address need is acute @@ -1879,9 +1747,6 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) else threadGroup.create_thread(boost::bind(&TraceThread, "dnsseed", &ThreadDNSAddressSeed)); - // Map ports with UPnP - MapPort(GetBoolArg("-upnp", DEFAULT_UPNP)); - // Send and receive from sockets, accept connections threadGroup.create_thread(boost::bind(&TraceThread, "net", &ThreadSocketHandler)); @@ -1901,7 +1766,6 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) bool StopNode() { LogPrintf("StopNode()\n"); - MapPort(false); if (semOutbound) for (int i=0; ipost(); diff --git a/src/net.h b/src/net.h index f7ebf11f6..6fd49536d 100644 --- a/src/net.h +++ b/src/net.h @@ -51,12 +51,6 @@ static const unsigned int MAX_ADDR_TO_SEND = 1000; static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 2 * 1024 * 1024; /** -listen default */ static const bool DEFAULT_LISTEN = true; -/** -upnp default */ -#ifdef USE_UPNP -static const bool DEFAULT_UPNP = USE_UPNP; -#else -static const bool DEFAULT_UPNP = false; -#endif /** The maximum number of entries in mapAskFor */ static const size_t MAPASKFOR_MAX_SZ = MAX_INV_SZ; /** The maximum number of entries in setAskFor (larger due to getdata latency)*/ @@ -75,7 +69,6 @@ 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(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler); @@ -118,7 +111,7 @@ enum LOCAL_NONE, // unknown LOCAL_IF, // address a local interface listens on LOCAL_BIND, // address explicit bound to - LOCAL_UPNP, // address reported by UPnP + LOCAL_UPNP, // unused (was: address reported by UPnP) LOCAL_MANUAL, // address explicitly specified (-externalip=) LOCAL_MAX diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 939430be2..6d8c911e3 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -3,6 +3,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" +#include "chain.h" +#include "chainparams.h" #include "checkpoints.h" #include "consensus/validation.h" #include "main.h" @@ -260,7 +263,7 @@ UniValue getrawmempool(const UniValue& params, bool fHelp) "{ (json object)\n" " \"transactionid\" : { (json object)\n" " \"size\" : n, (numeric) transaction size in bytes\n" - " \"fee\" : n, (numeric) transaction fee in bitcoins\n" + " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\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" @@ -510,7 +513,7 @@ UniValue gettxout(const UniValue& params, bool fHelp) "{\n" " \"bestblock\" : \"hash\", (string) the block hash\n" " \"confirmations\" : n, (numeric) The number of confirmations\n" - " \"value\" : x.xxx, (numeric) The transaction value in btc\n" + " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n" " \"scriptPubKey\" : { (json object)\n" " \"asm\" : \"code\", (string) \n" " \"hex\" : \"hex\", (string) \n" diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index e4273e42b..83ba5715d 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -883,8 +883,8 @@ UniValue getblocksubsidy(const UniValue& params, bool fHelp) "1. height (numeric, optional) The block height. If not provided, defaults to the current height of the chain.\n" "\nResult:\n" "{\n" - " \"miner\" : x.xxx (numeric) The mining reward amount in ZEC.\n" - " \"founders\" : x.xxx (numeric) The founders reward amount in ZEC.\n" + " \"miner\" : x.xxx (numeric) The mining reward amount in " + CURRENCY_UNIT + ".\n" + " \"founders\" : x.xxx (numeric) The founders reward amount in " + CURRENCY_UNIT + ".\n" "}\n" "\nExamples:\n" + HelpExampleCli("getblocksubsidy", "1000") diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index c12e0ccfa..9980ce1ed 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -61,8 +61,8 @@ UniValue getinfo(const UniValue& params, bool fHelp) " \"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 set in btc/kb\n" - " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n" + " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in " + CURRENCY_UNIT + "/kB\n" + " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n" " \"errors\": \"...\" (string) any error messages\n" "}\n" "\nExamples:\n" diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index b68897d16..71152a2e2 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -421,7 +421,7 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp) " }\n" " ,...\n" " ],\n" - " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n" + " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n" " \"localaddresses\": [ (array) list of local addresses\n" " {\n" " \"address\": \"xxxx\", (string) network address\n" diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 02fb66802..83cb8e877 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -204,7 +204,7 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) " ],\n" " \"vout\" : [ (array of json objects)\n" " {\n" - " \"value\" : x.xxx, (numeric) The value in btc\n" + " \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n" " \"n\" : n, (numeric) index\n" " \"scriptPubKey\" : { (json object)\n" " \"asm\" : \"asm\", (string) the asm\n" @@ -221,8 +221,8 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) " ],\n" " \"vjoinsplit\" : [ (array of json objects, only for version >= 2)\n" " {\n" - " \"vpub_old\" : x.xxx, (numeric) public input value in ZEC\n" - " \"vpub_new\" : x.xxx, (numeric) public output value in ZEC\n" + " \"vpub_old\" : x.xxx, (numeric) public input value in " + CURRENCY_UNIT + "\n" + " \"vpub_new\" : x.xxx, (numeric) public output value in " + CURRENCY_UNIT + "\n" " \"anchor\" : \"hex\", (string) the anchor\n" " \"nullifiers\" : [ (json array of string)\n" " \"hex\" (string) input note nullifier\n" @@ -417,7 +417,7 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) " ]\n" "2. \"addresses\" (string, required) a json object with addresses as keys and amounts as values\n" " {\n" - " \"address\": x.xxx (numeric, required) The key is the bitcoin address, the value is the btc amount\n" + " \"address\": x.xxx (numeric, required) The key is the bitcoin address, the value is the " + CURRENCY_UNIT + " amount\n" " ,...\n" " }\n" @@ -504,7 +504,7 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp) " ],\n" " \"vout\" : [ (array of json objects)\n" " {\n" - " \"value\" : x.xxx, (numeric) The value in btc\n" + " \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n" " \"n\" : n, (numeric) index\n" " \"scriptPubKey\" : { (json object)\n" " \"asm\" : \"asm\", (string) the asm\n" @@ -521,8 +521,8 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp) " ],\n" " \"vjoinsplit\" : [ (array of json objects, only for version >= 2)\n" " {\n" - " \"vpub_old\" : x.xxx, (numeric) public input value in ZEC\n" - " \"vpub_new\" : x.xxx, (numeric) public output value in ZEC\n" + " \"vpub_old\" : x.xxx, (numeric) public input value in " + CURRENCY_UNIT + "\n" + " \"vpub_new\" : x.xxx, (numeric) public output value in " + CURRENCY_UNIT + "\n" " \"anchor\" : \"hex\", (string) the anchor\n" " \"nullifiers\" : [ (json array of string)\n" " \"hex\" (string) input note nullifier\n" diff --git a/src/sendalert.cpp b/src/sendalert.cpp index f4935212f..3b7b53734 100644 --- a/src/sendalert.cpp +++ b/src/sendalert.cpp @@ -71,8 +71,8 @@ void ThreadSendAlert() // CAlert alert; alert.nRelayUntil = GetTime() + 15 * 60; - alert.nExpiration = GetTime() + 6 * 30 * 24 * 60 * 60; - alert.nID = 1003; // use https://github.com/zcash/zcash/wiki/specification#assigned-numbers to keep track of alert IDs + alert.nExpiration = GetTime() + 12 * 30 * 24 * 60 * 60; + alert.nID = 1004; // use https://github.com/zcash/zcash/wiki/specification#assigned-numbers to keep track of alert IDs alert.nCancel = 1001; // cancels previous messages up to this ID number // These versions are protocol versions @@ -86,9 +86,9 @@ void ThreadSendAlert() // 2000 for longer invalid proof-of-work chain // Higher numbers mean higher priority // 4000 or higher will put the RPC into safe mode - alert.nPriority = 1500; + alert.nPriority = 4000; alert.strComment = ""; - alert.strStatusBar = "Your client is out of date and vulnerable to denial of service. Please update to the most recent version of Zcash (1.0.8-1 or later). More info at: https://z.cash/support/security/"; + alert.strStatusBar = "Your client version 1.0.10 has degraded networking behavior. Please update to the most recent version of Zcash (1.0.10-1 or later)."; alert.strRPCError = alert.strStatusBar; // Set specific client version/versions here. If setSubVer is empty, no filtering on subver is done: @@ -96,13 +96,7 @@ void ThreadSendAlert() const std::vector useragents = {"MagicBean", "BeanStalk", "AppleSeed", "EleosZcash"}; BOOST_FOREACH(const std::string& useragent, useragents) { - alert.setSubVer.insert(std::string("/"+useragent+":1.0.3/")); - alert.setSubVer.insert(std::string("/"+useragent+":1.0.4/")); - alert.setSubVer.insert(std::string("/"+useragent+":1.0.5/")); - alert.setSubVer.insert(std::string("/"+useragent+":1.0.6/")); - alert.setSubVer.insert(std::string("/"+useragent+":1.0.7/")); - alert.setSubVer.insert(std::string("/"+useragent+":1.0.7-1/")); - alert.setSubVer.insert(std::string("/"+useragent+":1.0.8/")); + alert.setSubVer.insert(std::string("/"+useragent+":1.0.10/")); } // Sanity check diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 713f9c38b..42cbf109f 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -975,7 +975,19 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals) std::string msg = operation->getErrorMessage(); BOOST_CHECK( msg.find("Insufficient funds, no UTXOs found") != string::npos); } + + // minconf cannot be zero when sending from zaddr + { + try { + std::vector recipients = {SendManyRecipient(taddr1, 100.0, "DEADBEEF")}; + std::shared_ptr operation(new AsyncRPCOperation_sendmany(zaddr1, recipients, {}, 0)); + BOOST_CHECK(false); // Fail test if an exception is not thrown + } catch (const UniValue& objError) { + BOOST_CHECK(find_error(objError, "Minconf cannot be zero when sending from zaddr")); + } + } + // there are no unspent notes to spend { std::vector recipients = { SendManyRecipient(taddr1,100.0, "DEADBEEF") }; diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index a5cd1b7c6..ffa1f75f8 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -376,8 +376,10 @@ static std::pair ReadBinaryFile(const std::string &filename, s while ((n=fread(buffer, 1, sizeof(buffer), f)) > 0) { // Check for reading errors so we don't return any data if we couldn't // read the entire file (or up to maxsize) - if (ferror(f)) + if (ferror(f)) { + fclose(f); return std::make_pair(false,""); + } retval.append(buffer, buffer+n); if (retval.size() > maxsize) break; diff --git a/src/util.cpp b/src/util.cpp index d69bd77a7..855d642da 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -906,7 +906,7 @@ std::string LicenseInfo() "\n" + FormatParagraph(_("Distributed under the MIT software license, see the accompanying file COPYING or .")) + "\n" + "\n" + - FormatParagraph(_("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.")) + + FormatParagraph(_("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit and cryptographic software written by Eric Young.")) + "\n"; } diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index d84f121b6..db794b915 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -93,6 +93,10 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany( } } + if (isfromzaddr_ && minDepth==0) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Minconf cannot be zero when sending from zaddr"); + } + // Log the context info i.e. the call parameters to z_sendmany if (LogAcceptCategory("zrpcunsafe")) { LogPrint("zrpcunsafe", "%s: z_sendmany initialized (params=%s)\n", getId(), contextInfo.write()); @@ -589,6 +593,10 @@ bool AsyncRPCOperation_sendmany::main_impl() { { LOCK2(cs_main, pwalletMain->cs_wallet); const CWalletTx& wtx = pwalletMain->mapWallet[jso.hash]; + // Zero confirmaton notes belong to transactions which have not yet been mined + if (mapBlockIndex.find(wtx.hashBlock) == mapBlockIndex.end()) { + throw JSONRPCError(RPC_WALLET_ERROR, strprintf("mapBlockIndex does not contain block hash %s", wtx.hashBlock.ToString())); + } wtxHeight = mapBlockIndex[wtx.hashBlock]->nHeight; wtxDepth = wtx.GetDepthInMainChain(); } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index aa1ad9955..adeadf6e9 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -408,7 +408,7 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp) + HelpRequiringPassphrase() + "\nArguments:\n" "1. \"zcashaddress\" (string, required) The zcash address to send to.\n" - "2. \"amount\" (numeric, required) The amount in btc to send. eg 0.1\n" + "2. \"amount\" (numeric, required) The amount in " + CURRENCY_UNIT + " to send. eg 0.1\n" "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n" " This is not part of the transaction, just kept in your wallet.\n" "4. \"comment-to\" (string, optional) A comment to store the name of the person or organization \n" @@ -470,7 +470,7 @@ UniValue listaddressgroupings(const UniValue& params, bool fHelp) " [\n" " [\n" " \"zcashaddress\", (string) The zcash address\n" - " amount, (numeric) The amount in btc\n" + " amount, (numeric) The amount in " + CURRENCY_UNIT + "\n" " \"account\" (string, optional) The account (DEPRECATED)\n" " ]\n" " ,...\n" @@ -574,7 +574,7 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp) "1. \"zcashaddress\" (string, required) The zcash address for transactions.\n" "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" "\nResult:\n" - "amount (numeric) The total amount in btc received at this address.\n" + "amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n" "\nExamples:\n" "\nThe amount from transactions with at least 1 confirmation\n" + HelpExampleCli("getreceivedbyaddress", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\"") + @@ -632,7 +632,7 @@ UniValue getreceivedbyaccount(const UniValue& params, bool fHelp) "1. \"account\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" "\nResult:\n" - "amount (numeric) The total amount in btc received for this account.\n" + "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n" "\nExamples:\n" "\nAmount received by the default account with at least 1 confirmation\n" + HelpExampleCli("getreceivedbyaccount", "\"\"") + @@ -722,7 +722,7 @@ UniValue getbalance(const UniValue& params, bool fHelp) "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n" "\nResult:\n" - "amount (numeric) The total amount in btc received for this account.\n" + "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n" "\nExamples:\n" "\nThe total amount in the wallet\n" + HelpExampleCli("getbalance", "") + @@ -808,14 +808,15 @@ UniValue movecmd(const UniValue& params, bool fHelp) "\nArguments:\n" "1. \"fromaccount\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" "2. \"toaccount\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" - "3. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n" - "4. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n" + "3. amount (numeric) Quantity of " + CURRENCY_UNIT + " to move between accounts.\n" + "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n" + "5. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n" "\nResult:\n" "true|false (boolean) true if successful.\n" "\nExamples:\n" - "\nMove 0.01 btc from the default account to the account named tabby\n" + "\nMove 0.01 " + CURRENCY_UNIT + " from the default account to the account named tabby\n" + HelpExampleCli("move", "\"\" \"tabby\" 0.01") + - "\nMove 0.01 btc timotei to akiko with a comment and funds have 6 confirmations\n" + "\nMove 0.01 " + CURRENCY_UNIT + " timotei to akiko with a comment and funds have 6 confirmations\n" + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") + "\nAs a json rpc call\n" + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"") @@ -882,7 +883,7 @@ UniValue sendfrom(const UniValue& params, bool fHelp) "\nArguments:\n" "1. \"fromaccount\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" "2. \"tozcashaddress\" (string, required) The zcash address to send funds to.\n" - "3. amount (numeric, required) The amount in btc. (transaction fee is added on top).\n" + "3. amount (numeric, required) The amount in " + CURRENCY_UNIT + " (transaction fee is added on top).\n" "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n" "5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n" " This is not part of the transaction, just kept in your wallet.\n" @@ -892,7 +893,7 @@ UniValue sendfrom(const UniValue& params, bool fHelp) "\nResult:\n" "\"transactionid\" (string) The transaction id.\n" "\nExamples:\n" - "\nSend 0.01 btc from the default account to the address, must have at least 1 confirmation\n" + "\nSend 0.01 " + CURRENCY_UNIT + " from the default account to the address, must have at least 1 confirmation\n" + HelpExampleCli("sendfrom", "\"\" \"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") + "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n" + HelpExampleCli("sendfrom", "\"tabby\" \"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") + @@ -947,7 +948,7 @@ UniValue sendmany(const UniValue& params, bool fHelp) "1. \"fromaccount\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" "2. \"amounts\" (string, required) A json object with addresses and amounts\n" " {\n" - " \"address\":amount (numeric) The zcash address is the key, the numeric amount in btc is the value\n" + " \"address\":amount (numeric) The zcash address is the key, the numeric amount in " + CURRENCY_UNIT + " is the value\n" " ,...\n" " }\n" "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n" @@ -1248,7 +1249,7 @@ UniValue listreceivedbyaddress(const UniValue& params, bool fHelp) " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n" " \"address\" : \"receivingaddress\", (string) The receiving address\n" " \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n" - " \"amount\" : x.xxx, (numeric) The total amount in btc received by the address\n" + " \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n" " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n" " }\n" " ,...\n" @@ -1422,11 +1423,11 @@ UniValue listtransactions(const UniValue& params, bool fHelp) " transaction between accounts, and not associated with an address,\n" " transaction id or block. 'send' and 'receive' transactions are \n" " associated with an address, transaction id and block details\n" - " \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the\n" + " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the\n" " 'move' category for moves outbound. It is positive for the 'receive' category,\n" " and for the 'move' category for inbound funds.\n" " \"vout\" : n, (numeric) the vout value\n" - " \"fee\": x.xxx, (numeric) The amount of the fee in btc. This is negative and only available for the \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" " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n" " 'receive' category of transactions.\n" @@ -1618,10 +1619,10 @@ UniValue listsinceblock(const UniValue& params, bool fHelp) " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n" " \"address\":\"zcashaddress\", (string) The zcash address of the transaction. Not present for move transactions (category = move).\n" " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n" - " \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the 'move' category for moves \n" + " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the 'move' category for moves \n" " outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n" " \"vout\" : n, (numeric) the vout value\n" - " \"fee\": x.xxx, (numeric) The amount of the fee in btc. This is negative and only available for the 'send' category of transactions.\n" + " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the 'send' category of transactions.\n" " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n" " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n" " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n" @@ -1704,7 +1705,7 @@ UniValue gettransaction(const UniValue& params, bool fHelp) "2. \"includeWatchonly\" (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n" "\nResult:\n" "{\n" - " \"amount\" : x.xxx, (numeric) The transaction amount in btc\n" + " \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n" " \"confirmations\" : n, (numeric) The number of confirmations\n" " \"blockhash\" : \"hash\", (string) The block hash\n" " \"blockindex\" : xx, (numeric) The block index\n" @@ -1717,7 +1718,7 @@ UniValue gettransaction(const UniValue& params, bool fHelp) " \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n" " \"address\" : \"zcashaddress\", (string) The zcash address involved in the transaction\n" " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n" - " \"amount\" : x.xxx (numeric) The amount in btc\n" + " \"amount\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n" " \"vout\" : n, (numeric) the vout value\n" " }\n" " ,...\n" @@ -2224,7 +2225,7 @@ UniValue settxfee(const UniValue& params, bool fHelp) "settxfee amount\n" "\nSet the transaction fee per kB.\n" "\nArguments:\n" - "1. amount (numeric, required) The transaction fee in BTC/kB rounded to the nearest 0.00000001\n" + "1. amount (numeric, required) The transaction fee in " + CURRENCY_UNIT + "/kB rounded to the nearest 0.00000001\n" "\nResult\n" "true|false (boolean) Returns true if successful\n" "\nExamples:\n" @@ -2253,14 +2254,14 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp) "\nResult:\n" "{\n" " \"walletversion\": xxxxx, (numeric) the wallet version\n" - " \"balance\": xxxxxxx, (numeric) the total confirmed zcash balance of the wallet\n" - " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed zcash balance of the wallet\n" - " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet\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 ZEC/KB\n" + " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n" "}\n" "\nExamples:\n" + HelpExampleCli("getwalletinfo", "") @@ -2334,10 +2335,11 @@ UniValue listunspent(const UniValue& params, bool fHelp) " {\n" " \"txid\" : \"txid\", (string) the transaction id \n" " \"vout\" : n, (numeric) the vout value\n" + " \"generated\" : true|false (boolean) true if txout is a coinbase transaction output\n" " \"address\" : \"address\", (string) the zcash 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 btc\n" + " \"amount\" : x.xxx, (numeric) the transaction amount in " + CURRENCY_UNIT + "\n" " \"confirmations\" : n (numeric) The number of confirmations\n" " }\n" " ,...\n" @@ -2396,6 +2398,7 @@ UniValue listunspent(const UniValue& params, bool fHelp) UniValue entry(UniValue::VOBJ); entry.push_back(Pair("txid", out.tx->GetHash().GetHex())); entry.push_back(Pair("vout", out.i)); + entry.push_back(Pair("generated", out.tx->IsCoinBase())); CTxDestination address; if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) { entry.push_back(Pair("address", CBitcoinAddress(address).ToString())); @@ -2594,6 +2597,17 @@ UniValue zc_benchmark(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode"); } sample_times.push_back(benchmark_connectblock_slow()); + } else if (benchmarktype == "sendtoaddress") { + if (Params().NetworkIDString() != "regtest") { + throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode"); + } + auto amount = AmountFromValue(params[2]); + sample_times.push_back(benchmark_sendtoaddress(amount)); + } else if (benchmarktype == "loadwallet") { + if (Params().NetworkIDString() != "regtest") { + throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode"); + } + sample_times.push_back(benchmark_loadwallet()); } else { throw JSONRPCError(RPC_TYPE_ERROR, "Invalid benchmarktype"); } @@ -3098,7 +3112,7 @@ UniValue z_getbalance(const UniValue& params, bool fHelp) "1. \"address\" (string) The selected address. It may be a transparent or private address.\n" "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" "\nResult:\n" - "amount (numeric) The total amount in ZEC received for this address.\n" + "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this address.\n" "\nExamples:\n" "\nThe total amount received by address \"myaddress\"\n" + HelpExampleCli("z_getbalance", "\"myaddress\"") + @@ -3323,7 +3337,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) "2. \"amounts\" (array, required) An array of json objects representing the amounts to send.\n" " [{\n" " \"address\":address (string, required) The address is a taddr or zaddr\n" - " \"amount\":amount (numeric, required) The numeric amount in ZEC is the value\n" + " \"amount\":amount (numeric, required) The numeric amount in " + CURRENCY_UNIT + " is the value\n" " \"memo\":memo (string, optional) If the address is a zaddr, raw data represented in hexadecimal string format\n" " }, ... ]\n" "3. minconf (numeric, optional, default=1) Only use funds confirmed at least this many times.\n" diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index 86fe5de3f..5c20a67e3 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -17,6 +17,7 @@ #include "main.h" #include "miner.h" #include "pow.h" +#include "rpcserver.h" #include "script/sign.h" #include "sodium.h" #include "streams.h" @@ -30,6 +31,39 @@ #include "zcash/IncrementalMerkleTree.hpp" using namespace libzcash; +// This method is based on Shutdown from init.cpp +void pre_wallet_load() +{ + LogPrintf("%s: In progress...\n", __func__); + if (ShutdownRequested()) + throw new std::runtime_error("The node is shutting down"); + + if (pwalletMain) + pwalletMain->Flush(false); +#ifdef ENABLE_MINING + GenerateBitcoins(false, NULL, 0); +#endif + UnregisterNodeSignals(GetNodeSignals()); + if (pwalletMain) + pwalletMain->Flush(true); + + UnregisterValidationInterface(pwalletMain); + delete pwalletMain; + pwalletMain = NULL; + bitdb.Reset(); + RegisterNodeSignals(GetNodeSignals()); + LogPrintf("%s: done\n", __func__); +} + +void post_wallet_load(){ + RegisterValidationInterface(pwalletMain); +#ifdef ENABLE_MINING + // Generate coins in the background + if (pwalletMain || !GetArg("-mineraddress", "").empty()) + GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", 1)); +#endif +} + void timer_start(timeval &tv_start) { @@ -405,3 +439,29 @@ double benchmark_connectblock_slow() return duration; } +double benchmark_sendtoaddress(CAmount amount) +{ + UniValue params(UniValue::VARR); + auto addr = getnewaddress(params, false); + + params.push_back(addr); + params.push_back(ValueFromAmount(amount)); + + struct timeval tv_start; + timer_start(tv_start); + auto txid = sendtoaddress(params, false); + return timer_stop(tv_start); +} + +double benchmark_loadwallet() +{ + pre_wallet_load(); + struct timeval tv_start; + bool fFirstRunRet=true; + timer_start(tv_start); + pwalletMain = new CWallet("wallet.dat"); + DBErrors nLoadWalletRet = pwalletMain->LoadWallet(fFirstRunRet); + auto res = timer_stop(tv_start); + post_wallet_load(); + return res; +} diff --git a/src/zcbenchmarks.h b/src/zcbenchmarks.h index b00b76789..a2672daa0 100644 --- a/src/zcbenchmarks.h +++ b/src/zcbenchmarks.h @@ -16,5 +16,7 @@ extern double benchmark_large_tx(); extern double benchmark_try_decrypt_notes(size_t nAddrs); extern double benchmark_increment_note_witnesses(size_t nTxs); extern double benchmark_connectblock_slow(); +extern double benchmark_sendtoaddress(CAmount amount); +extern double benchmark_loadwallet(); #endif diff --git a/zcutil/build.sh b/zcutil/build.sh index 9d0194719..5e6b318f5 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -117,5 +117,5 @@ ld -v HOST="$HOST" BUILD="$BUILD" NO_RUST="$RUST_ARG" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1 ./autogen.sh -CC="$CC" CXX="$CXX" ./configure --prefix="${PREFIX}" --host="$HOST" --build="$BUILD" "$RUST_ARG" "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$LIBS_ARG" CXXFLAGS='-fwrapv -fno-strict-aliasing -Werror -g' +CC="$CC" CXX="$CXX" ./configure --prefix="${PREFIX}" --host="$HOST" --build="$BUILD" "$RUST_ARG" "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$LIBS_ARG" CXXFLAGS='-fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -g' "$MAKE" "$@" V=1 diff --git a/zcutil/make-release.py b/zcutil/make-release.py index 514d5883f..7d505c279 100755 --- a/zcutil/make-release.py +++ b/zcutil/make-release.py @@ -27,6 +27,7 @@ def main(args=sys.argv[1:]): opts.RELEASE_VERSION, opts.RELEASE_PREV, opts.RELEASE_HEIGHT, + opts.HOTFIX, ) except SystemExit as e: logging.error(str(e)) @@ -44,6 +45,12 @@ def parse_args(args): type=str, help='Path to repository root.', ) + p.add_argument( + '--hotfix', + action='store_true', + dest='HOTFIX', + help='Use if this is a hotfix release from a non-master branch.', + ) p.add_argument( 'RELEASE_VERSION', type=Version.parse_arg, @@ -63,9 +70,10 @@ def parse_args(args): # Top-level flow: -def main_logged(release, releaseprev, releaseheight): +def main_logged(release, releaseprev, releaseheight, hotfix): verify_releaseprev_tag(releaseprev) - initialize_git(release) + verify_version(release, releaseprev, hotfix) + initialize_git(release, hotfix) patch_version_in_files(release, releaseprev) patch_release_height(releaseheight) commit('Versioning changes for {}.'.format(release.novtext)) @@ -123,17 +131,41 @@ def verify_releaseprev_tag(releaseprev): ) +@phase('Checking version.') +def verify_version(release, releaseprev, hotfix): + if not hotfix: + return + + expected = Version( + releaseprev.major, + releaseprev.minor, + releaseprev.patch, + releaseprev.betarc, + releaseprev.hotfix + 1 if releaseprev.hotfix else 1, + ) + if release != expected: + raise SystemExit( + "Expected {!r}, given {!r}".format( + expected, release, + ), + ) + + @phase('Initializing git.') -def initialize_git(release): +def initialize_git(release, hotfix): junk = sh_out('git', 'status', '--porcelain') if junk.strip(): raise SystemExit('There are uncommitted changes:\n' + junk) branch = sh_out('git', 'rev-parse', '--abbrev-ref', 'HEAD').strip() - if branch != 'master': + if hotfix: + expected = 'hotfix-' + release.vtext + else: + expected = 'master' + if branch != expected: raise SystemExit( - "Expected branch 'master', found branch {!r}".format( - branch, + "Expected branch {!r}, found branch {!r}".format( + expected, branch, ), ) @@ -177,8 +209,27 @@ def patch_release_height(releaseheight): @phase('Building...') def build(): + base_dir = os.getcwd() + depends_dir = os.path.join(base_dir, 'depends') + src_dir = os.path.join(base_dir, 'src') nproc = sh_out('nproc').strip() - sh_log('./zcutil/build.sh', '-j', nproc) + sh_progress([ + 'Staging boost...', + 'Staging libevent...', + 'Staging zeromq...', + 'Staging libgmp...', + 'Staging libsodium...', + "Leaving directory '%s'" % depends_dir, + 'config.status: creating libzcashconsensus.pc', + "Entering directory '%s'" % src_dir, + 'httpserver.cpp', + 'torcontrol.cpp', + 'gtest/test_tautology.cpp', + 'gtest/test_metrics.cpp', + 'test/equihash_tests.cpp', + 'test/util_tests.cpp', + "Leaving directory '%s'" % src_dir, + ], './zcutil/build.sh', '-j', nproc) @phase('Generating manpages.') @@ -316,15 +367,48 @@ def sh_out(*args): def sh_log(*args): PIPE = subprocess.PIPE + STDOUT = subprocess.STDOUT + try: + p = subprocess.Popen(args, stdout=PIPE, stderr=STDOUT, stdin=None) + except OSError: + logging.error('Error launching %r...', args) + raise + + logging.debug('Run (log PID %r): %r', p.pid, args) + for line in p.stdout: + logging.debug('> %s', line.rstrip()) + status = p.wait() + if status != 0: + raise SystemExit('Nonzero exit status: {!r}'.format(status)) + + +def sh_progress(markers, *args): + try: + import progressbar + except: + sh_log(*args) + return + + PIPE = subprocess.PIPE + STDOUT = subprocess.STDOUT try: - p = subprocess.Popen(args, stdout=PIPE, stderr=PIPE, stdin=None) + p = subprocess.Popen(args, stdout=PIPE, stderr=STDOUT, stdin=None) except OSError: logging.error('Error launching %r...', args) raise + pbar = progressbar.ProgressBar(max_value=len(markers)) + marker = 0 + pbar.update(marker) logging.debug('Run (log PID %r): %r', p.pid, args) for line in p.stdout: logging.debug('> %s', line.rstrip()) + for idx, val in enumerate(markers[marker:]): + if val in line: + marker += idx + 1 + pbar.update(marker) + break + pbar.finish() status = p.wait() if status != 0: raise SystemExit('Nonzero exit status: {!r}'.format(status)) diff --git a/zcutil/release-notes.py b/zcutil/release-notes.py index 47f234906..24adff0d0 100755 --- a/zcutil/release-notes.py +++ b/zcutil/release-notes.py @@ -4,6 +4,21 @@ from itertools import islice from operator import itemgetter +TEMP_RELEASE_NOTES_HEADER = [ + '(note: this is a temporary file, to be added-to by anybody, and moved to\n', + 'release-notes at release time)\n', + '\n', + 'Notable changes\n', + '===============\n', + '\n', +] + +RELEASE_NOTES_CHANGELOG_HEADING = [ + 'Changelog\n', + '=========\n', + '\n', +] + author_aliases = { 'Simon': 'Simon Liu', 'bitcartel': 'Simon Liu', @@ -77,9 +92,22 @@ def generate_release_note(version, filename): notes = subprocess.Popen(['git shortlog --no-merges {0}..HEAD'.format(latest_tag)], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE).communicate()[0] lines = notes.split('\n') lines = [alias_authors_in_release_notes(line) for line in lines] + temp_release_note = os.path.join(doc_dir, 'release-notes.md') + with open(temp_release_note, 'r') as f: + notable_changes = f.readlines() + # Assumes that all notable changes are appended to the default header + if len(notable_changes) > 6: + notable_changes = notable_changes[3:] + ['\n'] + else: + notable_changes = [] release_note = os.path.join(doc_dir, 'release-notes', 'release-notes-{0}.md'.format(version)) with open(release_note, 'w') as f: + f.writelines(notable_changes) + f.writelines(RELEASE_NOTES_CHANGELOG_HEADING) f.writelines('\n'.join(lines)) + # Clear temporary release notes file + with open(temp_release_note, 'w') as f: + f.writelines(TEMP_RELEASE_NOTES_HEADER) def main(version, filename): if version != None: