aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcontrib/devtools/security-check.py2
-rwxr-xr-xcontrib/gitian-build.py203
-rwxr-xr-xcontrib/gitian-build.sh413
-rw-r--r--contrib/zmq/zmq_sub.py2
-rw-r--r--contrib/zmq/zmq_sub3.4.py2
-rw-r--r--doc/release-process.md2
-rw-r--r--src/Makefile.am1
-rw-r--r--src/bench/bech32.cpp1
-rw-r--r--src/chainparamsbase.cpp1
-rw-r--r--src/interfaces/handler.cpp2
-rw-r--r--src/net.cpp3
-rw-r--r--src/rpc/blockchain.cpp289
-rw-r--r--src/rpc/client.cpp1
-rw-r--r--src/util.h11
-rw-r--r--src/utilmemory.h19
-rw-r--r--src/validation.cpp12
-rwxr-xr-xtest/functional/p2p_segwit.py3
-rwxr-xr-xtest/functional/rpc_scantxoutset.py48
-rwxr-xr-xtest/functional/test_runner.py1
19 files changed, 578 insertions, 438 deletions
diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py
index c9516ef83f..47195f73c8 100755
--- a/contrib/devtools/security-check.py
+++ b/contrib/devtools/security-check.py
@@ -97,7 +97,7 @@ def check_ELF_RELRO(executable):
raise IOError('Error opening file')
for line in stdout.splitlines():
tokens = line.split()
- if len(tokens)>1 and tokens[1] == '(BIND_NOW)' or (len(tokens)>2 and tokens[1] == '(FLAGS)' and 'BIND_NOW' in tokens[2]):
+ if len(tokens)>1 and tokens[1] == '(BIND_NOW)' or (len(tokens)>2 and tokens[1] == '(FLAGS)' and 'BIND_NOW' in tokens[2:]):
have_bindnow = True
return have_gnu_relro and have_bindnow
diff --git a/contrib/gitian-build.py b/contrib/gitian-build.py
new file mode 100755
index 0000000000..1da9e43896
--- /dev/null
+++ b/contrib/gitian-build.py
@@ -0,0 +1,203 @@
+#!/usr/bin/env python3
+
+import argparse
+import os
+import subprocess
+import sys
+
+def setup():
+ global args, workdir
+ programs = ['ruby', 'git', 'apt-cacher-ng', 'make', 'wget']
+ if args.kvm:
+ programs += ['python-vm-builder', 'qemu-kvm', 'qemu-utils']
+ elif args.docker:
+ programs += ['docker.io']
+ else:
+ programs += ['lxc', 'debootstrap']
+ subprocess.check_call(['sudo', 'apt-get', 'install', '-qq'] + programs)
+ if not os.path.isdir('gitian.sigs'):
+ subprocess.check_call(['git', 'clone', 'https://github.com/bitcoin-core/gitian.sigs.git'])
+ if not os.path.isdir('bitcoin-detached-sigs'):
+ subprocess.check_call(['git', 'clone', 'https://github.com/bitcoin-core/bitcoin-detached-sigs.git'])
+ if not os.path.isdir('gitian-builder'):
+ subprocess.check_call(['git', 'clone', 'https://github.com/devrandom/gitian-builder.git'])
+ if not os.path.isdir('bitcoin'):
+ subprocess.check_call(['git', 'clone', 'https://github.com/bitcoin/bitcoin.git'])
+ os.chdir('gitian-builder')
+ make_image_prog = ['bin/make-base-vm', '--suite', 'bionic', '--arch', 'amd64']
+ if args.docker:
+ make_image_prog += ['--docker']
+ elif not args.kvm:
+ make_image_prog += ['--lxc']
+ subprocess.check_call(make_image_prog)
+ os.chdir(workdir)
+
+def build():
+ global args, workdir
+
+ os.makedirs('bitcoin-binaries/' + args.version, exist_ok=True)
+ print('\nBuilding Dependencies\n')
+ os.chdir('gitian-builder')
+ os.makedirs('inputs', exist_ok=True)
+
+ subprocess.check_call(['wget', '-N', '-P', 'inputs', 'http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz'])
+ subprocess.check_call(['wget', '-N', '-P', 'inputs', 'https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch'])
+ subprocess.check_call(['make', '-C', '../bitcoin/depends', 'download', 'SOURCES_PATH=' + os.getcwd() + '/cache/common'])
+
+ if args.linux:
+ print('\nCompiling ' + args.version + ' Linux')
+ subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'bitcoin='+args.commit, '--url', 'bitcoin='+args.url, '../bitcoin/contrib/gitian-descriptors/gitian-linux.yml'])
+ subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-linux', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-linux.yml'])
+ subprocess.check_call('mv build/out/bitcoin-*.tar.gz build/out/src/bitcoin-*.tar.gz ../bitcoin-binaries/'+args.version, shell=True)
+
+ if args.windows:
+ print('\nCompiling ' + args.version + ' Windows')
+ subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'bitcoin='+args.commit, '--url', 'bitcoin='+args.url, '../bitcoin/contrib/gitian-descriptors/gitian-win.yml'])
+ subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win-unsigned', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-win.yml'])
+ subprocess.check_call('mv build/out/bitcoin-*-win-unsigned.tar.gz inputs/bitcoin-win-unsigned.tar.gz', shell=True)
+ subprocess.check_call('mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ../bitcoin-binaries/'+args.version, shell=True)
+
+ if args.macos:
+ print('\nCompiling ' + args.version + ' MacOS')
+ subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'bitcoin='+args.commit, '--url', 'bitcoin='+args.url, '../bitcoin/contrib/gitian-descriptors/gitian-osx.yml'])
+ subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx-unsigned', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-osx.yml'])
+ subprocess.check_call('mv build/out/bitcoin-*-osx-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz', shell=True)
+ subprocess.check_call('mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ../bitcoin-binaries/'+args.version, shell=True)
+
+ os.chdir(workdir)
+
+ if args.commit_files:
+ print('\nCommitting '+args.version+' Unsigned Sigs\n')
+ os.chdir('gitian.sigs')
+ subprocess.check_call(['git', 'add', args.version+'-linux/'+args.signer])
+ subprocess.check_call(['git', 'add', args.version+'-win-unsigned/'+args.signer])
+ subprocess.check_call(['git', 'add', args.version+'-osx-unsigned/'+args.signer])
+ subprocess.check_call(['git', 'commit', '-m', 'Add '+args.version+' unsigned sigs for '+args.signer])
+ os.chdir(workdir)
+
+def sign():
+ global args, workdir
+ os.chdir('gitian-builder')
+
+ if args.windows:
+ print('\nSigning ' + args.version + ' Windows')
+ subprocess.check_call(['bin/gbuild', '-i', '--commit', 'signature='+args.commit, '../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml'])
+ subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win-signed', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml'])
+ subprocess.check_call('mv build/out/bitcoin-*win64-setup.exe ../bitcoin-binaries/'+args.version, shell=True)
+ subprocess.check_call('mv build/out/bitcoin-*win32-setup.exe ../bitcoin-binaries/'+args.version, shell=True)
+
+ if args.macos:
+ print('\nSigning ' + args.version + ' MacOS')
+ subprocess.check_call(['bin/gbuild', '-i', '--commit', 'signature='+args.commit, '../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml'])
+ subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx-signed', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml'])
+ subprocess.check_call('mv build/out/bitcoin-osx-signed.dmg ../bitcoin-binaries/'+args.version+'/bitcoin-'+args.version+'-osx.dmg', shell=True)
+
+ os.chdir(workdir)
+
+ if args.commit_files:
+ print('\nCommitting '+args.version+' Signed Sigs\n')
+ os.chdir('gitian.sigs')
+ subprocess.check_call(['git', 'add', args.version+'-win-signed/'+args.signer])
+ subprocess.check_call(['git', 'add', args.version+'-osx-signed/'+args.signer])
+ subprocess.check_call(['git', 'commit', '-a', '-m', 'Add '+args.version+' signed binary sigs for '+args.signer])
+ os.chdir(workdir)
+
+def verify():
+ global args, workdir
+ os.chdir('gitian-builder')
+
+ print('\nVerifying v'+args.version+' Linux\n')
+ subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-linux', '../bitcoin/contrib/gitian-descriptors/gitian-linux.yml'])
+ print('\nVerifying v'+args.version+' Windows\n')
+ subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-win-unsigned', '../bitcoin/contrib/gitian-descriptors/gitian-win.yml'])
+ print('\nVerifying v'+args.version+' MacOS\n')
+ subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-osx-unsigned', '../bitcoin/contrib/gitian-descriptors/gitian-osx.yml'])
+ print('\nVerifying v'+args.version+' Signed Windows\n')
+ subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-win-signed', '../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml'])
+ print('\nVerifying v'+args.version+' Signed MacOS\n')
+ subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-osx-signed', '../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml'])
+
+ os.chdir(workdir)
+
+def main():
+ global args, workdir
+
+ parser = argparse.ArgumentParser(usage='%(prog)s [options] signer version')
+ parser.add_argument('-c', '--commit', action='store_true', dest='commit', help='Indicate that the version argument is for a commit or branch')
+ parser.add_argument('-u', '--url', dest='url', default='https://github.com/bitcoin/bitcoin', help='Specify the URL of the repository. Default is %(default)s')
+ parser.add_argument('-v', '--verify', action='store_true', dest='verify', help='Verify the Gitian build')
+ parser.add_argument('-b', '--build', action='store_true', dest='build', help='Do a Gitian build')
+ parser.add_argument('-s', '--sign', action='store_true', dest='sign', help='Make signed binaries for Windows and MacOS')
+ parser.add_argument('-B', '--buildsign', action='store_true', dest='buildsign', help='Build both signed and unsigned binaries')
+ parser.add_argument('-o', '--os', dest='os', default='lwm', help='Specify which Operating Systems the build is for. Default is %(default)s. l for Linux, w for Windows, m for MacOS')
+ parser.add_argument('-j', '--jobs', dest='jobs', default='2', help='Number of processes to use. Default %(default)s')
+ parser.add_argument('-m', '--memory', dest='memory', default='2000', help='Memory to allocate in MiB. Default %(default)s')
+ parser.add_argument('-k', '--kvm', action='store_true', dest='kvm', help='Use KVM instead of LXC')
+ parser.add_argument('-d', '--docker', action='store_true', dest='docker', help='Use Docker instead of LXC')
+ parser.add_argument('-S', '--setup', action='store_true', dest='setup', help='Set up the Gitian building environment. Uses LXC. If you want to use KVM, use the --kvm option. Only works on Debian-based systems (Ubuntu, Debian)')
+ parser.add_argument('-D', '--detach-sign', action='store_true', dest='detach_sign', help='Create the assert file for detached signing. Will not commit anything.')
+ parser.add_argument('-n', '--no-commit', action='store_false', dest='commit_files', help='Do not commit anything to git')
+ parser.add_argument('signer', help='GPG signer to sign each build assert file')
+ parser.add_argument('version', help='Version number, commit, or branch to build. If building a commit or branch, the -c option must be specified')
+
+ args = parser.parse_args()
+ workdir = os.getcwd()
+
+ args.linux = 'l' in args.os
+ args.windows = 'w' in args.os
+ args.macos = 'm' in args.os
+
+ if args.buildsign:
+ args.build=True
+ args.sign=True
+
+ if args.kvm and args.docker:
+ raise Exception('Error: cannot have both kvm and docker')
+
+ args.sign_prog = 'true' if args.detach_sign else 'gpg --detach-sign'
+
+ # Set enviroment variable USE_LXC or USE_DOCKER, let gitian-builder know that we use lxc or docker
+ if args.docker:
+ os.environ['USE_DOCKER'] = '1'
+ elif not args.kvm:
+ os.environ['USE_LXC'] = '1'
+
+ # Disable for MacOS if no SDK found
+ if args.macos and not os.path.isfile('gitian-builder/inputs/MacOSX10.11.sdk.tar.gz'):
+ print('Cannot build for MacOS, SDK does not exist. Will build for other OSes')
+ args.macos = False
+
+ script_name = os.path.basename(sys.argv[0])
+ # Signer and version shouldn't be empty
+ if args.signer == '':
+ print(script_name+': Missing signer.')
+ print('Try '+script_name+' --help for more information')
+ exit(1)
+ if args.version == '':
+ print(script_name+': Missing version.')
+ print('Try '+script_name+' --help for more information')
+ exit(1)
+
+ # Add leading 'v' for tags
+ args.commit = ('' if args.commit else 'v') + args.version
+ print(args.commit)
+
+ if args.setup:
+ setup()
+
+ os.chdir('bitcoin')
+ subprocess.check_call(['git', 'fetch'])
+ subprocess.check_call(['git', 'checkout', args.commit])
+ os.chdir(workdir)
+
+ if args.build:
+ build()
+
+ if args.sign:
+ sign()
+
+ if args.verify:
+ verify()
+
+if __name__ == '__main__':
+ main()
diff --git a/contrib/gitian-build.sh b/contrib/gitian-build.sh
deleted file mode 100755
index d873580711..0000000000
--- a/contrib/gitian-build.sh
+++ /dev/null
@@ -1,413 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (c) 2016 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-export LC_ALL=C
-# What to do
-sign=false
-verify=false
-build=false
-
-# Systems to build
-linux=true
-windows=true
-osx=true
-
-# Other Basic variables
-SIGNER=
-VERSION=
-commit=false
-url=https://github.com/bitcoin/bitcoin
-proc=2
-mem=2000
-lxc=true
-docker=false
-osslTarUrl=http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz
-osslPatchUrl=https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch
-scriptName=$(basename -- "$0")
-signProg="gpg --detach-sign"
-commitFiles=true
-
-# Help Message
-read -d '' usage <<- EOF
-Usage: $scriptName [-c|u|v|b|s|B|o|h|j|m|] signer version
-
-Run this script from the directory containing the bitcoin, gitian-builder, gitian.sigs, and bitcoin-detached-sigs.
-
-Arguments:
-signer GPG signer to sign each build assert file
-version Version number, commit, or branch to build. If building a commit or branch, the -c option must be specified
-
-Options:
--c|--commit Indicate that the version argument is for a commit or branch
--u|--url Specify the URL of the repository. Default is https://github.com/bitcoin/bitcoin
--v|--verify Verify the Gitian build
--b|--build Do a Gitian build
--s|--sign Make signed binaries for Windows and Mac OSX
--B|--buildsign Build both signed and unsigned binaries
--o|--os Specify which Operating Systems the build is for. Default is lwx. l for linux, w for windows, x for osx
--j Number of processes to use. Default 2
--m Memory to allocate in MiB. Default 2000
---kvm Use KVM instead of LXC
---docker Use Docker instead of LXC
---setup Set up the Gitian building environment. Uses LXC. If you want to use KVM, use the --kvm option. Only works on Debian-based systems (Ubuntu, Debian)
---detach-sign Create the assert file for detached signing. Will not commit anything.
---no-commit Do not commit anything to git
--h|--help Print this help message
-EOF
-
-# Get options and arguments
-while :; do
- case $1 in
- # Verify
- -v|--verify)
- verify=true
- ;;
- # Build
- -b|--build)
- build=true
- ;;
- # Sign binaries
- -s|--sign)
- sign=true
- ;;
- # Build then Sign
- -B|--buildsign)
- sign=true
- build=true
- ;;
- # PGP Signer
- -S|--signer)
- if [ -n "$2" ]
- then
- SIGNER="$2"
- shift
- else
- echo 'Error: "--signer" requires a non-empty argument.'
- exit 1
- fi
- ;;
- # Operating Systems
- -o|--os)
- if [ -n "$2" ]
- then
- linux=false
- windows=false
- osx=false
- if [[ "$2" = *"l"* ]]
- then
- linux=true
- fi
- if [[ "$2" = *"w"* ]]
- then
- windows=true
- fi
- if [[ "$2" = *"x"* ]]
- then
- osx=true
- fi
- shift
- else
- echo 'Error: "--os" requires an argument containing an l (for linux), w (for windows), or x (for Mac OSX)'
- exit 1
- fi
- ;;
- # Help message
- -h|--help)
- echo "$usage"
- exit 0
- ;;
- # Commit or branch
- -c|--commit)
- commit=true
- ;;
- # Number of Processes
- -j)
- if [ -n "$2" ]
- then
- proc=$2
- shift
- else
- echo 'Error: "-j" requires an argument'
- exit 1
- fi
- ;;
- # Memory to allocate
- -m)
- if [ -n "$2" ]
- then
- mem=$2
- shift
- else
- echo 'Error: "-m" requires an argument'
- exit 1
- fi
- ;;
- # URL
- -u)
- if [ -n "$2" ]
- then
- url=$2
- shift
- else
- echo 'Error: "-u" requires an argument'
- exit 1
- fi
- ;;
- # kvm
- --kvm)
- lxc=false
- ;;
- # docker
- --docker)
- if [[ $lxc = false ]]
- then
- echo 'Error: cannot have both kvm and docker'
- exit 1
- fi
- lxc=false
- docker=true
- ;;
- # Detach sign
- --detach-sign)
- signProg="true"
- commitFiles=false
- ;;
- # Commit files
- --no-commit)
- commitFiles=false
- ;;
- # Setup
- --setup)
- setup=true
- ;;
- *) # Default case: If no more options then break out of the loop.
- break
- esac
- shift
-done
-
-# Set up LXC
-if [[ $lxc = true ]]
-then
- export USE_LXC=1
-fi
-
-# Setup docker
-if [[ $docker = true ]]
-then
- export USE_DOCKER=1
-fi
-
-# Check for OSX SDK
-if [[ ! -e "gitian-builder/inputs/MacOSX10.11.sdk.tar.gz" && $osx == true ]]
-then
- echo "Cannot build for OSX, SDK does not exist. Will build for other OSes"
- osx=false
-fi
-
-# Get signer
-if [[ -n "$1" ]]
-then
- SIGNER="$1"
- shift
-fi
-
-# Get version
-if [[ -n "$1" ]]
-then
- VERSION=$1
- COMMIT=$VERSION
- shift
-fi
-
-# Check that a signer is specified
-if [[ "$SIGNER" == "" ]]
-then
- echo "$scriptName: Missing signer."
- echo "Try $scriptName --help for more information"
- exit 1
-fi
-
-# Check that a version is specified
-if [[ $VERSION == "" ]]
-then
- echo "$scriptName: Missing version."
- echo "Try $scriptName --help for more information"
- exit 1
-fi
-
-# Add a "v" if no -c
-if [[ $commit = false ]]
-then
- COMMIT="v${VERSION}"
-fi
-echo ${COMMIT}
-
-# Setup build environment
-if [[ $setup = true ]]
-then
- sudo apt-get install ruby apache2 git apt-cacher-ng python-vm-builder qemu-kvm qemu-utils
- git clone https://github.com/bitcoin-core/gitian.sigs.git
- git clone https://github.com/bitcoin-core/bitcoin-detached-sigs.git
- git clone https://github.com/devrandom/gitian-builder.git
- pushd ./gitian-builder
- if [[ -n "$USE_LXC" ]]
- then
- sudo apt-get install lxc
- bin/make-base-vm --suite bionic --arch amd64 --lxc
- elif [[ -n "$USE_DOCKER" ]]
- then
- sudo apt-get install docker-ce
- bin/make-base-vm --suite bionic --arch amd64 --docker
- else
- bin/make-base-vm --suite bionic --arch amd64
- fi
- popd
-fi
-
-# Set up build
-pushd ./bitcoin
-git fetch
-git checkout ${COMMIT}
-popd
-
-# Build
-if [[ $build = true ]]
-then
- # Make output folder
- mkdir -p ./bitcoin-binaries/${VERSION}
-
- # Build Dependencies
- echo ""
- echo "Building Dependencies"
- echo ""
- pushd ./gitian-builder
- mkdir -p inputs
- wget -N -P inputs $osslPatchUrl
- wget -N -P inputs $osslTarUrl
- make -C ../bitcoin/depends download SOURCES_PATH=`pwd`/cache/common
-
- # Linux
- if [[ $linux = true ]]
- then
- echo ""
- echo "Compiling ${VERSION} Linux"
- echo ""
- ./bin/gbuild -j ${proc} -m ${mem} --commit bitcoin=${COMMIT} --url bitcoin=${url} ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml
- ./bin/gsign -p "$signProg" --signer "$SIGNER" --release ${VERSION}-linux --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml
- mv build/out/bitcoin-*.tar.gz build/out/src/bitcoin-*.tar.gz ../bitcoin-binaries/${VERSION}
- fi
- # Windows
- if [[ $windows = true ]]
- then
- echo ""
- echo "Compiling ${VERSION} Windows"
- echo ""
- ./bin/gbuild -j ${proc} -m ${mem} --commit bitcoin=${COMMIT} --url bitcoin=${url} ../bitcoin/contrib/gitian-descriptors/gitian-win.yml
- ./bin/gsign -p "$signProg" --signer "$SIGNER" --release ${VERSION}-win-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win.yml
- mv build/out/bitcoin-*-win-unsigned.tar.gz inputs/bitcoin-win-unsigned.tar.gz
- mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ../bitcoin-binaries/${VERSION}
- fi
- # Mac OSX
- if [[ $osx = true ]]
- then
- echo ""
- echo "Compiling ${VERSION} Mac OSX"
- echo ""
- ./bin/gbuild -j ${proc} -m ${mem} --commit bitcoin=${COMMIT} --url bitcoin=${url} ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml
- ./bin/gsign -p "$signProg" --signer "$SIGNER" --release ${VERSION}-osx-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml
- mv build/out/bitcoin-*-osx-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz
- mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ../bitcoin-binaries/${VERSION}
- fi
- popd
-
- if [[ $commitFiles = true ]]
- then
- # Commit to gitian.sigs repo
- echo ""
- echo "Committing ${VERSION} Unsigned Sigs"
- echo ""
- pushd gitian.sigs
- git add ${VERSION}-linux/"${SIGNER}"
- git add ${VERSION}-win-unsigned/"${SIGNER}"
- git add ${VERSION}-osx-unsigned/"${SIGNER}"
- git commit -a -m "Add ${VERSION} unsigned sigs for ${SIGNER}"
- popd
- fi
-fi
-
-# Verify the build
-if [[ $verify = true ]]
-then
- # Linux
- pushd ./gitian-builder
- echo ""
- echo "Verifying v${VERSION} Linux"
- echo ""
- ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-linux ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml
- # Windows
- echo ""
- echo "Verifying v${VERSION} Windows"
- echo ""
- ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-win-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-win.yml
- # Mac OSX
- echo ""
- echo "Verifying v${VERSION} Mac OSX"
- echo ""
- ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml
- # Signed Windows
- echo ""
- echo "Verifying v${VERSION} Signed Windows"
- echo ""
- ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-signed ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml
- # Signed Mac OSX
- echo ""
- echo "Verifying v${VERSION} Signed Mac OSX"
- echo ""
- ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-signed ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml
- popd
-fi
-
-# Sign binaries
-if [[ $sign = true ]]
-then
-
- pushd ./gitian-builder
- # Sign Windows
- if [[ $windows = true ]]
- then
- echo ""
- echo "Signing ${VERSION} Windows"
- echo ""
- ./bin/gbuild -i --commit signature=${COMMIT} ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml
- ./bin/gsign -p "$signProg" --signer "$SIGNER" --release ${VERSION}-win-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml
- mv build/out/bitcoin-*win64-setup.exe ../bitcoin-binaries/${VERSION}
- mv build/out/bitcoin-*win32-setup.exe ../bitcoin-binaries/${VERSION}
- fi
- # Sign Mac OSX
- if [[ $osx = true ]]
- then
- echo ""
- echo "Signing ${VERSION} Mac OSX"
- echo ""
- ./bin/gbuild -i --commit signature=${COMMIT} ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml
- ./bin/gsign -p "$signProg" --signer "$SIGNER" --release ${VERSION}-osx-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml
- mv build/out/bitcoin-osx-signed.dmg ../bitcoin-binaries/${VERSION}/bitcoin-${VERSION}-osx.dmg
- fi
- popd
-
- if [[ $commitFiles = true ]]
- then
- # Commit Sigs
- pushd gitian.sigs
- echo ""
- echo "Committing ${VERSION} Signed Sigs"
- echo ""
- git add ${VERSION}-win-signed/"${SIGNER}"
- git add ${VERSION}-osx-signed/"${SIGNER}"
- git commit -a -m "Add ${VERSION} signed binary sigs for ${SIGNER}"
- popd
- fi
-fi
diff --git a/contrib/zmq/zmq_sub.py b/contrib/zmq/zmq_sub.py
index 60768dc59a..fa9e669308 100644
--- a/contrib/zmq/zmq_sub.py
+++ b/contrib/zmq/zmq_sub.py
@@ -30,7 +30,7 @@ import signal
import struct
import sys
-if not (sys.version_info.major >= 3 and sys.version_info.minor >= 5):
+if (sys.version_info.major, sys.version_info.minor) < (3, 5):
print("This example only works with Python 3.5 and greater")
sys.exit(1)
diff --git a/contrib/zmq/zmq_sub3.4.py b/contrib/zmq/zmq_sub3.4.py
index 0df843c9a3..d05ecc2623 100644
--- a/contrib/zmq/zmq_sub3.4.py
+++ b/contrib/zmq/zmq_sub3.4.py
@@ -34,7 +34,7 @@ import signal
import struct
import sys
-if not (sys.version_info.major >= 3 and sys.version_info.minor >= 4):
+if (sys.version_info.major, sys.version_info.minor) < (3, 4):
print("This example only works with Python 3.4 and greater")
sys.exit(1)
diff --git a/doc/release-process.md b/doc/release-process.md
index 912b620794..f3fc4bdfdc 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -157,7 +157,7 @@ Commit your signature to gitian.sigs:
git add ${VERSION}-linux/"${SIGNER}"
git add ${VERSION}-win-unsigned/"${SIGNER}"
git add ${VERSION}-osx-unsigned/"${SIGNER}"
- git commit -a
+ git commit -m "Add ${VERSION} unsigned sigs for ${SIGNER}"
git push # Assuming you can push to the gitian.sigs tree
popd
diff --git a/src/Makefile.am b/src/Makefile.am
index 1dd202085a..2603dbae56 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -179,6 +179,7 @@ BITCOIN_CORE_H = \
ui_interface.h \
undo.h \
util.h \
+ utilmemory.h \
utilmoneystr.h \
utiltime.h \
validation.h \
diff --git a/src/bench/bech32.cpp b/src/bench/bech32.cpp
index ff655bded0..8b80e17391 100644
--- a/src/bench/bech32.cpp
+++ b/src/bench/bech32.cpp
@@ -27,7 +27,6 @@ static void Bech32Encode(benchmark::State& state)
static void Bech32Decode(benchmark::State& state)
{
std::string addr = "bc1qkallence7tjawwvy0dwt4twc62qjgaw8f4vlhyd006d99f09";
- std::vector<unsigned char> vch;
while (state.KeepRunning()) {
bech32::Decode(addr);
}
diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp
index 787d8d8f6a..da9f3e3209 100644
--- a/src/chainparamsbase.cpp
+++ b/src/chainparamsbase.cpp
@@ -7,6 +7,7 @@
#include <tinyformat.h>
#include <util.h>
+#include <utilmemory.h>
#include <assert.h>
diff --git a/src/interfaces/handler.cpp b/src/interfaces/handler.cpp
index 8e45faa2a5..80f461f4d3 100644
--- a/src/interfaces/handler.cpp
+++ b/src/interfaces/handler.cpp
@@ -4,7 +4,7 @@
#include <interfaces/handler.h>
-#include <util.h>
+#include <utilmemory.h>
#include <boost/signals2/connection.hpp>
#include <utility>
diff --git a/src/net.cpp b/src/net.cpp
index e44aa1fdb4..34dc4aec5c 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -2254,7 +2254,8 @@ bool CConnman::InitBinds(const std::vector<CService>& binds, const std::vector<C
if (binds.empty() && whiteBinds.empty()) {
struct in_addr inaddr_any;
inaddr_any.s_addr = INADDR_ANY;
- fBound |= Bind(CService((in6_addr)IN6ADDR_ANY_INIT, GetListenPort()), BF_NONE);
+ struct in6_addr inaddr6_any = IN6ADDR_ANY_INIT;
+ fBound |= Bind(CService(inaddr6_any, GetListenPort()), BF_NONE);
fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE);
}
return fBound;
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index d9d803ac7d..012e3e3ac1 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -6,6 +6,8 @@
#include <rpc/blockchain.h>
#include <amount.h>
+#include <base58.h>
+#include <chain.h>
#include <chainparams.h>
#include <checkpoints.h>
#include <coins.h>
@@ -13,6 +15,7 @@
#include <validation.h>
#include <core_io.h>
#include <index/txindex.h>
+#include <key_io.h>
#include <policy/feerate.h>
#include <policy/policy.h>
#include <primitives/transaction.h>
@@ -27,6 +30,7 @@
#include <validationinterface.h>
#include <warnings.h>
+#include <assert.h>
#include <stdint.h>
#include <univalue.h>
@@ -1920,6 +1924,290 @@ static UniValue savemempool(const JSONRPCRequest& request)
return NullUniValue;
}
+//! Search for a given set of pubkey scripts
+bool FindScriptPubKey(std::atomic<int>& scan_progress, const std::atomic<bool>& should_abort, int64_t& count, CCoinsViewCursor* cursor, const std::set<CScript>& needles, std::map<COutPoint, Coin>& out_results) {
+ scan_progress = 0;
+ count = 0;
+ while (cursor->Valid()) {
+ COutPoint key;
+ Coin coin;
+ if (!cursor->GetKey(key) || !cursor->GetValue(coin)) return false;
+ if (++count % 8192 == 0) {
+ boost::this_thread::interruption_point();
+ if (should_abort) {
+ // allow to abort the scan via the abort reference
+ return false;
+ }
+ }
+ if (count % 256 == 0) {
+ // update progress reference every 256 item
+ uint32_t high = 0x100 * *key.hash.begin() + *(key.hash.begin() + 1);
+ scan_progress = (int)(high * 100.0 / 65536.0 + 0.5);
+ }
+ if (needles.count(coin.out.scriptPubKey)) {
+ out_results.emplace(key, coin);
+ }
+ cursor->Next();
+ }
+ scan_progress = 100;
+ return true;
+}
+
+/** RAII object to prevent concurrency issue when scanning the txout set */
+static std::mutex g_utxosetscan;
+static std::atomic<int> g_scan_progress;
+static std::atomic<bool> g_scan_in_progress;
+static std::atomic<bool> g_should_abort_scan;
+class CoinsViewScanReserver
+{
+private:
+ bool m_could_reserve;
+public:
+ explicit CoinsViewScanReserver() : m_could_reserve(false) {}
+
+ bool reserve() {
+ assert (!m_could_reserve);
+ std::lock_guard<std::mutex> lock(g_utxosetscan);
+ if (g_scan_in_progress) {
+ return false;
+ }
+ g_scan_in_progress = true;
+ m_could_reserve = true;
+ return true;
+ }
+
+ ~CoinsViewScanReserver() {
+ if (m_could_reserve) {
+ std::lock_guard<std::mutex> lock(g_utxosetscan);
+ g_scan_in_progress = false;
+ }
+ }
+};
+
+static const char *g_default_scantxoutset_script_types[] = { "P2PKH", "P2SH_P2WPKH", "P2WPKH" };
+
+enum class OutputScriptType {
+ UNKNOWN,
+ P2PK,
+ P2PKH,
+ P2SH_P2WPKH,
+ P2WPKH
+};
+
+static inline OutputScriptType GetOutputScriptTypeFromString(const std::string& outputtype)
+{
+ if (outputtype == "P2PK") return OutputScriptType::P2PK;
+ else if (outputtype == "P2PKH") return OutputScriptType::P2PKH;
+ else if (outputtype == "P2SH_P2WPKH") return OutputScriptType::P2SH_P2WPKH;
+ else if (outputtype == "P2WPKH") return OutputScriptType::P2WPKH;
+ else return OutputScriptType::UNKNOWN;
+}
+
+CTxDestination GetDestinationForKey(const CPubKey& key, OutputScriptType type)
+{
+ switch (type) {
+ case OutputScriptType::P2PKH: return key.GetID();
+ case OutputScriptType::P2SH_P2WPKH:
+ case OutputScriptType::P2WPKH: {
+ if (!key.IsCompressed()) return key.GetID();
+ CTxDestination witdest = WitnessV0KeyHash(key.GetID());
+ if (type == OutputScriptType::P2SH_P2WPKH) {
+ CScript witprog = GetScriptForDestination(witdest);
+ return CScriptID(witprog);
+ } else {
+ return witdest;
+ }
+ }
+ default: assert(false);
+ }
+}
+
+UniValue scantxoutset(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
+ throw std::runtime_error(
+ "scantxoutset <action> ( <scanobjects> )\n"
+ "\nScans the unspent transaction output set for possible entries that matches common scripts of given public keys.\n"
+ "Using addresses as scanobjects will _not_ detect unspent P2PK txouts\n"
+ "\nArguments:\n"
+ "1. \"action\" (string, required) The action to execute\n"
+ " \"start\" for starting a scan\n"
+ " \"abort\" for aborting the current scan (returns true when abort was successful)\n"
+ " \"status\" for progress report (in %) of the current scan\n"
+ "2. \"scanobjects\" (array, optional) Array of scan objects (only one object type per scan object allowed)\n"
+ " [\n"
+ " { \"address\" : \"<address>\" }, (string, optional) Bitcoin address\n"
+ " { \"script\" : \"<scriptPubKey>\" }, (string, optional) HEX encoded script (scriptPubKey)\n"
+ " { \"pubkey\" : (object, optional) Public key\n"
+ " {\n"
+ " \"pubkey\" : \"<pubkey\">, (string, required) HEX encoded public key\n"
+ " \"script_types\" : [ ... ], (array, optional) Array of script-types to derive from the pubkey (possible values: \"P2PK\", \"P2PKH\", \"P2SH-P2WPKH\", \"P2WPKH\")\n"
+ " }\n"
+ " },\n"
+ " ]\n"
+ "\nResult:\n"
+ "{\n"
+ " \"unspents\": [\n"
+ " {\n"
+ " \"txid\" : \"transactionid\", (string) The transaction id\n"
+ " \"vout\": n, (numeric) the vout value\n"
+ " \"scriptPubKey\" : \"script\", (string) the script key\n"
+ " \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " of the unspent output\n"
+ " \"height\" : n, (numeric) Height of the unspent transaction output\n"
+ " }\n"
+ " ,...], \n"
+ " \"total_amount\" : x.xxx, (numeric) The total amount of all found unspent outputs in " + CURRENCY_UNIT + "\n"
+ "]\n"
+ );
+
+ RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR});
+
+ UniValue result(UniValue::VOBJ);
+ if (request.params[0].get_str() == "status") {
+ CoinsViewScanReserver reserver;
+ if (reserver.reserve()) {
+ // no scan in progress
+ return NullUniValue;
+ }
+ result.pushKV("progress", g_scan_progress);
+ return result;
+ } else if (request.params[0].get_str() == "abort") {
+ CoinsViewScanReserver reserver;
+ if (reserver.reserve()) {
+ // reserve was possible which means no scan was running
+ return false;
+ }
+ // set the abort flag
+ g_should_abort_scan = true;
+ return true;
+ } else if (request.params[0].get_str() == "start") {
+ CoinsViewScanReserver reserver;
+ if (!reserver.reserve()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan already in progress, use action \"abort\" or \"status\"");
+ }
+ std::set<CScript> needles;
+ CAmount total_in = 0;
+
+ // loop through the scan objects
+ for (const UniValue& scanobject : request.params[1].get_array().getValues()) {
+ if (!scanobject.isObject()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid scan object");
+ }
+ UniValue address_uni = find_value(scanobject, "address");
+ UniValue pubkey_uni = find_value(scanobject, "pubkey");
+ UniValue script_uni = find_value(scanobject, "script");
+
+ // make sure only one object type is present
+ if (1 != !address_uni.isNull() + !pubkey_uni.isNull() + !script_uni.isNull()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Only one object type is allowed per scan object");
+ } else if (!address_uni.isNull() && !address_uni.isStr()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Scanobject \"address\" must contain a single string as value");
+ } else if (!pubkey_uni.isNull() && !pubkey_uni.isObject()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Scanobject \"pubkey\" must contain an object as value");
+ } else if (!script_uni.isNull() && !script_uni.isStr()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Scanobject \"script\" must contain a single string as value");
+ } else if (address_uni.isStr()) {
+ // type: address
+ // decode destination and derive the scriptPubKey
+ // add the script to the scan containers
+ CTxDestination dest = DecodeDestination(address_uni.get_str());
+ if (!IsValidDestination(dest)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
+ }
+ CScript script = GetScriptForDestination(dest);
+ assert(!script.empty());
+ needles.insert(script);
+ } else if (pubkey_uni.isObject()) {
+ // type: pubkey
+ // derive script(s) according to the script_type parameter
+ UniValue script_types_uni = find_value(pubkey_uni, "script_types");
+ UniValue pubkeydata_uni = find_value(pubkey_uni, "pubkey");
+
+ // check the script types and use the default if not provided
+ if (!script_types_uni.isNull() && !script_types_uni.isArray()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "script_types must be an array");
+ } else if (script_types_uni.isNull()) {
+ // use the default script types
+ script_types_uni = UniValue(UniValue::VARR);
+ for (const char *t : g_default_scantxoutset_script_types) {
+ script_types_uni.push_back(t);
+ }
+ }
+
+ // check the acctual pubkey
+ if (!pubkeydata_uni.isStr() || !IsHex(pubkeydata_uni.get_str())) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Public key must be hex encoded");
+ }
+ CPubKey pubkey(ParseHexV(pubkeydata_uni, "pubkey"));
+ if (!pubkey.IsFullyValid()) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid public key");
+ }
+
+ // loop through the script types and derive the script
+ for (const UniValue& script_type_uni : script_types_uni.get_array().getValues()) {
+ OutputScriptType script_type = GetOutputScriptTypeFromString(script_type_uni.get_str());
+ if (script_type == OutputScriptType::UNKNOWN) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid script type");
+ CScript script;
+ if (script_type == OutputScriptType::P2PK) {
+ // support legacy P2PK scripts
+ script << ToByteVector(pubkey) << OP_CHECKSIG;
+ } else {
+ script = GetScriptForDestination(GetDestinationForKey(pubkey, script_type));
+ }
+ assert(!script.empty());
+ needles.insert(script);
+ }
+ } else if (script_uni.isStr()) {
+ // type: script
+ // check and add the script to the scan containers (needles array)
+ CScript script(ParseHexV(script_uni, "script"));
+ // TODO: check script: max length, has OP, is unspenable etc.
+ needles.insert(script);
+ }
+ }
+
+ // Scan the unspent transaction output set for inputs
+ UniValue unspents(UniValue::VARR);
+ std::vector<CTxOut> input_txos;
+ std::map<COutPoint, Coin> coins;
+ g_should_abort_scan = false;
+ g_scan_progress = 0;
+ int64_t count = 0;
+ std::unique_ptr<CCoinsViewCursor> pcursor;
+ {
+ LOCK(cs_main);
+ FlushStateToDisk();
+ pcursor = std::unique_ptr<CCoinsViewCursor>(pcoinsdbview->Cursor());
+ assert(pcursor);
+ }
+ bool res = FindScriptPubKey(g_scan_progress, g_should_abort_scan, count, pcursor.get(), needles, coins);
+ result.pushKV("success", res);
+ result.pushKV("searched_items", count);
+
+ for (const auto& it : coins) {
+ const COutPoint& outpoint = it.first;
+ const Coin& coin = it.second;
+ const CTxOut& txo = coin.out;
+ input_txos.push_back(txo);
+ total_in += txo.nValue;
+
+ UniValue unspent(UniValue::VOBJ);
+ unspent.pushKV("txid", outpoint.hash.GetHex());
+ unspent.pushKV("vout", (int32_t)outpoint.n);
+ unspent.pushKV("scriptPubKey", HexStr(txo.scriptPubKey.begin(), txo.scriptPubKey.end()));
+ unspent.pushKV("amount", ValueFromAmount(txo.nValue));
+ unspent.pushKV("height", (int32_t)coin.nHeight);
+
+ unspents.push_back(unspent);
+ }
+ result.pushKV("unspents", unspents);
+ result.pushKV("total_amount", ValueFromAmount(total_in));
+ } else {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid command");
+ }
+ return result;
+}
+
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
@@ -1945,6 +2233,7 @@ static const CRPCCommand commands[] =
{ "blockchain", "verifychain", &verifychain, {"checklevel","nblocks"} },
{ "blockchain", "preciousblock", &preciousblock, {"blockhash"} },
+ { "blockchain", "scantxoutset", &scantxoutset, {"action", "scanobjects"} },
/* Not shown in help */
{ "hidden", "invalidateblock", &invalidateblock, {"blockhash"} },
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index 0f35fd3770..ce608631ff 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -78,6 +78,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "sendmany", 4, "subtractfeefrom" },
{ "sendmany", 5 , "replaceable" },
{ "sendmany", 6 , "conf_target" },
+ { "scantxoutset", 1, "scanobjects" },
{ "addmultisigaddress", 0, "nrequired" },
{ "addmultisigaddress", 1, "keys" },
{ "createmultisig", 0, "nrequired" },
diff --git a/src/util.h b/src/util.h
index 8094d72d6b..f8bcc0192c 100644
--- a/src/util.h
+++ b/src/util.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -20,11 +20,11 @@
#include <sync.h>
#include <tinyformat.h>
#include <utiltime.h>
+#include <utilmemory.h>
#include <atomic>
#include <exception>
#include <map>
-#include <memory>
#include <set>
#include <stdint.h>
#include <string>
@@ -346,13 +346,6 @@ template <typename Callable> void TraceThread(const char* name, Callable func)
std::string CopyrightHolders(const std::string& strPrefix);
-//! Substitute for C++14 std::make_unique.
-template <typename T, typename... Args>
-std::unique_ptr<T> MakeUnique(Args&&... args)
-{
- return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
-}
-
/**
* On platforms that support it, tell the kernel the calling thread is
* CPU-intensive and non-interactive. See SCHED_BATCH in sched(7) for details.
diff --git a/src/utilmemory.h b/src/utilmemory.h
new file mode 100644
index 0000000000..e71fe92284
--- /dev/null
+++ b/src/utilmemory.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTILMEMORY_H
+#define BITCOIN_UTILMEMORY_H
+
+#include <memory>
+#include <utility>
+
+//! Substitute for C++14 std::make_unique.
+template <typename T, typename... Args>
+std::unique_ptr<T> MakeUnique(Args&&... args)
+{
+ return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+}
+
+#endif
diff --git a/src/validation.cpp b/src/validation.cpp
index 811530d40e..a30f1fd0ce 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -806,13 +806,11 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// be increased is also an easy-to-reason about way to prevent
// DoS attacks via replacements.
//
- // The mining code doesn't (currently) take children into
- // account (CPFP) so we only consider the feerates of
- // transactions being directly replaced, not their indirect
- // descendants. While that does mean high feerate children are
- // ignored when deciding whether or not to replace, we do
- // require the replacement to pay more overall fees too,
- // mitigating most cases.
+ // We only consider the feerates of transactions being directly
+ // replaced, not their indirect descendants. While that does
+ // mean high feerate children are ignored when deciding whether
+ // or not to replace, we do require the replacement to pay more
+ // overall fees too, mitigating most cases.
CFeeRate oldFeeRate(mi->GetModifiedFee(), mi->GetTxSize());
if (newFeeRate <= oldFeeRate)
{
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py
index 801c4b87a0..52f6482d56 100755
--- a/test/functional/p2p_segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -47,6 +47,7 @@ from test_framework.script import (
CScript,
CScriptNum,
CScriptOp,
+ MAX_SCRIPT_ELEMENT_SIZE,
OP_0,
OP_1,
OP_16,
@@ -1129,8 +1130,6 @@ class SegWitTest(BitcoinTestFramework):
def test_max_witness_push_length(self):
"""Test that witness stack can only allow up to 520 byte pushes."""
- MAX_SCRIPT_ELEMENT_SIZE = 520
-
block = self.build_next_block()
witness_program = CScript([OP_DROP, OP_TRUE])
diff --git a/test/functional/rpc_scantxoutset.py b/test/functional/rpc_scantxoutset.py
new file mode 100755
index 0000000000..ce5d4da9e7
--- /dev/null
+++ b/test/functional/rpc_scantxoutset.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+# Copyright (c) 2018 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test the scantxoutset rpc call."""
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+
+import shutil
+import os
+
+class ScantxoutsetTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 1
+ self.setup_clean_chain = True
+ def run_test(self):
+ self.log.info("Mining blocks...")
+ self.nodes[0].generate(110)
+
+ addr_P2SH_SEGWIT = self.nodes[0].getnewaddress("", "p2sh-segwit")
+ pubk1 = self.nodes[0].getaddressinfo(addr_P2SH_SEGWIT)['pubkey']
+ addr_LEGACY = self.nodes[0].getnewaddress("", "legacy")
+ pubk2 = self.nodes[0].getaddressinfo(addr_LEGACY)['pubkey']
+ addr_BECH32 = self.nodes[0].getnewaddress("", "bech32")
+ pubk3 = self.nodes[0].getaddressinfo(addr_BECH32)['pubkey']
+ self.nodes[0].sendtoaddress(addr_P2SH_SEGWIT, 1)
+ self.nodes[0].sendtoaddress(addr_LEGACY, 2)
+ self.nodes[0].sendtoaddress(addr_BECH32, 3)
+ self.nodes[0].generate(1)
+
+ self.log.info("Stop node, remove wallet, mine again some blocks...")
+ self.stop_node(0)
+ shutil.rmtree(os.path.join(self.nodes[0].datadir, "regtest", 'wallets'))
+ self.start_node(0)
+ self.nodes[0].generate(110)
+
+ self.restart_node(0, ['-nowallet'])
+ self.log.info("Test if we have found the non HD unspent outputs.")
+ assert_equal(self.nodes[0].scantxoutset("start", [ {"pubkey": {"pubkey": pubk1}}, {"pubkey": {"pubkey": pubk2}}, {"pubkey": {"pubkey": pubk3}}])['total_amount'], 6)
+ assert_equal(self.nodes[0].scantxoutset("start", [ {"address": addr_P2SH_SEGWIT}, {"address": addr_LEGACY}, {"address": addr_BECH32}])['total_amount'], 6)
+ assert_equal(self.nodes[0].scantxoutset("start", [ {"address": addr_P2SH_SEGWIT}, {"address": addr_LEGACY}, {"pubkey": {"pubkey": pubk3}} ])['total_amount'], 6)
+
+ self.log.info("Test invalid parameters.")
+ assert_raises_rpc_error(-8, 'Scanobject "pubkey" must contain an object as value', self.nodes[0].scantxoutset, "start", [ {"pubkey": pubk1}]) #missing pubkey object
+ assert_raises_rpc_error(-8, 'Scanobject "address" must contain a single string as value', self.nodes[0].scantxoutset, "start", [ {"address": {"address": addr_P2SH_SEGWIT}}]) #invalid object for address object
+
+if __name__ == '__main__':
+ ScantxoutsetTest().main()
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 49833e5dd4..5d039d7bc4 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -142,6 +142,7 @@ BASE_SCRIPTS = [
'feature_uacomment.py',
'p2p_unrequested_blocks.py',
'feature_includeconf.py',
+ 'rpc_scantxoutset.py',
'feature_logging.py',
'p2p_node_network_limited.py',
'feature_blocksdir.py',