diff --git a/.travis.yml b/.travis.yml
index a83735085c18..c05bd8944ddb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -78,10 +78,8 @@ script:
- BITCOIN_CONFIG_ALL="--disable-dependency-tracking --prefix=$TRAVIS_BUILD_DIR/depends/$HOST --bindir=$OUTDIR/bin --libdir=$OUTDIR/lib"
- depends/$HOST/native/bin/ccache --max-size=$CCACHE_SIZE
- test -n "$USE_SHELL" && eval '"$USE_SHELL" -c "./autogen.sh"' || ./autogen.sh
- - ./configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false)
- - make distdir PACKAGE=dash VERSION=$HOST
- - cd dash-$HOST
- - ./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false)
+ - mkdir build && cd build
+ - ../configure $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false)
- make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && make $GOAL V=1 ; false )
- export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib
- if [ "$RUN_TESTS" = "true" -a "$WINE" != "true" ]; then travis_wait 30 make $MAKEJOBS check VERBOSE=1; fi
diff --git a/Makefile.am b/Makefile.am
index c7b542600e4a..6405f10da5f0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -28,7 +28,7 @@ OSX_DSSTORE_GEN=$(top_srcdir)/contrib/macdeploy/custom_dsstore.py
OSX_DEPLOY_SCRIPT=$(top_srcdir)/contrib/macdeploy/macdeployqtplus
OSX_FANCY_PLIST=$(top_srcdir)/contrib/macdeploy/fancy.plist
OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/bitcoin.icns
-OSX_PLIST=$(top_srcdir)/share/qt/Info.plist #not installed
+OSX_PLIST=$(top_builddir)/share/qt/Info.plist #not installed
OSX_QT_TRANSLATIONS = da,de,es,hu,ru,uk,zh_CN,zh_TW
DIST_DOCS = $(wildcard doc/*.md) $(wildcard doc/release-notes/*.md)
@@ -53,18 +53,8 @@ COVERAGE_INFO = baseline_filtered_combined.info baseline.info block_test.info \
leveldb_baseline_filtered.info test_dash_coverage.info test_dash.info
dist-hook:
- -$(MAKE) -C $(top_distdir)/src/leveldb clean
- -$(MAKE) -C $(top_distdir)/src/secp256k1 distclean
-$(GIT) archive --format=tar HEAD -- src/clientversion.cpp | $(AMTAR) -C $(top_distdir) -xf -
-distcheck-hook:
- $(MKDIR_P) $(top_distdir)/_build/src/leveldb
- cp -rf $(top_srcdir)/src/leveldb/* $(top_distdir)/_build/src/leveldb/
- -$(MAKE) -C $(top_distdir)/_build/src/leveldb clean
-
-distcleancheck:
- @:
-
$(BITCOIN_WIN_INSTALLER): all-recursive
$(MKDIR_P) $(top_builddir)/release
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIND_BIN) $(top_builddir)/release
@@ -236,7 +226,11 @@ EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.py qa/rpc-
CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER)
+# This file is problematic for out-of-tree builds if it exists.
+DISTCLEANFILES = qa/pull-tester/tests_config.pyc
+
.INTERMEDIATE: $(COVERAGE_INFO)
clean-local:
rm -rf coverage_percent.txt test_dash.coverage/ total.coverage/ qa/tmp/ cache/ $(OSX_APP)
+ rm -rf qa/pull-tester/__pycache__
diff --git a/configure.ac b/configure.ac
index a46c36b9257a..c8cf51610eaf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -84,6 +84,7 @@ AC_PATH_PROG(XGETTEXT,xgettext)
AC_PATH_PROG(HEXDUMP,hexdump)
AC_PATH_TOOL(READELF, readelf)
AC_PATH_TOOL(CPPFILT, c++filt)
+AC_PATH_TOOL(OBJCOPY, objcopy)
AC_ARG_VAR(PYTHONPATH, Augments the default search path for python module files)
@@ -1070,6 +1071,8 @@ AC_SUBST(MINIUPNPC_LIBS)
AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py])
AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh])
AC_CONFIG_FILES([qa/pull-tester/tests_config.py],[chmod +x qa/pull-tester/tests_config.py])
+AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh])
+AC_CONFIG_LINKS([qa/pull-tester/rpc-tests.py:qa/pull-tester/rpc-tests.py])
dnl boost's m4 checks do something really nasty: they export these vars. As a
dnl result, they leak into secp256k1's configure and crazy things happen.
diff --git a/contrib/devtools/split-debug.sh.in b/contrib/devtools/split-debug.sh.in
new file mode 100644
index 000000000000..deda49cc5410
--- /dev/null
+++ b/contrib/devtools/split-debug.sh.in
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+if [ $# -ne 3 ];
+ then echo "usage: $0 "
+fi
+
+@OBJCOPY@ --enable-deterministic-archives -p --only-keep-debug $1 $3
+@OBJCOPY@ --enable-deterministic-archives -p --strip-debug $1 $2
+@STRIP@ --enable-deterministic-archives -p -s $2
+@OBJCOPY@ --enable-deterministic-archives -p --add-gnu-debuglink=$3 $2
diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml
index 7f84518a777b..ce4baee31ead 100755
--- a/contrib/gitian-descriptors/gitian-linux.yml
+++ b/contrib/gitian-descriptors/gitian-linux.yml
@@ -7,7 +7,17 @@ architectures:
- "amd64"
packages:
- "curl"
-- "g++-multilib"
+- "g++-aarch64-linux-gnu"
+- "g++-4.8-aarch64-linux-gnu"
+- "gcc-4.8-aarch64-linux-gnu"
+- "binutils-aarch64-linux-gnu"
+- "g++-arm-linux-gnueabihf"
+- "g++-4.8-arm-linux-gnueabihf"
+- "gcc-4.8-arm-linux-gnueabihf"
+- "binutils-arm-linux-gnueabihf"
+- "g++-4.8-multilib"
+- "gcc-4.8-multilib"
+- "binutils-gold"
- "git-core"
- "pkg-config"
- "autoconf"
@@ -15,20 +25,25 @@ packages:
- "automake"
- "faketime"
- "bsdmainutils"
-- "binutils-gold"
- "ca-certificates"
- "python"
-reference_datetime: "2017-01-01 00:00:00"
remotes:
- "url": "https://github.com/dashpay/dash.git"
"dir": "dash"
files: []
script: |
+
+ #unlock sudo
+ echo "ubuntu" | sudo -S true
+
+ sudo mkdir -p /usr/include/i386-linux-gnu/
+ sudo ln -s /usr/include/x86_64-linux-gnu/asm /usr/include/i386-linux-gnu/asm
+
WRAP_DIR=$HOME/wrapped
- HOSTS="i686-pc-linux-gnu x86_64-unknown-linux-gnu"
- CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests LDFLAGS=-static-libstdc++"
+ HOSTS="i686-pc-linux-gnu x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu"
+ CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests"
FAKETIME_HOST_PROGS=""
- FAKETIME_PROGS="date ar ranlib nm strip objcopy"
+ FAKETIME_PROGS="date ar ranlib nm"
HOST_CFLAGS="-O2 -g"
HOST_CXXFLAGS="-O2 -g"
HOST_LDFLAGS=-static-libstdc++
@@ -45,29 +60,36 @@ script: |
mkdir -p ${BASE_CACHE} ${SOURCES_PATH}
fi
- # Create global faketime wrappers
+ function create_global_faketime_wrappers {
for prog in ${FAKETIME_PROGS}; do
echo '#!/bin/bash' > ${WRAP_DIR}/${prog}
echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog}
echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog}
- echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${prog}
+ echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog}
echo "\$REAL \$@" >> $WRAP_DIR/${prog}
chmod +x ${WRAP_DIR}/${prog}
done
+ }
- # Create per-host faketime wrappers
+ function create_per-host_faketime_wrappers {
for i in $HOSTS; do
for prog in ${FAKETIME_HOST_PROGS}; do
echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog}
echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog}
echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog}
- echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${i}-${prog}
+ echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog}
echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog}
chmod +x ${WRAP_DIR}/${i}-${prog}
done
done
+ }
+
export PATH=${WRAP_DIR}:${PATH}
+ # Faketime for depends so intermediate results are comparable
+ create_global_faketime_wrappers "2000-01-01 12:00:00"
+ create_per-host_faketime_wrappers "2000-01-01 12:00:00"
+
cd dash
BASEPREFIX=`pwd`/depends
# Build dependencies for each host
@@ -75,6 +97,10 @@ script: |
make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}"
done
+ # Faketime for binaries
+ create_global_faketime_wrappers "${REFERENCE_DATETIME}"
+ create_per-host_faketime_wrappers "${REFERENCE_DATETIME}"
+
# Create the release tarball using (arbitrarily) the first host
./autogen.sh
CONFIG_SITE=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`/share/config.site ./configure --prefix=/
@@ -101,14 +127,24 @@ script: |
CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} CFLAGS="${HOST_CFLAGS}" CXXFLAGS="${HOST_CXXFLAGS}" LDFLAGS="${HOST_LDFLAGS}"
make ${MAKEOPTS}
make ${MAKEOPTS} -C src check-security
- make ${MAKEOPTS} -C src check-symbols
+
+ #TODO: This is a quick hack that disables symbol checking for arm.
+ # Instead, we should investigate why these are popping up.
+ # For aarch64, we'll need to bump up the min GLIBC version, as the abi
+ # support wasn't introduced until 2.17.
+ case $i in
+ aarch64-*) : ;;
+ arm-*) : ;;
+ *) make ${MAKEOPTS} -C src check-symbols ;;
+ esac
+
make install DESTDIR=${INSTALLPATH}
cd installed
find . -name "lib*.la" -delete
find . -name "lib*.a" -delete
rm -rf ${DISTNAME}/lib/pkgconfig
- find ${DISTNAME}/bin -type f -executable -exec objcopy --only-keep-debug {} {}.dbg \; -exec strip -s {} \; -exec objcopy --add-gnu-debuglink={}.dbg {} \;
- find ${DISTNAME}/lib -type f -exec objcopy --only-keep-debug {} {}.dbg \; -exec strip -s {} \; -exec objcopy --add-gnu-debuglink={}.dbg {} \;
+ find ${DISTNAME}/bin -type f -executable -exec ../contrib/devtools/split-debug.sh {} {} {}.dbg \;
+ find ${DISTNAME}/lib -type f -exec ../contrib/devtools/split-debug.sh {} {} {}.dbg \;
find ${DISTNAME} -not -name "*.dbg" | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}.tar.gz
find ${DISTNAME} -name "*.dbg" | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}-debug.tar.gz
cd ../../
@@ -116,8 +152,3 @@ script: |
done
mkdir -p $OUTDIR/src
mv $SOURCEDIST $OUTDIR/src
- mv ${OUTDIR}/${DISTNAME}-x86_64-*-debug.tar.gz ${OUTDIR}/${DISTNAME}-linux64-debug.tar.gz
- mv ${OUTDIR}/${DISTNAME}-i686-*-debug.tar.gz ${OUTDIR}/${DISTNAME}-linux32-debug.tar.gz
- mv ${OUTDIR}/${DISTNAME}-x86_64-*.tar.gz ${OUTDIR}/${DISTNAME}-linux64.tar.gz
- mv ${OUTDIR}/${DISTNAME}-i686-*.tar.gz ${OUTDIR}/${DISTNAME}-linux32.tar.gz
-
diff --git a/contrib/gitian-descriptors/gitian-osx-signer.yml b/contrib/gitian-descriptors/gitian-osx-signer.yml
index 0e56702dd7f1..ee73e6a1eae0 100644
--- a/contrib/gitian-descriptors/gitian-osx-signer.yml
+++ b/contrib/gitian-descriptors/gitian-osx-signer.yml
@@ -6,7 +6,6 @@ architectures:
- "amd64"
packages:
- "faketime"
-reference_datetime: "2017-01-01 00:00:00"
remotes:
- "url": "https://github.com/dashpay/dash-detached-sigs.git"
"dir": "signature"
diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml
index baac03ca14f5..29b8772c519b 100644
--- a/contrib/gitian-descriptors/gitian-osx.yml
+++ b/contrib/gitian-descriptors/gitian-osx.yml
@@ -5,7 +5,7 @@ suites:
- "trusty"
architectures:
- "amd64"
-packages:
+packages:
- "ca-certificates"
- "curl"
- "g++"
@@ -27,7 +27,6 @@ packages:
- "python-dev"
- "python-setuptools"
- "fonts-tuffy"
-reference_datetime: "2017-01-01 00:00:00"
remotes:
- "url": "https://github.com/dashpay/dash.git"
"dir": "dash"
@@ -54,29 +53,36 @@ script: |
export ZERO_AR_DATE=1
- # Create global faketime wrappers
+ function create_global_faketime_wrappers {
for prog in ${FAKETIME_PROGS}; do
echo '#!/bin/bash' > ${WRAP_DIR}/${prog}
echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog}
echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog}
- echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${prog}
+ echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog}
echo "\$REAL \$@" >> $WRAP_DIR/${prog}
chmod +x ${WRAP_DIR}/${prog}
done
+ }
- # Create per-host faketime wrappers
+ function create_per-host_faketime_wrappers {
for i in $HOSTS; do
for prog in ${FAKETIME_HOST_PROGS}; do
echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog}
echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog}
echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog}
- echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${i}-${prog}
+ echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog}
echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog}
chmod +x ${WRAP_DIR}/${i}-${prog}
done
done
+ }
+
export PATH=${WRAP_DIR}:${PATH}
+ # Faketime for depends so intermediate results are comparable
+ create_global_faketime_wrappers "2000-01-01 12:00:00"
+ create_per-host_faketime_wrappers "2000-01-01 12:00:00"
+
cd dash
BASEPREFIX=`pwd`/depends
@@ -88,6 +94,10 @@ script: |
make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}"
done
+ # Faketime for binaries
+ create_global_faketime_wrappers "${REFERENCE_DATETIME}"
+ create_per-host_faketime_wrappers "${REFERENCE_DATETIME}"
+
# Create the release tarball using (arbitrarily) the first host
./autogen.sh
CONFIG_SITE=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`/share/config.site ./configure --prefix=/
diff --git a/contrib/gitian-descriptors/gitian-win-signer.yml b/contrib/gitian-descriptors/gitian-win-signer.yml
index 5eda39ff6d5d..162ba965d085 100644
--- a/contrib/gitian-descriptors/gitian-win-signer.yml
+++ b/contrib/gitian-descriptors/gitian-win-signer.yml
@@ -7,7 +7,6 @@ architectures:
packages:
- "libssl-dev"
- "autoconf"
-reference_datetime: "2017-01-01 00:00:00"
remotes:
- "url": "https://github.com/dashpay/dash-detached-sigs.git"
"dir": "signature"
diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml
index f219f04217c8..299de65a8978 100755
--- a/contrib/gitian-descriptors/gitian-win.yml
+++ b/contrib/gitian-descriptors/gitian-win.yml
@@ -5,7 +5,7 @@ suites:
- "trusty"
architectures:
- "amd64"
-packages:
+packages:
- "curl"
- "g++"
- "git-core"
@@ -21,7 +21,6 @@ packages:
- "zip"
- "ca-certificates"
- "python"
-reference_datetime: "2017-01-01 00:00:00"
remotes:
- "url": "https://github.com/dashpay/dash.git"
"dir": "dash"
@@ -47,29 +46,31 @@ script: |
mkdir -p ${BASE_CACHE} ${SOURCES_PATH}
fi
- # Create global faketime wrappers
+ function create_global_faketime_wrappers {
for prog in ${FAKETIME_PROGS}; do
echo '#!/bin/bash' > ${WRAP_DIR}/${prog}
echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog}
echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog}
- echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${prog}
+ echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog}
echo "\$REAL \$@" >> $WRAP_DIR/${prog}
chmod +x ${WRAP_DIR}/${prog}
done
+ }
- # Create per-host faketime wrappers
+ function create_per-host_faketime_wrappers {
for i in $HOSTS; do
for prog in ${FAKETIME_HOST_PROGS}; do
echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog}
echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog}
echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog}
- echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${i}-${prog}
+ echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog}
echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog}
chmod +x ${WRAP_DIR}/${i}-${prog}
done
done
+ }
- # Create per-host linker wrapper
+ function create_per-host_linker_wrapper {
# This is only needed for trusty, as the mingw linker leaks a few bytes of
# heap, causing non-determinism. See discussion in https://github.com/bitcoin/bitcoin/pull/6900
for i in $HOSTS; do
@@ -85,15 +86,21 @@ script: |
echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog}
echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog}
echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog}
- echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${i}-${prog}
+ echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog}
echo "export COMPILER_PATH=${WRAP_DIR}/${i}" >> ${WRAP_DIR}/${i}-${prog}
echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog}
chmod +x ${WRAP_DIR}/${i}-${prog}
done
done
+ }
export PATH=${WRAP_DIR}:${PATH}
+ # Faketime for depends so intermediate results are comparable
+ create_global_faketime_wrappers "2000-01-01 12:00:00"
+ create_per-host_faketime_wrappers "2000-01-01 12:00:00"
+ create_per-host_linker_wrapper "2000-01-01 12:00:00"
+
cd dash
BASEPREFIX=`pwd`/depends
# Build dependencies for each host
@@ -101,6 +108,11 @@ script: |
make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}"
done
+ # Faketime for binaries
+ create_global_faketime_wrappers "${REFERENCE_DATETIME}"
+ create_per-host_faketime_wrappers "${REFERENCE_DATETIME}"
+ create_per-host_linker_wrapper "${REFERENCE_DATETIME}"
+
# Create the release tarball using (arbitrarily) the first host
./autogen.sh
CONFIG_SITE=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`/share/config.site ./configure --prefix=/
diff --git a/depends/Makefile b/depends/Makefile
index 3ddfc85a450d..dedb0674cf14 100644
--- a/depends/Makefile
+++ b/depends/Makefile
@@ -89,13 +89,17 @@ $(host_arch)_$(host_os)_id_string+=$(shell $(host_CXX) --version 2>/dev/null)
$(host_arch)_$(host_os)_id_string+=$(shell $(host_RANLIB) --version 2>/dev/null)
$(host_arch)_$(host_os)_id_string+=$(shell $(host_STRIP) --version 2>/dev/null)
-qt_packages_$(NO_QT) = $(qt_packages) $(qt_$(host_os)_packages)
-qt_native_packages_$(NO_QT) = $(qt_native_packages)
+qt_packages_$(NO_QT) = $(qt_packages) $(qt_$(host_os)_packages) $(qt_$(host_arch)_$(host_os)_packages)
wallet_packages_$(NO_WALLET) = $(wallet_packages)
upnp_packages_$(NO_UPNP) = $(upnp_packages)
packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(qt_packages_) $(wallet_packages_) $(upnp_packages_)
-native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages) $(qt_native_packages_)
+native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages)
+
+ifneq ($(qt_packages_),)
+native_packages += $(qt_native_packages)
+endif
+
all_packages = $(packages) $(native_packages)
meta_depends = Makefile funcs.mk builders/default.mk hosts/default.mk hosts/$(host_os).mk builders/$(build_os).mk
diff --git a/depends/config.guess b/depends/config.guess
index 373a659a0676..c4bd827a7bed 100755
--- a/depends/config.guess
+++ b/depends/config.guess
@@ -2,7 +2,7 @@
# Attempt to guess a canonical system name.
# Copyright 1992-2016 Free Software Foundation, Inc.
-timestamp='2016-02-11'
+timestamp='2016-05-15'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -186,9 +186,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
esac
# The Operating System including object format, if it has switched
- # to ELF recently, or will in the future.
+ # to ELF recently (or will in the future) and ABI.
case "${UNAME_MACHINE_ARCH}" in
- arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ earm*)
+ os=netbsdelf
+ ;;
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
eval $set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ELF__
@@ -386,7 +389,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# This test works for both compilers.
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
SUN_ARCH=x86_64
@@ -684,7 +687,7 @@ EOF
exit (0);
}
EOF
- (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
@@ -701,7 +704,7 @@ EOF
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
# => hppa64-hp-hpux11.23
- if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
grep -q __LP64__
then
HP_ARCH=hppa2.0w
@@ -900,7 +903,7 @@ EOF
exit ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
exit ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
@@ -1276,6 +1279,9 @@ EOF
SX-8R:SUPER-UX:*:*)
echo sx8r-nec-superux${UNAME_RELEASE}
exit ;;
+ SX-ACE:SUPER-UX:*:*)
+ echo sxace-nec-superux${UNAME_RELEASE}
+ exit ;;
Power*:Rhapsody:*:*)
echo powerpc-apple-rhapsody${UNAME_RELEASE}
exit ;;
@@ -1291,7 +1297,7 @@ EOF
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
case $UNAME_PROCESSOR in
@@ -1386,7 +1392,7 @@ EOF
echo i386-pc-xenix
exit ;;
i*86:skyos:*:*)
- echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
exit ;;
i*86:rdos:*:*)
echo ${UNAME_MACHINE}-pc-rdos
@@ -1405,18 +1411,17 @@ esac
cat >&2 < in order to provide the needed
-information to handle your system.
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary information to handle your system.
config.guess timestamp = $timestamp
diff --git a/depends/config.sub b/depends/config.sub
index 6223dde93191..6d86a1e2f77b 100755
--- a/depends/config.sub
+++ b/depends/config.sub
@@ -2,7 +2,7 @@
# Configuration validation subroutine script.
# Copyright 1992-2016 Free Software Foundation, Inc.
-timestamp='2016-01-01'
+timestamp='2016-05-10'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -1399,7 +1399,7 @@ case $os in
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
- | -onefs* | -tirtos*)
+ | -onefs* | -tirtos* | -phoenix*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1531,6 +1531,8 @@ case $os in
;;
-nacl*)
;;
+ -ios)
+ ;;
-none)
;;
*)
diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk
index 200d57314ea0..6c9876c2c7c7 100644
--- a/depends/packages/bdb.mk
+++ b/depends/packages/bdb.mk
@@ -14,7 +14,8 @@ endef
define $(package)_preprocess_cmds
sed -i.old 's/__atomic_compare_exchange/__atomic_compare_exchange_db/' dbinc/atomic.h && \
- sed -i.old 's/atomic_init/atomic_init_db/' dbinc/atomic.h mp/mp_region.c mp/mp_mvcc.c mp/mp_fget.c mutex/mut_method.c mutex/mut_tas.c
+ sed -i.old 's/atomic_init/atomic_init_db/' dbinc/atomic.h mp/mp_region.c mp/mp_mvcc.c mp/mp_fget.c mutex/mut_method.c mutex/mut_tas.c && \
+ cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub dist
endef
define $(package)_config_cmds
diff --git a/depends/packages/expat.mk b/depends/packages/expat.mk
index 1ac443537420..bd2927563850 100644
--- a/depends/packages/expat.mk
+++ b/depends/packages/expat.mk
@@ -1,8 +1,8 @@
package=expat
-$(package)_version=2.1.0
-$(package)_download_path=http://sourceforge.net/projects/expat/files/expat/$($(package)_version)
-$(package)_file_name=$(package)-$($(package)_version).tar.gz
-$(package)_sha256_hash=823705472f816df21c8f6aa026dd162b280806838bb55b3432b0fb1fcca7eb86
+$(package)_version=2.1.1
+$(package)_download_path=https://downloads.sourceforge.net/project/expat/expat/$($(package)_version)
+$(package)_file_name=$(package)-$($(package)_version).tar.bz2
+$(package)_sha256_hash=aff584e5a2f759dcfc6d48671e9529f6afe1e30b0cd6a4cec200cbe3f793de67
define $(package)_set_vars
$(package)_config_opts=--disable-static
diff --git a/depends/packages/freetype.mk b/depends/packages/freetype.mk
index f7d6e0f9fc58..7cea28ff0bbf 100644
--- a/depends/packages/freetype.mk
+++ b/depends/packages/freetype.mk
@@ -1,8 +1,8 @@
package=freetype
-$(package)_version=2.5.3
-$(package)_download_path=http://downloads.sourceforge.net/$(package)
+$(package)_version=2.6.3
+$(package)_download_path=http://download.savannah.gnu.org/releases/$(package)
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
-$(package)_sha256_hash=c0848b29d52ef3ca27ad92e08351f023c5e24ce8cea7d8fe69fc96358e65f75e
+$(package)_sha256_hash=371e707aa522acf5b15ce93f11183c725b8ed1ee8546d7b3af549863045863a2
define $(package)_set_vars
$(package)_config_opts=--without-zlib --without-png --disable-static
diff --git a/depends/packages/miniupnpc.mk b/depends/packages/miniupnpc.mk
index 45fa03631f89..e34cf7be2f1b 100644
--- a/depends/packages/miniupnpc.mk
+++ b/depends/packages/miniupnpc.mk
@@ -1,8 +1,8 @@
package=miniupnpc
-$(package)_version=1.9.20160209
+$(package)_version=2.0
$(package)_download_path=http://miniupnp.free.fr/files
$(package)_file_name=$(package)-$($(package)_version).tar.gz
-$(package)_sha256_hash=572171eacc1d72537ce47b6f4571260757ab7bcfdaf54c3a55c7f88594d94b6f
+$(package)_sha256_hash=d434ceb8986efbe199c5ca53f90ed53eab290b1e6d0530b717eb6fa49d61f93b
define $(package)_set_vars
$(package)_build_opts=CC="$($(package)_cc)"
diff --git a/depends/packages/native_ccache.mk b/depends/packages/native_ccache.mk
index 027174479ada..cd20fbe1e12b 100644
--- a/depends/packages/native_ccache.mk
+++ b/depends/packages/native_ccache.mk
@@ -1,8 +1,8 @@
package=native_ccache
-$(package)_version=3.2.4
+$(package)_version=3.2.5
$(package)_download_path=https://samba.org/ftp/ccache
$(package)_file_name=ccache-$($(package)_version).tar.bz2
-$(package)_sha256_hash=ffeb967edb549e67da0bd5f44f729a2022de9fdde65dfd80d2a7204d7f75332e
+$(package)_sha256_hash=7a553809e90faf9de3a23ee9c5b5f786cfd4836bf502744bedb824a24bee1097
define $(package)_set_vars
$(package)_config_opts=
diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk
index 59b009b66a27..ac43ef4a2e30 100644
--- a/depends/packages/packages.mk
+++ b/depends/packages/packages.mk
@@ -6,7 +6,9 @@ native_packages := native_ccache native_comparisontool
qt_native_packages = native_protobuf
qt_packages = qrencode protobuf
-qt_linux_packages= qt expat dbus libxcb xcb_proto libXau xproto freetype fontconfig libX11 xextproto libXext xtrans
+qt_x86_64_linux_packages:=qt expat dbus libxcb xcb_proto libXau xproto freetype fontconfig libX11 xextproto libXext xtrans
+qt_i686_linux_packages:=$(qt_x86_64_linux_packages)
+
qt_darwin_packages=qt
qt_mingw32_packages=qt
diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk
index b3f18db05696..f8901f72c26c 100644
--- a/depends/packages/zeromq.mk
+++ b/depends/packages/zeromq.mk
@@ -1,11 +1,11 @@
package=zeromq
-$(package)_version=4.0.7
+$(package)_version=4.1.4
$(package)_download_path=http://download.zeromq.org
$(package)_file_name=$(package)-$($(package)_version).tar.gz
-$(package)_sha256_hash=e00b2967e074990d0538361cc79084a0a92892df2c6e7585da34e4c61ee47b03
+$(package)_sha256_hash=e99f44fde25c2e4cb84ce440f87ca7d3fe3271c2b8cfbc67d55e4de25e6fe378
define $(package)_set_vars
- $(package)_config_opts=--without-documentation --disable-shared
+ $(package)_config_opts=--without-documentation --disable-shared --without-libsodium
$(package)_config_opts_linux=--with-pic
$(package)_cxxflags=-std=c++11
endef
@@ -15,11 +15,11 @@ define $(package)_config_cmds
endef
define $(package)_build_cmds
- $(MAKE) -C src
+ $(MAKE) libzmq.la
endef
define $(package)_stage_cmds
- $(MAKE) -C src DESTDIR=$($(package)_staging_dir) install
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install-libLTLIBRARIES install-includeHEADERS install-pkgconfigDATA
endef
define $(package)_postprocess_cmds
diff --git a/doc/bips.md b/doc/bips.md
index b8efabbcf251..b4b62e781ec6 100644
--- a/doc/bips.md
+++ b/doc/bips.md
@@ -1,5 +1,6 @@
-BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.12.0**):
+BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.13.0**):
+* [`BIP 9`](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki): The changes allowing multiple soft-forks to be deployed in parallel have been implemented since **v0.12.1** ([PR #7575](https://github.com/bitcoin/bitcoin/pull/7575))
* [`BIP 11`](https://github.com/bitcoin/bips/blob/master/bip-0011.mediawiki): Multisig outputs are standard since **v0.6.0** ([PR #669](https://github.com/bitcoin/bitcoin/pull/669)).
* [`BIP 13`](https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki): The address format for P2SH addresses has been implemented since **v0.6.0** ([PR #669](https://github.com/bitcoin/bitcoin/pull/669)).
* [`BIP 14`](https://github.com/bitcoin/bips/blob/master/bip-0014.mediawiki): The subversion string is being used as User Agent since **v0.6.0** ([PR #669](https://github.com/bitcoin/bitcoin/pull/669)).
@@ -16,8 +17,11 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.12.0**):
* [`BIP 61`](https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki): The 'reject' protocol message (and the protocol version bump to 70002) was added in **v0.9.0** ([PR #3185](https://github.com/bitcoin/bitcoin/pull/3185)).
* [`BIP 65`](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki): The CHECKLOCKTIMEVERIFY softfork was merged in **v0.12.0** ([PR #6351](https://github.com/bitcoin/bitcoin/pull/6351)), and backported to **v0.11.2** and **v0.10.4**. Mempool-only CLTV was added in [PR #6124](https://github.com/bitcoin/bitcoin/pull/6124).
* [`BIP 66`](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki): The strict DER rules and associated version 3 blocks have been implemented since **v0.10.0** ([PR #5713](https://github.com/bitcoin/bitcoin/pull/5713)).
+* [`BIP 68`](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki): Sequence locks have been implemented as of **v0.12.1** ([PR #7184](https://github.com/bitcoin/bitcoin/pull/7184)).
* [`BIP 70`](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki) [`71`](https://github.com/bitcoin/bips/blob/master/bip-0071.mediawiki) [`72`](https://github.com/bitcoin/bips/blob/master/bip-0072.mediawiki): Payment Protocol support has been available in Bitcoin Core GUI since **v0.9.0** ([PR #5216](https://github.com/bitcoin/bitcoin/pull/5216)).
* [`BIP 111`](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki): `NODE_BLOOM` service bit added, and enforced for all peer versions as of **v0.13.0** ([PR #6579](https://github.com/bitcoin/bitcoin/pull/6579) and [PR #6641](https://github.com/bitcoin/bitcoin/pull/6641)).
+* [`BIP 112`](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki): The CHECKSEQUENCEVERIFY opcode has been implemented since **v0.12.1** ([PR #7524](https://github.com/bitcoin/bitcoin/pull/7524)).
+* [`BIP 113`](https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki): Median time past lock-time calculations have been implemented since **v0.12.1** ([PR #6566](https://github.com/bitcoin/bitcoin/pull/6566)).
* [`BIP 125`](https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki): Opt-in full replace-by-fee signaling honoured in mempool and mining as of **v0.12.0** ([PR 6871](https://github.com/bitcoin/bitcoin/pull/6871)).
* [`BIP 130`](https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki): direct headers announcement is negotiated with peer versions `>=70012` as of **v0.12.0** ([PR 6494](https://github.com/bitcoin/bitcoin/pull/6494)).
* [`BIP 133`](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki): feefilter messages are respected and sent for peer versions `>=70013` as of **v0.13.0** ([PR 7542](https://github.com/bitcoin/bitcoin/pull/7542)).
diff --git a/doc/build-osx.md b/doc/build-osx.md
index f0793b446ce6..94d442f174f0 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -1,129 +1,93 @@
Mac OS X Build Instructions and Notes
====================================
-This guide will show you how to build Dash Core for OS X.
-
-Notes
------
-
-* Tested on OS X 10.7 through 10.11 on 64-bit Intel processors only.
-
-* All of the commands should be executed in a Terminal application. The
-built-in one is located in `/Applications/Utilities`.
+The commands in this guide should be executed in a Terminal application.
+The built-in one is located in `/Applications/Utilities/Terminal.app`.
Preparation
-----------
+Download and install [Xcode](https://developer.apple.com/xcode/download).
-You need to install Xcode with all the options checked so that the compiler
-and everything is available in /usr not just /Developer. Xcode should be
-available on your OS X installation media, but if not, you can get the
-current version from https://developer.apple.com/xcode/. If you install
-Xcode 4.3 or later, you'll need to install its command line tools. This can
-be done in `Xcode > Preferences > Downloads > Components` and generally must
-be re-done or updated every time Xcode is updated.
-
-You will also need to install [Homebrew](http://brew.sh) in order to install library
-dependencies.
+Once installed, run `xcode-select --install` to install the OS X command line tools.
-The installation of the actual dependencies is covered in the instructions
-sections below.
+Install [Homebrew](http://brew.sh).
-Instructions: Homebrew
+Dependencies
----------------------
-#### Install dependencies using Homebrew
+ brew install automake berkeley-db4 libtool boost --c++11 miniupnpc openssl pkg-config protobuf --c++11 qt5 libevent
- brew install autoconf automake berkeley-db4 libtool boost miniupnpc openssl pkg-config protobuf libevent qt
+NOTE: Building with Qt4 is still supported, however, doing so could result in a broken UI. Therefore, building with Qt5 is recommended.
-NOTE: Building with Qt4 is still supported, however, doing so could result in a broken UI. Therefore, building with Qt5 is recommended. Be aware that Qt5 5.7+ requires C++11 compiler support.
-
-### Building Dash Core
+Build Dash Core
+------------------------
-1. Clone the GitHub tree to get the source code and go into the directory.
+1. Clone the Dash Core source code and cd into `dash`
- git clone https://github.com/dashpay/dash.git
+ git clone https://github.com/dashpay/dash
cd dash
2. Build Dash Core:
- This will configure and build the headless dash binaries as well as the gui (if Qt is found).
- You can disable the gui build by passing `--without-gui` to configure.
+
+ Configure and build the headless dash binaries as well as the GUI (if Qt is found).
+
+ You can disable the GUI build by passing `--without-gui` to configure.
./autogen.sh
./configure
make
-3. It is also a good idea to build and run the unit tests:
+3. It is recommended to build and run the unit tests:
make check
-4. (Optional) You can also install dashd to your path:
-
- make install
-
-Use Qt Creator as IDE
-------------------------
-You can use Qt Creator as IDE, for debugging and for manipulating forms, etc.
-Download Qt Creator from https://www.qt.io/download/. Download the "community edition" and only install Qt Creator (uncheck the rest during the installation process).
-
-1. Make sure you installed everything through Homebrew mentioned above
-2. Do a proper ./configure --enable-debug
-3. In Qt Creator do "New Project" -> Import Project -> Import Existing Project
-4. Enter "dash-qt" as project name, enter src/qt as location
-5. Leave the file selection as it is
-6. Confirm the "summary page"
-7. In the "Projects" tab select "Manage Kits..."
-8. Select the default "Desktop" kit and select "Clang (x86 64bit in /usr/bin)" as compiler
-9. Select LLDB as debugger (you might need to set the path to your installation)
-10. Start debugging with Qt Creator
-
-Creating a release build
-------------------------
-You can ignore this section if you are building `dashd` for your own use.
-
-dashd/dash-cli binaries are not included in the Dash-Qt.app bundle.
-
-If you are building `dashd` or `Dash Core` for others, your build machine should be set up
-as follows for maximum compatibility:
+4. You can also create a .dmg that contains the .app bundle (optional):
-All dependencies should be compiled with these flags:
-
- -mmacosx-version-min=10.7
- -arch x86_64
- -isysroot $(xcode-select --print-path)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk
-
-Once dependencies are compiled, see [doc/release-process.md](release-process.md) for how the Dash Core
-bundle is packaged and signed to create the .dmg disk image that is distributed.
+ make deploy
Running
-------
-It's now available at `./dashd`, provided that you are still in the `src`
-directory. We have to first create the RPC configuration file, though.
+Dash Core is now available at `./src/dashd`
-Run `./dashd` to get the filename where it should be put, or just try these
-commands:
+Before running, it's recommended you create an RPC configuration file.
echo -e "rpcuser=dashrpc\nrpcpassword=$(xxd -l 16 -p /dev/urandom)" > "/Users/${USER}/Library/Application Support/DashCore/dash.conf"
+
chmod 600 "/Users/${USER}/Library/Application Support/DashCore/dash.conf"
-The next time you run it, it will start downloading the blockchain, but it won't
-output anything while it's doing this. This process may take several hours;
-you can monitor its process by looking at the debug.log file, like this:
+The first time you run dashd, it will start downloading the blockchain. This process could take several hours.
+
+You can monitor the download process by looking at the debug.log file:
tail -f $HOME/Library/Application\ Support/DashCore/debug.log
Other commands:
-------
- ./dashd -daemon # to start the dash daemon.
- ./dash-cli --help # for a list of command-line options.
- ./dash-cli help # When the daemon is running, to get a list of RPC commands
+ ./src/dashd -daemon # Starts the dash daemon.
+ ./src/dash-cli --help # Outputs a list of command-line options.
+ ./src/dash-cli help # Outputs a list of RPC commands when the daemon is running.
+
+Using Qt Creator as IDE
+------------------------
+You can use Qt Creator as an IDE, for dash development.
+Download and install the community edition of [Qt Creator](https://www.qt.io/download/).
+Uncheck everything except Qt Creator during the installation process.
-Using Qt official installer while building
-------------------------------------------
+1. Make sure you installed everything through Homebrew mentioned above
+2. Do a proper ./configure --enable-debug
+3. In Qt Creator do "New Project" -> Import Project -> Import Existing Project
+4. Enter "dash-qt" as project name, enter src/qt as location
+5. Leave the file selection as it is
+6. Confirm the "summary page"
+7. In the "Projects" tab select "Manage Kits..."
+8. Select the default "Desktop" kit and select "Clang (x86 64bit in /usr/bin)" as compiler
+9. Select LLDB as debugger (you might need to set the path to your installation)
+10. Start debugging with Qt Creator
+
+Notes
+-----
+
+* Tested on OS X 10.7 through 10.11 on 64-bit Intel processors only.
-If you prefer to use the latest Qt installed from the official binary
-installer over the brew version, you have to make several changes to
-the installed tree and its binaries (all these changes are contained
-in the brew version already). The changes needed are described in
-[#7714](https://github.com/bitcoin/bitcoin/issues/7714). We do not
-support building Dash Core this way though.
+* Building with downloaded Qt binaries is not officially supported. See the notes in [#7714](https://github.com/bitcoin/bitcoin/issues/7714)
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 2bcc9750c6d7..f27264d35478 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -268,7 +268,7 @@ General C++
the `.h` to the `.cpp` should not result in build errors
- Use the RAII (Resource Acquisition Is Initialization) paradigm where possible. For example by using
- `scoped_pointer` for allocations in a function.
+ `unique_ptr` for allocations in a function.
- *Rationale*: This avoids memory and resource leaks, and ensures exception safety
@@ -287,10 +287,9 @@ C++ data structures
- *Rationale*: Behavior is undefined. In C++ parlor this means "may reformat
the universe", in practice this has resulted in at least one hard-to-debug crash bug
-- Watch out for vector out-of-bounds exceptions. `&vch[0]` is illegal for an
- empty vector, `&vch[vch.size()]` is always illegal. Use `begin_ptr(vch)` and
- `end_ptr(vch)` to get the begin and end pointer instead (defined in
- `serialize.h`)
+- Watch out for out-of-bounds vector access. `&vch[vch.size()]` is illegal,
+ including `&vch[0]` for an empty vector. Use `vch.data()` and `vch.data() +
+ vch.size()` instead.
- Vector bounds checking is only enabled in debug mode. Do not rely on it
@@ -326,7 +325,7 @@ Strings and formatting
buffer overflows and surprises with `\0` characters. Also some C string manipulations
tend to act differently depending on platform, or even the user locale
-- Use `ParseInt32`, `ParseInt64`, `ParseDouble` from `utilstrencodings.h` for number parsing
+- Use `ParseInt32`, `ParseInt64`, `ParseUInt32`, `ParseUInt64`, `ParseDouble` from `utilstrencodings.h` for number parsing
- *Rationale*: These functions do overflow checking, and avoid pesky locale issues
@@ -383,3 +382,51 @@ GUI
- *Rationale*: Model classes pass through events and data from the core, they
should not interact with the user. That's where View classes come in. The converse also
holds: try to not directly access core data structures from Views.
+
+Git and github tips
+---------------------
+
+- For resolving merge/rebase conflicts, it can be useful to enable diff3 style using
+ `git config merge.conflictstyle diff3`. Instead of
+
+ <<<
+ yours
+ ===
+ theirs
+ >>>
+
+ you will see
+
+ <<<
+ yours
+ |||
+ original
+ ===
+ theirs
+ >>>
+
+ This may make it much clearer what caused the conflict. In this style, you can often just look
+ at what changed between *original* and *theirs*, and mechanically apply that to *yours* (or the other way around).
+
+- When reviewing patches which change indentation in C++ files, use `git diff -w` and `git show -w`. This makes
+ the diff algorithm ignore whitespace changes. This feature is also available on github.com, by adding `?w=1`
+ at the end of any URL which shows a diff.
+
+- When reviewing patches that change symbol names in many places, use `git diff --word-diff`. This will instead
+ of showing the patch as deleted/added *lines*, show deleted/added *words*.
+
+- When reviewing patches that move code around, try using
+ `git diff --patience commit~:old/file.cpp commit:new/file/name.cpp`, and ignoring everything except the
+ moved body of code which should show up as neither `+` or `-` lines. In case it was not a pure move, this may
+ even work when combined with the `-w` or `--word-diff` options described above.
+
+- When looking at other's pull requests, it may make sense to add the following section to your `.git/config`
+ file:
+
+ [remote "upstream-pull"]
+ fetch = +refs/pull/*:refs/remotes/upstream-pull/*
+ url = git@github.com:bitcoin/bitcoin.git
+
+ This will add an `upstream-pull` remote to your git repository, which can be fetched using `git fetch --all`
+ or `git fetch upstream-pull`. Afterwards, you can use `upstream-pull/NUMBER/head` in arguments to `git show`,
+ `git checkout` and anywhere a commit id would be acceptable to see the changes from pull request NUMBER.
diff --git a/doc/gitian-building.md b/doc/gitian-building.md
index 5fb60f987090..ef63605e326c 100644
--- a/doc/gitian-building.md
+++ b/doc/gitian-building.md
@@ -95,11 +95,11 @@ After creating the VM, we need to configure it.
- Click `Ok` twice to save.
-Get the [Debian 8.x net installer](http://cdimage.debian.org/debian-cd/8.4.0/amd64/iso-cd/debian-8.4.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)).
+Get the [Debian 8.x net installer](http://cdimage.debian.org/debian-cd/8.5.0/amd64/iso-cd/debian-8.5.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)).
This DVD image can be validated using a SHA256 hashing tool, for example on
Unixy OSes by entering the following in a terminal:
- echo "7a6b418e6a4ee3ca75dda04d79ed96c9e2c33bb0c703ca7e40c6374ab4590748 debian-8.4.0-amd64-netinst.iso" | sha256sum -c
+ echo "ad4e8c27c561ad8248d5ebc1d36eb172f884057bfeb2c22ead823f59fa8c3dff debian-8.5.0-amd64-netinst.iso" | sha256sum -c
# (must return OK)
Then start the VM. On the first launch you will be asked for a CD or DVD image. Choose the downloaded iso.
diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py
index 6afb8ccec78b..ab8cea220d53 100755
--- a/qa/pull-tester/rpc-tests.py
+++ b/qa/pull-tester/rpc-tests.py
@@ -29,6 +29,7 @@
import tempfile
import re
+sys.path.append("qa/pull-tester/")
from tests_config import *
BOLD = ("","")
@@ -37,7 +38,7 @@
# terminal via ANSI escape sequences:
BOLD = ('\033[0m', '\033[1m')
-RPC_TESTS_DIR = BUILDDIR + '/qa/rpc-tests/'
+RPC_TESTS_DIR = SRCDIR + '/qa/rpc-tests/'
#If imported values are not defined then set to zero (or disabled)
if 'ENABLE_WALLET' not in vars():
diff --git a/qa/pull-tester/tests_config.py.in b/qa/pull-tester/tests_config.py.in
index 2356b5200ebf..a0d0a3d98a86 100644
--- a/qa/pull-tester/tests_config.py.in
+++ b/qa/pull-tester/tests_config.py.in
@@ -3,6 +3,7 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+SRCDIR="@abs_top_srcdir@"
BUILDDIR="@abs_top_builddir@"
EXEEXT="@EXEEXT@"
diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py
index 0ca1a29ba054..4ceb5b0867d3 100755
--- a/qa/rpc-tests/fundrawtransaction.py
+++ b/qa/rpc-tests/fundrawtransaction.py
@@ -58,7 +58,6 @@ def run_test(self):
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 50)
- self.sync_all()
self.nodes[0].generate(1)
self.sync_all()
@@ -569,7 +568,6 @@ def run_test(self):
self.nodes[1].walletpassphrase("test", 100)
signedTx = self.nodes[1].signrawtransaction(fundedTx['hex'])
txId = self.nodes[1].sendrawtransaction(signedTx['hex'])
- self.sync_all()
self.nodes[1].generate(1)
self.sync_all()
@@ -588,7 +586,6 @@ def run_test(self):
for i in range(0,20):
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
- self.sync_all()
self.nodes[0].generate(1)
self.sync_all()
@@ -619,7 +616,6 @@ def run_test(self):
for i in range(0,20):
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
- self.sync_all()
self.nodes[0].generate(1)
self.sync_all()
@@ -693,7 +689,25 @@ def run_test(self):
signedtx = self.nodes[0].signrawtransaction(signedtx["hex"])
assert(signedtx["complete"])
self.nodes[0].sendrawtransaction(signedtx["hex"])
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ #######################
+ # Test feeRate option #
+ #######################
+
+ # Make sure there is exactly one input so coin selection can't skew the result
+ assert_equal(len(self.nodes[3].listunspent(1)), 1)
+ inputs = []
+ outputs = {self.nodes[2].getnewaddress() : 1}
+ rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
+ result = self.nodes[3].fundrawtransaction(rawtx) # uses min_relay_tx_fee (set by settxfee)
+ result2 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2*min_relay_tx_fee})
+ result3 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 10*min_relay_tx_fee})
+ result_fee_rate = result['fee'] * 1000 / count_bytes(result['hex'])
+ assert_fee_amount(result2['fee'], count_bytes(result2['hex']), 2 * result_fee_rate)
+ assert_fee_amount(result3['fee'], count_bytes(result3['hex']), 10 * result_fee_rate)
if __name__ == '__main__':
RawTransactionsTest().main()
diff --git a/qa/rpc-tests/mempool_packages.py b/qa/rpc-tests/mempool_packages.py
index 693ff593b348..45dc0e65c43c 100755
--- a/qa/rpc-tests/mempool_packages.py
+++ b/qa/rpc-tests/mempool_packages.py
@@ -65,7 +65,14 @@ def run_test(self):
descendant_fees = 0
descendant_size = 0
+ descendants = []
+ ancestors = list(chain)
for x in reversed(chain):
+ # Check that getmempoolentry is consistent with getrawmempool
+ entry = self.nodes[0].getmempoolentry(x)
+ assert_equal(entry, mempool[x])
+
+ # Check that the descendant calculations are correct
assert_equal(mempool[x]['descendantcount'], descendant_count)
descendant_fees += mempool[x]['fee']
assert_equal(mempool[x]['modifiedfee'], mempool[x]['fee'])
@@ -74,6 +81,27 @@ def run_test(self):
assert_equal(mempool[x]['descendantsize'], descendant_size)
descendant_count += 1
+ # Check that getmempooldescendants is correct
+ assert_equal(sorted(descendants), sorted(self.nodes[0].getmempooldescendants(x)))
+ descendants.append(x)
+
+ # Check that getmempoolancestors is correct
+ ancestors.remove(x)
+ assert_equal(sorted(ancestors), sorted(self.nodes[0].getmempoolancestors(x)))
+
+ # Check that getmempoolancestors/getmempooldescendants correctly handle verbose=true
+ v_ancestors = self.nodes[0].getmempoolancestors(chain[-1], True)
+ assert_equal(len(v_ancestors), len(chain)-1)
+ for x in v_ancestors.keys():
+ assert_equal(mempool[x], v_ancestors[x])
+ assert(chain[-1] not in v_ancestors.keys())
+
+ v_descendants = self.nodes[0].getmempooldescendants(chain[0], True)
+ assert_equal(len(v_descendants), len(chain)-1)
+ for x in v_descendants.keys():
+ assert_equal(mempool[x], v_descendants[x])
+ assert(chain[0] not in v_descendants.keys())
+
# Check that descendant modified fees includes fee deltas from
# prioritisetransaction
self.nodes[0].prioritisetransaction(chain[-1], 0, 1000)
diff --git a/qa/rpc-tests/p2p-fullblocktest.py b/qa/rpc-tests/p2p-fullblocktest.py
index 17244151bba8..501a3ff97291 100755
--- a/qa/rpc-tests/p2p-fullblocktest.py
+++ b/qa/rpc-tests/p2p-fullblocktest.py
@@ -9,7 +9,8 @@
from test_framework.blocktools import *
import time
from test_framework.key import CECKey
-from test_framework.script import CScript, SignatureHash, SIGHASH_ALL, OP_TRUE, OP_FALSE
+from test_framework.script import *
+import struct
class PreviousSpendableOutput(object):
def __init__(self, tx = CTransaction(), n = -1):
@@ -24,10 +25,36 @@ def __init__(self, tx = CTransaction(), n = -1):
each test.
'''
+def hash160(s):
+ return hashlib.new('ripemd160', sha256(s)).digest()
+
+# Use this class for tests that require behavior other than normal "mininode" behavior.
+# For now, it is used to serialize a bloated varint (b64).
+class CBrokenBlock(CBlock):
+ def __init__(self, header=None):
+ super(CBrokenBlock, self).__init__(header)
+
+ def initialize(self, base_block):
+ self.vtx = copy.deepcopy(base_block.vtx)
+ self.hashMerkleRoot = self.calc_merkle_root()
+
+ def serialize(self):
+ r = b""
+ r += super(CBlock, self).serialize()
+ r += struct.pack(" b1 (0) -> b2 (1)
- out0 = get_spendable_output()
- block(1, spend=out0)
+ block(1, spend=out[0])
save_spendable_output()
yield accepted()
- out1 = get_spendable_output()
- b2 = block(2, spend=out1)
+ block(2, spend=out[1])
yield accepted()
-
+ save_spendable_output()
# so fork like this:
- #
+ #
# genesis -> b1 (0) -> b2 (1)
# \-> b3 (1)
- #
+ #
# Nothing should happen at this point. We saw b2 first so it takes priority.
tip(1)
- b3 = block(3, spend=out1)
- txout_b3 = PreviousSpendableOutput(b3.vtx[1], 1)
+ b3 = block(3, spend=out[1])
+ txout_b3 = PreviousSpendableOutput(b3.vtx[1], 0)
yield rejected()
# Now we add another block to make the alternative chain longer.
- #
+ #
# genesis -> b1 (0) -> b2 (1)
# \-> b3 (1) -> b4 (2)
- out2 = get_spendable_output()
- block(4, spend=out2)
+ block(4, spend=out[2])
yield accepted()
@@ -198,46 +237,41 @@ def update_block(block_number, new_transactions):
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
# \-> b3 (1) -> b4 (2)
tip(2)
- block(5, spend=out2)
+ block(5, spend=out[2])
save_spendable_output()
yield rejected()
- out3 = get_spendable_output()
- block(6, spend=out3)
+ block(6, spend=out[3])
yield accepted()
-
# Try to create a fork that double-spends
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
# \-> b7 (2) -> b8 (4)
# \-> b3 (1) -> b4 (2)
tip(5)
- block(7, spend=out2)
+ block(7, spend=out[2])
yield rejected()
- out4 = get_spendable_output()
- block(8, spend=out4)
+ block(8, spend=out[4])
yield rejected()
-
# Try to create a block that has too much fee
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
# \-> b9 (4)
# \-> b3 (1) -> b4 (2)
tip(6)
- block(9, spend=out4, additional_coinbase_value=1)
+ block(9, spend=out[4], additional_coinbase_value=1)
yield rejected(RejectResult(16, b'bad-cb-amount'))
-
# Create a fork that ends in a block with too much fee (the one that causes the reorg)
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
# \-> b10 (3) -> b11 (4)
# \-> b3 (1) -> b4 (2)
tip(5)
- block(10, spend=out3)
+ block(10, spend=out[3])
yield rejected()
- block(11, spend=out4, additional_coinbase_value=1)
+ block(11, spend=out[4], additional_coinbase_value=1)
yield rejected(RejectResult(16, b'bad-cb-amount'))
@@ -247,19 +281,17 @@ def update_block(block_number, new_transactions):
# (b12 added last)
# \-> b3 (1) -> b4 (2)
tip(5)
- b12 = block(12, spend=out3)
+ b12 = block(12, spend=out[3])
save_spendable_output()
- #yield TestInstance([[b12, False]])
- b13 = block(13, spend=out4)
+ b13 = block(13, spend=out[4])
# Deliver the block header for b12, and the block b13.
# b13 should be accepted but the tip won't advance until b12 is delivered.
yield TestInstance([[CBlockHeader(b12), None], [b13, False]])
save_spendable_output()
- out5 = get_spendable_output()
# b14 is invalid, but the node won't know that until it tries to connect
# Tip still can't advance because b12 is missing
- block(14, spend=out5, additional_coinbase_value=1)
+ block(14, spend=out[5], additional_coinbase_value=1)
yield rejected()
yield TestInstance([[b12, True, b13.sha256]]) # New tip should be b13.
@@ -268,18 +300,18 @@ def update_block(block_number, new_transactions):
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
# \-> b12 (3) -> b13 (4) -> b15 (5) -> b16 (6)
# \-> b3 (1) -> b4 (2)
-
+
# Test that a block with a lot of checksigs is okay
- lots_of_checksigs = CScript([OP_CHECKSIG] * (1000000 // 50 - 1))
+ lots_of_checksigs = CScript([OP_CHECKSIG] * (MAX_BLOCK_SIGOPS - 1))
tip(13)
- block(15, spend=out5, script=lots_of_checksigs)
+ block(15, spend=out[5], script=lots_of_checksigs)
yield accepted()
+ save_spendable_output()
# Test that a block with too many checksigs is rejected
- out6 = get_spendable_output()
- too_many_checksigs = CScript([OP_CHECKSIG] * (1000000 // 50))
- block(16, spend=out6, script=too_many_checksigs)
+ too_many_checksigs = CScript([OP_CHECKSIG] * (MAX_BLOCK_SIGOPS))
+ block(16, spend=out[6], script=too_many_checksigs)
yield rejected(RejectResult(16, b'bad-blk-sigops'))
@@ -300,7 +332,7 @@ def update_block(block_number, new_transactions):
block(18, spend=txout_b3)
yield rejected()
- block(19, spend=out6)
+ block(19, spend=out[6])
yield rejected()
# Attempt to spend a coinbase at depth too low
@@ -308,8 +340,7 @@ def update_block(block_number, new_transactions):
# \-> b12 (3) -> b13 (4) -> b15 (5) -> b20 (7)
# \-> b3 (1) -> b4 (2)
tip(15)
- out7 = get_spendable_output()
- block(20, spend=out7)
+ block(20, spend=out[7])
yield rejected(RejectResult(16, b'bad-txns-premature-spend-of-coinbase'))
# Attempt to spend a coinbase at depth too low (on a fork this time)
@@ -318,10 +349,10 @@ def update_block(block_number, new_transactions):
# \-> b21 (6) -> b22 (5)
# \-> b3 (1) -> b4 (2)
tip(13)
- block(21, spend=out6)
+ block(21, spend=out[6])
yield rejected()
- block(22, spend=out5)
+ block(22, spend=out[5])
yield rejected()
# Create a block on either side of MAX_BLOCK_SIZE and make sure its accepted/rejected
@@ -330,21 +361,21 @@ def update_block(block_number, new_transactions):
# \-> b24 (6) -> b25 (7)
# \-> b3 (1) -> b4 (2)
tip(15)
- b23 = block(23, spend=out6)
- old_hash = b23.sha256
+ b23 = block(23, spend=out[6])
tx = CTransaction()
script_length = MAX_BLOCK_SIZE - len(b23.serialize()) - 69
script_output = CScript([b'\x00' * script_length])
tx.vout.append(CTxOut(0, script_output))
- tx.vin.append(CTxIn(COutPoint(b23.vtx[1].sha256, 1)))
+ tx.vin.append(CTxIn(COutPoint(b23.vtx[1].sha256, 0)))
b23 = update_block(23, [tx])
# Make sure the math above worked out to produce a max-sized block
assert_equal(len(b23.serialize()), MAX_BLOCK_SIZE)
yield accepted()
+ save_spendable_output()
# Make the next block one byte bigger and check that it fails
tip(15)
- b24 = block(24, spend=out6)
+ b24 = block(24, spend=out[6])
script_length = MAX_BLOCK_SIZE - len(b24.serialize()) - 69
script_output = CScript([b'\x00' * (script_length+1)])
tx.vout = [CTxOut(0, script_output)]
@@ -352,7 +383,7 @@ def update_block(block_number, new_transactions):
assert_equal(len(b24.serialize()), MAX_BLOCK_SIZE+1)
yield rejected(RejectResult(16, b'bad-blk-length'))
- b25 = block(25, spend=out7)
+ block(25, spend=out[7])
yield rejected()
# Create blocks with a coinbase input script size out of range
@@ -361,7 +392,7 @@ def update_block(block_number, new_transactions):
# \-> ... (6) -> ... (7)
# \-> b3 (1) -> b4 (2)
tip(15)
- b26 = block(26, spend=out6)
+ b26 = block(26, spend=out[6])
b26.vtx[0].vin[0].scriptSig = b'\x00'
b26.vtx[0].rehash()
# update_block causes the merkle root to get updated, even with no new
@@ -370,23 +401,20 @@ def update_block(block_number, new_transactions):
yield rejected(RejectResult(16, b'bad-cb-length'))
# Extend the b26 chain to make sure bitcoind isn't accepting b26
- b27 = block(27, spend=out7)
- yield rejected()
+ b27 = block(27, spend=out[7])
+ yield rejected(RejectResult(16, b'bad-prevblk'))
# Now try a too-large-coinbase script
tip(15)
- b28 = block(28, spend=out6)
+ b28 = block(28, spend=out[6])
b28.vtx[0].vin[0].scriptSig = b'\x00' * 101
b28.vtx[0].rehash()
b28 = update_block(28, [])
yield rejected(RejectResult(16, b'bad-cb-length'))
- # Extend the b28 chain to make sure bitcoind isn't accepted b28
- b29 = block(29, spend=out7)
- # TODO: Should get a reject message back with "bad-prevblk", except
- # there's a bug that prevents this from being detected. Just note
- # failure for now, and add the reject result later.
- yield rejected()
+ # Extend the b28 chain to make sure bitcoind isn't accepting b28
+ b29 = block(29, spend=out[7])
+ yield rejected(RejectResult(16, b'bad-prevblk'))
# b30 has a max-sized coinbase scriptSig.
tip(23)
@@ -395,6 +423,871 @@ def update_block(block_number, new_transactions):
b30.vtx[0].rehash()
b30 = update_block(30, [])
yield accepted()
+ save_spendable_output()
+
+ # b31 - b35 - check sigops of OP_CHECKMULTISIG / OP_CHECKMULTISIGVERIFY / OP_CHECKSIGVERIFY
+ #
+ # genesis -> ... -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10)
+ # \-> b36 (11)
+ # \-> b34 (10)
+ # \-> b32 (9)
+ #
+
+ # MULTISIG: each op code counts as 20 sigops. To create the edge case, pack another 19 sigops at the end.
+ lots_of_multisigs = CScript([OP_CHECKMULTISIG] * ((MAX_BLOCK_SIGOPS-1) // 20) + [OP_CHECKSIG] * 19)
+ b31 = block(31, spend=out[8], script=lots_of_multisigs)
+ assert_equal(get_legacy_sigopcount_block(b31), MAX_BLOCK_SIGOPS)
+ yield accepted()
+ save_spendable_output()
+
+ # this goes over the limit because the coinbase has one sigop
+ too_many_multisigs = CScript([OP_CHECKMULTISIG] * (MAX_BLOCK_SIGOPS // 20))
+ b32 = block(32, spend=out[9], script=too_many_multisigs)
+ assert_equal(get_legacy_sigopcount_block(b32), MAX_BLOCK_SIGOPS + 1)
+ yield rejected(RejectResult(16, b'bad-blk-sigops'))
+
+
+ # CHECKMULTISIGVERIFY
+ tip(31)
+ lots_of_multisigs = CScript([OP_CHECKMULTISIGVERIFY] * ((MAX_BLOCK_SIGOPS-1) // 20) + [OP_CHECKSIG] * 19)
+ block(33, spend=out[9], script=lots_of_multisigs)
+ yield accepted()
+ save_spendable_output()
+
+ too_many_multisigs = CScript([OP_CHECKMULTISIGVERIFY] * (MAX_BLOCK_SIGOPS // 20))
+ block(34, spend=out[10], script=too_many_multisigs)
+ yield rejected(RejectResult(16, b'bad-blk-sigops'))
+
+
+ # CHECKSIGVERIFY
+ tip(33)
+ lots_of_checksigs = CScript([OP_CHECKSIGVERIFY] * (MAX_BLOCK_SIGOPS - 1))
+ b35 = block(35, spend=out[10], script=lots_of_checksigs)
+ yield accepted()
+ save_spendable_output()
+
+ too_many_checksigs = CScript([OP_CHECKSIGVERIFY] * (MAX_BLOCK_SIGOPS))
+ block(36, spend=out[11], script=too_many_checksigs)
+ yield rejected(RejectResult(16, b'bad-blk-sigops'))
+
+
+ # Check spending of a transaction in a block which failed to connect
+ #
+ # b6 (3)
+ # b12 (3) -> b13 (4) -> b15 (5) -> b23 (6) -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10)
+ # \-> b37 (11)
+ # \-> b38 (11/37)
+ #
+
+ # save 37's spendable output, but then double-spend out11 to invalidate the block
+ tip(35)
+ b37 = block(37, spend=out[11])
+ txout_b37 = PreviousSpendableOutput(b37.vtx[1], 0)
+ tx = create_and_sign_tx(out[11].tx, out[11].n, 0)
+ b37 = update_block(37, [tx])
+ yield rejected(RejectResult(16, b'bad-txns-inputs-missingorspent'))
+
+ # attempt to spend b37's first non-coinbase tx, at which point b37 was still considered valid
+ tip(35)
+ block(38, spend=txout_b37)
+ yield rejected(RejectResult(16, b'bad-txns-inputs-missingorspent'))
+
+ # Check P2SH SigOp counting
+ #
+ #
+ # 13 (4) -> b15 (5) -> b23 (6) -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b41 (12)
+ # \-> b40 (12)
+ #
+ # b39 - create some P2SH outputs that will require 6 sigops to spend:
+ #
+ # redeem_script = COINBASE_PUBKEY, (OP_2DUP+OP_CHECKSIGVERIFY) * 5, OP_CHECKSIG
+ # p2sh_script = OP_HASH160, ripemd160(sha256(script)), OP_EQUAL
+ #
+ tip(35)
+ b39 = block(39)
+ b39_outputs = 0
+ b39_sigops_per_output = 6
+
+ # Build the redeem script, hash it, use hash to create the p2sh script
+ redeem_script = CScript([self.coinbase_pubkey] + [OP_2DUP, OP_CHECKSIGVERIFY]*5 + [OP_CHECKSIG])
+ redeem_script_hash = hash160(redeem_script)
+ p2sh_script = CScript([OP_HASH160, redeem_script_hash, OP_EQUAL])
+
+ # Create a transaction that spends one satoshi to the p2sh_script, the rest to OP_TRUE
+ # This must be signed because it is spending a coinbase
+ spend = out[11]
+ tx = create_tx(spend.tx, spend.n, 1, p2sh_script)
+ tx.vout.append(CTxOut(spend.tx.vout[spend.n].nValue - 1, CScript([OP_TRUE])))
+ self.sign_tx(tx, spend.tx, spend.n)
+ tx.rehash()
+ b39 = update_block(39, [tx])
+ b39_outputs += 1
+
+ # Until block is full, add tx's with 1 satoshi to p2sh_script, the rest to OP_TRUE
+ tx_new = None
+ tx_last = tx
+ total_size=len(b39.serialize())
+ while(total_size < MAX_BLOCK_SIZE):
+ tx_new = create_tx(tx_last, 1, 1, p2sh_script)
+ tx_new.vout.append(CTxOut(tx_last.vout[1].nValue - 1, CScript([OP_TRUE])))
+ tx_new.rehash()
+ total_size += len(tx_new.serialize())
+ if total_size >= MAX_BLOCK_SIZE:
+ break
+ b39.vtx.append(tx_new) # add tx to block
+ tx_last = tx_new
+ b39_outputs += 1
+
+ b39 = update_block(39, [])
+ yield accepted()
+ save_spendable_output()
+
+
+ # Test sigops in P2SH redeem scripts
+ #
+ # b40 creates 3333 tx's spending the 6-sigop P2SH outputs from b39 for a total of 19998 sigops.
+ # The first tx has one sigop and then at the end we add 2 more to put us just over the max.
+ #
+ # b41 does the same, less one, so it has the maximum sigops permitted.
+ #
+ tip(39)
+ b40 = block(40, spend=out[12])
+ sigops = get_legacy_sigopcount_block(b40)
+ numTxes = (MAX_BLOCK_SIGOPS - sigops) // b39_sigops_per_output
+ assert_equal(numTxes <= b39_outputs, True)
+
+ lastOutpoint = COutPoint(b40.vtx[1].sha256, 0)
+ new_txs = []
+ for i in range(1, numTxes+1):
+ tx = CTransaction()
+ tx.vout.append(CTxOut(1, CScript([OP_TRUE])))
+ tx.vin.append(CTxIn(lastOutpoint, b''))
+ # second input is corresponding P2SH output from b39
+ tx.vin.append(CTxIn(COutPoint(b39.vtx[i].sha256, 0), b''))
+ # Note: must pass the redeem_script (not p2sh_script) to the signature hash function
+ (sighash, err) = SignatureHash(redeem_script, tx, 1, SIGHASH_ALL)
+ sig = self.coinbase_key.sign(sighash) + bytes(bytearray([SIGHASH_ALL]))
+ scriptSig = CScript([sig, redeem_script])
+
+ tx.vin[1].scriptSig = scriptSig
+ tx.rehash()
+ new_txs.append(tx)
+ lastOutpoint = COutPoint(tx.sha256, 0)
+
+ b40_sigops_to_fill = MAX_BLOCK_SIGOPS - (numTxes * b39_sigops_per_output + sigops) + 1
+ tx = CTransaction()
+ tx.vin.append(CTxIn(lastOutpoint, b''))
+ tx.vout.append(CTxOut(1, CScript([OP_CHECKSIG] * b40_sigops_to_fill)))
+ tx.rehash()
+ new_txs.append(tx)
+ update_block(40, new_txs)
+ yield rejected(RejectResult(16, b'bad-blk-sigops'))
+
+ # same as b40, but one less sigop
+ tip(39)
+ b41 = block(41, spend=None)
+ update_block(41, b40.vtx[1:-1])
+ b41_sigops_to_fill = b40_sigops_to_fill - 1
+ tx = CTransaction()
+ tx.vin.append(CTxIn(lastOutpoint, b''))
+ tx.vout.append(CTxOut(1, CScript([OP_CHECKSIG] * b41_sigops_to_fill)))
+ tx.rehash()
+ update_block(41, [tx])
+ yield accepted()
+
+ # Fork off of b39 to create a constant base again
+ #
+ # b23 (6) -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13)
+ # \-> b41 (12)
+ #
+ tip(39)
+ block(42, spend=out[12])
+ yield rejected()
+ save_spendable_output()
+
+ block(43, spend=out[13])
+ yield accepted()
+ save_spendable_output()
+
+
+ # Test a number of really invalid scenarios
+ #
+ # -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b44 (14)
+ # \-> ??? (15)
+
+ # The next few blocks are going to be created "by hand" since they'll do funky things, such as having
+ # the first transaction be non-coinbase, etc. The purpose of b44 is to make sure this works.
+ height = self.block_heights[self.tip.sha256] + 1
+ coinbase = create_coinbase(height, self.coinbase_pubkey)
+ b44 = CBlock()
+ b44.nTime = self.tip.nTime + 1
+ b44.hashPrevBlock = self.tip.sha256
+ b44.nBits = 0x207fffff
+ b44.vtx.append(coinbase)
+ b44.hashMerkleRoot = b44.calc_merkle_root()
+ b44.solve()
+ self.tip = b44
+ self.block_heights[b44.sha256] = height
+ self.blocks[44] = b44
+ yield accepted()
+
+ # A block with a non-coinbase as the first tx
+ non_coinbase = create_tx(out[15].tx, out[15].n, 1)
+ b45 = CBlock()
+ b45.nTime = self.tip.nTime + 1
+ b45.hashPrevBlock = self.tip.sha256
+ b45.nBits = 0x207fffff
+ b45.vtx.append(non_coinbase)
+ b45.hashMerkleRoot = b45.calc_merkle_root()
+ b45.calc_sha256()
+ b45.solve()
+ self.block_heights[b45.sha256] = self.block_heights[self.tip.sha256]+1
+ self.tip = b45
+ self.blocks[45] = b45
+ yield rejected(RejectResult(16, b'bad-cb-missing'))
+
+ # A block with no txns
+ tip(44)
+ b46 = CBlock()
+ b46.nTime = b44.nTime+1
+ b46.hashPrevBlock = b44.sha256
+ b46.nBits = 0x207fffff
+ b46.vtx = []
+ b46.hashMerkleRoot = 0
+ b46.solve()
+ self.block_heights[b46.sha256] = self.block_heights[b44.sha256]+1
+ self.tip = b46
+ assert 46 not in self.blocks
+ self.blocks[46] = b46
+ s = ser_uint256(b46.hashMerkleRoot)
+ yield rejected(RejectResult(16, b'bad-blk-length'))
+
+ # A block with invalid work
+ tip(44)
+ b47 = block(47, solve=False)
+ target = uint256_from_compact(b47.nBits)
+ while b47.sha256 < target: #changed > to <
+ b47.nNonce += 1
+ b47.rehash()
+ yield rejected(RejectResult(16, b'high-hash'))
+
+ # A block with timestamp > 2 hrs in the future
+ tip(44)
+ b48 = block(48, solve=False)
+ b48.nTime = int(time.time()) + 60 * 60 * 3
+ b48.solve()
+ yield rejected(RejectResult(16, b'time-too-new'))
+
+ # A block with an invalid merkle hash
+ tip(44)
+ b49 = block(49)
+ b49.hashMerkleRoot += 1
+ b49.solve()
+ yield rejected(RejectResult(16, b'bad-txnmrklroot'))
+
+ # A block with an incorrect POW limit
+ tip(44)
+ b50 = block(50)
+ b50.nBits = b50.nBits - 1
+ b50.solve()
+ yield rejected(RejectResult(16, b'bad-diffbits'))
+
+ # A block with two coinbase txns
+ tip(44)
+ b51 = block(51)
+ cb2 = create_coinbase(51, self.coinbase_pubkey)
+ b51 = update_block(51, [cb2])
+ yield rejected(RejectResult(16, b'bad-cb-multiple'))
+
+ # A block w/ duplicate txns
+ # Note: txns have to be in the right position in the merkle tree to trigger this error
+ tip(44)
+ b52 = block(52, spend=out[15])
+ tx = create_tx(b52.vtx[1], 0, 1)
+ b52 = update_block(52, [tx, tx])
+ yield rejected(RejectResult(16, b'bad-txns-duplicate'))
+
+ # Test block timestamps
+ # -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15)
+ # \-> b54 (15)
+ #
+ tip(43)
+ block(53, spend=out[14])
+ yield rejected() # rejected since b44 is at same height
+ save_spendable_output()
+
+ # invalid timestamp (b35 is 5 blocks back, so its time is MedianTimePast)
+ b54 = block(54, spend=out[15])
+ b54.nTime = b35.nTime - 1
+ b54.solve()
+ yield rejected(RejectResult(16, b'time-too-old'))
+
+ # valid timestamp
+ tip(53)
+ b55 = block(55, spend=out[15])
+ b55.nTime = b35.nTime
+ update_block(55, [])
+ yield accepted()
+ save_spendable_output()
+
+
+ # Test CVE-2012-2459
+ #
+ # -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57p2 (16)
+ # \-> b57 (16)
+ # \-> b56p2 (16)
+ # \-> b56 (16)
+ #
+ # Merkle tree malleability (CVE-2012-2459): repeating sequences of transactions in a block without
+ # affecting the merkle root of a block, while still invalidating it.
+ # See: src/consensus/merkle.h
+ #
+ # b57 has three txns: coinbase, tx, tx1. The merkle root computation will duplicate tx.
+ # Result: OK
+ #
+ # b56 copies b57 but duplicates tx1 and does not recalculate the block hash. So it has a valid merkle
+ # root but duplicate transactions.
+ # Result: Fails
+ #
+ # b57p2 has six transactions in its merkle tree:
+ # - coinbase, tx, tx1, tx2, tx3, tx4
+ # Merkle root calculation will duplicate as necessary.
+ # Result: OK.
+ #
+ # b56p2 copies b57p2 but adds both tx3 and tx4. The purpose of the test is to make sure the code catches
+ # duplicate txns that are not next to one another with the "bad-txns-duplicate" error (which indicates
+ # that the error was caught early, avoiding a DOS vulnerability.)
+
+ # b57 - a good block with 2 txs, don't submit until end
+ tip(55)
+ b57 = block(57)
+ tx = create_and_sign_tx(out[16].tx, out[16].n, 1)
+ tx1 = create_tx(tx, 0, 1)
+ b57 = update_block(57, [tx, tx1])
+
+ # b56 - copy b57, add a duplicate tx
+ tip(55)
+ b56 = copy.deepcopy(b57)
+ self.blocks[56] = b56
+ assert_equal(len(b56.vtx),3)
+ b56 = update_block(56, [tx1])
+ assert_equal(b56.hash, b57.hash)
+ yield rejected(RejectResult(16, b'bad-txns-duplicate'))
+
+ # b57p2 - a good block with 6 tx'es, don't submit until end
+ tip(55)
+ b57p2 = block("57p2")
+ tx = create_and_sign_tx(out[16].tx, out[16].n, 1)
+ tx1 = create_tx(tx, 0, 1)
+ tx2 = create_tx(tx1, 0, 1)
+ tx3 = create_tx(tx2, 0, 1)
+ tx4 = create_tx(tx3, 0, 1)
+ b57p2 = update_block("57p2", [tx, tx1, tx2, tx3, tx4])
+
+ # b56p2 - copy b57p2, duplicate two non-consecutive tx's
+ tip(55)
+ b56p2 = copy.deepcopy(b57p2)
+ self.blocks["b56p2"] = b56p2
+ assert_equal(b56p2.hash, b57p2.hash)
+ assert_equal(len(b56p2.vtx),6)
+ b56p2 = update_block("b56p2", [tx3, tx4])
+ yield rejected(RejectResult(16, b'bad-txns-duplicate'))
+
+ tip("57p2")
+ yield accepted()
+
+ tip(57)
+ yield rejected() #rejected because 57p2 seen first
+ save_spendable_output()
+
+ # Test a few invalid tx types
+ #
+ # -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17)
+ # \-> ??? (17)
+ #
+
+ # tx with prevout.n out of range
+ tip(57)
+ b58 = block(58, spend=out[17])
+ tx = CTransaction()
+ assert(len(out[17].tx.vout) < 42)
+ tx.vin.append(CTxIn(COutPoint(out[17].tx.sha256, 42), CScript([OP_TRUE]), 0xffffffff))
+ tx.vout.append(CTxOut(0, b""))
+ tx.calc_sha256()
+ b58 = update_block(58, [tx])
+ yield rejected(RejectResult(16, b'bad-txns-inputs-missingorspent'))
+
+ # tx with output value > input value out of range
+ tip(57)
+ b59 = block(59)
+ tx = create_and_sign_tx(out[17].tx, out[17].n, 510*COIN)
+ b59 = update_block(59, [tx])
+ yield rejected(RejectResult(16, b'bad-txns-in-belowout'))
+
+ # reset to good chain
+ tip(57)
+ b60 = block(60, spend=out[17])
+ yield accepted()
+ save_spendable_output()
+
+ # Test BIP30
+ #
+ # -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17)
+ # \-> b61 (18)
+ #
+ # Blocks are not allowed to contain a transaction whose id matches that of an earlier,
+ # not-fully-spent transaction in the same chain. To test, make identical coinbases;
+ # the second one should be rejected.
+ #
+ tip(60)
+ b61 = block(61, spend=out[18])
+ b61.vtx[0].vin[0].scriptSig = b60.vtx[0].vin[0].scriptSig #equalize the coinbases
+ b61.vtx[0].rehash()
+ b61 = update_block(61, [])
+ assert_equal(b60.vtx[0].serialize(), b61.vtx[0].serialize())
+ yield rejected(RejectResult(16, b'bad-txns-BIP30'))
+
+
+ # Test tx.isFinal is properly rejected (not an exhaustive tx.isFinal test, that should be in data-driven transaction tests)
+ #
+ # -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17)
+ # \-> b62 (18)
+ #
+ tip(60)
+ b62 = block(62)
+ tx = CTransaction()
+ tx.nLockTime = 0xffffffff #this locktime is non-final
+ assert(out[18].n < len(out[18].tx.vout))
+ tx.vin.append(CTxIn(COutPoint(out[18].tx.sha256, out[18].n))) # don't set nSequence
+ tx.vout.append(CTxOut(0, CScript([OP_TRUE])))
+ assert(tx.vin[0].nSequence < 0xffffffff)
+ tx.calc_sha256()
+ b62 = update_block(62, [tx])
+ yield rejected(RejectResult(16, b'bad-txns-nonfinal'))
+
+
+ # Test a non-final coinbase is also rejected
+ #
+ # -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17)
+ # \-> b63 (-)
+ #
+ tip(60)
+ b63 = block(63)
+ b63.vtx[0].nLockTime = 0xffffffff
+ b63.vtx[0].vin[0].nSequence = 0xDEADBEEF
+ b63.vtx[0].rehash()
+ b63 = update_block(63, [])
+ yield rejected(RejectResult(16, b'bad-txns-nonfinal'))
+
+
+ # This checks that a block with a bloated VARINT between the block_header and the array of tx such that
+ # the block is > MAX_BLOCK_SIZE with the bloated varint, but <= MAX_BLOCK_SIZE without the bloated varint,
+ # does not cause a subsequent, identical block with canonical encoding to be rejected. The test does not
+ # care whether the bloated block is accepted or rejected; it only cares that the second block is accepted.
+ #
+ # What matters is that the receiving node should not reject the bloated block, and then reject the canonical
+ # block on the basis that it's the same as an already-rejected block (which would be a consensus failure.)
+ #
+ # -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18)
+ # \
+ # b64a (18)
+ # b64a is a bloated block (non-canonical varint)
+ # b64 is a good block (same as b64 but w/ canonical varint)
+ #
+ tip(60)
+ regular_block = block("64a", spend=out[18])
+
+ # make it a "broken_block," with non-canonical serialization
+ b64a = CBrokenBlock(regular_block)
+ b64a.initialize(regular_block)
+ self.blocks["64a"] = b64a
+ self.tip = b64a
+ tx = CTransaction()
+
+ # use canonical serialization to calculate size
+ script_length = MAX_BLOCK_SIZE - len(b64a.normal_serialize()) - 69
+ script_output = CScript([b'\x00' * script_length])
+ tx.vout.append(CTxOut(0, script_output))
+ tx.vin.append(CTxIn(COutPoint(b64a.vtx[1].sha256, 0)))
+ b64a = update_block("64a", [tx])
+ assert_equal(len(b64a.serialize()), MAX_BLOCK_SIZE + 8)
+ yield TestInstance([[self.tip, None]])
+
+ # comptool workaround: to make sure b64 is delivered, manually erase b64a from blockstore
+ self.test.block_store.erase(b64a.sha256)
+
+ tip(60)
+ b64 = CBlock(b64a)
+ b64.vtx = copy.deepcopy(b64a.vtx)
+ assert_equal(b64.hash, b64a.hash)
+ assert_equal(len(b64.serialize()), MAX_BLOCK_SIZE)
+ self.blocks[64] = b64
+ update_block(64, [])
+ yield accepted()
+ save_spendable_output()
+
+ # Spend an output created in the block itself
+ #
+ # -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19)
+ #
+ tip(64)
+ b65 = block(65)
+ tx1 = create_and_sign_tx(out[19].tx, out[19].n, out[19].tx.vout[0].nValue)
+ tx2 = create_and_sign_tx(tx1, 0, 0)
+ update_block(65, [tx1, tx2])
+ yield accepted()
+ save_spendable_output()
+
+ # Attempt to spend an output created later in the same block
+ #
+ # -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19)
+ # \-> b66 (20)
+ tip(65)
+ b66 = block(66)
+ tx1 = create_and_sign_tx(out[20].tx, out[20].n, out[20].tx.vout[0].nValue)
+ tx2 = create_and_sign_tx(tx1, 0, 1)
+ update_block(66, [tx2, tx1])
+ yield rejected(RejectResult(16, b'bad-txns-inputs-missingorspent'))
+
+ # Attempt to double-spend a transaction created in a block
+ #
+ # -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19)
+ # \-> b67 (20)
+ #
+ #
+ tip(65)
+ b67 = block(67)
+ tx1 = create_and_sign_tx(out[20].tx, out[20].n, out[20].tx.vout[0].nValue)
+ tx2 = create_and_sign_tx(tx1, 0, 1)
+ tx3 = create_and_sign_tx(tx1, 0, 2)
+ update_block(67, [tx1, tx2, tx3])
+ yield rejected(RejectResult(16, b'bad-txns-inputs-missingorspent'))
+
+ # More tests of block subsidy
+ #
+ # -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20)
+ # \-> b68 (20)
+ #
+ # b68 - coinbase with an extra 10 satoshis,
+ # creates a tx that has 9 satoshis from out[20] go to fees
+ # this fails because the coinbase is trying to claim 1 satoshi too much in fees
+ #
+ # b69 - coinbase with extra 10 satoshis, and a tx that gives a 10 satoshi fee
+ # this succeeds
+ #
+ tip(65)
+ b68 = block(68, additional_coinbase_value=10)
+ tx = create_and_sign_tx(out[20].tx, out[20].n, out[20].tx.vout[0].nValue-9)
+ update_block(68, [tx])
+ yield rejected(RejectResult(16, b'bad-cb-amount'))
+
+ tip(65)
+ b69 = block(69, additional_coinbase_value=10)
+ tx = create_and_sign_tx(out[20].tx, out[20].n, out[20].tx.vout[0].nValue-10)
+ update_block(69, [tx])
+ yield accepted()
+ save_spendable_output()
+
+ # Test spending the outpoint of a non-existent transaction
+ #
+ # -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20)
+ # \-> b70 (21)
+ #
+ tip(69)
+ block(70, spend=out[21])
+ bogus_tx = CTransaction()
+ bogus_tx.sha256 = uint256_from_str(b"23c70ed7c0506e9178fc1a987f40a33946d4ad4c962b5ae3a52546da53af0c5c")
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(bogus_tx.sha256, 0), b"", 0xffffffff))
+ tx.vout.append(CTxOut(1, b""))
+ update_block(70, [tx])
+ yield rejected(RejectResult(16, b'bad-txns-inputs-missingorspent'))
+
+
+ # Test accepting an invalid block which has the same hash as a valid one (via merkle tree tricks)
+ #
+ # -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20) -> b72 (21)
+ # \-> b71 (21)
+ #
+ # b72 is a good block.
+ # b71 is a copy of 72, but re-adds one of its transactions. However, it has the same hash as b71.
+ #
+ tip(69)
+ b72 = block(72)
+ tx1 = create_and_sign_tx(out[21].tx, out[21].n, 2)
+ tx2 = create_and_sign_tx(tx1, 0, 1)
+ b72 = update_block(72, [tx1, tx2]) # now tip is 72
+ b71 = copy.deepcopy(b72)
+ b71.vtx.append(tx2) # add duplicate tx2
+ self.block_heights[b71.sha256] = self.block_heights[b69.sha256] + 1 # b71 builds off b69
+ self.blocks[71] = b71
+
+ assert_equal(len(b71.vtx), 4)
+ assert_equal(len(b72.vtx), 3)
+ assert_equal(b72.sha256, b71.sha256)
+
+ tip(71)
+ yield rejected(RejectResult(16, b'bad-txns-duplicate'))
+ tip(72)
+ yield accepted()
+ save_spendable_output()
+
+
+ # Test some invalid scripts and MAX_BLOCK_SIGOPS
+ #
+ # -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20) -> b72 (21)
+ # \-> b** (22)
+ #
+
+ # b73 - tx with excessive sigops that are placed after an excessively large script element.
+ # The purpose of the test is to make sure those sigops are counted.
+ #
+ # script is a bytearray of size 20,526
+ #
+ # bytearray[0-19,998] : OP_CHECKSIG
+ # bytearray[19,999] : OP_PUSHDATA4
+ # bytearray[20,000-20,003]: 521 (max_script_element_size+1, in little-endian format)
+ # bytearray[20,004-20,525]: unread data (script_element)
+ # bytearray[20,526] : OP_CHECKSIG (this puts us over the limit)
+ #
+ tip(72)
+ b73 = block(73)
+ size = MAX_BLOCK_SIGOPS - 1 + MAX_SCRIPT_ELEMENT_SIZE + 1 + 5 + 1
+ a = bytearray([OP_CHECKSIG] * size)
+ a[MAX_BLOCK_SIGOPS - 1] = int("4e",16) # OP_PUSHDATA4
+
+ element_size = MAX_SCRIPT_ELEMENT_SIZE + 1
+ a[MAX_BLOCK_SIGOPS] = element_size % 256
+ a[MAX_BLOCK_SIGOPS+1] = element_size // 256
+ a[MAX_BLOCK_SIGOPS+2] = 0
+ a[MAX_BLOCK_SIGOPS+3] = 0
+
+ tx = create_and_sign_tx(out[22].tx, 0, 1, CScript(a))
+ b73 = update_block(73, [tx])
+ assert_equal(get_legacy_sigopcount_block(b73), MAX_BLOCK_SIGOPS+1)
+ yield rejected(RejectResult(16, b'bad-blk-sigops'))
+
+ # b74/75 - if we push an invalid script element, all prevous sigops are counted,
+ # but sigops after the element are not counted.
+ #
+ # The invalid script element is that the push_data indicates that
+ # there will be a large amount of data (0xffffff bytes), but we only
+ # provide a much smaller number. These bytes are CHECKSIGS so they would
+ # cause b75 to fail for excessive sigops, if those bytes were counted.
+ #
+ # b74 fails because we put MAX_BLOCK_SIGOPS+1 before the element
+ # b75 succeeds because we put MAX_BLOCK_SIGOPS before the element
+ #
+ #
+ tip(72)
+ b74 = block(74)
+ size = MAX_BLOCK_SIGOPS - 1 + MAX_SCRIPT_ELEMENT_SIZE + 42 # total = 20,561
+ a = bytearray([OP_CHECKSIG] * size)
+ a[MAX_BLOCK_SIGOPS] = 0x4e
+ a[MAX_BLOCK_SIGOPS+1] = 0xfe
+ a[MAX_BLOCK_SIGOPS+2] = 0xff
+ a[MAX_BLOCK_SIGOPS+3] = 0xff
+ a[MAX_BLOCK_SIGOPS+4] = 0xff
+ tx = create_and_sign_tx(out[22].tx, 0, 1, CScript(a))
+ b74 = update_block(74, [tx])
+ yield rejected(RejectResult(16, b'bad-blk-sigops'))
+
+ tip(72)
+ b75 = block(75)
+ size = MAX_BLOCK_SIGOPS - 1 + MAX_SCRIPT_ELEMENT_SIZE + 42
+ a = bytearray([OP_CHECKSIG] * size)
+ a[MAX_BLOCK_SIGOPS-1] = 0x4e
+ a[MAX_BLOCK_SIGOPS] = 0xff
+ a[MAX_BLOCK_SIGOPS+1] = 0xff
+ a[MAX_BLOCK_SIGOPS+2] = 0xff
+ a[MAX_BLOCK_SIGOPS+3] = 0xff
+ tx = create_and_sign_tx(out[22].tx, 0, 1, CScript(a))
+ b75 = update_block(75, [tx])
+ yield accepted()
+ save_spendable_output()
+
+ # Check that if we push an element filled with CHECKSIGs, they are not counted
+ tip(75)
+ b76 = block(76)
+ size = MAX_BLOCK_SIGOPS - 1 + MAX_SCRIPT_ELEMENT_SIZE + 1 + 5
+ a = bytearray([OP_CHECKSIG] * size)
+ a[MAX_BLOCK_SIGOPS-1] = 0x4e # PUSHDATA4, but leave the following bytes as just checksigs
+ tx = create_and_sign_tx(out[23].tx, 0, 1, CScript(a))
+ b76 = update_block(76, [tx])
+ yield accepted()
+ save_spendable_output()
+
+ # Test transaction resurrection
+ #
+ # -> b77 (24) -> b78 (25) -> b79 (26)
+ # \-> b80 (25) -> b81 (26) -> b82 (27)
+ #
+ # b78 creates a tx, which is spent in b79. After b82, both should be in mempool
+ #
+ # The tx'es must be unsigned and pass the node's mempool policy. It is unsigned for the
+ # rather obscure reason that the Python signature code does not distinguish between
+ # Low-S and High-S values (whereas the bitcoin code has custom code which does so);
+ # as a result of which, the odds are 50% that the python code will use the right
+ # value and the transaction will be accepted into the mempool. Until we modify the
+ # test framework to support low-S signing, we are out of luck.
+ #
+ # To get around this issue, we construct transactions which are not signed and which
+ # spend to OP_TRUE. If the standard-ness rules change, this test would need to be
+ # updated. (Perhaps to spend to a P2SH OP_TRUE script)
+ #
+ tip(76)
+ block(77)
+ tx77 = create_and_sign_tx(out[24].tx, out[24].n, 10*COIN)
+ update_block(77, [tx77])
+ yield accepted()
+ save_spendable_output()
+
+ block(78)
+ tx78 = create_tx(tx77, 0, 9*COIN)
+ update_block(78, [tx78])
+ yield accepted()
+
+ block(79)
+ tx79 = create_tx(tx78, 0, 8*COIN)
+ update_block(79, [tx79])
+ yield accepted()
+
+ # mempool should be empty
+ assert_equal(len(self.nodes[0].getrawmempool()), 0)
+
+ tip(77)
+ block(80, spend=out[25])
+ yield rejected()
+ save_spendable_output()
+
+ block(81, spend=out[26])
+ yield rejected() # other chain is same length
+ save_spendable_output()
+
+ block(82, spend=out[27])
+ yield accepted() # now this chain is longer, triggers re-org
+ save_spendable_output()
+
+ # now check that tx78 and tx79 have been put back into the peer's mempool
+ mempool = self.nodes[0].getrawmempool()
+ assert_equal(len(mempool), 2)
+ assert(tx78.hash in mempool)
+ assert(tx79.hash in mempool)
+
+
+ # Test invalid opcodes in dead execution paths.
+ #
+ # -> b81 (26) -> b82 (27) -> b83 (28)
+ #
+ b83 = block(83)
+ op_codes = [OP_IF, OP_INVALIDOPCODE, OP_ELSE, OP_TRUE, OP_ENDIF]
+ script = CScript(op_codes)
+ tx1 = create_and_sign_tx(out[28].tx, out[28].n, out[28].tx.vout[0].nValue, script)
+
+ tx2 = create_and_sign_tx(tx1, 0, 0, CScript([OP_TRUE]))
+ tx2.vin[0].scriptSig = CScript([OP_FALSE])
+ tx2.rehash()
+
+ update_block(83, [tx1, tx2])
+ yield accepted()
+ save_spendable_output()
+
+
+ # Reorg on/off blocks that have OP_RETURN in them (and try to spend them)
+ #
+ # -> b81 (26) -> b82 (27) -> b83 (28) -> b84 (29) -> b87 (30) -> b88 (31)
+ # \-> b85 (29) -> b86 (30) \-> b89a (32)
+ #
+ #
+ b84 = block(84)
+ tx1 = create_tx(out[29].tx, out[29].n, 0, CScript([OP_RETURN]))
+ tx1.vout.append(CTxOut(0, CScript([OP_TRUE])))
+ tx1.vout.append(CTxOut(0, CScript([OP_TRUE])))
+ tx1.vout.append(CTxOut(0, CScript([OP_TRUE])))
+ tx1.vout.append(CTxOut(0, CScript([OP_TRUE])))
+ tx1.calc_sha256()
+ self.sign_tx(tx1, out[29].tx, out[29].n)
+ tx1.rehash()
+ tx2 = create_tx(tx1, 1, 0, CScript([OP_RETURN]))
+ tx2.vout.append(CTxOut(0, CScript([OP_RETURN])))
+ tx3 = create_tx(tx1, 2, 0, CScript([OP_RETURN]))
+ tx3.vout.append(CTxOut(0, CScript([OP_TRUE])))
+ tx4 = create_tx(tx1, 3, 0, CScript([OP_TRUE]))
+ tx4.vout.append(CTxOut(0, CScript([OP_RETURN])))
+ tx5 = create_tx(tx1, 4, 0, CScript([OP_RETURN]))
+
+ update_block(84, [tx1,tx2,tx3,tx4,tx5])
+ yield accepted()
+ save_spendable_output()
+
+ tip(83)
+ block(85, spend=out[29])
+ yield rejected()
+
+ block(86, spend=out[30])
+ yield accepted()
+
+ tip(84)
+ block(87, spend=out[30])
+ yield rejected()
+ save_spendable_output()
+
+ block(88, spend=out[31])
+ yield accepted()
+ save_spendable_output()
+
+ # trying to spend the OP_RETURN output is rejected
+ block("89a", spend=out[32])
+ tx = create_tx(tx1, 0, 0, CScript([OP_TRUE]))
+ update_block("89a", [tx])
+ yield rejected()
+
+
+ # Test re-org of a week's worth of blocks (1088 blocks)
+ # This test takes a minute or two and can be accomplished in memory
+ #
+ if self.options.runbarelyexpensive:
+ tip(88)
+ LARGE_REORG_SIZE = 1088
+ test1 = TestInstance(sync_every_block=False)
+ spend=out[32]
+ for i in range(89, LARGE_REORG_SIZE + 89):
+ b = block(i, spend)
+ tx = CTransaction()
+ script_length = MAX_BLOCK_SIZE - len(b.serialize()) - 69
+ script_output = CScript([b'\x00' * script_length])
+ tx.vout.append(CTxOut(0, script_output))
+ tx.vin.append(CTxIn(COutPoint(b.vtx[1].sha256, 0)))
+ b = update_block(i, [tx])
+ assert_equal(len(b.serialize()), MAX_BLOCK_SIZE)
+ test1.blocks_and_transactions.append([self.tip, True])
+ save_spendable_output()
+ spend = get_spendable_output()
+
+ yield test1
+ chain1_tip = i
+
+ # now create alt chain of same length
+ tip(88)
+ test2 = TestInstance(sync_every_block=False)
+ for i in range(89, LARGE_REORG_SIZE + 89):
+ block("alt"+str(i))
+ test2.blocks_and_transactions.append([self.tip, False])
+ yield test2
+
+ # extend alt chain to trigger re-org
+ block("alt" + str(chain1_tip + 1))
+ yield accepted()
+
+ # ... and re-org back to the first chain
+ tip(chain1_tip)
+ block(chain1_tip + 1)
+ yield rejected()
+ block(chain1_tip + 2)
+ yield accepted()
+
+ chain1_tip += 2
+
if __name__ == '__main__':
diff --git a/qa/rpc-tests/p2p-mempool.py b/qa/rpc-tests/p2p-mempool.py
new file mode 100755
index 000000000000..5d2daf39f828
--- /dev/null
+++ b/qa/rpc-tests/p2p-mempool.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python3
+# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+from test_framework.mininode import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+import time
+
+class TestNode(NodeConnCB):
+ def __init__(self):
+ NodeConnCB.__init__(self)
+ self.connection = None
+ self.ping_counter = 1
+ self.last_pong = msg_pong()
+ self.block_receive_map = {}
+
+ def add_connection(self, conn):
+ self.connection = conn
+ self.peer_disconnected = False
+
+ def on_inv(self, conn, message):
+ pass
+
+ # Track the last getdata message we receive (used in the test)
+ def on_getdata(self, conn, message):
+ self.last_getdata = message
+
+ def on_block(self, conn, message):
+ message.block.calc_sha256()
+ try:
+ self.block_receive_map[message.block.sha256] += 1
+ except KeyError as e:
+ self.block_receive_map[message.block.sha256] = 1
+
+ # Spin until verack message is received from the node.
+ # We use this to signal that our test can begin. This
+ # is called from the testing thread, so it needs to acquire
+ # the global lock.
+ def wait_for_verack(self):
+ def veracked():
+ return self.verack_received
+ return wait_until(veracked, timeout=10)
+
+ def wait_for_disconnect(self):
+ def disconnected():
+ return self.peer_disconnected
+ return wait_until(disconnected, timeout=10)
+
+ # Wrapper for the NodeConn's send_message function
+ def send_message(self, message):
+ self.connection.send_message(message)
+
+ def on_pong(self, conn, message):
+ self.last_pong = message
+
+ def on_close(self, conn):
+ self.peer_disconnected = True
+
+ # Sync up with the node after delivery of a block
+ def sync_with_ping(self, timeout=30):
+ def received_pong():
+ return (self.last_pong.nonce == self.ping_counter)
+ self.connection.send_message(msg_ping(nonce=self.ping_counter))
+ success = wait_until(received_pong, timeout)
+ self.ping_counter += 1
+ return success
+
+ def send_mempool(self):
+ self.lastInv = []
+ self.send_message(msg_mempool())
+
+class P2PMempoolTests(BitcoinTestFramework):
+ def setup_chain(self):
+ initialize_chain_clean(self.options.tmpdir, 2)
+
+ def setup_network(self):
+ # Start a node with maxuploadtarget of 200 MB (/24h)
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-peerbloomfilters=0"]))
+
+ def run_test(self):
+ #connect a mininode
+ aTestNode = TestNode()
+ node = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], aTestNode)
+ aTestNode.add_connection(node)
+ NetworkThread().start()
+ aTestNode.wait_for_verack()
+
+ #request mempool
+ aTestNode.send_mempool()
+ aTestNode.wait_for_disconnect()
+
+ #mininode must be disconnected at this point
+ assert_equal(len(self.nodes[0].getpeerinfo()), 0)
+
+if __name__ == '__main__':
+ P2PMempoolTests().main()
diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py
index 1e3d7236ec52..cec626b0db52 100755
--- a/qa/rpc-tests/rawtransactions.py
+++ b/qa/rpc-tests/rawtransactions.py
@@ -138,5 +138,11 @@ def run_test(self):
self.sync_all()
assert_equal(self.nodes[0].getbalance(), bal+Decimal('500.00000000')+Decimal('2.19000000')) #block reward + tx
+ inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 1000}]
+ outputs = { self.nodes[0].getnewaddress() : 1 }
+ rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
+ decrawtx= self.nodes[0].decoderawtransaction(rawtx)
+ assert_equal(decrawtx['vin'][0]['sequence'], 1000)
+
if __name__ == '__main__':
RawTransactionsTest().main()
diff --git a/qa/rpc-tests/test_framework/authproxy.py b/qa/rpc-tests/test_framework/authproxy.py
index 3bc84bc5c1f1..d095a56ce75e 100644
--- a/qa/rpc-tests/test_framework/authproxy.py
+++ b/qa/rpc-tests/test_framework/authproxy.py
@@ -126,6 +126,11 @@ def _request(self, method, path, postdata):
return self._get_response()
else:
raise
+ except BrokenPipeError:
+ # Python 3.5+ raises this instead of BadStatusLine when the connection was reset
+ self.__conn.close()
+ self.__conn.request(method, path, postdata, headers)
+ return self._get_response()
def __call__(self, *args):
AuthServiceProxy.__id_count += 1
diff --git a/qa/rpc-tests/test_framework/blockstore.py b/qa/rpc-tests/test_framework/blockstore.py
index 4bc279032bf0..6120dd574b5d 100644
--- a/qa/rpc-tests/test_framework/blockstore.py
+++ b/qa/rpc-tests/test_framework/blockstore.py
@@ -13,20 +13,31 @@ def __init__(self, datadir):
self.blockDB = dbm.ndbm.open(datadir + "/blocks", 'c')
self.currentBlock = 0
self.headers_map = dict()
-
+
def close(self):
self.blockDB.close()
+ def erase(self, blockhash):
+ del self.blockDB[repr(blockhash)]
+
+ # lookup an entry and return the item as raw bytes
def get(self, blockhash):
- serialized_block = None
+ value = None
try:
- serialized_block = self.blockDB[repr(blockhash)]
+ value = self.blockDB[repr(blockhash)]
except KeyError:
return None
- f = BytesIO(serialized_block)
- ret = CBlock()
- ret.deserialize(f)
- ret.calc_sha256()
+ return value
+
+ # lookup an entry and return it as a CBlock
+ def get_block(self, blockhash):
+ ret = None
+ serialized_block = self.get(blockhash)
+ if serialized_block is not None:
+ f = BytesIO(serialized_block)
+ ret = CBlock()
+ ret.deserialize(f)
+ ret.calc_sha256()
return ret
def get_header(self, blockhash):
@@ -75,13 +86,16 @@ def add_block(self, block):
def add_header(self, header):
self.headers_map[header.sha256] = header
+ # lookup the hashes in "inv", and return p2p messages for delivering
+ # blocks found.
def get_blocks(self, inv):
responses = []
for i in inv:
if (i.type == 2): # MSG_BLOCK
- block = self.get(i.hash)
- if block is not None:
- responses.append(msg_block(block))
+ data = self.get(i.hash)
+ if data is not None:
+ # Use msg_generic to avoid re-serialization
+ responses.append(msg_generic(b"block", data))
return responses
def get_locator(self, current_tip=None):
@@ -90,11 +104,11 @@ def get_locator(self, current_tip=None):
r = []
counter = 0
step = 1
- lastBlock = self.get(current_tip)
+ lastBlock = self.get_block(current_tip)
while lastBlock is not None:
r.append(lastBlock.hashPrevBlock)
for i in range(step):
- lastBlock = self.get(lastBlock.hashPrevBlock)
+ lastBlock = self.get_block(lastBlock.hashPrevBlock)
if lastBlock is None:
break
counter += 1
@@ -111,16 +125,23 @@ def __init__(self, datadir):
def close(self):
self.txDB.close()
+ # lookup an entry and return the item as raw bytes
def get(self, txhash):
- serialized_tx = None
+ value = None
try:
- serialized_tx = self.txDB[repr(txhash)]
+ value = self.txDB[repr(txhash)]
except KeyError:
return None
- f = BytesIO(serialized_tx)
- ret = CTransaction()
- ret.deserialize(f)
- ret.calc_sha256()
+ return value
+
+ def get_transaction(self, txhash):
+ ret = None
+ serialized_tx = self.get(txhash)
+ if serialized_tx is not None:
+ f = BytesIO(serialized_tx)
+ ret = CTransaction()
+ ret.deserialize(f)
+ ret.calc_sha256()
return ret
def add_transaction(self, tx):
@@ -136,5 +157,5 @@ def get_transactions(self, inv):
if (i.type == 1): # MSG_TX
tx = self.get(i.hash)
if tx is not None:
- responses.append(msg_tx(tx))
+ responses.append(msg_generic(b"tx", tx))
return responses
diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py
index 39edadc6a784..6266318342d5 100644
--- a/qa/rpc-tests/test_framework/blocktools.py
+++ b/qa/rpc-tests/test_framework/blocktools.py
@@ -56,12 +56,27 @@ def create_coinbase(height, pubkey = None):
coinbase.calc_sha256()
return coinbase
-# Create a transaction with an anyone-can-spend output, that spends the
-# nth output of prevtx.
-def create_transaction(prevtx, n, sig, value):
+# Create a transaction.
+# If the scriptPubKey is not specified, make it anyone-can-spend.
+def create_transaction(prevtx, n, sig, value, scriptPubKey=CScript()):
tx = CTransaction()
assert(n < len(prevtx.vout))
tx.vin.append(CTxIn(COutPoint(prevtx.sha256, n), sig, 0xffffffff))
- tx.vout.append(CTxOut(value, b""))
+ tx.vout.append(CTxOut(value, scriptPubKey))
tx.calc_sha256()
return tx
+
+def get_legacy_sigopcount_block(block, fAccurate=True):
+ count = 0
+ for tx in block.vtx:
+ count += get_legacy_sigopcount_tx(tx, fAccurate)
+ return count
+
+def get_legacy_sigopcount_tx(tx, fAccurate=True):
+ count = 0
+ for i in tx.vout:
+ count += i.scriptPubKey.GetSigOpCount(fAccurate)
+ for j in tx.vin:
+ # scriptSig might be of type bytes, so convert to CScript for the moment
+ count += CScript(j.scriptSig).GetSigOpCount(fAccurate)
+ return count
diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py
index d0252132b136..822c10ac1a06 100755
--- a/qa/rpc-tests/test_framework/mininode.py
+++ b/qa/rpc-tests/test_framework/mininode.py
@@ -840,6 +840,18 @@ def serialize(self):
def __repr__(self):
return "msg_block(block=%s)" % (repr(self.block))
+# for cases where a user needs tighter control over what is sent over the wire
+# note that the user must supply the name of the command, and the data
+class msg_generic(object):
+ def __init__(self, command, data=None):
+ self.command = command
+ self.data = data
+
+ def serialize(self):
+ return self.data
+
+ def __repr__(self):
+ return "msg_generic()"
class msg_getaddr(object):
command = b"getaddr"
diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py
index 0a8515a89700..89396863c0cc 100644
--- a/qa/rpc-tests/test_framework/util.py
+++ b/qa/rpc-tests/test_framework/util.py
@@ -501,6 +501,15 @@ def random_transaction(nodes, amount, min_fee, fee_increment, fee_variants):
return (txid, signresult["hex"], fee)
+def assert_fee_amount(fee, tx_size, fee_per_kB):
+ """Assert the fee was in range"""
+ target_fee = tx_size * fee_per_kB / 1000
+ if fee < target_fee:
+ raise AssertionError("Fee of %s DASH too low! (Should be %s DASH)"%(str(fee), str(target_fee)))
+ # allow the wallet's estimation to be at most 2 bytes off
+ if fee > (tx_size + 2) * fee_per_kB / 1000:
+ raise AssertionError("Fee of %s DASH too high! (Should be %s DASH)"%(str(fee), str(target_fee)))
+
def assert_equal(thing1, thing2):
if thing1 != thing2:
raise AssertionError("%s != %s"%(str(thing1),str(thing2)))
diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py
index 8580c19f0878..83b1d6200b73 100755
--- a/qa/rpc-tests/wallet.py
+++ b/qa/rpc-tests/wallet.py
@@ -11,12 +11,7 @@ class WalletTest (BitcoinTestFramework):
def check_fee_amount(self, curr_balance, balance_with_fee, fee_per_byte, tx_size):
"""Return curr_balance after asserting the fee was in range"""
fee = balance_with_fee - curr_balance
- target_fee = fee_per_byte * tx_size
- if fee < target_fee:
- raise AssertionError("Fee of %s DASH too low! (Should be %s DASH)"%(str(fee), str(target_fee)))
- # allow the node's estimation to be at most 2 bytes off
- if fee > fee_per_byte * (tx_size + 2):
- raise AssertionError("Fee of %s DASH too high! (Should be %s DASH)"%(str(fee), str(target_fee)))
+ assert_fee_amount(fee, tx_size, fee_per_byte * 1000)
return curr_balance
def __init__(self):
diff --git a/share/genbuild.sh b/share/genbuild.sh
index a15cb34e47ae..1ef77d706f7a 100755
--- a/share/genbuild.sh
+++ b/share/genbuild.sh
@@ -15,7 +15,6 @@ fi
DESC=""
SUFFIX=""
-LAST_COMMIT_DATE=""
if [ -e "$(which git 2>/dev/null)" -a "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]; then
# clean 'dirty' status of touched files that haven't been modified
git diff >/dev/null 2>/dev/null
@@ -29,9 +28,6 @@ if [ -e "$(which git 2>/dev/null)" -a "$(git rev-parse --is-inside-work-tree 2>/
# otherwise generate suffix from git, i.e. string like "59887e8-dirty"
SUFFIX=$(git rev-parse --short HEAD)
git diff-index --quiet HEAD -- || SUFFIX="$SUFFIX-dirty"
-
- # get a string like "2012-04-10 16:27:19 +0200"
- LAST_COMMIT_DATE="$(git log -n 1 --format="%ci")"
fi
if [ -n "$DESC" ]; then
@@ -45,7 +41,4 @@ fi
# only update build.h if necessary
if [ "$INFO" != "$NEWINFO" ]; then
echo "$NEWINFO" >"$FILE"
- if [ -n "$LAST_COMMIT_DATE" ]; then
- echo "#define BUILD_DATE \"$LAST_COMMIT_DATE\"" >> "$FILE"
- fi
fi
diff --git a/src/Makefile.am b/src/Makefile.am
index 5e7001f95a75..7ec818e06d12 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -15,13 +15,12 @@ LIBUNIVALUE = $(UNIVALUE_LIBS)
endif
BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config
-BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS)
+BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS)
BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include
BITCOIN_INCLUDES += $(UNIVALUE_CFLAGS)
LIBBITCOIN_SERVER=libbitcoin_server.a
-LIBBITCOIN_WALLET=libbitcoin_wallet.a
LIBBITCOIN_COMMON=libbitcoin_common.a
LIBBITCOIN_CONSENSUS=libbitcoin_consensus.a
LIBBITCOIN_CLI=libbitcoin_cli.a
@@ -30,32 +29,32 @@ LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a
LIBBITCOINQT=qt/libbitcoinqt.a
LIBSECP256K1=secp256k1/libsecp256k1.la
+if ENABLE_ZMQ
+LIBBITCOIN_ZMQ=libbitcoin_zmq.a
+endif
+if BUILD_BITCOIN_LIBS
+LIBBITCOINCONSENSUS=libdashconsensus.la
+endif
+if ENABLE_WALLET
+LIBBITCOIN_WALLET=libbitcoin_wallet.a
+endif
+
$(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F)
# Make is not made aware of per-object dependencies to avoid limiting building parallelization
# But to build the less dependent modules first, we manually select their order here:
EXTRA_LIBRARIES += \
- crypto/libbitcoin_crypto.a \
- libbitcoin_util.a \
- libbitcoin_common.a \
- libbitcoin_consensus.a \
- libbitcoin_server.a \
- libbitcoin_cli.a
-if ENABLE_WALLET
-BITCOIN_INCLUDES += $(BDB_CPPFLAGS)
-EXTRA_LIBRARIES += libbitcoin_wallet.a
-endif
-if ENABLE_ZMQ
-EXTRA_LIBRARIES += libbitcoin_zmq.a
-endif
+ $(LIBBITCOIN_CRYPTO) \
+ $(LIBBITCOIN_UTIL) \
+ $(LIBBITCOIN_COMMON) \
+ $(LIBBITCOIN_CONSENSUS) \
+ $(LIBBITCOIN_SERVER) \
+ $(LIBBITCOIN_CLI) \
+ $(LIBBITCOIN_WALLET) \
+ $(LIBBITCOIN_ZMQ)
-if BUILD_BITCOIN_LIBS
-lib_LTLIBRARIES = libdashconsensus.la
-LIBBITCOINCONSENSUS=libdashconsensus.la
-else
-LIBBITCOINCONSENSUS=
-endif
+lib_LTLIBRARIES = $(LIBBITCOINCONSENSUS)
bin_PROGRAMS =
TESTS =
@@ -117,6 +116,7 @@ BITCOIN_CORE_H = \
hdchain.h \
httprpc.h \
httpserver.h \
+ indirectmap.h \
init.h \
instantx.h \
key.h \
@@ -257,8 +257,6 @@ libbitcoin_server_a_SOURCES = \
$(BITCOIN_CORE_H)
if ENABLE_ZMQ
-LIBBITCOIN_ZMQ=libbitcoin_zmq.a
-
libbitcoin_zmq_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(ZMQ_CFLAGS)
libbitcoin_zmq_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_zmq_a_SOURCES = \
@@ -289,6 +287,8 @@ libbitcoin_wallet_a_SOURCES = \
crypto_libbitcoin_crypto_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_CONFIG_INCLUDES) $(PIC_FLAGS)
crypto_libbitcoin_crypto_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) $(PIC_FLAGS)
crypto_libbitcoin_crypto_a_SOURCES = \
+ crypto/aes.cpp \
+ crypto/aes.h \
crypto/common.h \
crypto/hmac_sha256.cpp \
crypto/hmac_sha256.h \
@@ -440,21 +440,15 @@ dashd_LDADD = \
$(LIBBITCOIN_COMMON) \
$(LIBUNIVALUE) \
$(LIBBITCOIN_UTIL) \
+ $(LIBBITCOIN_WALLET) \
+ $(LIBBITCOIN_ZMQ) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBLEVELDB) \
$(LIBMEMENV) \
$(LIBSECP256K1)
-if ENABLE_ZMQ
-dashd_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
-endif
-
-if ENABLE_WALLET
-dashd_LDADD += libbitcoin_wallet.a
-endif
-
-dashd_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
+dashd_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS)
# dash-cli binary #
dash_cli_SOURCES = dash-cli.cpp
@@ -512,8 +506,14 @@ libdashconsensus_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
endif
#
-CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a
-CLEANFILES += $(EXTRA_LIBRARIES)
+CTAES_DIST = crypto/ctaes/bench.c
+CTAES_DIST += crypto/ctaes/ctaes.c
+CTAES_DIST += crypto/ctaes/ctaes.h
+CTAES_DIST += crypto/ctaes/README.md
+CTAES_DIST += crypto/ctaes/test.c
+
+CLEANFILES = $(EXTRA_LIBRARIES)
+
CLEANFILES += *.gcda *.gcno
CLEANFILES += compat/*.gcda compat/*.gcno
CLEANFILES += consensus/*.gcda consensus/*.gcno
@@ -529,14 +529,14 @@ CLEANFILES += zmq/*.gcda zmq/*.gcno
DISTCLEANFILES = obj/build.h
-EXTRA_DIST = leveldb
+EXTRA_DIST = $(CTAES_DIST)
clean-local:
- -$(MAKE) -C leveldb clean
-$(MAKE) -C secp256k1 clean
-$(MAKE) -C univalue clean
-rm -f leveldb/*/*.gcda leveldb/*/*.gcno leveldb/helpers/memenv/*.gcda leveldb/helpers/memenv/*.gcno
-rm -f config.h
+ -rm -rf test/__pycache__
.rc.o:
@test -f $(WINDRES)
diff --git a/src/Makefile.leveldb.include b/src/Makefile.leveldb.include
index 88bb0c19326f..4b3cd6364a29 100644
--- a/src/Makefile.leveldb.include
+++ b/src/Makefile.leveldb.include
@@ -26,6 +26,61 @@ leveldb_libleveldb_a_CPPFLAGS = $(AM_CPPFLAGS) $(LEVELDB_CPPFLAGS_INT) $(LEVELDB
leveldb_libleveldb_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
leveldb_libleveldb_a_SOURCES=
+leveldb_libleveldb_a_SOURCES += leveldb/port/atomic_pointer.h
+leveldb_libleveldb_a_SOURCES += leveldb/port/port_example.h
+leveldb_libleveldb_a_SOURCES += leveldb/port/port_posix.h
+leveldb_libleveldb_a_SOURCES += leveldb/port/win/stdint.h
+leveldb_libleveldb_a_SOURCES += leveldb/port/port.h
+leveldb_libleveldb_a_SOURCES += leveldb/port/port_win.h
+leveldb_libleveldb_a_SOURCES += leveldb/port/thread_annotations.h
+leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/db.h
+leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/options.h
+leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/comparator.h
+leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/filter_policy.h
+leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/slice.h
+leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/table_builder.h
+leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/env.h
+leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/c.h
+leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/iterator.h
+leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/cache.h
+leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/dumpfile.h
+leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/table.h
+leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/write_batch.h
+leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/status.h
+leveldb_libleveldb_a_SOURCES += leveldb/db/log_format.h
+leveldb_libleveldb_a_SOURCES += leveldb/db/memtable.h
+leveldb_libleveldb_a_SOURCES += leveldb/db/version_set.h
+leveldb_libleveldb_a_SOURCES += leveldb/db/write_batch_internal.h
+leveldb_libleveldb_a_SOURCES += leveldb/db/filename.h
+leveldb_libleveldb_a_SOURCES += leveldb/db/version_edit.h
+leveldb_libleveldb_a_SOURCES += leveldb/db/dbformat.h
+leveldb_libleveldb_a_SOURCES += leveldb/db/builder.h
+leveldb_libleveldb_a_SOURCES += leveldb/db/log_writer.h
+leveldb_libleveldb_a_SOURCES += leveldb/db/db_iter.h
+leveldb_libleveldb_a_SOURCES += leveldb/db/skiplist.h
+leveldb_libleveldb_a_SOURCES += leveldb/db/db_impl.h
+leveldb_libleveldb_a_SOURCES += leveldb/db/table_cache.h
+leveldb_libleveldb_a_SOURCES += leveldb/db/snapshot.h
+leveldb_libleveldb_a_SOURCES += leveldb/db/log_reader.h
+leveldb_libleveldb_a_SOURCES += leveldb/table/filter_block.h
+leveldb_libleveldb_a_SOURCES += leveldb/table/block_builder.h
+leveldb_libleveldb_a_SOURCES += leveldb/table/block.h
+leveldb_libleveldb_a_SOURCES += leveldb/table/two_level_iterator.h
+leveldb_libleveldb_a_SOURCES += leveldb/table/merger.h
+leveldb_libleveldb_a_SOURCES += leveldb/table/format.h
+leveldb_libleveldb_a_SOURCES += leveldb/table/iterator_wrapper.h
+leveldb_libleveldb_a_SOURCES += leveldb/util/crc32c.h
+leveldb_libleveldb_a_SOURCES += leveldb/util/arena.h
+leveldb_libleveldb_a_SOURCES += leveldb/util/random.h
+leveldb_libleveldb_a_SOURCES += leveldb/util/posix_logger.h
+leveldb_libleveldb_a_SOURCES += leveldb/util/hash.h
+leveldb_libleveldb_a_SOURCES += leveldb/util/histogram.h
+leveldb_libleveldb_a_SOURCES += leveldb/util/coding.h
+leveldb_libleveldb_a_SOURCES += leveldb/util/testutil.h
+leveldb_libleveldb_a_SOURCES += leveldb/util/mutexlock.h
+leveldb_libleveldb_a_SOURCES += leveldb/util/logging.h
+leveldb_libleveldb_a_SOURCES += leveldb/util/testharness.h
+
leveldb_libleveldb_a_SOURCES += leveldb/db/builder.cc
leveldb_libleveldb_a_SOURCES += leveldb/db/c.cc
leveldb_libleveldb_a_SOURCES += leveldb/db/dbformat.cc
@@ -76,3 +131,4 @@ endif
leveldb_libmemenv_a_CPPFLAGS = $(leveldb_libleveldb_a_CPPFLAGS)
leveldb_libmemenv_a_CXXFLAGS = $(leveldb_libleveldb_a_CXXFLAGS)
leveldb_libmemenv_a_SOURCES = leveldb/helpers/memenv/memenv.cc
+leveldb_libmemenv_a_SOURCES += leveldb/helpers/memenv/memenv.h
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 90ee497c60be..dbdf3fcea4b2 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -569,19 +569,20 @@ QT_QM=$(QT_TS:.ts=.qm)
SECONDARY: $(QT_QM)
-qt/dashstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_zmq_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) $(libbitcoin_util_a_SOURCES)
+$(srcdir)/qt/dashstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_zmq_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) $(libbitcoin_util_a_SOURCES)
@test -n $(XGETTEXT) || echo "xgettext is required for updating translations"
$(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) PACKAGE_NAME="$(PACKAGE_NAME)" COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" COPYRIGHT_HOLDERS_SUBSTITUTION="$(COPYRIGHT_HOLDERS_SUBSTITUTION)" $(PYTHON) ../share/qt/extract_strings_qt.py $^
-translate: qt/dashstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) qt/dash.cpp $(BITCOIN_QT_H) $(BITCOIN_MM)
+translate: $(srcdir)/qt/dashstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(srcdir)/qt/dash.cpp $(BITCOIN_QT_H) $(BITCOIN_MM)
@test -n $(LUPDATE) || echo "lupdate is required for updating translations"
- $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LUPDATE) $^ -locations relative -no-obsolete -ts qt/locale/dash_en.ts
+ $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LUPDATE) $^ -locations relative -no-obsolete -ts $(srcdir)/qt/locale/dash_en.ts
$(QT_QRC_LOCALE_CPP): $(QT_QRC_LOCALE) $(QT_QM)
@test -f $(RCC)
- @test -f $(@D)/$( $@
+ @rm $(@D)/temp_$(
-struct CDNSSeedData {
+class CDNSSeedData {
+public:
std::string name, host;
- CDNSSeedData(const std::string &strName, const std::string &strHost) : name(strName), host(strHost) {}
+ bool supportsServiceBitsFiltering;
+ std::string getHost(uint64_t requiredServiceBits) const;
+ CDNSSeedData(const std::string &strName, const std::string &strHost, bool supportsServiceBitsFilteringIn = false) : name(strName), host(strHost), supportsServiceBitsFiltering(supportsServiceBitsFilteringIn) {}
};
struct SeedSpec6 {
diff --git a/src/clientversion.cpp b/src/clientversion.cpp
index 03c93e0ec840..5061eb3a6e36 100644
--- a/src/clientversion.cpp
+++ b/src/clientversion.cpp
@@ -67,16 +67,7 @@ const std::string CLIENT_NAME("Dash Core");
#endif
#endif
-#ifndef BUILD_DATE
-#ifdef GIT_COMMIT_DATE
-#define BUILD_DATE GIT_COMMIT_DATE
-#else
-#define BUILD_DATE __DATE__ ", " __TIME__
-#endif
-#endif
-
const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
-const std::string CLIENT_DATE(BUILD_DATE);
static std::string FormatVersion(int nVersion)
{
diff --git a/src/clientversion.h b/src/clientversion.h
index 496d0e0bf043..071c386c9af6 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -59,7 +59,6 @@ static const int CLIENT_VERSION =
extern const std::string CLIENT_NAME;
extern const std::string CLIENT_BUILD;
-extern const std::string CLIENT_DATE;
std::string FormatFullVersion();
diff --git a/src/coincontrol.h b/src/coincontrol.h
index ff8f33a8475c..cd382c7abb31 100644
--- a/src/coincontrol.h
+++ b/src/coincontrol.h
@@ -20,6 +20,10 @@ class CCoinControl
bool fAllowWatchOnly;
//! Minimum absolute fee (not per kilobyte)
CAmount nMinimumTotalFee;
+ //! Override estimated feerate
+ bool fOverrideFeeRate;
+ //! Feerate to use if overrideFeeRate is true
+ CFeeRate nFeeRate;
CCoinControl()
{
@@ -35,6 +39,8 @@ class CCoinControl
fUseInstantSend = false;
fUsePrivateSend = true;
nMinimumTotalFee = 0;
+ nFeeRate = CFeeRate(0);
+ fOverrideFeeRate = false;
}
bool HasSelected() const
diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp
new file mode 100644
index 000000000000..1d469d0fb462
--- /dev/null
+++ b/src/crypto/aes.cpp
@@ -0,0 +1,217 @@
+// Copyright (c) 2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "aes.h"
+#include "crypto/common.h"
+
+#include
+#include
+
+extern "C" {
+#include "crypto/ctaes/ctaes.c"
+}
+
+AES128Encrypt::AES128Encrypt(const unsigned char key[16])
+{
+ AES128_init(&ctx, key);
+}
+
+AES128Encrypt::~AES128Encrypt()
+{
+ memset(&ctx, 0, sizeof(ctx));
+}
+
+void AES128Encrypt::Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const
+{
+ AES128_encrypt(&ctx, 1, ciphertext, plaintext);
+}
+
+AES128Decrypt::AES128Decrypt(const unsigned char key[16])
+{
+ AES128_init(&ctx, key);
+}
+
+AES128Decrypt::~AES128Decrypt()
+{
+ memset(&ctx, 0, sizeof(ctx));
+}
+
+void AES128Decrypt::Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const
+{
+ AES128_decrypt(&ctx, 1, plaintext, ciphertext);
+}
+
+AES256Encrypt::AES256Encrypt(const unsigned char key[32])
+{
+ AES256_init(&ctx, key);
+}
+
+AES256Encrypt::~AES256Encrypt()
+{
+ memset(&ctx, 0, sizeof(ctx));
+}
+
+void AES256Encrypt::Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const
+{
+ AES256_encrypt(&ctx, 1, ciphertext, plaintext);
+}
+
+AES256Decrypt::AES256Decrypt(const unsigned char key[32])
+{
+ AES256_init(&ctx, key);
+}
+
+AES256Decrypt::~AES256Decrypt()
+{
+ memset(&ctx, 0, sizeof(ctx));
+}
+
+void AES256Decrypt::Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const
+{
+ AES256_decrypt(&ctx, 1, plaintext, ciphertext);
+}
+
+
+template
+static int CBCEncrypt(const T& enc, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out)
+{
+ int written = 0;
+ int padsize = size % AES_BLOCKSIZE;
+ unsigned char mixed[AES_BLOCKSIZE];
+
+ if (!data || !size || !out)
+ return 0;
+
+ if (!pad && padsize != 0)
+ return 0;
+
+ memcpy(mixed, iv, AES_BLOCKSIZE);
+
+ // Write all but the last block
+ while (written + AES_BLOCKSIZE <= size) {
+ for (int i = 0; i != AES_BLOCKSIZE; i++)
+ mixed[i] ^= *data++;
+ enc.Encrypt(out + written, mixed);
+ memcpy(mixed, out + written, AES_BLOCKSIZE);
+ written += AES_BLOCKSIZE;
+ }
+ if (pad) {
+ // For all that remains, pad each byte with the value of the remaining
+ // space. If there is none, pad by a full block.
+ for (int i = 0; i != padsize; i++)
+ mixed[i] ^= *data++;
+ for (int i = padsize; i != AES_BLOCKSIZE; i++)
+ mixed[i] ^= AES_BLOCKSIZE - padsize;
+ enc.Encrypt(out + written, mixed);
+ written += AES_BLOCKSIZE;
+ }
+ return written;
+}
+
+template
+static int CBCDecrypt(const T& dec, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out)
+{
+ unsigned char padsize = 0;
+ int written = 0;
+ bool fail = false;
+ const unsigned char* prev = iv;
+
+ if (!data || !size || !out)
+ return 0;
+
+ if (size % AES_BLOCKSIZE != 0)
+ return 0;
+
+ // Decrypt all data. Padding will be checked in the output.
+ while (written != size) {
+ dec.Decrypt(out, data + written);
+ for (int i = 0; i != AES_BLOCKSIZE; i++)
+ *out++ ^= prev[i];
+ prev = data + written;
+ written += AES_BLOCKSIZE;
+ }
+
+ // When decrypting padding, attempt to run in constant-time
+ if (pad) {
+ // If used, padding size is the value of the last decrypted byte. For
+ // it to be valid, It must be between 1 and AES_BLOCKSIZE.
+ padsize = *--out;
+ fail = !padsize | (padsize > AES_BLOCKSIZE);
+
+ // If not well-formed, treat it as though there's no padding.
+ padsize *= !fail;
+
+ // All padding must equal the last byte otherwise it's not well-formed
+ for (int i = AES_BLOCKSIZE; i != 0; i--)
+ fail |= ((i > AES_BLOCKSIZE - padsize) & (*out-- != padsize));
+
+ written -= padsize;
+ }
+ return written * !fail;
+}
+
+AES256CBCEncrypt::AES256CBCEncrypt(const unsigned char key[AES256_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn)
+ : enc(key), pad(padIn)
+{
+ memcpy(iv, ivIn, AES_BLOCKSIZE);
+}
+
+int AES256CBCEncrypt::Encrypt(const unsigned char* data, int size, unsigned char* out) const
+{
+ return CBCEncrypt(enc, iv, data, size, pad, out);
+}
+
+AES256CBCEncrypt::~AES256CBCEncrypt()
+{
+ memset(iv, 0, sizeof(iv));
+}
+
+AES256CBCDecrypt::AES256CBCDecrypt(const unsigned char key[AES256_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn)
+ : dec(key), pad(padIn)
+{
+ memcpy(iv, ivIn, AES_BLOCKSIZE);
+}
+
+
+int AES256CBCDecrypt::Decrypt(const unsigned char* data, int size, unsigned char* out) const
+{
+ return CBCDecrypt(dec, iv, data, size, pad, out);
+}
+
+AES256CBCDecrypt::~AES256CBCDecrypt()
+{
+ memset(iv, 0, sizeof(iv));
+}
+
+AES128CBCEncrypt::AES128CBCEncrypt(const unsigned char key[AES128_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn)
+ : enc(key), pad(padIn)
+{
+ memcpy(iv, ivIn, AES_BLOCKSIZE);
+}
+
+AES128CBCEncrypt::~AES128CBCEncrypt()
+{
+ memset(iv, 0, AES_BLOCKSIZE);
+}
+
+int AES128CBCEncrypt::Encrypt(const unsigned char* data, int size, unsigned char* out) const
+{
+ return CBCEncrypt(enc, iv, data, size, pad, out);
+}
+
+AES128CBCDecrypt::AES128CBCDecrypt(const unsigned char key[AES128_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn)
+ : dec(key), pad(padIn)
+{
+ memcpy(iv, ivIn, AES_BLOCKSIZE);
+}
+
+AES128CBCDecrypt::~AES128CBCDecrypt()
+{
+ memset(iv, 0, AES_BLOCKSIZE);
+}
+
+int AES128CBCDecrypt::Decrypt(const unsigned char* data, int size, unsigned char* out) const
+{
+ return CBCDecrypt(dec, iv, data, size, pad, out);
+}
diff --git a/src/crypto/aes.h b/src/crypto/aes.h
new file mode 100644
index 000000000000..8cae357c1287
--- /dev/null
+++ b/src/crypto/aes.h
@@ -0,0 +1,118 @@
+// Copyright (c) 2015 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+//
+// C++ wrapper around ctaes, a constant-time AES implementation
+
+#ifndef BITCOIN_CRYPTO_AES_H
+#define BITCOIN_CRYPTO_AES_H
+
+extern "C" {
+#include "crypto/ctaes/ctaes.h"
+}
+
+static const int AES_BLOCKSIZE = 16;
+static const int AES128_KEYSIZE = 16;
+static const int AES256_KEYSIZE = 32;
+
+/** An encryption class for AES-128. */
+class AES128Encrypt
+{
+private:
+ AES128_ctx ctx;
+
+public:
+ AES128Encrypt(const unsigned char key[16]);
+ ~AES128Encrypt();
+ void Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const;
+};
+
+/** A decryption class for AES-128. */
+class AES128Decrypt
+{
+private:
+ AES128_ctx ctx;
+
+public:
+ AES128Decrypt(const unsigned char key[16]);
+ ~AES128Decrypt();
+ void Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const;
+};
+
+/** An encryption class for AES-256. */
+class AES256Encrypt
+{
+private:
+ AES256_ctx ctx;
+
+public:
+ AES256Encrypt(const unsigned char key[32]);
+ ~AES256Encrypt();
+ void Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const;
+};
+
+/** A decryption class for AES-256. */
+class AES256Decrypt
+{
+private:
+ AES256_ctx ctx;
+
+public:
+ AES256Decrypt(const unsigned char key[32]);
+ ~AES256Decrypt();
+ void Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const;
+};
+
+class AES256CBCEncrypt
+{
+public:
+ AES256CBCEncrypt(const unsigned char key[AES256_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn);
+ ~AES256CBCEncrypt();
+ int Encrypt(const unsigned char* data, int size, unsigned char* out) const;
+
+private:
+ const AES256Encrypt enc;
+ const bool pad;
+ unsigned char iv[AES_BLOCKSIZE];
+};
+
+class AES256CBCDecrypt
+{
+public:
+ AES256CBCDecrypt(const unsigned char key[AES256_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn);
+ ~AES256CBCDecrypt();
+ int Decrypt(const unsigned char* data, int size, unsigned char* out) const;
+
+private:
+ const AES256Decrypt dec;
+ const bool pad;
+ unsigned char iv[AES_BLOCKSIZE];
+};
+
+class AES128CBCEncrypt
+{
+public:
+ AES128CBCEncrypt(const unsigned char key[AES128_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn);
+ ~AES128CBCEncrypt();
+ int Encrypt(const unsigned char* data, int size, unsigned char* out) const;
+
+private:
+ const AES128Encrypt enc;
+ const bool pad;
+ unsigned char iv[AES_BLOCKSIZE];
+};
+
+class AES128CBCDecrypt
+{
+public:
+ AES128CBCDecrypt(const unsigned char key[AES128_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn);
+ ~AES128CBCDecrypt();
+ int Decrypt(const unsigned char* data, int size, unsigned char* out) const;
+
+private:
+ const AES128Decrypt dec;
+ const bool pad;
+ unsigned char iv[AES_BLOCKSIZE];
+};
+
+#endif // BITCOIN_CRYPTO_AES_H
diff --git a/src/crypto/ctaes/COPYING b/src/crypto/ctaes/COPYING
new file mode 100644
index 000000000000..415b202a2a54
--- /dev/null
+++ b/src/crypto/ctaes/COPYING
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Pieter Wuille
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/src/crypto/ctaes/README.md b/src/crypto/ctaes/README.md
new file mode 100644
index 000000000000..0e7fe1775153
--- /dev/null
+++ b/src/crypto/ctaes/README.md
@@ -0,0 +1,41 @@
+ctaes
+=====
+
+Simple C module for constant-time AES encryption and decryption.
+
+Features:
+* Simple, pure C code without any dependencies.
+* No tables or data-dependent branches whatsoever, but using bit sliced approach from https://eprint.iacr.org/2009/129.pdf.
+* Very small object code: slightly over 4k of executable code when compiled with -Os.
+* Slower than implementations based on precomputed tables or specialized instructions, but can do ~15 MB/s on modern CPUs.
+
+Performance
+-----------
+
+Compiled with GCC 5.3.1 with -O3, on an Intel(R) Core(TM) i7-4800MQ CPU, numbers in CPU cycles:
+
+| Algorithm | Key schedule | Encryption per byte | Decryption per byte |
+| --------- | ------------:| -------------------:| -------------------:|
+| AES-128 | 2.8k | 154 | 161 |
+| AES-192 | 3.1k | 169 | 181 |
+| AES-256 | 4.0k | 191 | 203 |
+
+Build steps
+-----------
+
+Object code:
+
+ $ gcc -O3 ctaes.c -c -o ctaes.o
+
+Tests:
+
+ $ gcc -O3 ctaes.c test.c -o test
+
+Benchmark:
+
+ $ gcc -O3 ctaes.c bench.c -o bench
+
+Review
+------
+
+Results of a formal review of the code can be found in http://bitcoin.sipa.be/ctaes/review.zip
diff --git a/src/crypto/ctaes/bench.c b/src/crypto/ctaes/bench.c
new file mode 100644
index 000000000000..a86df496c830
--- /dev/null
+++ b/src/crypto/ctaes/bench.c
@@ -0,0 +1,170 @@
+#include
+#include
+#include "sys/time.h"
+
+#include "ctaes.h"
+
+static double gettimedouble(void) {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_usec * 0.000001 + tv.tv_sec;
+}
+
+static void print_number(double x) {
+ double y = x;
+ int c = 0;
+ if (y < 0.0) {
+ y = -y;
+ }
+ while (y < 100.0) {
+ y *= 10.0;
+ c++;
+ }
+ printf("%.*f", c, x);
+}
+
+static void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) {
+ int i;
+ double min = HUGE_VAL;
+ double sum = 0.0;
+ double max = 0.0;
+ for (i = 0; i < count; i++) {
+ double begin, total;
+ if (setup != NULL) {
+ setup(data);
+ }
+ begin = gettimedouble();
+ benchmark(data);
+ total = gettimedouble() - begin;
+ if (teardown != NULL) {
+ teardown(data);
+ }
+ if (total < min) {
+ min = total;
+ }
+ if (total > max) {
+ max = total;
+ }
+ sum += total;
+ }
+ printf("%s: min ", name);
+ print_number(min * 1000000000.0 / iter);
+ printf("ns / avg ");
+ print_number((sum / count) * 1000000000.0 / iter);
+ printf("ns / max ");
+ print_number(max * 1000000000.0 / iter);
+ printf("ns\n");
+}
+
+static void bench_AES128_init(void* data) {
+ AES128_ctx* ctx = (AES128_ctx*)data;
+ int i;
+ for (i = 0; i < 50000; i++) {
+ AES128_init(ctx, (unsigned char*)ctx);
+ }
+}
+
+static void bench_AES128_encrypt_setup(void* data) {
+ AES128_ctx* ctx = (AES128_ctx*)data;
+ static const unsigned char key[16] = {0};
+ AES128_init(ctx, key);
+}
+
+static void bench_AES128_encrypt(void* data) {
+ const AES128_ctx* ctx = (const AES128_ctx*)data;
+ unsigned char scratch[16] = {0};
+ int i;
+ for (i = 0; i < 4000000 / 16; i++) {
+ AES128_encrypt(ctx, 1, scratch, scratch);
+ }
+}
+
+static void bench_AES128_decrypt(void* data) {
+ const AES128_ctx* ctx = (const AES128_ctx*)data;
+ unsigned char scratch[16] = {0};
+ int i;
+ for (i = 0; i < 4000000 / 16; i++) {
+ AES128_decrypt(ctx, 1, scratch, scratch);
+ }
+}
+
+static void bench_AES192_init(void* data) {
+ AES192_ctx* ctx = (AES192_ctx*)data;
+ int i;
+ for (i = 0; i < 50000; i++) {
+ AES192_init(ctx, (unsigned char*)ctx);
+ }
+}
+
+static void bench_AES192_encrypt_setup(void* data) {
+ AES192_ctx* ctx = (AES192_ctx*)data;
+ static const unsigned char key[16] = {0};
+ AES192_init(ctx, key);
+}
+
+static void bench_AES192_encrypt(void* data) {
+ const AES192_ctx* ctx = (const AES192_ctx*)data;
+ unsigned char scratch[16] = {0};
+ int i;
+ for (i = 0; i < 4000000 / 16; i++) {
+ AES192_encrypt(ctx, 1, scratch, scratch);
+ }
+}
+
+static void bench_AES192_decrypt(void* data) {
+ const AES192_ctx* ctx = (const AES192_ctx*)data;
+ unsigned char scratch[16] = {0};
+ int i;
+ for (i = 0; i < 4000000 / 16; i++) {
+ AES192_decrypt(ctx, 1, scratch, scratch);
+ }
+}
+
+static void bench_AES256_init(void* data) {
+ AES256_ctx* ctx = (AES256_ctx*)data;
+ int i;
+ for (i = 0; i < 50000; i++) {
+ AES256_init(ctx, (unsigned char*)ctx);
+ }
+}
+
+
+static void bench_AES256_encrypt_setup(void* data) {
+ AES256_ctx* ctx = (AES256_ctx*)data;
+ static const unsigned char key[16] = {0};
+ AES256_init(ctx, key);
+}
+
+static void bench_AES256_encrypt(void* data) {
+ const AES256_ctx* ctx = (const AES256_ctx*)data;
+ unsigned char scratch[16] = {0};
+ int i;
+ for (i = 0; i < 4000000 / 16; i++) {
+ AES256_encrypt(ctx, 1, scratch, scratch);
+ }
+}
+
+static void bench_AES256_decrypt(void* data) {
+ const AES256_ctx* ctx = (const AES256_ctx*)data;
+ unsigned char scratch[16] = {0};
+ int i;
+ for (i = 0; i < 4000000 / 16; i++) {
+ AES256_decrypt(ctx, 1, scratch, scratch);
+ }
+}
+
+int main(void) {
+ AES128_ctx ctx128;
+ AES192_ctx ctx192;
+ AES256_ctx ctx256;
+ run_benchmark("aes128_init", bench_AES128_init, NULL, NULL, &ctx128, 20, 50000);
+ run_benchmark("aes128_encrypt_byte", bench_AES128_encrypt, bench_AES128_encrypt_setup, NULL, &ctx128, 20, 4000000);
+ run_benchmark("aes128_decrypt_byte", bench_AES128_decrypt, bench_AES128_encrypt_setup, NULL, &ctx128, 20, 4000000);
+ run_benchmark("aes192_init", bench_AES192_init, NULL, NULL, &ctx192, 20, 50000);
+ run_benchmark("aes192_encrypt_byte", bench_AES192_encrypt, bench_AES192_encrypt_setup, NULL, &ctx192, 20, 4000000);
+ run_benchmark("aes192_decrypt_byte", bench_AES192_decrypt, bench_AES192_encrypt_setup, NULL, &ctx192, 20, 4000000);
+ run_benchmark("aes256_init", bench_AES256_init, NULL, NULL, &ctx256, 20, 50000);
+ run_benchmark("aes256_encrypt_byte", bench_AES256_encrypt, bench_AES256_encrypt_setup, NULL, &ctx256, 20, 4000000);
+ run_benchmark("aes256_decrypt_byte", bench_AES256_decrypt, bench_AES256_encrypt_setup, NULL, &ctx256, 20, 4000000);
+ return 0;
+}
diff --git a/src/crypto/ctaes/ctaes.c b/src/crypto/ctaes/ctaes.c
new file mode 100644
index 000000000000..2389fc0bb254
--- /dev/null
+++ b/src/crypto/ctaes/ctaes.c
@@ -0,0 +1,556 @@
+ /*********************************************************************
+ * Copyright (c) 2016 Pieter Wuille *
+ * Distributed under the MIT software license, see the accompanying *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+
+/* Constant time, unoptimized, concise, plain C, AES implementation
+ * Based On:
+ * Emilia Kasper and Peter Schwabe, Faster and Timing-Attack Resistant AES-GCM
+ * http://www.iacr.org/archive/ches2009/57470001/57470001.pdf
+ * But using 8 16-bit integers representing a single AES state rather than 8 128-bit
+ * integers representing 8 AES states.
+ */
+
+#include "ctaes.h"
+
+/* Slice variable slice_i contains the i'th bit of the 16 state variables in this order:
+ * 0 1 2 3
+ * 4 5 6 7
+ * 8 9 10 11
+ * 12 13 14 15
+ */
+
+/** Convert a byte to sliced form, storing it corresponding to given row and column in s */
+static void LoadByte(AES_state* s, unsigned char byte, int r, int c) {
+ int i;
+ for (i = 0; i < 8; i++) {
+ s->slice[i] |= (byte & 1) << (r * 4 + c);
+ byte >>= 1;
+ }
+}
+
+/** Load 16 bytes of data into 8 sliced integers */
+static void LoadBytes(AES_state *s, const unsigned char* data16) {
+ int c;
+ for (c = 0; c < 4; c++) {
+ int r;
+ for (r = 0; r < 4; r++) {
+ LoadByte(s, *(data16++), r, c);
+ }
+ }
+}
+
+/** Convert 8 sliced integers into 16 bytes of data */
+static void SaveBytes(unsigned char* data16, const AES_state *s) {
+ int c;
+ for (c = 0; c < 4; c++) {
+ int r;
+ for (r = 0; r < 4; r++) {
+ int b;
+ uint8_t v = 0;
+ for (b = 0; b < 8; b++) {
+ v |= ((s->slice[b] >> (r * 4 + c)) & 1) << b;
+ }
+ *(data16++) = v;
+ }
+ }
+}
+
+/* S-box implementation based on the gate logic from:
+ * Joan Boyar and Rene Peralta, A depth-16 circuit for the AES S-box.
+ * https://eprint.iacr.org/2011/332.pdf
+*/
+static void SubBytes(AES_state *s, int inv) {
+ /* Load the bit slices */
+ uint16_t U0 = s->slice[7], U1 = s->slice[6], U2 = s->slice[5], U3 = s->slice[4];
+ uint16_t U4 = s->slice[3], U5 = s->slice[2], U6 = s->slice[1], U7 = s->slice[0];
+
+ uint16_t T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16;
+ uint16_t T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, D;
+ uint16_t M1, M6, M11, M13, M15, M20, M21, M22, M23, M25, M37, M38, M39, M40;
+ uint16_t M41, M42, M43, M44, M45, M46, M47, M48, M49, M50, M51, M52, M53, M54;
+ uint16_t M55, M56, M57, M58, M59, M60, M61, M62, M63;
+
+ if (inv) {
+ uint16_t R5, R13, R17, R18, R19;
+ /* Undo linear postprocessing */
+ T23 = U0 ^ U3;
+ T22 = ~(U1 ^ U3);
+ T2 = ~(U0 ^ U1);
+ T1 = U3 ^ U4;
+ T24 = ~(U4 ^ U7);
+ R5 = U6 ^ U7;
+ T8 = ~(U1 ^ T23);
+ T19 = T22 ^ R5;
+ T9 = ~(U7 ^ T1);
+ T10 = T2 ^ T24;
+ T13 = T2 ^ R5;
+ T3 = T1 ^ R5;
+ T25 = ~(U2 ^ T1);
+ R13 = U1 ^ U6;
+ T17 = ~(U2 ^ T19);
+ T20 = T24 ^ R13;
+ T4 = U4 ^ T8;
+ R17 = ~(U2 ^ U5);
+ R18 = ~(U5 ^ U6);
+ R19 = ~(U2 ^ U4);
+ D = U0 ^ R17;
+ T6 = T22 ^ R17;
+ T16 = R13 ^ R19;
+ T27 = T1 ^ R18;
+ T15 = T10 ^ T27;
+ T14 = T10 ^ R18;
+ T26 = T3 ^ T16;
+ } else {
+ /* Linear preprocessing. */
+ T1 = U0 ^ U3;
+ T2 = U0 ^ U5;
+ T3 = U0 ^ U6;
+ T4 = U3 ^ U5;
+ T5 = U4 ^ U6;
+ T6 = T1 ^ T5;
+ T7 = U1 ^ U2;
+ T8 = U7 ^ T6;
+ T9 = U7 ^ T7;
+ T10 = T6 ^ T7;
+ T11 = U1 ^ U5;
+ T12 = U2 ^ U5;
+ T13 = T3 ^ T4;
+ T14 = T6 ^ T11;
+ T15 = T5 ^ T11;
+ T16 = T5 ^ T12;
+ T17 = T9 ^ T16;
+ T18 = U3 ^ U7;
+ T19 = T7 ^ T18;
+ T20 = T1 ^ T19;
+ T21 = U6 ^ U7;
+ T22 = T7 ^ T21;
+ T23 = T2 ^ T22;
+ T24 = T2 ^ T10;
+ T25 = T20 ^ T17;
+ T26 = T3 ^ T16;
+ T27 = T1 ^ T12;
+ D = U7;
+ }
+
+ /* Non-linear transformation (identical to the code in SubBytes) */
+ M1 = T13 & T6;
+ M6 = T3 & T16;
+ M11 = T1 & T15;
+ M13 = (T4 & T27) ^ M11;
+ M15 = (T2 & T10) ^ M11;
+ M20 = T14 ^ M1 ^ (T23 & T8) ^ M13;
+ M21 = (T19 & D) ^ M1 ^ T24 ^ M15;
+ M22 = T26 ^ M6 ^ (T22 & T9) ^ M13;
+ M23 = (T20 & T17) ^ M6 ^ M15 ^ T25;
+ M25 = M22 & M20;
+ M37 = M21 ^ ((M20 ^ M21) & (M23 ^ M25));
+ M38 = M20 ^ M25 ^ (M21 | (M20 & M23));
+ M39 = M23 ^ ((M22 ^ M23) & (M21 ^ M25));
+ M40 = M22 ^ M25 ^ (M23 | (M21 & M22));
+ M41 = M38 ^ M40;
+ M42 = M37 ^ M39;
+ M43 = M37 ^ M38;
+ M44 = M39 ^ M40;
+ M45 = M42 ^ M41;
+ M46 = M44 & T6;
+ M47 = M40 & T8;
+ M48 = M39 & D;
+ M49 = M43 & T16;
+ M50 = M38 & T9;
+ M51 = M37 & T17;
+ M52 = M42 & T15;
+ M53 = M45 & T27;
+ M54 = M41 & T10;
+ M55 = M44 & T13;
+ M56 = M40 & T23;
+ M57 = M39 & T19;
+ M58 = M43 & T3;
+ M59 = M38 & T22;
+ M60 = M37 & T20;
+ M61 = M42 & T1;
+ M62 = M45 & T4;
+ M63 = M41 & T2;
+
+ if (inv){
+ /* Undo linear preprocessing */
+ uint16_t P0 = M52 ^ M61;
+ uint16_t P1 = M58 ^ M59;
+ uint16_t P2 = M54 ^ M62;
+ uint16_t P3 = M47 ^ M50;
+ uint16_t P4 = M48 ^ M56;
+ uint16_t P5 = M46 ^ M51;
+ uint16_t P6 = M49 ^ M60;
+ uint16_t P7 = P0 ^ P1;
+ uint16_t P8 = M50 ^ M53;
+ uint16_t P9 = M55 ^ M63;
+ uint16_t P10 = M57 ^ P4;
+ uint16_t P11 = P0 ^ P3;
+ uint16_t P12 = M46 ^ M48;
+ uint16_t P13 = M49 ^ M51;
+ uint16_t P14 = M49 ^ M62;
+ uint16_t P15 = M54 ^ M59;
+ uint16_t P16 = M57 ^ M61;
+ uint16_t P17 = M58 ^ P2;
+ uint16_t P18 = M63 ^ P5;
+ uint16_t P19 = P2 ^ P3;
+ uint16_t P20 = P4 ^ P6;
+ uint16_t P22 = P2 ^ P7;
+ uint16_t P23 = P7 ^ P8;
+ uint16_t P24 = P5 ^ P7;
+ uint16_t P25 = P6 ^ P10;
+ uint16_t P26 = P9 ^ P11;
+ uint16_t P27 = P10 ^ P18;
+ uint16_t P28 = P11 ^ P25;
+ uint16_t P29 = P15 ^ P20;
+ s->slice[7] = P13 ^ P22;
+ s->slice[6] = P26 ^ P29;
+ s->slice[5] = P17 ^ P28;
+ s->slice[4] = P12 ^ P22;
+ s->slice[3] = P23 ^ P27;
+ s->slice[2] = P19 ^ P24;
+ s->slice[1] = P14 ^ P23;
+ s->slice[0] = P9 ^ P16;
+ } else {
+ /* Linear postprocessing */
+ uint16_t L0 = M61 ^ M62;
+ uint16_t L1 = M50 ^ M56;
+ uint16_t L2 = M46 ^ M48;
+ uint16_t L3 = M47 ^ M55;
+ uint16_t L4 = M54 ^ M58;
+ uint16_t L5 = M49 ^ M61;
+ uint16_t L6 = M62 ^ L5;
+ uint16_t L7 = M46 ^ L3;
+ uint16_t L8 = M51 ^ M59;
+ uint16_t L9 = M52 ^ M53;
+ uint16_t L10 = M53 ^ L4;
+ uint16_t L11 = M60 ^ L2;
+ uint16_t L12 = M48 ^ M51;
+ uint16_t L13 = M50 ^ L0;
+ uint16_t L14 = M52 ^ M61;
+ uint16_t L15 = M55 ^ L1;
+ uint16_t L16 = M56 ^ L0;
+ uint16_t L17 = M57 ^ L1;
+ uint16_t L18 = M58 ^ L8;
+ uint16_t L19 = M63 ^ L4;
+ uint16_t L20 = L0 ^ L1;
+ uint16_t L21 = L1 ^ L7;
+ uint16_t L22 = L3 ^ L12;
+ uint16_t L23 = L18 ^ L2;
+ uint16_t L24 = L15 ^ L9;
+ uint16_t L25 = L6 ^ L10;
+ uint16_t L26 = L7 ^ L9;
+ uint16_t L27 = L8 ^ L10;
+ uint16_t L28 = L11 ^ L14;
+ uint16_t L29 = L11 ^ L17;
+ s->slice[7] = L6 ^ L24;
+ s->slice[6] = ~(L16 ^ L26);
+ s->slice[5] = ~(L19 ^ L28);
+ s->slice[4] = L6 ^ L21;
+ s->slice[3] = L20 ^ L22;
+ s->slice[2] = L25 ^ L29;
+ s->slice[1] = ~(L13 ^ L27);
+ s->slice[0] = ~(L6 ^ L23);
+ }
+}
+
+#define BIT_RANGE(from,to) (((1 << ((to) - (from))) - 1) << (from))
+
+#define BIT_RANGE_LEFT(x,from,to,shift) (((x) & BIT_RANGE((from), (to))) << (shift))
+#define BIT_RANGE_RIGHT(x,from,to,shift) (((x) & BIT_RANGE((from), (to))) >> (shift))
+
+static void ShiftRows(AES_state* s) {
+ int i;
+ for (i = 0; i < 8; i++) {
+ uint16_t v = s->slice[i];
+ s->slice[i] =
+ (v & BIT_RANGE(0, 4)) |
+ BIT_RANGE_LEFT(v, 4, 5, 3) | BIT_RANGE_RIGHT(v, 5, 8, 1) |
+ BIT_RANGE_LEFT(v, 8, 10, 2) | BIT_RANGE_RIGHT(v, 10, 12, 2) |
+ BIT_RANGE_LEFT(v, 12, 15, 1) | BIT_RANGE_RIGHT(v, 15, 16, 3);
+ }
+}
+
+static void InvShiftRows(AES_state* s) {
+ int i;
+ for (i = 0; i < 8; i++) {
+ uint16_t v = s->slice[i];
+ s->slice[i] =
+ (v & BIT_RANGE(0, 4)) |
+ BIT_RANGE_LEFT(v, 4, 7, 1) | BIT_RANGE_RIGHT(v, 7, 8, 3) |
+ BIT_RANGE_LEFT(v, 8, 10, 2) | BIT_RANGE_RIGHT(v, 10, 12, 2) |
+ BIT_RANGE_LEFT(v, 12, 13, 3) | BIT_RANGE_RIGHT(v, 13, 16, 1);
+ }
+}
+
+#define ROT(x,b) (((x) >> ((b) * 4)) | ((x) << ((4-(b)) * 4)))
+
+static void MixColumns(AES_state* s, int inv) {
+ /* The MixColumns transform treats the bytes of the columns of the state as
+ * coefficients of a 3rd degree polynomial over GF(2^8) and multiplies them
+ * by the fixed polynomial a(x) = {03}x^3 + {01}x^2 + {01}x + {02}, modulo
+ * x^4 + {01}.
+ *
+ * In the inverse transform, we multiply by the inverse of a(x),
+ * a^-1(x) = {0b}x^3 + {0d}x^2 + {09}x + {0e}. This is equal to
+ * a(x) * ({04}x^2 + {05}), so we can reuse the forward transform's code
+ * (found in OpenSSL's bsaes-x86_64.pl, attributed to Jussi Kivilinna)
+ *
+ * In the bitsliced representation, a multiplication of every column by x
+ * mod x^4 + 1 is simply a right rotation.
+ */
+
+ /* Shared for both directions is a multiplication by a(x), which can be
+ * rewritten as (x^3 + x^2 + x) + {02}*(x^3 + {01}).
+ *
+ * First compute s into the s? variables, (x^3 + {01}) * s into the s?_01
+ * variables and (x^3 + x^2 + x)*s into the s?_123 variables.
+ */
+ uint16_t s0 = s->slice[0], s1 = s->slice[1], s2 = s->slice[2], s3 = s->slice[3];
+ uint16_t s4 = s->slice[4], s5 = s->slice[5], s6 = s->slice[6], s7 = s->slice[7];
+ uint16_t s0_01 = s0 ^ ROT(s0, 1), s0_123 = ROT(s0_01, 1) ^ ROT(s0, 3);
+ uint16_t s1_01 = s1 ^ ROT(s1, 1), s1_123 = ROT(s1_01, 1) ^ ROT(s1, 3);
+ uint16_t s2_01 = s2 ^ ROT(s2, 1), s2_123 = ROT(s2_01, 1) ^ ROT(s2, 3);
+ uint16_t s3_01 = s3 ^ ROT(s3, 1), s3_123 = ROT(s3_01, 1) ^ ROT(s3, 3);
+ uint16_t s4_01 = s4 ^ ROT(s4, 1), s4_123 = ROT(s4_01, 1) ^ ROT(s4, 3);
+ uint16_t s5_01 = s5 ^ ROT(s5, 1), s5_123 = ROT(s5_01, 1) ^ ROT(s5, 3);
+ uint16_t s6_01 = s6 ^ ROT(s6, 1), s6_123 = ROT(s6_01, 1) ^ ROT(s6, 3);
+ uint16_t s7_01 = s7 ^ ROT(s7, 1), s7_123 = ROT(s7_01, 1) ^ ROT(s7, 3);
+ /* Now compute s = s?_123 + {02} * s?_01. */
+ s->slice[0] = s7_01 ^ s0_123;
+ s->slice[1] = s7_01 ^ s0_01 ^ s1_123;
+ s->slice[2] = s1_01 ^ s2_123;
+ s->slice[3] = s7_01 ^ s2_01 ^ s3_123;
+ s->slice[4] = s7_01 ^ s3_01 ^ s4_123;
+ s->slice[5] = s4_01 ^ s5_123;
+ s->slice[6] = s5_01 ^ s6_123;
+ s->slice[7] = s6_01 ^ s7_123;
+ if (inv) {
+ /* In the reverse direction, we further need to multiply by
+ * {04}x^2 + {05}, which can be written as {04} * (x^2 + {01}) + {01}.
+ *
+ * First compute (x^2 + {01}) * s into the t?_02 variables: */
+ uint16_t t0_02 = s->slice[0] ^ ROT(s->slice[0], 2);
+ uint16_t t1_02 = s->slice[1] ^ ROT(s->slice[1], 2);
+ uint16_t t2_02 = s->slice[2] ^ ROT(s->slice[2], 2);
+ uint16_t t3_02 = s->slice[3] ^ ROT(s->slice[3], 2);
+ uint16_t t4_02 = s->slice[4] ^ ROT(s->slice[4], 2);
+ uint16_t t5_02 = s->slice[5] ^ ROT(s->slice[5], 2);
+ uint16_t t6_02 = s->slice[6] ^ ROT(s->slice[6], 2);
+ uint16_t t7_02 = s->slice[7] ^ ROT(s->slice[7], 2);
+ /* And then update s += {04} * t?_02 */
+ s->slice[0] ^= t6_02;
+ s->slice[1] ^= t6_02 ^ t7_02;
+ s->slice[2] ^= t0_02 ^ t7_02;
+ s->slice[3] ^= t1_02 ^ t6_02;
+ s->slice[4] ^= t2_02 ^ t6_02 ^ t7_02;
+ s->slice[5] ^= t3_02 ^ t7_02;
+ s->slice[6] ^= t4_02;
+ s->slice[7] ^= t5_02;
+ }
+}
+
+static void AddRoundKey(AES_state* s, const AES_state* round) {
+ int b;
+ for (b = 0; b < 8; b++) {
+ s->slice[b] ^= round->slice[b];
+ }
+}
+
+/** column_0(s) = column_c(a) */
+static void GetOneColumn(AES_state* s, const AES_state* a, int c) {
+ int b;
+ for (b = 0; b < 8; b++) {
+ s->slice[b] = (a->slice[b] >> c) & 0x1111;
+ }
+}
+
+/** column_c1(r) |= (column_0(s) ^= column_c2(a)) */
+static void KeySetupColumnMix(AES_state* s, AES_state* r, const AES_state* a, int c1, int c2) {
+ int b;
+ for (b = 0; b < 8; b++) {
+ r->slice[b] |= ((s->slice[b] ^= ((a->slice[b] >> c2) & 0x1111)) & 0x1111) << c1;
+ }
+}
+
+/** Rotate the rows in s one position upwards, and xor in r */
+static void KeySetupTransform(AES_state* s, const AES_state* r) {
+ int b;
+ for (b = 0; b < 8; b++) {
+ s->slice[b] = ((s->slice[b] >> 4) | (s->slice[b] << 12)) ^ r->slice[b];
+ }
+}
+
+/* Multiply the cells in s by x, as polynomials over GF(2) mod x^8 + x^4 + x^3 + x + 1 */
+static void MultX(AES_state* s) {
+ uint16_t top = s->slice[7];
+ s->slice[7] = s->slice[6];
+ s->slice[6] = s->slice[5];
+ s->slice[5] = s->slice[4];
+ s->slice[4] = s->slice[3] ^ top;
+ s->slice[3] = s->slice[2] ^ top;
+ s->slice[2] = s->slice[1];
+ s->slice[1] = s->slice[0] ^ top;
+ s->slice[0] = top;
+}
+
+/** Expand the cipher key into the key schedule.
+ *
+ * state must be a pointer to an array of size nrounds + 1.
+ * key must be a pointer to 4 * nkeywords bytes.
+ *
+ * AES128 uses nkeywords = 4, nrounds = 10
+ * AES192 uses nkeywords = 6, nrounds = 12
+ * AES256 uses nkeywords = 8, nrounds = 14
+ */
+static void AES_setup(AES_state* rounds, const uint8_t* key, int nkeywords, int nrounds)
+{
+ int i;
+
+ /* The one-byte round constant */
+ AES_state rcon = {{1,0,0,0,0,0,0,0}};
+ /* The number of the word being generated, modulo nkeywords */
+ int pos = 0;
+ /* The column representing the word currently being processed */
+ AES_state column;
+
+ for (i = 0; i < nrounds + 1; i++) {
+ int b;
+ for (b = 0; b < 8; b++) {
+ rounds[i].slice[b] = 0;
+ }
+ }
+
+ /* The first nkeywords round columns are just taken from the key directly. */
+ for (i = 0; i < nkeywords; i++) {
+ int r;
+ for (r = 0; r < 4; r++) {
+ LoadByte(&rounds[i >> 2], *(key++), r, i & 3);
+ }
+ }
+
+ GetOneColumn(&column, &rounds[(nkeywords - 1) >> 2], (nkeywords - 1) & 3);
+
+ for (i = nkeywords; i < 4 * (nrounds + 1); i++) {
+ /* Transform column */
+ if (pos == 0) {
+ SubBytes(&column, 0);
+ KeySetupTransform(&column, &rcon);
+ MultX(&rcon);
+ } else if (nkeywords > 6 && pos == 4) {
+ SubBytes(&column, 0);
+ }
+ if (++pos == nkeywords) pos = 0;
+ KeySetupColumnMix(&column, &rounds[i >> 2], &rounds[(i - nkeywords) >> 2], i & 3, (i - nkeywords) & 3);
+ }
+}
+
+static void AES_encrypt(const AES_state* rounds, int nrounds, unsigned char* cipher16, const unsigned char* plain16) {
+ AES_state s = {{0}};
+ int round;
+
+ LoadBytes(&s, plain16);
+ AddRoundKey(&s, rounds++);
+
+ for (round = 1; round < nrounds; round++) {
+ SubBytes(&s, 0);
+ ShiftRows(&s);
+ MixColumns(&s, 0);
+ AddRoundKey(&s, rounds++);
+ }
+
+ SubBytes(&s, 0);
+ ShiftRows(&s);
+ AddRoundKey(&s, rounds);
+
+ SaveBytes(cipher16, &s);
+}
+
+static void AES_decrypt(const AES_state* rounds, int nrounds, unsigned char* plain16, const unsigned char* cipher16) {
+ /* Most AES decryption implementations use the alternate scheme
+ * (the Equivalent Inverse Cipher), which looks more like encryption, but
+ * needs different round constants. We can't reuse any code here anyway, so
+ * don't bother. */
+ AES_state s = {{0}};
+ int round;
+
+ rounds += nrounds;
+
+ LoadBytes(&s, cipher16);
+ AddRoundKey(&s, rounds--);
+
+ for (round = 1; round < nrounds; round++) {
+ InvShiftRows(&s);
+ SubBytes(&s, 1);
+ AddRoundKey(&s, rounds--);
+ MixColumns(&s, 1);
+ }
+
+ InvShiftRows(&s);
+ SubBytes(&s, 1);
+ AddRoundKey(&s, rounds);
+
+ SaveBytes(plain16, &s);
+}
+
+void AES128_init(AES128_ctx* ctx, const unsigned char* key16) {
+ AES_setup(ctx->rk, key16, 4, 10);
+}
+
+void AES128_encrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) {
+ while (blocks--) {
+ AES_encrypt(ctx->rk, 10, cipher16, plain16);
+ cipher16 += 16;
+ plain16 += 16;
+ }
+}
+
+void AES128_decrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) {
+ while (blocks--) {
+ AES_decrypt(ctx->rk, 10, plain16, cipher16);
+ cipher16 += 16;
+ plain16 += 16;
+ }
+}
+
+void AES192_init(AES192_ctx* ctx, const unsigned char* key24) {
+ AES_setup(ctx->rk, key24, 6, 12);
+}
+
+void AES192_encrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) {
+ while (blocks--) {
+ AES_encrypt(ctx->rk, 12, cipher16, plain16);
+ cipher16 += 16;
+ plain16 += 16;
+ }
+
+}
+
+void AES192_decrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) {
+ while (blocks--) {
+ AES_decrypt(ctx->rk, 12, plain16, cipher16);
+ cipher16 += 16;
+ plain16 += 16;
+ }
+}
+
+void AES256_init(AES256_ctx* ctx, const unsigned char* key32) {
+ AES_setup(ctx->rk, key32, 8, 14);
+}
+
+void AES256_encrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) {
+ while (blocks--) {
+ AES_encrypt(ctx->rk, 14, cipher16, plain16);
+ cipher16 += 16;
+ plain16 += 16;
+ }
+}
+
+void AES256_decrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) {
+ while (blocks--) {
+ AES_decrypt(ctx->rk, 14, plain16, cipher16);
+ cipher16 += 16;
+ plain16 += 16;
+ }
+}
diff --git a/src/crypto/ctaes/ctaes.h b/src/crypto/ctaes/ctaes.h
new file mode 100644
index 000000000000..2f0af0421605
--- /dev/null
+++ b/src/crypto/ctaes/ctaes.h
@@ -0,0 +1,41 @@
+ /*********************************************************************
+ * Copyright (c) 2016 Pieter Wuille *
+ * Distributed under the MIT software license, see the accompanying *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+
+#ifndef _CTAES_H_
+#define _CTAES_H_ 1
+
+#include
+#include
+
+typedef struct {
+ uint16_t slice[8];
+} AES_state;
+
+typedef struct {
+ AES_state rk[11];
+} AES128_ctx;
+
+typedef struct {
+ AES_state rk[13];
+} AES192_ctx;
+
+typedef struct {
+ AES_state rk[15];
+} AES256_ctx;
+
+void AES128_init(AES128_ctx* ctx, const unsigned char* key16);
+void AES128_encrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16);
+void AES128_decrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16);
+
+void AES192_init(AES192_ctx* ctx, const unsigned char* key24);
+void AES192_encrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16);
+void AES192_decrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16);
+
+void AES256_init(AES256_ctx* ctx, const unsigned char* key32);
+void AES256_encrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16);
+void AES256_decrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16);
+
+#endif
diff --git a/src/crypto/ctaes/test.c b/src/crypto/ctaes/test.c
new file mode 100644
index 000000000000..fce1696acdc2
--- /dev/null
+++ b/src/crypto/ctaes/test.c
@@ -0,0 +1,110 @@
+ /*********************************************************************
+ * Copyright (c) 2016 Pieter Wuille *
+ * Distributed under the MIT software license, see the accompanying *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+
+#include "ctaes.h"
+
+#include
+#include
+#include
+
+typedef struct {
+ int keysize;
+ const char* key;
+ const char* plain;
+ const char* cipher;
+} ctaes_test;
+
+static const ctaes_test ctaes_tests[] = {
+ /* AES test vectors from FIPS 197. */
+ {128, "000102030405060708090a0b0c0d0e0f", "00112233445566778899aabbccddeeff", "69c4e0d86a7b0430d8cdb78070b4c55a"},
+ {192, "000102030405060708090a0b0c0d0e0f1011121314151617", "00112233445566778899aabbccddeeff", "dda97ca4864cdfe06eaf70a0ec0d7191"},
+ {256, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "00112233445566778899aabbccddeeff", "8ea2b7ca516745bfeafc49904b496089"},
+
+ /* AES-ECB test vectors from NIST sp800-38a. */
+ {128, "2b7e151628aed2a6abf7158809cf4f3c", "6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97"},
+ {128, "2b7e151628aed2a6abf7158809cf4f3c", "ae2d8a571e03ac9c9eb76fac45af8e51", "f5d3d58503b9699de785895a96fdbaaf"},
+ {128, "2b7e151628aed2a6abf7158809cf4f3c", "30c81c46a35ce411e5fbc1191a0a52ef", "43b1cd7f598ece23881b00e3ed030688"},
+ {128, "2b7e151628aed2a6abf7158809cf4f3c", "f69f2445df4f9b17ad2b417be66c3710", "7b0c785e27e8ad3f8223207104725dd4"},
+ {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "6bc1bee22e409f96e93d7e117393172a", "bd334f1d6e45f25ff712a214571fa5cc"},
+ {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "ae2d8a571e03ac9c9eb76fac45af8e51", "974104846d0ad3ad7734ecb3ecee4eef"},
+ {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "30c81c46a35ce411e5fbc1191a0a52ef", "ef7afd2270e2e60adce0ba2face6444e"},
+ {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "f69f2445df4f9b17ad2b417be66c3710", "9a4b41ba738d6c72fb16691603c18e0e"},
+ {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "6bc1bee22e409f96e93d7e117393172a", "f3eed1bdb5d2a03c064b5a7e3db181f8"},
+ {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "ae2d8a571e03ac9c9eb76fac45af8e51", "591ccb10d410ed26dc5ba74a31362870"},
+ {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "30c81c46a35ce411e5fbc1191a0a52ef", "b6ed21b99ca6f4f9f153e7b1beafed1d"},
+ {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "f69f2445df4f9b17ad2b417be66c3710", "23304b7a39f9f3ff067d8d8f9e24ecc7"}
+};
+
+static void from_hex(unsigned char* data, int len, const char* hex) {
+ int p;
+ for (p = 0; p < len; p++) {
+ int v = 0;
+ int n;
+ for (n = 0; n < 2; n++) {
+ assert((*hex >= '0' && *hex <= '9') || (*hex >= 'a' && *hex <= 'f'));
+ if (*hex >= '0' && *hex <= '9') {
+ v |= (*hex - '0') << (4 * (1 - n));
+ } else {
+ v |= (*hex - 'a' + 10) << (4 * (1 - n));
+ }
+ hex++;
+ }
+ *(data++) = v;
+ }
+ assert(*hex == 0);
+}
+
+int main(void) {
+ int i;
+ int fail = 0;
+ for (i = 0; i < sizeof(ctaes_tests) / sizeof(ctaes_tests[0]); i++) {
+ unsigned char key[32], plain[16], cipher[16], ciphered[16], deciphered[16];
+ const ctaes_test* test = &ctaes_tests[i];
+ assert(test->keysize == 128 || test->keysize == 192 || test->keysize == 256);
+ from_hex(plain, 16, test->plain);
+ from_hex(cipher, 16, test->cipher);
+ switch (test->keysize) {
+ case 128: {
+ AES128_ctx ctx;
+ from_hex(key, 16, test->key);
+ AES128_init(&ctx, key);
+ AES128_encrypt(&ctx, 1, ciphered, plain);
+ AES128_decrypt(&ctx, 1, deciphered, cipher);
+ break;
+ }
+ case 192: {
+ AES192_ctx ctx;
+ from_hex(key, 24, test->key);
+ AES192_init(&ctx, key);
+ AES192_encrypt(&ctx, 1, ciphered, plain);
+ AES192_decrypt(&ctx, 1, deciphered, cipher);
+ break;
+ }
+ case 256: {
+ AES256_ctx ctx;
+ from_hex(key, 32, test->key);
+ AES256_init(&ctx, key);
+ AES256_encrypt(&ctx, 1, ciphered, plain);
+ AES256_decrypt(&ctx, 1, deciphered, cipher);
+ break;
+ }
+ }
+ if (memcmp(cipher, ciphered, 16)) {
+ fprintf(stderr, "E(key=\"%s\", plain=\"%s\") != \"%s\"\n", test->key, test->plain, test->cipher);
+ fail++;
+ }
+ if (memcmp(plain, deciphered, 16)) {
+ fprintf(stderr, "D(key=\"%s\", cipher=\"%s\") != \"%s\"\n", test->key, test->cipher, test->plain);
+ fail++;
+ }
+ }
+ if (fail == 0) {
+ fprintf(stderr, "All tests succesful\n");
+ } else {
+ fprintf(stderr, "%i tests failed\n", fail);
+ }
+ return (fail != 0);
+}
diff --git a/src/dash-tx.cpp b/src/dash-tx.cpp
index c796aaa51964..8f25f72cba68 100644
--- a/src/dash-tx.cpp
+++ b/src/dash-tx.cpp
@@ -76,7 +76,7 @@ static int AppInitRawTx(int argc, char* argv[])
strUsage = HelpMessageGroup(_("Commands:"));
strUsage += HelpMessageOpt("delin=N", _("Delete input N from TX"));
strUsage += HelpMessageOpt("delout=N", _("Delete output N from TX"));
- strUsage += HelpMessageOpt("in=TXID:VOUT", _("Add input to TX"));
+ strUsage += HelpMessageOpt("in=TXID:VOUT(:SEQUENCE_NUMBER)", _("Add input to TX"));
strUsage += HelpMessageOpt("locktime=N", _("Set TX lock time to N"));
strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N"));
strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", _("Add address-based output to TX"));
@@ -190,15 +190,15 @@ static void MutateTxLocktime(CMutableTransaction& tx, const string& cmdVal)
static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput)
{
+ std::vector vStrInputParts;
+ boost::split(vStrInputParts, strInput, boost::is_any_of(":"));
+
// separate TXID:VOUT in string
- size_t pos = strInput.find(':');
- if ((pos == string::npos) ||
- (pos == 0) ||
- (pos == (strInput.size() - 1)))
+ if (vStrInputParts.size()<2)
throw runtime_error("TX input missing separator");
// extract and validate TXID
- string strTxid = strInput.substr(0, pos);
+ string strTxid = vStrInputParts[0];
if ((strTxid.size() != 64) || !IsHex(strTxid))
throw runtime_error("invalid TX input txid");
uint256 txid(uint256S(strTxid));
@@ -207,13 +207,18 @@ static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput)
static const unsigned int maxVout = MaxBlockSize(true) / minTxOutSz;
// extract and validate vout
- string strVout = strInput.substr(pos + 1, string::npos);
+ string strVout = vStrInputParts[1];
int vout = atoi(strVout);
if ((vout < 0) || (vout > (int)maxVout))
throw runtime_error("invalid TX input vout");
+ // extract the optional sequence number
+ uint32_t nSequenceIn=std::numeric_limits::max();
+ if (vStrInputParts.size() > 2)
+ nSequenceIn = std::stoul(vStrInputParts[2]);
+
// append to transaction input list
- CTxIn txin(txid, vout);
+ CTxIn txin(txid, vout, CScript(), nSequenceIn);
tx.vin.push_back(txin);
}
diff --git a/src/hash.cpp b/src/hash.cpp
index 599670bd491a..7dae238bdda2 100644
--- a/src/hash.cpp
+++ b/src/hash.cpp
@@ -100,12 +100,15 @@ CSipHasher::CSipHasher(uint64_t k0, uint64_t k1)
v[2] = 0x6c7967656e657261ULL ^ k0;
v[3] = 0x7465646279746573ULL ^ k1;
count = 0;
+ tmp = 0;
}
CSipHasher& CSipHasher::Write(uint64_t data)
{
uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
+ assert(count % 8 == 0);
+
v3 ^= data;
SIPROUND;
SIPROUND;
@@ -116,7 +119,35 @@ CSipHasher& CSipHasher::Write(uint64_t data)
v[2] = v2;
v[3] = v3;
- count++;
+ count += 8;
+ return *this;
+}
+
+CSipHasher& CSipHasher::Write(const unsigned char* data, size_t size)
+{
+ uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
+ uint64_t t = tmp;
+ int c = count;
+
+ while (size--) {
+ t |= ((uint64_t)(*(data++))) << (8 * (c % 8));
+ c++;
+ if ((c & 7) == 0) {
+ v3 ^= t;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= t;
+ t = 0;
+ }
+ }
+
+ v[0] = v0;
+ v[1] = v1;
+ v[2] = v2;
+ v[3] = v3;
+ count = c;
+ tmp = t;
+
return *this;
}
@@ -124,10 +155,12 @@ uint64_t CSipHasher::Finalize() const
{
uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
- v3 ^= ((uint64_t)count) << 59;
+ uint64_t t = tmp | (((uint64_t)count) << 56);
+
+ v3 ^= t;
SIPROUND;
SIPROUND;
- v0 ^= ((uint64_t)count) << 59;
+ v0 ^= t;
v2 ^= 0xFF;
SIPROUND;
SIPROUND;
diff --git a/src/hash.h b/src/hash.h
index d648e92e5ed4..622f9315d5c7 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -313,19 +313,38 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector
+struct DereferencingComparator { bool operator()(const T a, const T b) const { return *a < *b; } };
+
+/* Map whose keys are pointers, but are compared by their dereferenced values.
+ *
+ * Differs from a plain std::map > in
+ * that methods that take a key for comparison take a K rather than taking a K*
+ * (taking a K* would be confusing, since it's the value rather than the address
+ * of the object for comparison that matters due to the dereferencing comparator).
+ *
+ * Objects pointed to by keys must not be modified in any way that changes the
+ * result of DereferencingComparator.
+ */
+template
+class indirectmap {
+private:
+ typedef std::map > base;
+ base m;
+public:
+ typedef typename base::iterator iterator;
+ typedef typename base::const_iterator const_iterator;
+ typedef typename base::size_type size_type;
+ typedef typename base::value_type value_type;
+
+ // passthrough (pointer interface)
+ std::pair insert(const value_type& value) { return m.insert(value); }
+
+ // pass address (value interface)
+ iterator find(const K& key) { return m.find(&key); }
+ const_iterator find(const K& key) const { return m.find(&key); }
+ iterator lower_bound(const K& key) { return m.lower_bound(&key); }
+ const_iterator lower_bound(const K& key) const { return m.lower_bound(&key); }
+ size_type erase(const K& key) { return m.erase(&key); }
+ size_type count(const K& key) const { return m.count(&key); }
+
+ // passthrough
+ bool empty() const { return m.empty(); }
+ size_type size() const { return m.size(); }
+ size_type max_size() const { return m.max_size(); }
+ void clear() { m.clear(); }
+ iterator begin() { return m.begin(); }
+ iterator end() { return m.end(); }
+ const_iterator begin() const { return m.begin(); }
+ const_iterator end() const { return m.end(); }
+ const_iterator cbegin() const { return m.cbegin(); }
+ const_iterator cend() const { return m.cend(); }
+};
+
+#endif // BITCOIN_INDIRECTMAP_H
diff --git a/src/init.cpp b/src/init.cpp
index 8d242a1d5a6c..a442b241fe79 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -158,7 +158,7 @@ static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
// shutdown thing.
//
-volatile sig_atomic_t fRequestShutdown = false;
+std::atomic fRequestShutdown(false);
void StartShutdown()
{
@@ -395,7 +395,8 @@ std::string HelpMessage(HelpMessageMode mode)
}
strUsage += HelpMessageOpt("-datadir=", _("Specify data directory"));
strUsage += HelpMessageOpt("-dbcache=", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache));
- strUsage += HelpMessageOpt("-feefilter", strprintf(_("Tell other nodes to filter invs to us by our mempool min fee (default: %u)"), DEFAULT_FEEFILTER));
+ if (showDebug)
+ strUsage += HelpMessageOpt("-feefilter", strprintf("Tell other nodes to filter invs to us by our mempool min fee (default: %u)", DEFAULT_FEEFILTER));
strUsage += HelpMessageOpt("-loadblock=", _("Imports blocks from external blk000??.dat file on startup"));
strUsage += HelpMessageOpt("-maxorphantx=", strprintf(_("Keep at most unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS));
strUsage += HelpMessageOpt("-maxmempool=", strprintf(_("Keep the transaction memory pool below megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE));
@@ -903,7 +904,7 @@ void InitLogging()
fLogIPs = GetBoolArg("-logips", DEFAULT_LOGIPS);
LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
- LogPrintf("Dash Core version %s (%s)\n", FormatFullVersion(), CLIENT_DATE);
+ LogPrintf("Dash Core version %s\n", FormatFullVersion());
}
/** Initialize Dash Core.
diff --git a/src/instantx.cpp b/src/instantx.cpp
index 7cd95298da52..f654a1a34dff 100644
--- a/src/instantx.cpp
+++ b/src/instantx.cpp
@@ -590,7 +590,7 @@ bool CInstantSend::ResolveConflicts(const CTxLockCandidate& txLockCandidate)
return false;
} else if (mempool.mapNextTx.count(txin.prevout)) {
// check if it's in mempool
- hashConflicting = mempool.mapNextTx[txin.prevout].ptx->GetHash();
+ hashConflicting = mempool.mapNextTx.find(txin.prevout)->second->GetHash();
if(txHash == hashConflicting) continue; // matches current, not a conflict, skip to next txin
// conflicts with tx in mempool
LogPrintf("CInstantSend::ResolveConflicts -- ERROR: Failed to complete Transaction Lock, conflicts with mempool, txid=%s\n", txHash.ToString());
diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp
index 3bd9bfb05333..a8dd91f75898 100644
--- a/src/masternodeman.cpp
+++ b/src/masternodeman.cpp
@@ -1044,7 +1044,7 @@ bool CMasternodeMan::SendVerifyRequest(const CAddress& addr, const std::vector
#include