Match va_start and va_end calls, pointed by clang-tidy #176

Closed
bvbfan wants to merge 277 commits from va_brach into master
215 changed files with 5440 additions and 3383 deletions
Showing only changes of commit 4fc3834cdd - Show all commits

View file

@ -26,7 +26,9 @@ WINDOWS_PACKAGING = $(top_srcdir)/share/pixmaps/bitcoin.ico \
OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_FANCY_PLIST) $(OSX_INSTALLER_ICONS) \ OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_FANCY_PLIST) $(OSX_INSTALLER_ICONS) \
$(top_srcdir)/contrib/macdeploy/background.png \ $(top_srcdir)/contrib/macdeploy/background.png \
$(top_srcdir)/contrib/macdeploy/DS_Store $(top_srcdir)/contrib/macdeploy/DS_Store \
$(top_srcdir)/contrib/macdeploy/detached-sig-apply.sh \
$(top_srcdir)/contrib/macdeploy/detached-sig-create.sh
COVERAGE_INFO = baseline_filtered_combined.info baseline.info block_test.info \ COVERAGE_INFO = baseline_filtered_combined.info baseline.info block_test.info \
leveldb_baseline.info test_bitcoin_filtered.info total_coverage.info \ leveldb_baseline.info test_bitcoin_filtered.info total_coverage.info \
@ -85,14 +87,30 @@ if BUILD_DARWIN
$(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING) $(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING)
$(OSX_DEPLOY_SCRIPT) $(OSX_APP) -add-qt-tr $(OSX_QT_TRANSLATIONS) -translations-dir=$(QT_TRANSLATION_DIR) -dmg -fancy $(OSX_FANCY_PLIST) -verbose 2 $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -add-qt-tr $(OSX_QT_TRANSLATIONS) -translations-dir=$(QT_TRANSLATION_DIR) -dmg -fancy $(OSX_FANCY_PLIST) -verbose 2
deploydir: $(OSX_DMG)
else else
$(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING) APP_DIST_DIR=$(top_builddir)/dist
INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -add-qt-tr $(OSX_QT_TRANSLATIONS) -translations-dir=$(QT_TRANSLATION_DIR) -verbose 2 APP_DIST_EXTRAS=$(APP_DIST_DIR)/.background/background.png $(APP_DIST_DIR)/.DS_Store $(APP_DIST_DIR)/Applications
$(MKDIR_P) dist/.background
$(INSTALL) contrib/macdeploy/background.png dist/.background $(APP_DIST_DIR)/Applications:
$(INSTALL) contrib/macdeploy/DS_Store dist/.DS_Store @rm -f $@
cd dist; $(LN_S) /Applications Applications @cd $(@D); $(LN_S) /Applications $(@F)
$(GENISOIMAGE) -no-cache-inodes -l -probe -V "Bitcoin-Qt" -no-pad -r -apple -o $@ dist
$(APP_DIST_EXTRAS): $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt
$(OSX_DMG): $(APP_DIST_EXTRAS)
$(GENISOIMAGE) -no-cache-inodes -D -l -probe -V "Bitcoin-Qt" -no-pad -r -apple -o $@ dist
$(APP_DIST_DIR)/.background/background.png:
$(MKDIR_P) $(@D)
$(INSTALL) $(top_srcdir)/contrib/macdeploy/background.png $@
$(APP_DIST_DIR)/.DS_Store:
$(INSTALL) $(top_srcdir)/contrib/macdeploy/DS_Store $@
$(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt: $(OSX_APP_BUILT) $(OSX_PACKAGING)
INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -translations-dir=$(QT_TRANSLATION_DIR) -add-qt-tr $(OSX_QT_TRANSLATIONS) -verbose 2
deploydir: $(APP_DIST_EXTRAS)
endif endif
if TARGET_DARWIN if TARGET_DARWIN

View file

@ -281,6 +281,12 @@ case $host in
AC_PATH_TOOL([INSTALLNAMETOOL], [install_name_tool], install_name_tool) AC_PATH_TOOL([INSTALLNAMETOOL], [install_name_tool], install_name_tool)
AC_PATH_TOOL([OTOOL], [otool], otool) AC_PATH_TOOL([OTOOL], [otool], otool)
AC_PATH_PROGS([GENISOIMAGE], [genisoimage mkisofs],genisoimage) AC_PATH_PROGS([GENISOIMAGE], [genisoimage mkisofs],genisoimage)
dnl libtool will try to strip the static lib, which is a problem for
dnl cross-builds because strip attempts to call a hard-coded ld,
dnl which may not exist in the path. Stripping the .a is not
dnl necessary, so just disable it.
old_striplib=
;; ;;
esac esac
fi fi
@ -421,6 +427,8 @@ AC_CHECK_HEADERS([endian.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/s
AC_SEARCH_LIBS([getaddrinfo_a], [anl], [AC_DEFINE(HAVE_GETADDRINFO_A, 1, [Define this symbol if you have getaddrinfo_a])]) AC_SEARCH_LIBS([getaddrinfo_a], [anl], [AC_DEFINE(HAVE_GETADDRINFO_A, 1, [Define this symbol if you have getaddrinfo_a])])
AC_SEARCH_LIBS([inet_pton], [nsl resolv], [AC_DEFINE(HAVE_INET_PTON, 1, [Define this symbol if you have inet_pton])]) AC_SEARCH_LIBS([inet_pton], [nsl resolv], [AC_DEFINE(HAVE_INET_PTON, 1, [Define this symbol if you have inet_pton])])
AC_CHECK_DECLS([strnlen])
AC_CHECK_DECLS([le32toh, le64toh, htole32, htole64, be32toh, be64toh, htobe32, htobe64],,, AC_CHECK_DECLS([le32toh, le64toh, htole32, htole64, be32toh, be64toh, htobe32, htobe64],,,
[#if HAVE_ENDIAN_H [#if HAVE_ENDIAN_H
#include <endian.h> #include <endian.h>

View file

@ -73,13 +73,13 @@ script: |
./autogen.sh ./autogen.sh
./configure --prefix=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'` ./configure --prefix=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`
make dist make dist
DISTNAME=`echo bitcoin-*.tar.gz` SOURCEDIST=`echo bitcoin-*.tar.gz`
DISTNAME=`echo ${SOURCEDIST} | sed 's/.tar.*//'`
# Correct tar file order # Correct tar file order
mkdir -p temp mkdir -p temp
pushd temp pushd temp
tar xf ../$DISTNAME tar xf ../$SOURCEDIST
find bitcoin-* | sort | tar --no-recursion -c -T - | gzip -9n > ../$DISTNAME find bitcoin-* | sort | tar --no-recursion -c -T - | gzip -9n > ../$SOURCEDIST
popd popd
ORIGPATH="$PATH" ORIGPATH="$PATH"
@ -88,17 +88,22 @@ script: |
export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH} export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH}
mkdir -p distsrc-${i} mkdir -p distsrc-${i}
cd distsrc-${i} cd distsrc-${i}
tar --strip-components=1 -xf ../$DISTNAME INSTALLPATH=`pwd`/installed/${DISTNAME}
mkdir -p ${INSTALLPATH}
tar --strip-components=1 -xf ../$SOURCEDIST
./configure --prefix=${BASEPREFIX}/${i} --bindir=${OUTDIR}/${i}/bin --includedir=${OUTDIR}/${i}/include --libdir=${OUTDIR}/${i}/lib --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} ./configure --prefix=${BASEPREFIX}/${i} --bindir=${INSTALLPATH}/bin --includedir=${INSTALLPATH}/include --libdir=${INSTALLPATH}/lib --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS}
make ${MAKEOPTS} make ${MAKEOPTS}
make install-strip make install-strip
cd .. cd installed
find . -name "lib*.la" -delete
find . -name "lib*.a" -delete
rm -rf ${DISTNAME}/lib/pkgconfig
find . | sort | tar --no-recursion -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}.tar.gz
cd ../../
done done
mkdir -p $OUTDIR/src mkdir -p $OUTDIR/src
mv $DISTNAME $OUTDIR/src mv $SOURCEDIST $OUTDIR/src
mv ${OUTDIR}/x86_64-* ${OUTDIR}/64 mv ${OUTDIR}/${DISTNAME}-x86_64-*.tar.gz ${OUTDIR}/${DISTNAME}-linux64.tar.gz
mv ${OUTDIR}/i686-* ${OUTDIR}/32 mv ${OUTDIR}/${DISTNAME}-i686-*.tar.gz ${OUTDIR}/${DISTNAME}-linux32.tar.gz
# Delete unwanted stuff
find ${OUTDIR} -name "lib*.la" -delete

View file

@ -0,0 +1,37 @@
---
name: "bitcoin-dmg-signer"
suites:
- "precise"
architectures:
- "amd64"
packages:
- "libc6:i386"
- "faketime"
reference_datetime: "2013-06-01 00:00:00"
remotes: []
files:
- "bitcoin-0.9.99-osx-unsigned.tar.gz"
- "signature.tar.gz"
script: |
WRAP_DIR=$HOME/wrapped
mkdir -p ${WRAP_DIR}
export PATH=`pwd`:$PATH
FAKETIME_PROGS="dmg genisoimage"
# 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/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog}
echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${prog}
echo "\$REAL \$@" >> $WRAP_DIR/${prog}
chmod +x ${WRAP_DIR}/${prog}
done
UNSIGNED=`echo bitcoin-*.tar.gz`
SIGNED=`echo ${UNSIGNED} | sed 's/.tar.*//' | sed 's/-unsigned//'`.dmg
tar -xf ${UNSIGNED}
./detached-sig-apply.sh ${UNSIGNED} signature.tar.gz
${WRAP_DIR}/genisoimage -no-cache-inodes -D -l -probe -V "Bitcoin-Qt" -no-pad -r -apple -o uncompressed.dmg signed-app
${WRAP_DIR}/dmg dmg uncompressed.dmg ${OUTDIR}/${SIGNED}

View file

@ -83,13 +83,14 @@ script: |
./autogen.sh ./autogen.sh
./configure --prefix=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'` ./configure --prefix=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`
make dist make dist
DISTNAME=`echo bitcoin-*.tar.gz` SOURCEDIST=`echo bitcoin-*.tar.gz`
DISTNAME=`echo ${SOURCEDIST} | sed 's/.tar.*//'`
# Correct tar file order # Correct tar file order
mkdir -p temp mkdir -p temp
pushd temp pushd temp
tar xf ../$DISTNAME tar xf ../$SOURCEDIST
find bitcoin-* | sort | tar --no-recursion -c -T - | gzip -9n > ../$DISTNAME find bitcoin-* | sort | tar --no-recursion -c -T - | gzip -9n > ../$SOURCEDIST
popd popd
ORIGPATH="$PATH" ORIGPATH="$PATH"
@ -98,17 +99,36 @@ script: |
export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH} export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH}
mkdir -p distsrc-${i} mkdir -p distsrc-${i}
cd distsrc-${i} cd distsrc-${i}
tar --strip-components=1 -xf ../$DISTNAME INSTALLPATH=`pwd`/installed/${DISTNAME}
mkdir -p ${INSTALLPATH}
tar --strip-components=1 -xf ../$SOURCEDIST
./configure --prefix=${BASEPREFIX}/${i} --bindir=${OUTDIR}/${i}/bin --includedir=${OUTDIR}/${i}/include --libdir=${OUTDIR}/${i}/lib --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} ./configure --prefix=${BASEPREFIX}/${i} --bindir=${INSTALLPATH}/bin --includedir=${INSTALLPATH}/include --libdir=${INSTALLPATH}/lib --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS}
make ${MAKEOPTS} make ${MAKEOPTS}
make install-strip make install-strip
make deploydir
mkdir -p unsigned-app-${i}
cp contrib/macdeploy/detached-sig-apply.sh unsigned-app-${i}
cp contrib/macdeploy/detached-sig-create.sh unsigned-app-${i}
cp ${BASEPREFIX}/${i}/native/bin/dmg ${BASEPREFIX}/${i}/native/bin/genisoimage unsigned-app-${i}
cp ${BASEPREFIX}/${i}/native/bin/${i}-codesign_allocate unsigned-app-${i}/codesign_allocate
cp ${BASEPREFIX}/${i}/native/bin/${i}-pagestuff unsigned-app-${i}/pagestuff
mv dist unsigned-app-${i}
pushd unsigned-app-${i}
find . | sort | tar --no-recursion -czf ${OUTDIR}/${DISTNAME}-osx-unsigned.tar.gz -T -
popd
make deploy make deploy
${WRAP_DIR}/dmg dmg Bitcoin-Qt.dmg ${OUTDIR}/Bitcoin-Qt.dmg ${WRAP_DIR}/dmg dmg Bitcoin-Qt.dmg ${OUTDIR}/${DISTNAME}-osx-unsigned.dmg
cd ..
cd installed
find . -name "lib*.la" -delete
find . -name "lib*.a" -delete
rm -rf ${DISTNAME}/lib/pkgconfig
find . | sort | tar --no-recursion -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}.tar.gz
cd ../../
done done
mkdir -p $OUTDIR/src mkdir -p $OUTDIR/src
mv $DISTNAME $OUTDIR/src mv $SOURCEDIST $OUTDIR/src
mv ${OUTDIR}/${DISTNAME}-x86_64-*.tar.gz ${OUTDIR}/${DISTNAME}-osx64.tar.gz
# Delete unwanted stuff
find ${OUTDIR} -name "lib*.la" -delete

View file

@ -17,6 +17,7 @@ packages:
- "mingw-w64" - "mingw-w64"
- "g++-mingw-w64" - "g++-mingw-w64"
- "nsis" - "nsis"
- "zip"
reference_datetime: "2013-06-01 00:00:00" reference_datetime: "2013-06-01 00:00:00"
remotes: remotes:
- "url": "https://github.com/bitcoin/bitcoin.git" - "url": "https://github.com/bitcoin/bitcoin.git"
@ -27,7 +28,7 @@ script: |
HOSTS="x86_64-w64-mingw32 i686-w64-mingw32" HOSTS="x86_64-w64-mingw32 i686-w64-mingw32"
CONFIGFLAGS="--enable-upnp-default" CONFIGFLAGS="--enable-upnp-default"
FAKETIME_HOST_PROGS="g++ ar ranlib nm windres strip" FAKETIME_HOST_PROGS="g++ ar ranlib nm windres strip"
FAKETIME_PROGS="date makensis" FAKETIME_PROGS="date makensis zip"
export QT_RCC_TEST=1 export QT_RCC_TEST=1
export GZIP="-9n" export GZIP="-9n"
@ -75,13 +76,14 @@ script: |
./autogen.sh ./autogen.sh
./configure --prefix=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'` ./configure --prefix=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`
make dist make dist
DISTNAME=`echo bitcoin-*.tar.gz` SOURCEDIST=`echo bitcoin-*.tar.gz`
DISTNAME=`echo ${SOURCEDIST} | sed 's/.tar.*//'`
# Correct tar file order # Correct tar file order
mkdir -p temp mkdir -p temp
pushd temp pushd temp
tar xf ../$DISTNAME tar xf ../$SOURCEDIST
find bitcoin-* | sort | tar --no-recursion -c -T - | gzip -9n > ../$DISTNAME find bitcoin-* | sort | tar --no-recursion -c -T - | gzip -9n > ../$SOURCEDIST
popd popd
ORIGPATH="$PATH" ORIGPATH="$PATH"
@ -90,19 +92,24 @@ script: |
export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH} export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH}
mkdir -p distsrc-${i} mkdir -p distsrc-${i}
cd distsrc-${i} cd distsrc-${i}
tar --strip-components=1 -xf ../$DISTNAME INSTALLPATH=`pwd`/installed/${DISTNAME}
mkdir -p ${INSTALLPATH}
tar --strip-components=1 -xf ../$SOURCEDIST
./configure --prefix=${BASEPREFIX}/${i} --bindir=${OUTDIR}/${i}/bin --includedir=${OUTDIR}/${i}/include --libdir=${OUTDIR}/${i}/lib --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} ./configure --prefix=${BASEPREFIX}/${i} --bindir=${INSTALLPATH}/bin --includedir=${INSTALLPATH}/include --libdir=${INSTALLPATH}/lib --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS}
make ${MAKEOPTS} make ${MAKEOPTS}
make deploy make deploy
make install-strip make install-strip
cp -f bitcoin-*setup*.exe $OUTDIR/ cp -f bitcoin-*setup*.exe $OUTDIR/
cd .. cd installed
mv ${DISTNAME}/bin/*.dll ${DISTNAME}/lib/
find . -name "lib*.la" -delete
find . -name "lib*.a" -delete
rm -rf ${DISTNAME}/lib/pkgconfig
find . -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${i}.zip
cd ../..
done done
mkdir -p $OUTDIR/src mkdir -p $OUTDIR/src
mv $DISTNAME $OUTDIR/src mv $SOURCEDIST $OUTDIR/src
mv ${OUTDIR}/x86_64-* ${OUTDIR}/64 mv ${OUTDIR}/${DISTNAME}-x86_64-*.zip ${OUTDIR}/${DISTNAME}-win64.zip
mv ${OUTDIR}/i686-* ${OUTDIR}/32 mv ${OUTDIR}/${DISTNAME}-i686-*.zip ${OUTDIR}/${DISTNAME}-win32.zip
# Delete unwanted stuff
find ${OUTDIR} -name "lib*.la" -delete

Binary file not shown.

View file

@ -0,0 +1,53 @@
#!/bin/sh
set -e
UNSIGNED=$1
SIGNATURE=$2
ARCH=x86_64
ROOTDIR=dist
BUNDLE=${ROOTDIR}/Bitcoin-Qt.app
TEMPDIR=signed.temp
OUTDIR=signed-app
if [ -z "$UNSIGNED" ]; then
echo "usage: $0 <unsigned app> <signature>"
exit 1
fi
if [ -z "$SIGNATURE" ]; then
echo "usage: $0 <unsigned app> <signature>"
exit 1
fi
rm -rf ${TEMPDIR} && mkdir -p ${TEMPDIR}
tar -C ${TEMPDIR} -xf ${UNSIGNED}
tar -C ${TEMPDIR} -xf ${SIGNATURE}
if [ -z "${PAGESTUFF}" ]; then
PAGESTUFF=${TEMPDIR}/pagestuff
fi
if [ -z "${CODESIGN_ALLOCATE}" ]; then
CODESIGN_ALLOCATE=${TEMPDIR}/codesign_allocate
fi
for i in `find ${TEMPDIR} -name "*.sign"`; do
SIZE=`stat -c %s ${i}`
TARGET_FILE=`echo ${i} | sed 's/\.sign$//'`
echo "Allocating space for the signature of size ${SIZE} in ${TARGET_FILE}"
${CODESIGN_ALLOCATE} -i ${TARGET_FILE} -a ${ARCH} ${SIZE} -o ${i}.tmp
OFFSET=`${PAGESTUFF} ${i}.tmp -p | tail -2 | grep offset | sed 's/[^0-9]*//g'`
if [ -z ${QUIET} ]; then
echo "Attaching signature at offset ${OFFSET}"
fi
dd if=$i of=${i}.tmp bs=1 seek=${OFFSET} count=${SIZE} 2>/dev/null
mv ${i}.tmp ${TARGET_FILE}
rm ${i}
echo "Success."
done
mv ${TEMPDIR}/${ROOTDIR} ${OUTDIR}
rm -rf ${TEMPDIR}
echo "Signed: ${OUTDIR}"

View file

@ -0,0 +1,46 @@
#!/bin/sh
set -e
ROOTDIR=dist
BUNDLE=${ROOTDIR}/Bitcoin-Qt.app
CODESIGN=codesign
TEMPDIR=sign.temp
TEMPLIST=${TEMPDIR}/signatures.txt
OUT=signature.tar.gz
if [ ! -n "$1" ]; then
echo "usage: $0 <codesign args>"
echo "example: $0 -s MyIdentity"
exit 1
fi
rm -rf ${TEMPDIR} ${TEMPLIST}
mkdir -p ${TEMPDIR}
${CODESIGN} -f --file-list ${TEMPLIST} "$@" "${BUNDLE}"
for i in `grep -v CodeResources ${TEMPLIST}`; do
TARGETFILE="${BUNDLE}/`echo ${i} | sed "s|.*${BUNDLE}/||"`"
SIZE=`pagestuff $i -p | tail -2 | grep size | sed 's/[^0-9]*//g'`
OFFSET=`pagestuff $i -p | tail -2 | grep offset | sed 's/[^0-9]*//g'`
SIGNFILE="${TEMPDIR}/${TARGETFILE}.sign"
DIRNAME="`dirname ${SIGNFILE}`"
mkdir -p "${DIRNAME}"
echo "Adding detached signature for: ${TARGETFILE}. Size: ${SIZE}. Offset: ${OFFSET}"
dd if=$i of=${SIGNFILE} bs=1 skip=${OFFSET} count=${SIZE} 2>/dev/null
done
for i in `grep CodeResources ${TEMPLIST}`; do
TARGETFILE="${BUNDLE}/`echo ${i} | sed "s|.*${BUNDLE}/||"`"
RESOURCE="${TEMPDIR}/${TARGETFILE}"
DIRNAME="`dirname "${RESOURCE}"`"
mkdir -p "${DIRNAME}"
echo "Adding resource for: "${TARGETFILE}""
cp "${i}" "${RESOURCE}"
done
rm ${TEMPLIST}
tar -C ${TEMPDIR} -czf ${OUT} .
rm -rf ${TEMPDIR}
echo "Created ${OUT}"

View file

@ -1,30 +0,0 @@
package=gmp
$(package)_version=6.0.0a
$(package)_download_path=https://gmplib.org/download/gmp
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
$(package)_sha256_hash=7f8e9a804b9c6d07164cf754207be838ece1219425d64e28cfa3e70d5c759aaf
$(package)_patches=arm_gmp_build_fix.patch darwin_gmp_build_fix.patch
define $(package)_preprocess_cmds
patch -p1 < $($(package)_patch_dir)/arm_gmp_build_fix.patch && \
patch -p1 < $($(package)_patch_dir)/darwin_gmp_build_fix.patch
endef
define $(package)_set_vars
$(package)_config_opts=--disable-shared CC_FOR_BUILD=$(build_CC)
$(package)_config_opts_x86_64_darwin=--with-pic
$(package)_config_opts_x86_64_linux=--with-pic
$(package)_config_opts_arm_linux=--with-pic
endef
define $(package)_config_cmds
$($(package)_autoconf)
endef
define $(package)_build_cmds
$(MAKE)
endef
define $(package)_stage_cmds
$(MAKE) DESTDIR=$($(package)_staging_dir) install
endef

View file

@ -1,4 +1,4 @@
packages:=boost openssl gmp packages:=boost openssl
native_packages := native_ccache native_comparisontool native_packages := native_ccache native_comparisontool
qt_native_packages = native_protobuf qt_native_packages = native_protobuf

View file

@ -48,6 +48,7 @@ define $(package)_preprocess_cmds
sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \ sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \
sed -i.old "s/src_plugins.depends = src_sql src_xml src_network/src_plugins.depends = src_xml src_network/" qtbase/src/src.pro && \ sed -i.old "s/src_plugins.depends = src_sql src_xml src_network/src_plugins.depends = src_xml src_network/" qtbase/src/src.pro && \
sed -i.old "/XIproto.h/d" qtbase/src/plugins/platforms/xcb/qxcbxsettings.cpp && \ sed -i.old "/XIproto.h/d" qtbase/src/plugins/platforms/xcb/qxcbxsettings.cpp && \
sed -i.old 's/if \[ "$$$$XPLATFORM_MAC" = "yes" \]; then xspecvals=$$$$(macSDKify/if \[ "$$$$BUILD_ON_MAC" = "yes" \]; then xspecvals=$$$$(macSDKify/' qtbase/configure && \
mkdir -p qtbase/mkspecs/macx-clang-linux &&\ mkdir -p qtbase/mkspecs/macx-clang-linux &&\
cp -f qtbase/mkspecs/macx-clang/Info.plist.lib qtbase/mkspecs/macx-clang-linux/ &&\ cp -f qtbase/mkspecs/macx-clang/Info.plist.lib qtbase/mkspecs/macx-clang-linux/ &&\
cp -f qtbase/mkspecs/macx-clang/Info.plist.app qtbase/mkspecs/macx-clang-linux/ &&\ cp -f qtbase/mkspecs/macx-clang/Info.plist.app qtbase/mkspecs/macx-clang-linux/ &&\

View file

@ -1,21 +0,0 @@
# HG changeset patch
# User Torbjorn Granlund <tege@gmplib.org>
# Date 1396602422 -7200
# Node ID 676e2d0f0e4dd301a7066079d2c9326c25c34a40
# Parent 0194a75b56b21a9196626430af86c5bd9110c42d
Conditionalise ARM asm on !__thumb__.
diff -r 0194a75b56b2 -r 676e2d0f0e4d mpn/generic/div_qr_1n_pi1.c
--- a/mpn/generic/div_qr_1n_pi1.c Thu Apr 03 23:58:51 2014 +0200
+++ b/mpn/generic/div_qr_1n_pi1.c Fri Apr 04 11:07:02 2014 +0200
@@ -130,7 +130,7 @@
"%2" ((UDItype)(a0)), "r" ((UDItype)(b0)) __CLOBBER_CC)
#endif
-#if defined (__arm__) && W_TYPE_SIZE == 32
+#if defined (__arm__) && !defined (__thumb__) && W_TYPE_SIZE == 32
#define add_mssaaaa(m, sh, sl, ah, al, bh, bl) \
__asm__ ( "adds %2, %5, %6\n\t" \
"adcs %1, %3, %4\n\t" \

View file

@ -1,29 +0,0 @@
# HG changeset patch
# User Torbjorn Granlund <tege@gmplib.org>
# Date 1396470504 -7200
# Node ID 1fab0adc5ff7d9ecddcbda96f407da58347bb49c
# Parent db645603dcdb41afcf78b19b551ecd5a01c3841c
Workaround for Darwin assembler quirk.
diff -r db645603dcdb -r 1fab0adc5ff7 mpn/x86_64/k8/redc_1.asm
--- a/mpn/x86_64/k8/redc_1.asm Mon Mar 31 23:04:32 2014 +0200
+++ b/mpn/x86_64/k8/redc_1.asm Wed Apr 02 22:28:24 2014 +0200
@@ -114,7 +114,7 @@
JUMPTABSECT
ALIGN(8)
-L(tab): JMPENT( L(0m4), L(tab))
+L(tab): JMPENT( L(0), L(tab))
JMPENT( L(1), L(tab))
JMPENT( L(2), L(tab))
JMPENT( L(3), L(tab))
@@ -397,6 +397,7 @@
ALIGN(16)
+L(0):
L(0m4):
L(lo0): mov (mp,nneg,8), %rax
mov nneg, i

View file

@ -65,3 +65,18 @@ Background images and other features can be added to DMG files by inserting a
.DS_Store before creation. The easiest way to create this file is to build a .DS_Store before creation. The easiest way to create this file is to build a
DMG without one, move it to a device running OSX, customize the layout, then DMG without one, move it to a device running OSX, customize the layout, then
grab the .DS_Store file for later use. That is the approach taken here. grab the .DS_Store file for later use. That is the approach taken here.
As of OSX Mavericks (10.9), using an Apple-blessed key to sign binaries is a
requirement in order to satisfy the new Gatekeeper requirements. Because this
private key cannot be shared, we'll have to be a bit creative in order for the
build process to remain somewhat deterministic. Here's how it works:
- Builders use gitian to create an unsigned release. This outputs an unsigned
dmg which users may choose to bless and run. It also outputs an unsigned app
structure in the form of a tarball, which also contains all of the tools
that have been previously (deterministically) built in order to create a
final dmg.
- The Apple keyholder uses this unsigned app to create a detached signature,
using the script that is also included there.
- Builders feed the unsigned app + detached signature back into gitian. It
uses the pre-built tools to recombine the pieces into a deterministic dmg.

24
doc/REST-interface.md Normal file
View file

@ -0,0 +1,24 @@
Unauthenticated REST Interface
==============================
The REST API can be enabled with the `-rest` option.
Supported API
-------------
`GET /rest/tx/TX-HASH.{bin|hex|json}`
Given a transaction hash,
Returns a transaction, in binary, hex-encoded binary or JSON formats.
`GET /rest/block/BLOCK-HASH.{bin|hex|json}`
Given a block hash,
Returns a block, in binary, hex-encoded binary or JSON formats.
The HTTP request and response are both handled entirely in-memory, thus making maximum memory usage at least 2.66MB (1 MB max block, plus hex encoding) per request.
For full TX query capability, one must enable the transaction index via "txindex=1" command line / configuration option.
Risks
-------------
Running a webbrowser on the same node with a REST enabled bitcoind can be a risk. Accessing prepared XSS websites could read out tx/block data of your node by placing links like `<script src="http://127.0.0.1:1234/tx/json/1234567890">` which might break the nodes privacy.

View file

@ -38,7 +38,7 @@ Instructions: Homebrew
#### Install dependencies using Homebrew #### Install dependencies using Homebrew
brew install autoconf automake libtool boost miniupnpc openssl pkg-config protobuf qt gmp brew install autoconf automake libtool boost miniupnpc openssl pkg-config protobuf qt
#### Installing berkeley-db4 using Homebrew #### Installing berkeley-db4 using Homebrew

View file

@ -33,7 +33,6 @@ These dependencies are required:
------------|------------------|---------------------- ------------|------------------|----------------------
libssl | SSL Support | Secure communications libssl | SSL Support | Secure communications
libboost | Boost | C++ Library libboost | Boost | C++ Library
libgmp | secp256k1 | Arbitrary-precision arithmetic (version >= 3.1)
Optional dependencies: Optional dependencies:
@ -58,7 +57,7 @@ Dependency Build Instructions: Ubuntu & Debian
---------------------------------------------- ----------------------------------------------
Build requirements: Build requirements:
sudo apt-get install build-essential libtool autotools-dev autoconf pkg-config libssl-dev libgmp-dev sudo apt-get install build-essential libtool autotools-dev autoconf pkg-config libssl-dev
for Ubuntu 12.04 and later or Debian 7 and later libboost-all-dev has to be installed: for Ubuntu 12.04 and later or Debian 7 and later libboost-all-dev has to be installed:
@ -106,7 +105,7 @@ To build with Qt 4 you need the following:
For Qt 5 you need the following: For Qt 5 you need the following:
sudo apt-get install libqt5gui5 libqt5core5 libqt5dbus5 qttools5-dev qttools5-dev-tools libprotobuf-dev protobuf-compiler sudo apt-get install libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools libprotobuf-dev protobuf-compiler
libqrencode (optional) can be installed with: libqrencode (optional) can be installed with:

View file

@ -95,3 +95,32 @@ are done, it always returns an immediate error with code -28 to all calls.
This new behaviour can be useful for clients to know that a server is already This new behaviour can be useful for clients to know that a server is already
started and will be available soon (for instance, so that they do not started and will be available soon (for instance, so that they do not
have to start it themselves). have to start it themselves).
Improved signing security
=========================
For 0.10 the security of signing against unusual attacks has been
improved by making the signatures constant time and deterministic.
This change is a result of switching signing to use libsecp256k1
instead of OpenSSL. Libsecp256k1 is a cryptographic library
optimized for the curve Bitcoin uses which was created by Bitcoin
Core developer Pieter Wuille.
There exist attacks[1] against most ECC implementations where an
attacker on shared virtual machine hardware could extract a private
key if they could cause a target to sign using the same key hundreds
of times. While using shared hosts and reusing keys are inadvisable
for other reasons, it's a better practice to avoid the exposure.
OpenSSL has code in their source repository for derandomization
and reduction in timing leaks, and we've eagerly wanted to use
it for a long time but this functionality has still not made its
way into a released version of OpenSSL. Libsecp256k1 achieves
significantly stronger protection: As far as we're aware this is
the only deployed implementation of constant time signing for
the curve Bitcoin uses and we have reason to believe that
libsecp256k1 is better tested and more thoroughly reviewed
than the implementation in OpenSSL.
[1] https://eprint.iacr.org/2014/161.pdf

View file

@ -54,48 +54,23 @@ Release Process
./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml
./bin/gsign --signer $SIGNER --release ${VERSION}-linux --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml ./bin/gsign --signer $SIGNER --release ${VERSION}-linux --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml
pushd build/out mv build/out/bitcoin-*.tar.gz build/out/src/bitcoin-*.tar.gz ../
zip -r bitcoin-${VERSION}-linux-gitian.zip *
mv bitcoin-${VERSION}-linux-gitian.zip ../../../
popd
./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win.yml ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win.yml
./bin/gsign --signer $SIGNER --release ${VERSION}-win --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win.yml ./bin/gsign --signer $SIGNER --release ${VERSION}-win --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win.yml
pushd build/out mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ../
zip -r bitcoin-${VERSION}-win-gitian.zip *
mv bitcoin-${VERSION}-win-gitian.zip ../../../
popd
./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml
./bin/gsign --signer $SIGNER --release ${VERSION}-osx --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml ./bin/gsign --signer $SIGNER --release ${VERSION}-osx-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml
pushd build/out mv build/out/bitcoin-*-unsigned.tar.gz inputs
mv Bitcoin-Qt.dmg ../../../ mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ../
popd popd
popd bitcoin-0.9.99-osx-unsigned.tar.gz
Build output expected: Build output expected:
1. linux 32-bit and 64-bit binaries + source (bitcoin-${VERSION}-linux-gitian.zip) 1. source tarball (bitcoin-${VERSION}.tar.gz)
2. windows 32-bit and 64-bit binaries + installer + source (bitcoin-${VERSION}-win-gitian.zip) 2. linux 32-bit and 64-bit binaries dist tarballs (bitcoin-${VERSION}-linux[32|64].tar.gz)
3. OSX installer (Bitcoin-Qt.dmg) 3. windows 32-bit and 64-bit installers and dist zips (bitcoin-${VERSION}-win[32|64]-setup.exe, bitcoin-${VERSION}-win[32|64].zip)
4. Gitian signatures (in gitian.sigs/${VERSION}-<linux|win|osx>/(your gitian key)/ 4. OSX unsigned installer (bitcoin-${VERSION}-osx-unsigned.dmg)
5. Gitian signatures (in gitian.sigs/${VERSION}-<linux|win|osx-unsigned>/(your gitian key)/
repackage gitian builds for release as stand-alone zip/tar/installer exe
**Linux .tar.gz:**
unzip bitcoin-${VERSION}-linux-gitian.zip -d bitcoin-${VERSION}-linux
tar czvf bitcoin-${VERSION}-linux.tar.gz bitcoin-${VERSION}-linux
rm -rf bitcoin-${VERSION}-linux
**Windows .zip and setup.exe:**
unzip bitcoin-${VERSION}-win-gitian.zip -d bitcoin-${VERSION}-win
mv bitcoin-${VERSION}-win/bitcoin-*-setup.exe .
zip -r bitcoin-${VERSION}-win.zip bitcoin-${VERSION}-win
rm -rf bitcoin-${VERSION}-win
**Mac OS X .dmg:**
mv Bitcoin-Qt.dmg bitcoin-${VERSION}-osx.dmg
###Next steps: ###Next steps:
@ -104,7 +79,28 @@ Commit your signature to gitian.sigs:
pushd gitian.sigs pushd gitian.sigs
git add ${VERSION}-linux/${SIGNER} git add ${VERSION}-linux/${SIGNER}
git add ${VERSION}-win/${SIGNER} git add ${VERSION}-win/${SIGNER}
git add ${VERSION}-osx/${SIGNER} git add ${VERSION}-osx-unsigned/${SIGNER}
git commit -a
git push # Assuming you can push to the gitian.sigs tree
popd
Wait for OSX detached signature:
Once the OSX build has 3 matching signatures, Gavin will sign it with the apple App-Store key.
He will then upload a detached signature to be combined with the unsigned app to create a signed binary.
Create the signed OSX binary:
pushd ./gitian-builder
# Fetch the signature as instructed by Gavin
cp signature.tar.gz inputs/
./bin/gbuild -i ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml
./bin/gsign --signer $SIGNER --release ${VERSION}-osx-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml
mv build/out/bitcoin-${VERSION}-osx.dmg ../
popd
Commit your signature for the signed OSX binary:
pushd gitian.sigs
git add ${VERSION}-osx-signed/${SIGNER}
git commit -a git commit -a
git push # Assuming you can push to the gitian.sigs tree git push # Assuming you can push to the gitian.sigs tree
popd popd
@ -117,8 +113,6 @@ Commit your signature to gitian.sigs:
- Code-sign Windows -setup.exe (in a Windows virtual machine using signtool) - Code-sign Windows -setup.exe (in a Windows virtual machine using signtool)
- Code-sign MacOSX .dmg
Note: only Gavin has the code-signing keys currently. Note: only Gavin has the code-signing keys currently.
- Create `SHA256SUMS.asc` for the builds, and GPG-sign it: - Create `SHA256SUMS.asc` for the builds, and GPG-sign it:

View file

@ -18,8 +18,13 @@ fi
if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then
${BUILDDIR}/qa/rpc-tests/wallet.py --srcdir "${BUILDDIR}/src" ${BUILDDIR}/qa/rpc-tests/wallet.py --srcdir "${BUILDDIR}/src"
${BUILDDIR}/qa/rpc-tests/listtransactions.py --srcdir "${BUILDDIR}/src" ${BUILDDIR}/qa/rpc-tests/listtransactions.py --srcdir "${BUILDDIR}/src"
${BUILDDIR}/qa/rpc-tests/mempool_resurrect_test.py --srcdir "${BUILDDIR}/src"
${BUILDDIR}/qa/rpc-tests/txn_doublespend.py --srcdir "${BUILDDIR}/src" ${BUILDDIR}/qa/rpc-tests/txn_doublespend.py --srcdir "${BUILDDIR}/src"
${BUILDDIR}/qa/rpc-tests/txn_doublespend.py --mineblock --srcdir "${BUILDDIR}/src" ${BUILDDIR}/qa/rpc-tests/txn_doublespend.py --mineblock --srcdir "${BUILDDIR}/src"
${BUILDDIR}/qa/rpc-tests/getchaintips.py --srcdir "${BUILDDIR}/src"
${BUILDDIR}/qa/rpc-tests/rest.py --srcdir "${BUILDDIR}/src"
${BUILDDIR}/qa/rpc-tests/mempool_spendcoinbase.py --srcdir "${BUILDDIR}/src"
${BUILDDIR}/qa/rpc-tests/httpbasics.py --srcdir "${BUILDDIR}/src"
#${BUILDDIR}/qa/rpc-tests/forknotify.py --srcdir "${BUILDDIR}/src" #${BUILDDIR}/qa/rpc-tests/forknotify.py --srcdir "${BUILDDIR}/src"
else else
echo "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled" echo "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled"

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers # Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers # Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers # Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers # Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -19,6 +19,7 @@ class GetChainTipsTest (BitcoinTestFramework):
assert_equal (len (tips), 1) assert_equal (len (tips), 1)
assert_equal (tips[0]['branchlen'], 0) assert_equal (tips[0]['branchlen'], 0)
assert_equal (tips[0]['height'], 200) assert_equal (tips[0]['height'], 200)
assert_equal (tips[0]['status'], 'active')
# Split the network and build two chains of different lengths. # Split the network and build two chains of different lengths.
self.split_network () self.split_network ()
@ -31,12 +32,14 @@ class GetChainTipsTest (BitcoinTestFramework):
shortTip = tips[0] shortTip = tips[0]
assert_equal (shortTip['branchlen'], 0) assert_equal (shortTip['branchlen'], 0)
assert_equal (shortTip['height'], 210) assert_equal (shortTip['height'], 210)
assert_equal (tips[0]['status'], 'active')
tips = self.nodes[3].getchaintips () tips = self.nodes[3].getchaintips ()
assert_equal (len (tips), 1) assert_equal (len (tips), 1)
longTip = tips[0] longTip = tips[0]
assert_equal (longTip['branchlen'], 0) assert_equal (longTip['branchlen'], 0)
assert_equal (longTip['height'], 220) assert_equal (longTip['height'], 220)
assert_equal (tips[0]['status'], 'active')
# Join the network halves and check that we now have two tips # Join the network halves and check that we now have two tips
# (at least at the nodes that previously had the short chain). # (at least at the nodes that previously had the short chain).
@ -47,7 +50,9 @@ class GetChainTipsTest (BitcoinTestFramework):
assert_equal (tips[0], longTip) assert_equal (tips[0], longTip)
assert_equal (tips[1]['branchlen'], 10) assert_equal (tips[1]['branchlen'], 10)
tips[1]['branchlen'] = 0; assert_equal (tips[1]['status'], 'valid-fork')
tips[1]['branchlen'] = 0
tips[1]['status'] = 'active'
assert_equal (tips[1], shortTip) assert_equal (tips[1], shortTip)
if __name__ == '__main__': if __name__ == '__main__':

76
qa/rpc-tests/httpbasics.py Executable file
View file

@ -0,0 +1,76 @@
#!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
# Test REST interface
#
from test_framework import BitcoinTestFramework
from util import *
import base64
try:
import http.client as httplib
except ImportError:
import httplib
try:
import urllib.parse as urlparse
except ImportError:
import urlparse
class RESTTest (BitcoinTestFramework):
def run_test(self):
#################################################
# lowlevel check for http persistent connection #
#################################################
url = urlparse.urlparse(self.nodes[0].url)
authpair = url.username + ':' + url.password
headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
conn.request('GET', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read();
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
#send 2nd request without closing connection
conn.request('GET', '/', '{"method": "getchaintips"}', headers)
out2 = conn.getresponse().read();
assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
conn.close()
#same should be if we add keep-alive because this should be the std. behaviour
headers = {"Authorization": "Basic " + base64.b64encode(authpair), "Connection": "keep-alive"}
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
conn.request('GET', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read();
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
#send 2nd request without closing connection
conn.request('GET', '/', '{"method": "getchaintips"}', headers)
out2 = conn.getresponse().read();
assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
conn.close()
#now do the same with "Connection: close"
headers = {"Authorization": "Basic " + base64.b64encode(authpair), "Connection":"close"}
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
conn.request('GET', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read();
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, False) #now the connection must be closed after the response
if __name__ == '__main__':
RESTTest ().main ()

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers # Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers # Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.

View file

@ -0,0 +1,88 @@
#!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
# Test resurrection of mined transactions when
# the blockchain is re-organized.
#
from test_framework import BitcoinTestFramework
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
from util import *
import os
import shutil
# Create one-input, one-output, no-fee transaction:
class MempoolCoinbaseTest(BitcoinTestFramework):
def setup_network(self):
# Just need one node for this test
args = ["-checkmempool", "-debug=mempool"]
self.nodes = []
self.nodes.append(start_node(0, self.options.tmpdir, args))
self.is_network_split = False
def create_tx(self, from_txid, to_address, amount):
inputs = [{ "txid" : from_txid, "vout" : 0}]
outputs = { to_address : amount }
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
signresult = self.nodes[0].signrawtransaction(rawtx)
assert_equal(signresult["complete"], True)
return signresult["hex"]
def run_test(self):
node0_address = self.nodes[0].getnewaddress()
# Spend block 1/2/3's coinbase transactions
# Mine a block.
# Create three more transactions, spending the spends
# Mine another block.
# ... make sure all the transactions are confirmed
# Invalidate both blocks
# ... make sure all the transactions are put back in the mempool
# Mine a new block
# ... make sure all the transactions are confirmed again.
b = [ self.nodes[0].getblockhash(n) for n in range(1, 4) ]
coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
spends1_raw = [ self.create_tx(txid, node0_address, 50) for txid in coinbase_txids ]
spends1_id = [ self.nodes[0].sendrawtransaction(tx) for tx in spends1_raw ]
blocks = []
blocks.extend(self.nodes[0].setgenerate(True, 1))
spends2_raw = [ self.create_tx(txid, node0_address, 49.99) for txid in spends1_id ]
spends2_id = [ self.nodes[0].sendrawtransaction(tx) for tx in spends2_raw ]
blocks.extend(self.nodes[0].setgenerate(True, 1))
# mempool should be empty, all txns confirmed
assert_equal(set(self.nodes[0].getrawmempool()), set())
for txid in spends1_id+spends2_id:
tx = self.nodes[0].gettransaction(txid)
assert(tx["confirmations"] > 0)
# Use invalidateblock to re-org back; all transactions should
# end up unconfirmed and back in the mempool
for node in self.nodes:
node.invalidateblock(blocks[0])
# mempool should be empty, all txns confirmed
assert_equal(set(self.nodes[0].getrawmempool()), set(spends1_id+spends2_id))
for txid in spends1_id+spends2_id:
tx = self.nodes[0].gettransaction(txid)
assert(tx["confirmations"] == 0)
# Generate another block, they should all get mined
self.nodes[0].setgenerate(True, 1)
# mempool should be empty, all txns confirmed
assert_equal(set(self.nodes[0].getrawmempool()), set())
for txid in spends1_id+spends2_id:
tx = self.nodes[0].gettransaction(txid)
assert(tx["confirmations"] > 0)
if __name__ == '__main__':
MempoolCoinbaseTest().main()

View file

@ -0,0 +1,69 @@
#!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
# Test spending coinbase transactions.
# The coinbase transaction in block N can appear in block
# N+100... so is valid in the mempool when the best block
# height is N+99.
# This test makes sure coinbase spends that will be mature
# in the next block are accepted into the memory pool,
# but less mature coinbase spends are NOT.
#
from test_framework import BitcoinTestFramework
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
from util import *
import os
import shutil
# Create one-input, one-output, no-fee transaction:
class MempoolSpendCoinbaseTest(BitcoinTestFramework):
def setup_network(self):
# Just need one node for this test
args = ["-checkmempool", "-debug=mempool"]
self.nodes = []
self.nodes.append(start_node(0, self.options.tmpdir, args))
self.is_network_split = False
def create_tx(self, from_txid, to_address, amount):
inputs = [{ "txid" : from_txid, "vout" : 0}]
outputs = { to_address : amount }
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
signresult = self.nodes[0].signrawtransaction(rawtx)
assert_equal(signresult["complete"], True)
return signresult["hex"]
def run_test(self):
chain_height = self.nodes[0].getblockcount()
assert_equal(chain_height, 200)
node0_address = self.nodes[0].getnewaddress()
# Coinbase at height chain_height-100+1 ok in mempool, should
# get mined. Coinbase at height chain_height-100+2 is
# is too immature to spend.
b = [ self.nodes[0].getblockhash(n) for n in range(101, 103) ]
coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
spends_raw = [ self.create_tx(txid, node0_address, 50) for txid in coinbase_txids ]
spend_101_id = self.nodes[0].sendrawtransaction(spends_raw[0])
# coinbase at height 102 should be too immature to spend
assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, spends_raw[1])
# mempool should have just spend_101:
assert_equal(self.nodes[0].getrawmempool(), [ spend_101_id ])
# mine a block, spend_101 should get confirmed
self.nodes[0].setgenerate(True, 1)
assert_equal(set(self.nodes[0].getrawmempool()), set())
# ... and now height 102 can be spent:
spend_102_id = self.nodes[0].sendrawtransaction(spends_raw[1])
assert_equal(self.nodes[0].getrawmempool(), [ spend_102_id ])
if __name__ == '__main__':
MempoolSpendCoinbaseTest().main()

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers # Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python2
from distutils.core import setup from distutils.core import setup

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers # Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.

62
qa/rpc-tests/rest.py Executable file
View file

@ -0,0 +1,62 @@
#!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
# Test REST interface
#
from test_framework import BitcoinTestFramework
from util import *
import json
try:
import http.client as httplib
except ImportError:
import httplib
try:
import urllib.parse as urlparse
except ImportError:
import urlparse
def http_get_call(host, port, path, response_object = 0):
conn = httplib.HTTPConnection(host, port)
conn.request('GET', path)
if response_object:
return conn.getresponse()
return conn.getresponse().read()
class RESTTest (BitcoinTestFramework):
FORMAT_SEPARATOR = "."
def run_test(self):
url = urlparse.urlparse(self.nodes[0].url)
bb_hash = self.nodes[0].getbestblockhash()
# check binary format
response = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+"bin", True)
assert_equal(response.status, 200)
assert_greater_than(int(response.getheader('content-length')), 10)
# check json format
json_string = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+'json')
json_obj = json.loads(json_string)
assert_equal(json_obj['hash'], bb_hash)
# do tx test
tx_hash = json_obj['tx'][0];
json_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"json")
json_obj = json.loads(json_string)
assert_equal(json_obj['txid'], tx_hash)
# check hex format response
hex_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"hex", True)
assert_equal(response.status, 200)
assert_greater_than(int(response.getheader('content-length')), 10)
if __name__ == '__main__':
RESTTest ().main ()

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers # Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers # Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers # Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers # Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.

View file

@ -163,7 +163,7 @@ def start_node(i, dirname, extra_args=None, rpchost=None):
Start a bitcoind and return RPC connection to it Start a bitcoind and return RPC connection to it
""" """
datadir = os.path.join(dirname, "node"+str(i)) datadir = os.path.join(dirname, "node"+str(i))
args = [ os.getenv("BITCOIND", "bitcoind"), "-datadir="+datadir, "-keypool=1", "-discover=0" ] args = [ os.getenv("BITCOIND", "bitcoind"), "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest" ]
if extra_args is not None: args.extend(extra_args) if extra_args is not None: args.extend(extra_args)
bitcoind_processes[i] = subprocess.Popen(args) bitcoind_processes[i] = subprocess.Popen(args)
devnull = open("/dev/null", "w+") devnull = open("/dev/null", "w+")
@ -327,3 +327,17 @@ def random_transaction(nodes, amount, min_fee, fee_increment, fee_variants):
def assert_equal(thing1, thing2): def assert_equal(thing1, thing2):
if thing1 != thing2: if thing1 != thing2:
raise AssertionError("%s != %s"%(str(thing1),str(thing2))) raise AssertionError("%s != %s"%(str(thing1),str(thing2)))
def assert_greater_than(thing1, thing2):
if thing1 <= thing2:
raise AssertionError("%s <= %s"%(str(thing1),str(thing2)))
def assert_raises(exc, fun, *args, **kwds):
try:
fun(*args, **kwds)
except exc:
pass
except Exception as e:
raise AssertionError("Unexpected exception raised: "+type(e).__name__)
else:
raise AssertionError("No exception raised")

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers # Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT/X11 software license, see the accompanying # Distributed under the MIT/X11 software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.

View file

@ -87,8 +87,8 @@ BITCOIN_CORE_H = \
coins.h \ coins.h \
compat.h \ compat.h \
compressor.h \ compressor.h \
core/block.h \ primitives/block.h \
core/transaction.h \ primitives/transaction.h \
core_io.h \ core_io.h \
crypter.h \ crypter.h \
db.h \ db.h \
@ -101,6 +101,7 @@ BITCOIN_CORE_H = \
leveldbwrapper.h \ leveldbwrapper.h \
limitedmap.h \ limitedmap.h \
main.h \ main.h \
merkleblock.h \
miner.h \ miner.h \
mruset.h \ mruset.h \
netbase.h \ netbase.h \
@ -168,6 +169,7 @@ libbitcoin_server_a_SOURCES = \
init.cpp \ init.cpp \
leveldbwrapper.cpp \ leveldbwrapper.cpp \
main.cpp \ main.cpp \
merkleblock.cpp \
miner.cpp \ miner.cpp \
net.cpp \ net.cpp \
noui.cpp \ noui.cpp \
@ -203,10 +205,18 @@ libbitcoin_wallet_a_SOURCES = \
crypto_libbitcoin_crypto_a_CPPFLAGS = $(BITCOIN_CONFIG_INCLUDES) crypto_libbitcoin_crypto_a_CPPFLAGS = $(BITCOIN_CONFIG_INCLUDES)
crypto_libbitcoin_crypto_a_SOURCES = \ crypto_libbitcoin_crypto_a_SOURCES = \
crypto/sha1.cpp \ crypto/sha1.cpp \
crypto/sha2.cpp \ crypto/sha256.cpp \
crypto/sha512.cpp \
crypto/hmac_sha256.cpp \
crypto/rfc6979_hmac_sha256.cpp \
crypto/hmac_sha512.cpp \
crypto/ripemd160.cpp \ crypto/ripemd160.cpp \
crypto/common.h \ crypto/common.h \
crypto/sha2.h \ crypto/sha256.h \
crypto/sha512.h \
crypto/hmac_sha256.h \
crypto/rfc6979_hmac_sha256.h \
crypto/hmac_sha512.h \
crypto/sha1.h \ crypto/sha1.h \
crypto/ripemd160.h crypto/ripemd160.h
@ -227,8 +237,8 @@ libbitcoin_common_a_SOURCES = \
chainparams.cpp \ chainparams.cpp \
coins.cpp \ coins.cpp \
compressor.cpp \ compressor.cpp \
core/block.cpp \ primitives/block.cpp \
core/transaction.cpp \ primitives/transaction.cpp \
core_read.cpp \ core_read.cpp \
core_write.cpp \ core_write.cpp \
eccryptoverify.cpp \ eccryptoverify.cpp \
@ -251,6 +261,7 @@ libbitcoin_common_a_SOURCES = \
# backward-compatibility objects and their sanity checks are linked. # backward-compatibility objects and their sanity checks are linked.
libbitcoin_util_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_util_a_CPPFLAGS = $(BITCOIN_INCLUDES)
libbitcoin_util_a_SOURCES = \ libbitcoin_util_a_SOURCES = \
compat/strnlen.cpp \
compat/glibc_sanity.cpp \ compat/glibc_sanity.cpp \
compat/glibcxx_sanity.cpp \ compat/glibcxx_sanity.cpp \
chainparamsbase.cpp \ chainparamsbase.cpp \
@ -341,9 +352,11 @@ bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
if BUILD_BITCOIN_LIBS if BUILD_BITCOIN_LIBS
include_HEADERS = script/bitcoinconsensus.h include_HEADERS = script/bitcoinconsensus.h
libbitcoinconsensus_la_SOURCES = \ libbitcoinconsensus_la_SOURCES = \
core/transaction.cpp \ primitives/transaction.cpp \
crypto/hmac_sha512.cpp \
crypto/sha1.cpp \ crypto/sha1.cpp \
crypto/sha2.cpp \ crypto/sha256.cpp \
crypto/sha512.cpp \
crypto/ripemd160.cpp \ crypto/ripemd160.cpp \
eccryptoverify.cpp \ eccryptoverify.cpp \
ecwrapper.cpp \ ecwrapper.cpp \

View file

@ -66,6 +66,20 @@ static bool AppInitRPC(int argc, char* argv[])
// Parameters // Parameters
// //
ParseParameters(argc, argv); ParseParameters(argc, argv);
if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) {
std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n";
if (!mapArgs.count("-version")) {
strUsage += "\n" + _("Usage:") + "\n" +
" bitcoin-cli [options] <command> [params] " + _("Send command to Bitcoin Core") + "\n" +
" bitcoin-cli [options] help " + _("List commands") + "\n" +
" bitcoin-cli [options] help <command> " + _("Get help for a command") + "\n";
strUsage += "\n" + HelpMessageCli();
}
fprintf(stdout, "%s", strUsage.c_str());
return false;
}
if (!boost::filesystem::is_directory(GetDataDir(false))) { if (!boost::filesystem::is_directory(GetDataDir(false))) {
fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str()); fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
return false; return false;
@ -81,20 +95,6 @@ static bool AppInitRPC(int argc, char* argv[])
fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n"); fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
return false; return false;
} }
if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) {
std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n";
if (!mapArgs.count("-version")) {
strUsage += "\n" + _("Usage:") + "\n" +
" bitcoin-cli [options] <command> [params] " + _("Send command to Bitcoin Core") + "\n" +
" bitcoin-cli [options] help " + _("List commands") + "\n" +
" bitcoin-cli [options] help <command> " + _("Get help for a command") + "\n";
strUsage += "\n" + HelpMessageCli();
}
fprintf(stdout, "%s", strUsage.c_str());
return false;
}
return true; return true;
} }
@ -110,7 +110,7 @@ Object CallRPC(const string& strMethod, const Array& params)
bool fUseSSL = GetBoolArg("-rpcssl", false); bool fUseSSL = GetBoolArg("-rpcssl", false);
asio::io_service io_service; asio::io_service io_service;
ssl::context context(io_service, ssl::context::sslv23); ssl::context context(io_service, ssl::context::sslv23);
context.set_options(ssl::context::no_sslv2); context.set_options(ssl::context::no_sslv2 | ssl::context::no_sslv3);
asio::ssl::stream<asio::ip::tcp::socket> sslStream(io_service, context); asio::ssl::stream<asio::ip::tcp::socket> sslStream(io_service, context);
SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL); SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL);
iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d); iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d);

View file

@ -4,15 +4,17 @@
#include "base58.h" #include "base58.h"
#include "clientversion.h" #include "clientversion.h"
#include "core/transaction.h" #include "primitives/block.h" // for MAX_BLOCK_SIZE
#include "primitives/transaction.h"
#include "core_io.h" #include "core_io.h"
#include "coins.h"
#include "keystore.h" #include "keystore.h"
#include "main.h" // for MAX_BLOCK_SIZE
#include "script/script.h" #include "script/script.h"
#include "script/sign.h" #include "script/sign.h"
#include "ui_interface.h" // for _(...) #include "ui_interface.h" // for _(...)
#include "univalue/univalue.h" #include "univalue/univalue.h"
#include "util.h" #include "util.h"
#include "utilstrencodings.h"
#include "utilmoneystr.h" #include "utilmoneystr.h"
#include <stdio.h> #include <stdio.h>
@ -57,6 +59,7 @@ static bool AppInitRawTx(int argc, char* argv[])
strUsage += " -? " + _("This help message") + "\n"; strUsage += " -? " + _("This help message") + "\n";
strUsage += " -create " + _("Create new, empty TX.") + "\n"; strUsage += " -create " + _("Create new, empty TX.") + "\n";
strUsage += " -json " + _("Select JSON output") + "\n"; strUsage += " -json " + _("Select JSON output") + "\n";
strUsage += " -txid " + _("Output only the hex-encoded transaction id of the resultant transaction.") + "\n";
strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n"; strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n";
strUsage += " -testnet " + _("Use the test network") + "\n"; strUsage += " -testnet " + _("Use the test network") + "\n";
strUsage += "\n"; strUsage += "\n";
@ -488,6 +491,13 @@ static void OutputTxJSON(const CTransaction& tx)
fprintf(stdout, "%s\n", jsonOutput.c_str()); fprintf(stdout, "%s\n", jsonOutput.c_str());
} }
static void OutputTxHash(const CTransaction& tx)
{
string strHexHash = tx.GetHash().GetHex(); // the hex-encoded transaction hash (aka the transaction id)
fprintf(stdout, "%s\n", strHexHash.c_str());
}
static void OutputTxHex(const CTransaction& tx) static void OutputTxHex(const CTransaction& tx)
{ {
string strHex = EncodeHexTx(tx); string strHex = EncodeHexTx(tx);
@ -499,6 +509,8 @@ static void OutputTx(const CTransaction& tx)
{ {
if (GetBoolArg("-json", false)) if (GetBoolArg("-json", false))
OutputTxJSON(tx); OutputTxJSON(tx);
else if (GetBoolArg("-txid", false))
OutputTxHash(tx);
else else
OutputTxHex(tx); OutputTxHex(tx);
} }

View file

@ -59,31 +59,14 @@ bool AppInit(int argc, char* argv[])
boost::thread* detectShutdownThread = NULL; boost::thread* detectShutdownThread = NULL;
bool fRet = false; bool fRet = false;
try
{
// //
// Parameters // Parameters
// //
// If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main() // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
ParseParameters(argc, argv); ParseParameters(argc, argv);
if (!boost::filesystem::is_directory(GetDataDir(false)))
{
fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
return false;
}
try
{
ReadConfigFile(mapArgs, mapMultiArgs);
} catch(std::exception &e) {
fprintf(stderr,"Error reading configuration file: %s\n", e.what());
return false;
}
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
if (!SelectParamsFromCommandLine()) {
fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
return false;
}
// Process help and version before taking care about datadir
if (mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) if (mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version"))
{ {
std::string strUsage = _("Bitcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n"; std::string strUsage = _("Bitcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n";
@ -104,6 +87,26 @@ bool AppInit(int argc, char* argv[])
return false; return false;
} }
try
{
if (!boost::filesystem::is_directory(GetDataDir(false)))
{
fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
return false;
}
try
{
ReadConfigFile(mapArgs, mapMultiArgs);
} catch(std::exception &e) {
fprintf(stderr,"Error reading configuration file: %s\n", e.what());
return false;
}
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
if (!SelectParamsFromCommandLine()) {
fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
return false;
}
// Command-line RPC // Command-line RPC
bool fCommandLine = false; bool fCommandLine = false;
for (int i = 1; i < argc; i++) for (int i = 1; i < argc; i++)

View file

@ -4,7 +4,7 @@
#include "bloom.h" #include "bloom.h"
#include "core/transaction.h" #include "primitives/transaction.h"
#include "hash.h" #include "hash.h"
#include "script/script.h" #include "script/script.h"
#include "script/standard.h" #include "script/standard.h"

View file

@ -6,7 +6,7 @@
#ifndef BITCOIN_CHAIN_H #ifndef BITCOIN_CHAIN_H
#define BITCOIN_CHAIN_H #define BITCOIN_CHAIN_H
#include "core/block.h" #include "primitives/block.h"
#include "pow.h" #include "pow.h"
#include "tinyformat.h" #include "tinyformat.h"
#include "uint256.h" #include "uint256.h"

View file

@ -8,7 +8,7 @@
#include "chainparamsbase.h" #include "chainparamsbase.h"
#include "checkpoints.h" #include "checkpoints.h"
#include "core/block.h" #include "primitives/block.h"
#include "protocol.h" #include "protocol.h"
#include "uint256.h" #include "uint256.h"

View file

@ -5,7 +5,7 @@
#ifndef BITCOIN_COINCONTROL_H #ifndef BITCOIN_COINCONTROL_H
#define BITCOIN_COINCONTROL_H #define BITCOIN_COINCONTROL_H
#include "core/transaction.h" #include "primitives/transaction.h"
/** Coin Control Features. */ /** Coin Control Features. */
class CCoinControl class CCoinControl

View file

@ -6,6 +6,10 @@
#ifndef BITCOIN_COMPAT_H #ifndef BITCOIN_COMPAT_H
#define BITCOIN_COMPAT_H #define BITCOIN_COMPAT_H
#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif
#ifdef WIN32 #ifdef WIN32
#ifdef _WIN32_WINNT #ifdef _WIN32_WINNT
#undef _WIN32_WINNT #undef _WIN32_WINNT
@ -84,4 +88,8 @@ typedef u_int SOCKET;
#define THREAD_PRIORITY_ABOVE_NORMAL (-2) #define THREAD_PRIORITY_ABOVE_NORMAL (-2)
#endif #endif
#if HAVE_DECL_STRNLEN == 0
size_t strnlen( const char *start, size_t max_len);
#endif // HAVE_DECL_STRNLEN
#endif // BITCOIN_COMPAT_H #endif // BITCOIN_COMPAT_H

18
src/compat/strnlen.cpp Normal file
View file

@ -0,0 +1,18 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif
#include <cstring>
#if HAVE_DECL_STRNLEN == 0
size_t strnlen( const char *start, size_t max_len)
{
const char *end = (const char *)memchr(start, '\0', max_len);
return end ? (size_t)(end - start) : max_len;
}
#endif // HAVE_DECL_STRNLEN

View file

@ -6,7 +6,7 @@
#ifndef BITCOIN_COMPRESSOR_H #ifndef BITCOIN_COMPRESSOR_H
#define BITCOIN_COMPRESSOR_H #define BITCOIN_COMPRESSOR_H
#include "core/transaction.h" #include "primitives/transaction.h"
#include "script/script.h" #include "script/script.h"
#include "serialize.h" #include "serialize.h"

View file

@ -4,8 +4,8 @@
#include "core_io.h" #include "core_io.h"
#include "core/block.h" #include "primitives/block.h"
#include "core/transaction.h" #include "primitives/transaction.h"
#include "script/script.h" #include "script/script.h"
#include "serialize.h" #include "serialize.h"
#include "streams.h" #include "streams.h"

View file

@ -5,7 +5,7 @@
#include "core_io.h" #include "core_io.h"
#include "base58.h" #include "base58.h"
#include "core/transaction.h" #include "primitives/transaction.h"
#include "script/script.h" #include "script/script.h"
#include "script/standard.h" #include "script/standard.h"
#include "serialize.h" #include "serialize.h"
@ -129,4 +129,6 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry)
if (hashBlock != 0) if (hashBlock != 0)
entry.pushKV("blockhash", hashBlock.GetHex()); entry.pushKV("blockhash", hashBlock.GetHex());
entry.pushKV("hex", EncodeHexTx(tx)); // the hex-encoded transaction. used the name "hex" to be consistent with the verbose output of "getrawtransaction".
} }

View file

@ -0,0 +1,34 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "crypto/hmac_sha256.h"
#include <string.h>
CHMAC_SHA256::CHMAC_SHA256(const unsigned char* key, size_t keylen)
{
unsigned char rkey[64];
if (keylen <= 64) {
memcpy(rkey, key, keylen);
memset(rkey + keylen, 0, 64 - keylen);
} else {
CSHA256().Write(key, keylen).Finalize(rkey);
memset(rkey + 32, 0, 32);
}
for (int n = 0; n < 64; n++)
rkey[n] ^= 0x5c;
outer.Write(rkey, 64);
for (int n = 0; n < 64; n++)
rkey[n] ^= 0x5c ^ 0x36;
inner.Write(rkey, 64);
}
void CHMAC_SHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
{
unsigned char temp[32];
inner.Finalize(temp);
outer.Write(temp, 32).Finalize(hash);
}

32
src/crypto/hmac_sha256.h Normal file
View file

@ -0,0 +1,32 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_CRYPTO_HMAC_SHA256_H
#define BITCOIN_CRYPTO_HMAC_SHA256_H
#include "crypto/sha256.h"
#include <stdint.h>
#include <stdlib.h>
/** A hasher class for HMAC-SHA-512. */
class CHMAC_SHA256
{
private:
CSHA256 outer;
CSHA256 inner;
public:
static const size_t OUTPUT_SIZE = 32;
CHMAC_SHA256(const unsigned char* key, size_t keylen);
CHMAC_SHA256& Write(const unsigned char* data, size_t len)
{
inner.Write(data, len);
return *this;
}
void Finalize(unsigned char hash[OUTPUT_SIZE]);
};
#endif // BITCOIN_CRYPTO_HMAC_SHA256_H

View file

@ -0,0 +1,34 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "crypto/hmac_sha512.h"
#include <string.h>
CHMAC_SHA512::CHMAC_SHA512(const unsigned char* key, size_t keylen)
{
unsigned char rkey[128];
if (keylen <= 128) {
memcpy(rkey, key, keylen);
memset(rkey + keylen, 0, 128 - keylen);
} else {
CSHA512().Write(key, keylen).Finalize(rkey);
memset(rkey + 64, 0, 64);
}
for (int n = 0; n < 128; n++)
rkey[n] ^= 0x5c;
outer.Write(rkey, 128);
for (int n = 0; n < 128; n++)
rkey[n] ^= 0x5c ^ 0x36;
inner.Write(rkey, 128);
}
void CHMAC_SHA512::Finalize(unsigned char hash[OUTPUT_SIZE])
{
unsigned char temp[64];
inner.Finalize(temp);
outer.Write(temp, 64).Finalize(hash);
}

32
src/crypto/hmac_sha512.h Normal file
View file

@ -0,0 +1,32 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_CRYPTO_HMAC_SHA512_H
#define BITCOIN_CRYPTO_HMAC_SHA512_H
#include "crypto/sha512.h"
#include <stdint.h>
#include <stdlib.h>
/** A hasher class for HMAC-SHA-512. */
class CHMAC_SHA512
{
private:
CSHA512 outer;
CSHA512 inner;
public:
static const size_t OUTPUT_SIZE = 64;
CHMAC_SHA512(const unsigned char* key, size_t keylen);
CHMAC_SHA512& Write(const unsigned char* data, size_t len)
{
inner.Write(data, len);
return *this;
}
void Finalize(unsigned char hash[OUTPUT_SIZE]);
};
#endif // BITCOIN_CRYPTO_HMAC_SHA512_H

View file

@ -0,0 +1,47 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "crypto/rfc6979_hmac_sha256.h"
#include <string.h>
#include <algorithm>
static const unsigned char zero[1] = {0x00};
static const unsigned char one[1] = {0x01};
RFC6979_HMAC_SHA256::RFC6979_HMAC_SHA256(const unsigned char* key, size_t keylen, const unsigned char* msg, size_t msglen) : retry(false)
{
memset(V, 0x01, sizeof(V));
memset(K, 0x00, sizeof(K));
CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(zero, sizeof(zero)).Write(key, keylen).Write(msg, msglen).Finalize(K);
CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(one, sizeof(one)).Write(key, keylen).Write(msg, msglen).Finalize(K);
CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
}
RFC6979_HMAC_SHA256::~RFC6979_HMAC_SHA256()
{
memset(V, 0x01, sizeof(V));
memset(K, 0x00, sizeof(K));
}
void RFC6979_HMAC_SHA256::Generate(unsigned char* output, size_t outputlen)
{
if (retry) {
CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(zero, sizeof(zero)).Finalize(K);
CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
}
while (outputlen > 0) {
CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
size_t len = std::min(outputlen, sizeof(V));
memcpy(output, V, len);
output += len;
outputlen -= len;
}
retry = true;
}

View file

@ -0,0 +1,36 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_RFC6979_HMAC_SHA256_H
#define BITCOIN_RFC6979_HMAC_SHA256_H
#include "crypto/hmac_sha256.h"
#include <stdint.h>
#include <stdlib.h>
/** The RFC 6979 PRNG using HMAC-SHA256. */
class RFC6979_HMAC_SHA256
{
private:
unsigned char V[CHMAC_SHA256::OUTPUT_SIZE];
unsigned char K[CHMAC_SHA256::OUTPUT_SIZE];
bool retry;
public:
/**
* Construct a new RFC6979 PRNG, using the given key and message.
* The message is assumed to be already hashed.
*/
RFC6979_HMAC_SHA256(const unsigned char* key, size_t keylen, const unsigned char* msg, size_t msglen);
/**
* Generate a byte array.
*/
void Generate(unsigned char* output, size_t outputlen);
~RFC6979_HMAC_SHA256();
};
#endif // BITCOIN_RFC6979_HMAC_SHA256_H

View file

@ -1,64 +0,0 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_CRYPTO_SHA2_H
#define BITCOIN_CRYPTO_SHA2_H
#include <stdint.h>
#include <stdlib.h>
/** A hasher class for SHA-256. */
class CSHA256
{
private:
uint32_t s[8];
unsigned char buf[64];
size_t bytes;
public:
static const size_t OUTPUT_SIZE = 32;
CSHA256();
CSHA256& Write(const unsigned char* data, size_t len);
void Finalize(unsigned char hash[OUTPUT_SIZE]);
CSHA256& Reset();
};
/** A hasher class for SHA-512. */
class CSHA512
{
private:
uint64_t s[8];
unsigned char buf[128];
size_t bytes;
public:
static const size_t OUTPUT_SIZE = 64;
CSHA512();
CSHA512& Write(const unsigned char* data, size_t len);
void Finalize(unsigned char hash[OUTPUT_SIZE]);
CSHA512& Reset();
};
/** A hasher class for HMAC-SHA-512. */
class CHMAC_SHA512
{
private:
CSHA512 outer;
CSHA512 inner;
public:
static const size_t OUTPUT_SIZE = 64;
CHMAC_SHA512(const unsigned char* key, size_t keylen);
CHMAC_SHA512& Write(const unsigned char* data, size_t len)
{
inner.Write(data, len);
return *this;
}
void Finalize(unsigned char hash[OUTPUT_SIZE]);
};
#endif // BITCOIN_CRYPTO_SHA2_H

189
src/crypto/sha256.cpp Normal file
View file

@ -0,0 +1,189 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "crypto/sha256.h"
#include "crypto/common.h"
#include <string.h>
// Internal implementation code.
namespace
{
/// Internal SHA-256 implementation.
namespace sha256
{
uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); }
uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); }
uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); }
uint32_t inline Sigma1(uint32_t x) { return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); }
uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); }
uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); }
/** One round of SHA-256. */
void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t& d, uint32_t e, uint32_t f, uint32_t g, uint32_t& h, uint32_t k, uint32_t w)
{
uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w;
uint32_t t2 = Sigma0(a) + Maj(a, b, c);
d += t1;
h = t1 + t2;
}
/** Initialize SHA-256 state. */
void inline Initialize(uint32_t* s)
{
s[0] = 0x6a09e667ul;
s[1] = 0xbb67ae85ul;
s[2] = 0x3c6ef372ul;
s[3] = 0xa54ff53aul;
s[4] = 0x510e527ful;
s[5] = 0x9b05688cul;
s[6] = 0x1f83d9abul;
s[7] = 0x5be0cd19ul;
}
/** Perform one SHA-256 transformation, processing a 64-byte chunk. */
void Transform(uint32_t* s, const unsigned char* chunk)
{
uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7];
uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0));
Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4));
Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8));
Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12));
Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16));
Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20));
Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24));
Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28));
Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32));
Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36));
Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40));
Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44));
Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48));
Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52));
Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56));
Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60));
Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1));
Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2));
Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3));
Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4));
Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5));
Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6));
Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7));
Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8));
Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9));
Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10));
Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11));
Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12));
Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13));
Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14));
Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15));
Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0));
Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1));
Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2));
Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3));
Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4));
Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5));
Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6));
Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7));
Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8));
Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9));
Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10));
Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11));
Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12));
Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13));
Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14));
Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15));
Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0));
Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1));
Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2));
Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3));
Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4));
Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5));
Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6));
Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7));
Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8));
Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9));
Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10));
Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11));
Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12));
Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13));
Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14));
Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15));
Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0));
s[0] += a;
s[1] += b;
s[2] += c;
s[3] += d;
s[4] += e;
s[5] += f;
s[6] += g;
s[7] += h;
}
} // namespace sha256
} // namespace
////// SHA-256
CSHA256::CSHA256() : bytes(0)
{
sha256::Initialize(s);
}
CSHA256& CSHA256::Write(const unsigned char* data, size_t len)
{
const unsigned char* end = data + len;
size_t bufsize = bytes % 64;
if (bufsize && bufsize + len >= 64) {
// Fill the buffer, and process it.
memcpy(buf + bufsize, data, 64 - bufsize);
bytes += 64 - bufsize;
data += 64 - bufsize;
sha256::Transform(s, buf);
bufsize = 0;
}
while (end >= data + 64) {
// Process full chunks directly from the source.
sha256::Transform(s, data);
bytes += 64;
data += 64;
}
if (end > data) {
// Fill the buffer with what remains.
memcpy(buf + bufsize, data, end - data);
bytes += end - data;
}
return *this;
}
void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
{
static const unsigned char pad[64] = {0x80};
unsigned char sizedesc[8];
WriteBE64(sizedesc, bytes << 3);
Write(pad, 1 + ((119 - (bytes % 64)) % 64));
Write(sizedesc, 8);
WriteBE32(hash, s[0]);
WriteBE32(hash + 4, s[1]);
WriteBE32(hash + 8, s[2]);
WriteBE32(hash + 12, s[3]);
WriteBE32(hash + 16, s[4]);
WriteBE32(hash + 20, s[5]);
WriteBE32(hash + 24, s[6]);
WriteBE32(hash + 28, s[7]);
}
CSHA256& CSHA256::Reset()
{
bytes = 0;
sha256::Initialize(s);
return *this;
}

28
src/crypto/sha256.h Normal file
View file

@ -0,0 +1,28 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_CRYPTO_SHA256_H
#define BITCOIN_CRYPTO_SHA256_H
#include <stdint.h>
#include <stdlib.h>
/** A hasher class for SHA-256. */
class CSHA256
{
private:
uint32_t s[8];
unsigned char buf[64];
size_t bytes;
public:
static const size_t OUTPUT_SIZE = 32;
CSHA256();
CSHA256& Write(const unsigned char* data, size_t len);
void Finalize(unsigned char hash[OUTPUT_SIZE]);
CSHA256& Reset();
};
#endif // BITCOIN_CRYPTO_SHA256_H

View file

@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "crypto/sha2.h" #include "crypto/sha512.h"
#include "crypto/common.h" #include "crypto/common.h"
@ -11,124 +11,6 @@
// Internal implementation code. // Internal implementation code.
namespace namespace
{ {
/// Internal SHA-256 implementation.
namespace sha256
{
uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); }
uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); }
uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); }
uint32_t inline Sigma1(uint32_t x) { return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); }
uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); }
uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); }
/** One round of SHA-256. */
void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t& d, uint32_t e, uint32_t f, uint32_t g, uint32_t& h, uint32_t k, uint32_t w)
{
uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w;
uint32_t t2 = Sigma0(a) + Maj(a, b, c);
d += t1;
h = t1 + t2;
}
/** Initialize SHA-256 state. */
void inline Initialize(uint32_t* s)
{
s[0] = 0x6a09e667ul;
s[1] = 0xbb67ae85ul;
s[2] = 0x3c6ef372ul;
s[3] = 0xa54ff53aul;
s[4] = 0x510e527ful;
s[5] = 0x9b05688cul;
s[6] = 0x1f83d9abul;
s[7] = 0x5be0cd19ul;
}
/** Perform one SHA-256 transformation, processing a 64-byte chunk. */
void Transform(uint32_t* s, const unsigned char* chunk)
{
uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7];
uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0));
Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4));
Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8));
Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12));
Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16));
Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20));
Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24));
Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28));
Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32));
Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36));
Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40));
Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44));
Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48));
Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52));
Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56));
Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60));
Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1));
Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2));
Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3));
Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4));
Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5));
Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6));
Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7));
Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8));
Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9));
Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10));
Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11));
Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12));
Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13));
Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14));
Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15));
Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0));
Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1));
Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2));
Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3));
Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4));
Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5));
Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6));
Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7));
Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8));
Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9));
Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10));
Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11));
Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12));
Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13));
Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14));
Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15));
Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0));
Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1));
Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2));
Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3));
Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4));
Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5));
Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6));
Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7));
Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8));
Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9));
Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10));
Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11));
Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12));
Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13));
Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14));
Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15));
Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0));
s[0] += a;
s[1] += b;
s[2] += c;
s[3] += d;
s[4] += e;
s[5] += f;
s[6] += g;
s[7] += h;
}
} // namespace sha256
/// Internal SHA-512 implementation. /// Internal SHA-512 implementation.
namespace sha512 namespace sha512
{ {
@ -249,8 +131,8 @@ void Transform(uint64_t* s, const unsigned char* chunk)
Round(f, g, h, a, b, c, d, e, 0x431d67c49c100d4cull, w11 += sigma1(w9) + w4 + sigma0(w12)); Round(f, g, h, a, b, c, d, e, 0x431d67c49c100d4cull, w11 += sigma1(w9) + w4 + sigma0(w12));
Round(e, f, g, h, a, b, c, d, 0x4cc5d4becb3e42b6ull, w12 += sigma1(w10) + w5 + sigma0(w13)); Round(e, f, g, h, a, b, c, d, 0x4cc5d4becb3e42b6ull, w12 += sigma1(w10) + w5 + sigma0(w13));
Round(d, e, f, g, h, a, b, c, 0x597f299cfc657e2aull, w13 += sigma1(w11) + w6 + sigma0(w14)); Round(d, e, f, g, h, a, b, c, 0x597f299cfc657e2aull, w13 += sigma1(w11) + w6 + sigma0(w14));
Round(c, d, e, f, g, h, a, b, 0x5fcb6fab3ad6faecull, w14 += sigma1(w12) + w7 + sigma0(w15)); Round(c, d, e, f, g, h, a, b, 0x5fcb6fab3ad6faecull, w14 + sigma1(w12) + w7 + sigma0(w15));
Round(b, c, d, e, f, g, h, a, 0x6c44198c4a475817ull, w15 += sigma1(w13) + w8 + sigma0(w0)); Round(b, c, d, e, f, g, h, a, 0x6c44198c4a475817ull, w15 + sigma1(w13) + w8 + sigma0(w0));
s[0] += a; s[0] += a;
s[1] += b; s[1] += b;
@ -267,63 +149,6 @@ void Transform(uint64_t* s, const unsigned char* chunk)
} // namespace } // namespace
////// SHA-256
CSHA256::CSHA256() : bytes(0)
{
sha256::Initialize(s);
}
CSHA256& CSHA256::Write(const unsigned char* data, size_t len)
{
const unsigned char* end = data + len;
size_t bufsize = bytes % 64;
if (bufsize && bufsize + len >= 64) {
// Fill the buffer, and process it.
memcpy(buf + bufsize, data, 64 - bufsize);
bytes += 64 - bufsize;
data += 64 - bufsize;
sha256::Transform(s, buf);
bufsize = 0;
}
while (end >= data + 64) {
// Process full chunks directly from the source.
sha256::Transform(s, data);
bytes += 64;
data += 64;
}
if (end > data) {
// Fill the buffer with what remains.
memcpy(buf + bufsize, data, end - data);
bytes += end - data;
}
return *this;
}
void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
{
static const unsigned char pad[64] = {0x80};
unsigned char sizedesc[8];
WriteBE64(sizedesc, bytes << 3);
Write(pad, 1 + ((119 - (bytes % 64)) % 64));
Write(sizedesc, 8);
WriteBE32(hash, s[0]);
WriteBE32(hash + 4, s[1]);
WriteBE32(hash + 8, s[2]);
WriteBE32(hash + 12, s[3]);
WriteBE32(hash + 16, s[4]);
WriteBE32(hash + 20, s[5]);
WriteBE32(hash + 24, s[6]);
WriteBE32(hash + 28, s[7]);
}
CSHA256& CSHA256::Reset()
{
bytes = 0;
sha256::Initialize(s);
return *this;
}
////// SHA-512 ////// SHA-512
CSHA512::CSHA512() : bytes(0) CSHA512::CSHA512() : bytes(0)
@ -380,32 +205,3 @@ CSHA512& CSHA512::Reset()
sha512::Initialize(s); sha512::Initialize(s);
return *this; return *this;
} }
////// HMAC-SHA-512
CHMAC_SHA512::CHMAC_SHA512(const unsigned char* key, size_t keylen)
{
unsigned char rkey[128];
if (keylen <= 128) {
memcpy(rkey, key, keylen);
memset(rkey + keylen, 0, 128 - keylen);
} else {
CSHA512().Write(key, keylen).Finalize(rkey);
memset(rkey + 64, 0, 64);
}
for (int n = 0; n < 128; n++)
rkey[n] ^= 0x5c;
outer.Write(rkey, 128);
for (int n = 0; n < 128; n++)
rkey[n] ^= 0x5c ^ 0x36;
inner.Write(rkey, 128);
}
void CHMAC_SHA512::Finalize(unsigned char hash[OUTPUT_SIZE])
{
unsigned char temp[64];
inner.Finalize(temp);
outer.Write(temp, 64).Finalize(hash);
}

28
src/crypto/sha512.h Normal file
View file

@ -0,0 +1,28 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_CRYPTO_SHA512_H
#define BITCOIN_CRYPTO_SHA512_H
#include <stdint.h>
#include <stdlib.h>
/** A hasher class for SHA-512. */
class CSHA512
{
private:
uint64_t s[8];
unsigned char buf[128];
size_t bytes;
public:
static const size_t OUTPUT_SIZE = 64;
CSHA512();
CSHA512& Write(const unsigned char* data, size_t len);
void Finalize(unsigned char hash[OUTPUT_SIZE]);
CSHA512& Reset();
};
#endif // BITCOIN_CRYPTO_SHA512_H

View file

@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "hash.h" #include "hash.h"
#include "crypto/hmac_sha512.h"
inline uint32_t ROTL32(uint32_t x, int8_t r) inline uint32_t ROTL32(uint32_t x, int8_t r)
{ {

View file

@ -7,7 +7,7 @@
#define BITCOIN_HASH_H #define BITCOIN_HASH_H
#include "crypto/ripemd160.h" #include "crypto/ripemd160.h"
#include "crypto/sha2.h" #include "crypto/sha256.h"
#include "serialize.h" #include "serialize.h"
#include "uint256.h" #include "uint256.h"
#include "version.h" #include "version.h"

View file

@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers // Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H) #if defined(HAVE_CONFIG_H)
@ -60,7 +60,7 @@ bool fFeeEstimatesInitialized = false;
#define MIN_CORE_FILEDESCRIPTORS 150 #define MIN_CORE_FILEDESCRIPTORS 150
#endif #endif
// Used to pass flags to the Bind() function /** Used to pass flags to the Bind() function */
enum BindFlags { enum BindFlags {
BF_NONE = 0, BF_NONE = 0,
BF_EXPLICIT = (1U << 0), BF_EXPLICIT = (1U << 0),
@ -150,14 +150,9 @@ void Shutdown()
{ {
LOCK(cs_main); LOCK(cs_main);
#ifdef ENABLE_WALLET if (pcoinsTip != NULL) {
if (pwalletMain) FlushStateToDisk();
pwalletMain->SetBestChain(chainActive.GetLocator()); }
#endif
if (pblocktree)
pblocktree->Flush();
if (pcoinsTip)
pcoinsTip->Flush();
delete pcoinsTip; delete pcoinsTip;
pcoinsTip = NULL; pcoinsTip = NULL;
delete pcoinsdbview; delete pcoinsdbview;
@ -180,9 +175,9 @@ void Shutdown()
LogPrintf("%s: done\n", __func__); LogPrintf("%s: done\n", __func__);
} }
// /**
// Signal handlers are very limited in what they are allowed to do, so: * Signal handlers are very limited in what they are allowed to do, so:
// */
void HandleSIGTERM(int) void HandleSIGTERM(int)
{ {
fRequestShutdown = true; fRequestShutdown = true;
@ -335,8 +330,6 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n"; strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n";
if (GetBoolArg("-help-debug", false)) if (GetBoolArg("-help-debug", false))
{ {
strUsage += " -printblock=<hash> " + _("Print block on startup, if found in block index") + "\n";
strUsage += " -printblocktree " + strprintf(_("Print block tree on startup (default: %u)"), 0) + "\n";
strUsage += " -printpriority " + strprintf(_("Log transaction priority and fee per kB when mining blocks (default: %u)"), 0) + "\n"; strUsage += " -printpriority " + strprintf(_("Log transaction priority and fee per kB when mining blocks (default: %u)"), 0) + "\n";
strUsage += " -privdb " + strprintf(_("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)"), 1) + "\n"; strUsage += " -privdb " + strprintf(_("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)"), 1) + "\n";
strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n"; strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n";
@ -357,6 +350,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += "\n" + _("RPC server options:") + "\n"; strUsage += "\n" + _("RPC server options:") + "\n";
strUsage += " -server " + _("Accept command line and JSON-RPC commands") + "\n"; strUsage += " -server " + _("Accept command line and JSON-RPC commands") + "\n";
strUsage += " -rest " + strprintf(_("Accept public REST requests (default: %u)"), 0) + "\n";
strUsage += " -rpcbind=<addr> " + _("Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces)") + "\n"; strUsage += " -rpcbind=<addr> " + _("Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces)") + "\n";
strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n"; strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n";
strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n"; strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n";
@ -1052,34 +1046,6 @@ bool AppInit2(boost::thread_group& threadGroup)
} }
LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart); LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart);
if (GetBoolArg("-printblockindex", false) || GetBoolArg("-printblocktree", false))
{
PrintBlockTree();
return false;
}
if (mapArgs.count("-printblock"))
{
string strMatch = mapArgs["-printblock"];
int nFound = 0;
for (BlockMap::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
{
uint256 hash = (*mi).first;
if (boost::algorithm::starts_with(hash.ToString(), strMatch))
{
CBlockIndex* pindex = (*mi).second;
CBlock block;
ReadBlockFromDisk(block, pindex);
block.BuildMerkleTree();
LogPrintf("%s\n", block.ToString());
nFound++;
}
}
if (nFound == 0)
LogPrintf("No blocks matching %s were found\n", strMatch);
return false;
}
boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
CAutoFile est_filein(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION); CAutoFile est_filein(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION);
// Allowed to fail as this file IS missing on first startup. // Allowed to fail as this file IS missing on first startup.

View file

@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2013 The Bitcoin developers // Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_INIT_H #ifndef BITCOIN_INIT_H
@ -22,7 +22,7 @@ bool ShutdownRequested();
void Shutdown(); void Shutdown();
bool AppInit2(boost::thread_group& threadGroup); bool AppInit2(boost::thread_group& threadGroup);
/* The help message mode determines what help message to show */ /** The help message mode determines what help message to show */
enum HelpMessageMode { enum HelpMessageMode {
HMM_BITCOIND, HMM_BITCOIND,
HMM_BITCOIN_QT HMM_BITCOIN_QT

View file

@ -4,7 +4,8 @@
#include "key.h" #include "key.h"
#include "crypto/sha2.h" #include "crypto/hmac_sha512.h"
#include "crypto/rfc6979_hmac_sha256.h"
#include "eccryptoverify.h" #include "eccryptoverify.h"
#include "pubkey.h" #include "pubkey.h"
#include "random.h" #include "random.h"
@ -71,20 +72,24 @@ CPubKey CKey::GetPubKey() const {
return result; return result;
} }
bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const { bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_t test_case) const {
if (!fValid) if (!fValid)
return false; return false;
vchSig.resize(72); vchSig.resize(72);
int nSigLen = 72; RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32);
CKey nonce;
do { do {
nonce.MakeNewKey(true); uint256 nonce;
if (secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), nonce.begin())) prng.Generate((unsigned char*)&nonce, 32);
break; nonce += test_case;
} while(true); int nSigLen = 72;
int ret = secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), (unsigned char*)&nonce);
nonce = 0;
if (ret) {
vchSig.resize(nSigLen); vchSig.resize(nSigLen);
return true; return true;
} }
} while(true);
}
bool CKey::VerifyPubKey(const CPubKey& pubkey) const { bool CKey::VerifyPubKey(const CPubKey& pubkey) const {
if (pubkey.IsCompressed() != fCompressed) { if (pubkey.IsCompressed() != fCompressed) {
@ -105,10 +110,13 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig)
return false; return false;
vchSig.resize(65); vchSig.resize(65);
int rec = -1; int rec = -1;
CKey nonce; RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32);
do { do {
nonce.MakeNewKey(true); uint256 nonce;
if (secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), nonce.begin(), &rec)) prng.Generate((unsigned char*)&nonce, 32);
int ret = secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), (unsigned char*)&nonce, &rec);
nonce = 0;
if (ret)
break; break;
} while(true); } while(true);
assert(rec != -1); assert(rec != -1);

View file

@ -122,8 +122,12 @@ public:
*/ */
CPubKey GetPubKey() const; CPubKey GetPubKey() const;
//! Create a DER-serialized signature. /**
bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig) const; * Create a DER-serialized signature.
* The test_case parameter tweaks the deterministic nonce, and is only for
* testing. It should be zero for normal use.
*/
bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, uint32_t test_case = 0) const;
/** /**
* Create a compact signature (65 bytes), which allows reconstructing the used public key. * Create a compact signature (65 bytes), which allows reconstructing the used public key.

View file

@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers // Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "main.h" #include "main.h"
@ -11,6 +11,7 @@
#include "checkpoints.h" #include "checkpoints.h"
#include "checkqueue.h" #include "checkqueue.h"
#include "init.h" #include "init.h"
#include "merkleblock.h"
#include "net.h" #include "net.h"
#include "pow.h" #include "pow.h"
#include "txdb.h" #include "txdb.h"
@ -33,9 +34,9 @@ using namespace std;
# error "Bitcoin cannot be compiled without assertions." # error "Bitcoin cannot be compiled without assertions."
#endif #endif
// /**
// Global state * Global state
// */
CCriticalSection cs_main; CCriticalSection cs_main;
@ -66,7 +67,7 @@ map<uint256, COrphanTx> mapOrphanTransactions;
map<uint256, set<uint256> > mapOrphanTransactionsByPrev; map<uint256, set<uint256> > mapOrphanTransactionsByPrev;
void EraseOrphansFor(NodeId peer); void EraseOrphansFor(NodeId peer);
// Constant stuff for coinbase transactions we create: /** Constant stuff for coinbase transactions we create: */
CScript COINBASE_FLAGS; CScript COINBASE_FLAGS;
const string strMessageMagic = "Bitcoin Signed Message:\n"; const string strMessageMagic = "Bitcoin Signed Message:\n";
@ -97,39 +98,50 @@ namespace {
CBlockIndex *pindexBestInvalid; CBlockIndex *pindexBestInvalid;
// The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS or better that are at least /**
// as good as our current tip. Entries may be failed, though. * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS or better that are at least
* as good as our current tip. Entries may be failed, though.
*/
set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates; set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates;
// Number of nodes with fSyncStarted. /** Number of nodes with fSyncStarted. */
int nSyncStarted = 0; int nSyncStarted = 0;
// All pairs A->B, where A (or one if its ancestors) misses transactions, but B has transactions. /** All pairs A->B, where A (or one if its ancestors) misses transactions, but B has transactions. */
multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked; multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
CCriticalSection cs_LastBlockFile; CCriticalSection cs_LastBlockFile;
std::vector<CBlockFileInfo> vinfoBlockFile; std::vector<CBlockFileInfo> vinfoBlockFile;
int nLastBlockFile = 0; int nLastBlockFile = 0;
// Every received block is assigned a unique and increasing identifier, so we /**
// know which one to give priority in case of a fork. * Every received block is assigned a unique and increasing identifier, so we
* know which one to give priority in case of a fork.
*/
CCriticalSection cs_nBlockSequenceId; CCriticalSection cs_nBlockSequenceId;
// Blocks loaded from disk are assigned id 0, so start the counter at 1. /** Blocks loaded from disk are assigned id 0, so start the counter at 1. */
uint32_t nBlockSequenceId = 1; uint32_t nBlockSequenceId = 1;
// Sources of received blocks, to be able to send them reject messages or ban /**
// them, if processing happens afterwards. Protected by cs_main. * Sources of received blocks, to be able to send them reject messages or ban
* them, if processing happens afterwards. Protected by cs_main.
*/
map<uint256, NodeId> mapBlockSource; map<uint256, NodeId> mapBlockSource;
// Blocks that are in flight, and that are in the queue to be downloaded. /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */
// Protected by cs_main.
struct QueuedBlock { struct QueuedBlock {
uint256 hash; uint256 hash;
CBlockIndex *pindex; // Optional. CBlockIndex *pindex; //! Optional.
int64_t nTime; // Time of "getdata" request in microseconds. int64_t nTime; //! Time of "getdata" request in microseconds.
}; };
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight; map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight;
// Number of preferrable block download peers. /** Number of preferable block download peers. */
int nPreferredDownload = 0; int nPreferredDownload = 0;
/** Dirty block index entries. */
set<CBlockIndex*> setDirtyBlockIndex;
/** Dirty block file entries. */
set<int> setDirtyFileInfo;
} // anon namespace } // anon namespace
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -142,19 +154,19 @@ namespace {
namespace { namespace {
struct CMainSignals { struct CMainSignals {
// Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. /** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */
boost::signals2::signal<void (const CTransaction &, const CBlock *)> SyncTransaction; boost::signals2::signal<void (const CTransaction &, const CBlock *)> SyncTransaction;
// Notifies listeners of an erased transaction (currently disabled, requires transaction replacement). /** Notifies listeners of an erased transaction (currently disabled, requires transaction replacement). */
boost::signals2::signal<void (const uint256 &)> EraseTransaction; boost::signals2::signal<void (const uint256 &)> EraseTransaction;
// Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). /** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */
boost::signals2::signal<void (const uint256 &)> UpdatedTransaction; boost::signals2::signal<void (const uint256 &)> UpdatedTransaction;
// Notifies listeners of a new active block chain. /** Notifies listeners of a new active block chain. */
boost::signals2::signal<void (const CBlockLocator &)> SetBestChain; boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
// Notifies listeners about an inventory item being seen on the network. /** Notifies listeners about an inventory item being seen on the network. */
boost::signals2::signal<void (const uint256 &)> Inventory; boost::signals2::signal<void (const uint256 &)> Inventory;
// Tells listeners to broadcast their data. /** Tells listeners to broadcast their data. */
boost::signals2::signal<void ()> Broadcast; boost::signals2::signal<void ()> Broadcast;
// Notifies listeners of a block validation result /** Notifies listeners of a block validation result */
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked; boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
} g_signals; } g_signals;
@ -207,32 +219,34 @@ struct CBlockReject {
uint256 hashBlock; uint256 hashBlock;
}; };
// Maintain validation-specific state about nodes, protected by cs_main, instead /**
// by CNode's own locks. This simplifies asynchronous operation, where * Maintain validation-specific state about nodes, protected by cs_main, instead
// processing of incoming data is done after the ProcessMessage call returns, * by CNode's own locks. This simplifies asynchronous operation, where
// and we're no longer holding the node's locks. * processing of incoming data is done after the ProcessMessage call returns,
* and we're no longer holding the node's locks.
*/
struct CNodeState { struct CNodeState {
// Accumulated misbehaviour score for this peer. //! Accumulated misbehaviour score for this peer.
int nMisbehavior; int nMisbehavior;
// Whether this peer should be disconnected and banned (unless whitelisted). //! Whether this peer should be disconnected and banned (unless whitelisted).
bool fShouldBan; bool fShouldBan;
// String name of this peer (debugging/logging purposes). //! String name of this peer (debugging/logging purposes).
std::string name; std::string name;
// List of asynchronously-determined block rejections to notify this peer about. //! List of asynchronously-determined block rejections to notify this peer about.
std::vector<CBlockReject> rejects; std::vector<CBlockReject> rejects;
// The best known block we know this peer has announced. //! The best known block we know this peer has announced.
CBlockIndex *pindexBestKnownBlock; CBlockIndex *pindexBestKnownBlock;
// The hash of the last unknown block this peer has announced. //! The hash of the last unknown block this peer has announced.
uint256 hashLastUnknownBlock; uint256 hashLastUnknownBlock;
// The last full block we both have. //! The last full block we both have.
CBlockIndex *pindexLastCommonBlock; CBlockIndex *pindexLastCommonBlock;
// Whether we've started headers synchronization with this peer. //! Whether we've started headers synchronization with this peer.
bool fSyncStarted; bool fSyncStarted;
// Since when we're stalling block download progress (in microseconds), or 0. //! Since when we're stalling block download progress (in microseconds), or 0.
int64_t nStallingSince; int64_t nStallingSince;
list<QueuedBlock> vBlocksInFlight; list<QueuedBlock> vBlocksInFlight;
int nBlocksInFlight; int nBlocksInFlight;
// Whether we consider this a preferred download peer. //! Whether we consider this a preferred download peer.
bool fPreferredDownload; bool fPreferredDownload;
CNodeState() { CNodeState() {
@ -248,7 +262,7 @@ struct CNodeState {
} }
}; };
// Map maintaining per-node state. Requires cs_main. /** Map maintaining per-node state. Requires cs_main. */
map<NodeId, CNodeState> mapNodeState; map<NodeId, CNodeState> mapNodeState;
// Requires cs_main. // Requires cs_main.
@ -702,15 +716,15 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
return true; return true;
} }
// /**
// Check transaction inputs to mitigate two * Check transaction inputs to mitigate two
// potential denial-of-service attacks: * potential denial-of-service attacks:
// *
// 1. scriptSigs with extra data stuffed into them, * 1. scriptSigs with extra data stuffed into them,
// not consumed by scriptPubKey (or P2SH script) * not consumed by scriptPubKey (or P2SH script)
// 2. P2SH scripts with a crazy number of expensive * 2. P2SH scripts with a crazy number of expensive
// CHECKSIG/CHECKMULTISIG operations * CHECKSIG/CHECKMULTISIG operations
// */
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
{ {
if (tx.IsCoinBase()) if (tx.IsCoinBase())
@ -1048,7 +1062,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
return true; return true;
} }
// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock /** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */
bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow) bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow)
{ {
CBlockIndex *pindexSlow = NULL; CBlockIndex *pindexSlow = NULL;
@ -1137,11 +1151,6 @@ bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos)
pos.nPos = (unsigned int)fileOutPos; pos.nPos = (unsigned int)fileOutPos;
fileout << block; fileout << block;
// Flush stdio buffers and commit to disk before returning
fflush(fileout.Get());
if (!IsInitialBlockDownload())
FileCommit(fileout.Get());
return true; return true;
} }
@ -1180,7 +1189,7 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex)
CAmount GetBlockValue(int nHeight, const CAmount& nFees) CAmount GetBlockValue(int nHeight, const CAmount& nFees)
{ {
int64_t nSubsidy = 50 * COIN; CAmount nSubsidy = 50 * COIN;
int halvings = nHeight / Params().SubsidyHalvingInterval(); int halvings = nHeight / Params().SubsidyHalvingInterval();
// Force block reward to zero when right shift is undefined. // Force block reward to zero when right shift is undefined.
@ -1198,15 +1207,14 @@ bool IsInitialBlockDownload()
LOCK(cs_main); LOCK(cs_main);
if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate()) if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate())
return true; return true;
static int64_t nLastUpdate; static bool lockIBDState = false;
static CBlockIndex* pindexLastBest; if (lockIBDState)
if (chainActive.Tip() != pindexLastBest) return false;
{ bool state = (chainActive.Height() < pindexBestHeader->nHeight - 24 * 6 ||
pindexLastBest = chainActive.Tip(); pindexBestHeader->GetBlockTime() < GetTime() - 24 * 60 * 60);
nLastUpdate = GetTime(); if (!state)
} lockIBDState = true;
return (GetTime() - nLastUpdate < 10 && return state;
chainActive.Tip()->GetBlockTime() < GetTime() - 24 * 60 * 60);
} }
bool fLargeWorkForkFound = false; bool fLargeWorkForkFound = false;
@ -1327,7 +1335,7 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state
if (state.IsInvalid(nDoS)) { if (state.IsInvalid(nDoS)) {
std::map<uint256, NodeId>::iterator it = mapBlockSource.find(pindex->GetBlockHash()); std::map<uint256, NodeId>::iterator it = mapBlockSource.find(pindex->GetBlockHash());
if (it != mapBlockSource.end() && State(it->second)) { if (it != mapBlockSource.end() && State(it->second)) {
CBlockReject reject = {state.GetRejectCode(), state.GetRejectReason(), pindex->GetBlockHash()}; CBlockReject reject = {state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), pindex->GetBlockHash()};
State(it->second)->rejects.push_back(reject); State(it->second)->rejects.push_back(reject);
if (nDoS > 0) if (nDoS > 0)
Misbehaving(it->second, nDoS); Misbehaving(it->second, nDoS);
@ -1335,7 +1343,7 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state
} }
if (!state.CorruptionPossible()) { if (!state.CorruptionPossible()) {
pindex->nStatus |= BLOCK_FAILED_VALID; pindex->nStatus |= BLOCK_FAILED_VALID;
pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex)); setDirtyBlockIndex.insert(pindex);
setBlockIndexCandidates.erase(pindex); setBlockIndexCandidates.erase(pindex);
InvalidChainFound(pindex); InvalidChainFound(pindex);
} }
@ -1357,10 +1365,11 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight); inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight);
} }
bool CScriptCheck::operator()() const { bool CScriptCheck::operator()() {
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingSignatureChecker(*ptxTo, nIn, cacheStore))) if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingSignatureChecker(*ptxTo, nIn, cacheStore), &error)) {
return error("CScriptCheck() : %s:%d VerifySignature failed", ptxTo->GetHash().ToString(), nIn); return ::error("CScriptCheck() : %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), nIn, ScriptErrorString(error));
}
return true; return true;
} }
@ -1448,7 +1457,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
CScriptCheck check(*coins, tx, i, CScriptCheck check(*coins, tx, i,
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore); flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore);
if (check()) if (check())
return state.Invalid(false, REJECT_NONSTANDARD, "non-mandatory-script-verify-flag"); return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
} }
// Failures of other flags indicate a transaction that is // Failures of other flags indicate a transaction that is
// invalid in new blocks, e.g. a invalid P2SH. We DoS ban // invalid in new blocks, e.g. a invalid P2SH. We DoS ban
@ -1457,7 +1466,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
// as to the correct behavior - we may want to continue // as to the correct behavior - we may want to continue
// peering with non-upgraded nodes even after a soft-fork // peering with non-upgraded nodes even after a soft-fork
// super-majority vote has passed. // super-majority vote has passed.
return state.DoS(100,false, REJECT_INVALID, "mandatory-script-verify-flag-failed"); return state.DoS(100,false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError())));
} }
} }
} }
@ -1732,10 +1741,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
} }
pindex->RaiseValidity(BLOCK_VALID_SCRIPTS); pindex->RaiseValidity(BLOCK_VALID_SCRIPTS);
setDirtyBlockIndex.insert(pindex);
CDiskBlockIndex blockindex(pindex);
if (!pblocktree->WriteBlockIndex(blockindex))
return state.Abort("Failed to write block index");
} }
if (fTxIndex) if (fTxIndex)
@ -1759,10 +1765,23 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return true; return true;
} }
// Update the on-disk chain state. enum FlushStateMode {
bool static WriteChainState(CValidationState &state, bool forceWrite=false) { FLUSH_STATE_IF_NEEDED,
FLUSH_STATE_PERIODIC,
FLUSH_STATE_ALWAYS
};
/**
* Update the on-disk chain state.
* The caches and indexes are flushed if either they're too large, forceWrite is set, or
* fast is not set and it's been a while since the last write.
*/
bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) {
LOCK(cs_main);
static int64_t nLastWrite = 0; static int64_t nLastWrite = 0;
if (forceWrite || pcoinsTip->GetCacheSize() > nCoinCacheSize || (!IsInitialBlockDownload() && GetTimeMicros() > nLastWrite + 600*1000000)) { if ((mode == FLUSH_STATE_ALWAYS) ||
((mode == FLUSH_STATE_PERIODIC || mode == FLUSH_STATE_IF_NEEDED) && pcoinsTip->GetCacheSize() > nCoinCacheSize) ||
(mode == FLUSH_STATE_PERIODIC && GetTimeMicros() > nLastWrite + DATABASE_WRITE_INTERVAL * 1000000)) {
// Typical CCoins structures on disk are around 100 bytes in size. // Typical CCoins structures on disk are around 100 bytes in size.
// Pushing a new one to the database can cause it to be written // Pushing a new one to the database can cause it to be written
// twice (once in the log, and once in the tables). This is already // twice (once in the log, and once in the tables). This is already
@ -1770,16 +1789,45 @@ bool static WriteChainState(CValidationState &state, bool forceWrite=false) {
// overwrite one. Still, use a conservative safety factor of 2. // overwrite one. Still, use a conservative safety factor of 2.
if (!CheckDiskSpace(100 * 2 * 2 * pcoinsTip->GetCacheSize())) if (!CheckDiskSpace(100 * 2 * 2 * pcoinsTip->GetCacheSize()))
return state.Error("out of disk space"); return state.Error("out of disk space");
// First make sure all block and undo data is flushed to disk.
FlushBlockFile(); FlushBlockFile();
// Then update all block file information (which may refer to block and undo files).
bool fileschanged = false;
for (set<int>::iterator it = setDirtyFileInfo.begin(); it != setDirtyFileInfo.end(); ) {
if (!pblocktree->WriteBlockFileInfo(*it, vinfoBlockFile[*it])) {
return state.Abort("Failed to write to block index");
}
fileschanged = true;
setDirtyFileInfo.erase(it++);
}
if (fileschanged && !pblocktree->WriteLastBlockFile(nLastBlockFile)) {
return state.Abort("Failed to write to block index");
}
for (set<CBlockIndex*>::iterator it = setDirtyBlockIndex.begin(); it != setDirtyBlockIndex.end(); ) {
if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(*it))) {
return state.Abort("Failed to write to block index");
}
setDirtyBlockIndex.erase(it++);
}
pblocktree->Sync(); pblocktree->Sync();
// Finally flush the chainstate (which may refer to block index entries).
if (!pcoinsTip->Flush()) if (!pcoinsTip->Flush())
return state.Abort("Failed to write to coin database"); return state.Abort("Failed to write to coin database");
// Update best block in wallet (so we can detect restored wallets).
if (mode != FLUSH_STATE_IF_NEEDED) {
g_signals.SetBestChain(chainActive.GetLocator());
}
nLastWrite = GetTimeMicros(); nLastWrite = GetTimeMicros();
} }
return true; return true;
} }
// Update chainActive and related internal data structures. void FlushStateToDisk() {
CValidationState state;
FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
}
/** Update chainActive and related internal data structures. */
void static UpdateTip(CBlockIndex *pindexNew) { void static UpdateTip(CBlockIndex *pindexNew) {
chainActive.SetTip(pindexNew); chainActive.SetTip(pindexNew);
@ -1818,7 +1866,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
} }
} }
// Disconnect chainActive's tip. /** Disconnect chainActive's tip. */
bool static DisconnectTip(CValidationState &state) { bool static DisconnectTip(CValidationState &state) {
CBlockIndex *pindexDelete = chainActive.Tip(); CBlockIndex *pindexDelete = chainActive.Tip();
assert(pindexDelete); assert(pindexDelete);
@ -1837,7 +1885,7 @@ bool static DisconnectTip(CValidationState &state) {
} }
LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001); LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
// Write the chain state to disk, if necessary. // Write the chain state to disk, if necessary.
if (!WriteChainState(state)) if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
return false; return false;
// Resurrect mempool transactions from the disconnected block. // Resurrect mempool transactions from the disconnected block.
BOOST_FOREACH(const CTransaction &tx, block.vtx) { BOOST_FOREACH(const CTransaction &tx, block.vtx) {
@ -1865,8 +1913,10 @@ static int64_t nTimeFlush = 0;
static int64_t nTimeChainState = 0; static int64_t nTimeChainState = 0;
static int64_t nTimePostConnect = 0; static int64_t nTimePostConnect = 0;
// Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock /**
// corresponding to pindexNew, to bypass loading it again from disk. * Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
* corresponding to pindexNew, to bypass loading it again from disk.
*/
bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) { bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) {
assert(pindexNew->pprev == chainActive.Tip()); assert(pindexNew->pprev == chainActive.Tip());
mempool.check(pcoinsTip); mempool.check(pcoinsTip);
@ -1900,7 +1950,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
int64_t nTime4 = GetTimeMicros(); nTimeFlush += nTime4 - nTime3; int64_t nTime4 = GetTimeMicros(); nTimeFlush += nTime4 - nTime3;
LogPrint("bench", " - Flush: %.2fms [%.2fs]\n", (nTime4 - nTime3) * 0.001, nTimeFlush * 0.000001); LogPrint("bench", " - Flush: %.2fms [%.2fs]\n", (nTime4 - nTime3) * 0.001, nTimeFlush * 0.000001);
// Write the chain state to disk, if necessary. // Write the chain state to disk, if necessary.
if (!WriteChainState(state)) if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
return false; return false;
int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4; int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4;
LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001); LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001);
@ -1919,10 +1969,6 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
BOOST_FOREACH(const CTransaction &tx, pblock->vtx) { BOOST_FOREACH(const CTransaction &tx, pblock->vtx) {
SyncWithWallets(tx, pblock); SyncWithWallets(tx, pblock);
} }
// Update best block in wallet (so we can detect restored wallets)
// Emit this signal after the SyncWithWallets signals as the wallet relies on that everything up to this point has been synced
if ((chainActive.Height() % 20160) == 0 || ((chainActive.Height() % 144) == 0 && !IsInitialBlockDownload()))
g_signals.SetBestChain(chainActive.GetLocator());
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001); LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001);
@ -1930,8 +1976,10 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
return true; return true;
} }
// Return the tip of the chain with the most work in it, that isn't /**
// known to be invalid (it's however far from certain to be valid). * Return the tip of the chain with the most work in it, that isn't
* known to be invalid (it's however far from certain to be valid).
*/
static CBlockIndex* FindMostWorkChain() { static CBlockIndex* FindMostWorkChain() {
do { do {
CBlockIndex *pindexNew = NULL; CBlockIndex *pindexNew = NULL;
@ -1972,8 +2020,22 @@ static CBlockIndex* FindMostWorkChain() {
} while(true); } while(true);
} }
// Try to make some progress towards making pindexMostWork the active block. /** Delete all entries in setBlockIndexCandidates that are worse than the current tip. */
// pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. static void PruneBlockIndexCandidates() {
// Note that we can't delete the current block itself, as we may need to return to it later in case a
// reorganization to a better block fails.
std::set<CBlockIndex*, CBlockIndexWorkComparator>::iterator it = setBlockIndexCandidates.begin();
while (it != setBlockIndexCandidates.end() && setBlockIndexCandidates.value_comp()(*it, chainActive.Tip())) {
setBlockIndexCandidates.erase(it++);
}
// Either the current tip or a successor of it we're working towards is left in setBlockIndexCandidates.
assert(!setBlockIndexCandidates.empty());
}
/**
* Try to make some progress towards making pindexMostWork the active block.
* pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
*/
static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, CBlock *pblock) { static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, CBlock *pblock) {
AssertLockHeld(cs_main); AssertLockHeld(cs_main);
bool fInvalidFound = false; bool fInvalidFound = false;
@ -2019,15 +2081,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
return false; return false;
} }
} else { } else {
// Delete all entries in setBlockIndexCandidates that are worse than our new current block. PruneBlockIndexCandidates();
// Note that we can't delete the current block itself, as we may need to return to it later in case a
// reorganization to a better block fails.
std::set<CBlockIndex*, CBlockIndexWorkComparator>::iterator it = setBlockIndexCandidates.begin();
while (setBlockIndexCandidates.value_comp()(*it, chainActive.Tip())) {
setBlockIndexCandidates.erase(it++);
}
// Either the current tip or a successor of it we're working towards is left in setBlockIndexCandidates.
assert(!setBlockIndexCandidates.empty());
if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) { if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) {
// We're in a better position than we were. Return temporarily to release the lock. // We're in a better position than we were. Return temporarily to release the lock.
fContinue = false; fContinue = false;
@ -2043,15 +2097,14 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
else else
CheckForkWarningConditions(); CheckForkWarningConditions();
if (!pblocktree->Flush())
return state.Abort("Failed to sync block index");
return true; return true;
} }
// Make the best chain active, in multiple steps. The result is either failure /**
// or an activated best chain. pblock is either NULL or a pointer to a block * Make the best chain active, in multiple steps. The result is either failure
// that is already loaded (to avoid loading it again from disk). * or an activated best chain. pblock is either NULL or a pointer to a block
* that is already loaded (to avoid loading it again from disk).
*/
bool ActivateBestChain(CValidationState &state, CBlock *pblock) { bool ActivateBestChain(CValidationState &state, CBlock *pblock) {
CBlockIndex *pindexNewTip = NULL; CBlockIndex *pindexNewTip = NULL;
CBlockIndex *pindexMostWork = NULL; CBlockIndex *pindexMostWork = NULL;
@ -2086,11 +2139,83 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) {
if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
pnode->PushInventory(CInv(MSG_BLOCK, hashNewTip)); pnode->PushInventory(CInv(MSG_BLOCK, hashNewTip));
} }
// Notify external listeners about the new tip.
uiInterface.NotifyBlockTip(hashNewTip); uiInterface.NotifyBlockTip(hashNewTip);
} }
} while(pindexMostWork != chainActive.Tip()); } while(pindexMostWork != chainActive.Tip());
// Write changes periodically to disk, after relay.
if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC)) {
return false;
}
return true;
}
bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) {
AssertLockHeld(cs_main);
// Mark the block itself as invalid.
pindex->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(pindex);
setBlockIndexCandidates.erase(pindex);
while (chainActive.Contains(pindex)) {
CBlockIndex *pindexWalk = chainActive.Tip();
pindexWalk->nStatus |= BLOCK_FAILED_CHILD;
setDirtyBlockIndex.insert(pindexWalk);
setBlockIndexCandidates.erase(pindexWalk);
// ActivateBestChain considers blocks already in chainActive
// unconditionally valid already, so force disconnect away from it.
if (!DisconnectTip(state)) {
return false;
}
}
// The resulting new best tip may not be in setBlockIndexCandidates anymore, so
// add them again.
BlockMap::iterator it = mapBlockIndex.begin();
while (it != mapBlockIndex.end()) {
if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) {
setBlockIndexCandidates.insert(pindex);
}
it++;
}
InvalidChainFound(pindex);
return true;
}
bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex) {
AssertLockHeld(cs_main);
int nHeight = pindex->nHeight;
// Remove the invalidity flag from this block and all its descendants.
BlockMap::iterator it = mapBlockIndex.begin();
while (it != mapBlockIndex.end()) {
if (!it->second->IsValid() && it->second->GetAncestor(nHeight) == pindex) {
it->second->nStatus &= ~BLOCK_FAILED_MASK;
setDirtyBlockIndex.insert(it->second);
if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) {
setBlockIndexCandidates.insert(it->second);
}
if (it->second == pindexBestInvalid) {
// Reset invalid block marker if it was pointing to one of those.
pindexBestInvalid = NULL;
}
}
it++;
}
// Remove the invalidity flag from all ancestors too.
while (pindex != NULL) {
if (pindex->nStatus & BLOCK_FAILED_MASK) {
pindex->nStatus &= ~BLOCK_FAILED_MASK;
setDirtyBlockIndex.insert(pindex);
}
pindex = pindex->pprev;
}
return true; return true;
} }
@ -2123,13 +2248,12 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
if (pindexBestHeader == NULL || pindexBestHeader->nChainWork < pindexNew->nChainWork) if (pindexBestHeader == NULL || pindexBestHeader->nChainWork < pindexNew->nChainWork)
pindexBestHeader = pindexNew; pindexBestHeader = pindexNew;
// Ok if it fails, we'll download the header again next time. setDirtyBlockIndex.insert(pindexNew);
pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew));
return pindexNew; return pindexNew;
} }
// Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). /** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos) bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos)
{ {
pindexNew->nTx = block.vtx.size(); pindexNew->nTx = block.vtx.size();
@ -2143,6 +2267,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
LOCK(cs_nBlockSequenceId); LOCK(cs_nBlockSequenceId);
pindexNew->nSequenceId = nBlockSequenceId++; pindexNew->nSequenceId = nBlockSequenceId++;
} }
setDirtyBlockIndex.insert(pindexNew);
if (pindexNew->pprev == NULL || pindexNew->pprev->nChainTx) { if (pindexNew->pprev == NULL || pindexNew->pprev->nChainTx) {
// If pindexNew is the genesis block or all parents are BLOCK_VALID_TRANSACTIONS. // If pindexNew is the genesis block or all parents are BLOCK_VALID_TRANSACTIONS.
@ -2162,15 +2287,11 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
range.first++; range.first++;
mapBlocksUnlinked.erase(it); mapBlocksUnlinked.erase(it);
} }
if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex)))
return state.Abort("Failed to write block index");
} }
} else { } else {
if (pindexNew->pprev && pindexNew->pprev->IsValid(BLOCK_VALID_TREE)) { if (pindexNew->pprev && pindexNew->pprev->IsValid(BLOCK_VALID_TREE)) {
mapBlocksUnlinked.insert(std::make_pair(pindexNew->pprev, pindexNew)); mapBlocksUnlinked.insert(std::make_pair(pindexNew->pprev, pindexNew));
} }
if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew)))
return state.Abort("Failed to write block index");
} }
return true; return true;
@ -2178,8 +2299,6 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false)
{ {
bool fUpdatedLast = false;
LOCK(cs_LastBlockFile); LOCK(cs_LastBlockFile);
unsigned int nFile = fKnown ? pos.nFile : nLastBlockFile; unsigned int nFile = fKnown ? pos.nFile : nLastBlockFile;
@ -2195,7 +2314,6 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd
if (vinfoBlockFile.size() <= nFile) { if (vinfoBlockFile.size() <= nFile) {
vinfoBlockFile.resize(nFile + 1); vinfoBlockFile.resize(nFile + 1);
} }
fUpdatedLast = true;
} }
pos.nFile = nFile; pos.nFile = nFile;
pos.nPos = vinfoBlockFile[nFile].nSize; pos.nPos = vinfoBlockFile[nFile].nSize;
@ -2222,11 +2340,7 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd
} }
} }
if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, vinfoBlockFile[nFile])) setDirtyFileInfo.insert(nFile);
return state.Abort("Failed to write file info");
if (fUpdatedLast)
pblocktree->WriteLastBlockFile(nLastBlockFile);
return true; return true;
} }
@ -2239,9 +2353,7 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
unsigned int nNewSize; unsigned int nNewSize;
pos.nPos = vinfoBlockFile[nFile].nUndoSize; pos.nPos = vinfoBlockFile[nFile].nUndoSize;
nNewSize = vinfoBlockFile[nFile].nUndoSize += nAddSize; nNewSize = vinfoBlockFile[nFile].nUndoSize += nAddSize;
if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, vinfoBlockFile[nLastBlockFile])) { setDirtyFileInfo.insert(nFile);
return state.Abort("Failed to write block info");
}
unsigned int nOldChunks = (pos.nPos + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE; unsigned int nOldChunks = (pos.nPos + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE;
unsigned int nNewChunks = (nNewSize + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE; unsigned int nNewChunks = (nNewSize + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE;
@ -2462,6 +2574,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
if ((!CheckBlock(block, state)) || !ContextualCheckBlock(block, state, pindex->pprev)) { if ((!CheckBlock(block, state)) || !ContextualCheckBlock(block, state, pindex->pprev)) {
if (state.IsInvalid() && !state.CorruptionPossible()) { if (state.IsInvalid() && !state.CorruptionPossible()) {
pindex->nStatus |= BLOCK_FAILED_VALID; pindex->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(pindex);
} }
return false; return false;
} }
@ -2609,159 +2722,6 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex
CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
{
header = block.GetBlockHeader();
vector<bool> vMatch;
vector<uint256> vHashes;
vMatch.reserve(block.vtx.size());
vHashes.reserve(block.vtx.size());
for (unsigned int i = 0; i < block.vtx.size(); i++)
{
const uint256& hash = block.vtx[i].GetHash();
if (filter.IsRelevantAndUpdate(block.vtx[i]))
{
vMatch.push_back(true);
vMatchedTxn.push_back(make_pair(i, hash));
}
else
vMatch.push_back(false);
vHashes.push_back(hash);
}
txn = CPartialMerkleTree(vHashes, vMatch);
}
uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid) {
if (height == 0) {
// hash at height 0 is the txids themself
return vTxid[pos];
} else {
// calculate left hash
uint256 left = CalcHash(height-1, pos*2, vTxid), right;
// calculate right hash if not beyong the end of the array - copy left hash otherwise1
if (pos*2+1 < CalcTreeWidth(height-1))
right = CalcHash(height-1, pos*2+1, vTxid);
else
right = left;
// combine subhashes
return Hash(BEGIN(left), END(left), BEGIN(right), END(right));
}
}
void CPartialMerkleTree::TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch) {
// determine whether this node is the parent of at least one matched txid
bool fParentOfMatch = false;
for (unsigned int p = pos << height; p < (pos+1) << height && p < nTransactions; p++)
fParentOfMatch |= vMatch[p];
// store as flag bit
vBits.push_back(fParentOfMatch);
if (height==0 || !fParentOfMatch) {
// if at height 0, or nothing interesting below, store hash and stop
vHash.push_back(CalcHash(height, pos, vTxid));
} else {
// otherwise, don't store any hash, but descend into the subtrees
TraverseAndBuild(height-1, pos*2, vTxid, vMatch);
if (pos*2+1 < CalcTreeWidth(height-1))
TraverseAndBuild(height-1, pos*2+1, vTxid, vMatch);
}
}
uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch) {
if (nBitsUsed >= vBits.size()) {
// overflowed the bits array - failure
fBad = true;
return 0;
}
bool fParentOfMatch = vBits[nBitsUsed++];
if (height==0 || !fParentOfMatch) {
// if at height 0, or nothing interesting below, use stored hash and do not descend
if (nHashUsed >= vHash.size()) {
// overflowed the hash array - failure
fBad = true;
return 0;
}
const uint256 &hash = vHash[nHashUsed++];
if (height==0 && fParentOfMatch) // in case of height 0, we have a matched txid
vMatch.push_back(hash);
return hash;
} else {
// otherwise, descend into the subtrees to extract matched txids and hashes
uint256 left = TraverseAndExtract(height-1, pos*2, nBitsUsed, nHashUsed, vMatch), right;
if (pos*2+1 < CalcTreeWidth(height-1))
right = TraverseAndExtract(height-1, pos*2+1, nBitsUsed, nHashUsed, vMatch);
else
right = left;
// and combine them before returning
return Hash(BEGIN(left), END(left), BEGIN(right), END(right));
}
}
CPartialMerkleTree::CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch) : nTransactions(vTxid.size()), fBad(false) {
// reset state
vBits.clear();
vHash.clear();
// calculate height of tree
int nHeight = 0;
while (CalcTreeWidth(nHeight) > 1)
nHeight++;
// traverse the partial tree
TraverseAndBuild(nHeight, 0, vTxid, vMatch);
}
CPartialMerkleTree::CPartialMerkleTree() : nTransactions(0), fBad(true) {}
uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch) {
vMatch.clear();
// An empty set will not work
if (nTransactions == 0)
return 0;
// check for excessively high numbers of transactions
if (nTransactions > MAX_BLOCK_SIZE / 60) // 60 is the lower bound for the size of a serialized CTransaction
return 0;
// there can never be more hashes provided than one for every txid
if (vHash.size() > nTransactions)
return 0;
// there must be at least one bit per node in the partial tree, and at least one node per hash
if (vBits.size() < vHash.size())
return 0;
// calculate height of tree
int nHeight = 0;
while (CalcTreeWidth(nHeight) > 1)
nHeight++;
// traverse the partial tree
unsigned int nBitsUsed = 0, nHashUsed = 0;
uint256 hashMerkleRoot = TraverseAndExtract(nHeight, 0, nBitsUsed, nHashUsed, vMatch);
// verify that no problems occured during the tree traversal
if (fBad)
return 0;
// verify that all bits were consumed (except for the padding caused by serializing it as a byte sequence)
if ((nBitsUsed+7)/8 != (vBits.size()+7)/8)
return 0;
// verify that all hashes were consumed
if (nHashUsed != vHash.size())
return 0;
return hashMerkleRoot;
}
bool AbortNode(const std::string &strMessage, const std::string &userMessage) { bool AbortNode(const std::string &strMessage, const std::string &userMessage) {
strMiscWarning = strMessage; strMiscWarning = strMessage;
LogPrintf("*** %s\n", strMessage); LogPrintf("*** %s\n", strMessage);
@ -2930,6 +2890,9 @@ bool static LoadBlockIndexDB()
if (it == mapBlockIndex.end()) if (it == mapBlockIndex.end())
return true; return true;
chainActive.SetTip(it->second); chainActive.SetTip(it->second);
PruneBlockIndexCandidates();
LogPrintf("LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s progress=%f\n", LogPrintf("LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s progress=%f\n",
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(),
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
@ -3070,7 +3033,7 @@ bool InitBlockIndex() {
if (!ActivateBestChain(state, &block)) if (!ActivateBestChain(state, &block))
return error("LoadBlockIndex() : genesis block cannot be activated"); return error("LoadBlockIndex() : genesis block cannot be activated");
// Force a chainstate write so that when we VerifyDB in a moment, it doesnt check stale data // Force a chainstate write so that when we VerifyDB in a moment, it doesnt check stale data
return WriteChainState(state, true); return FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
} catch(std::runtime_error &e) { } catch(std::runtime_error &e) {
return error("LoadBlockIndex() : failed to initialize block database: %s", e.what()); return error("LoadBlockIndex() : failed to initialize block database: %s", e.what());
} }
@ -3081,75 +3044,6 @@ bool InitBlockIndex() {
void PrintBlockTree()
{
AssertLockHeld(cs_main);
// pre-compute tree structure
map<CBlockIndex*, vector<CBlockIndex*> > mapNext;
for (BlockMap::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
{
CBlockIndex* pindex = (*mi).second;
mapNext[pindex->pprev].push_back(pindex);
// test
//while (rand() % 3 == 0)
// mapNext[pindex->pprev].push_back(pindex);
}
vector<pair<int, CBlockIndex*> > vStack;
vStack.push_back(make_pair(0, chainActive.Genesis()));
int nPrevCol = 0;
while (!vStack.empty())
{
int nCol = vStack.back().first;
CBlockIndex* pindex = vStack.back().second;
vStack.pop_back();
// print split or gap
if (nCol > nPrevCol)
{
for (int i = 0; i < nCol-1; i++)
LogPrintf("| ");
LogPrintf("|\\\n");
}
else if (nCol < nPrevCol)
{
for (int i = 0; i < nCol; i++)
LogPrintf("| ");
LogPrintf("|\n");
}
nPrevCol = nCol;
// print columns
for (int i = 0; i < nCol; i++)
LogPrintf("| ");
// print item
CBlock block;
ReadBlockFromDisk(block, pindex);
LogPrintf("%d (blk%05u.dat:0x%x) %s tx %u\n",
pindex->nHeight,
pindex->GetBlockPos().nFile, pindex->GetBlockPos().nPos,
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", block.GetBlockTime()),
block.vtx.size());
// put the main time-chain first
vector<CBlockIndex*>& vNext = mapNext[pindex];
for (unsigned int i = 0; i < vNext.size(); i++)
{
if (chainActive.Next(vNext[i]))
{
swap(vNext[0], vNext[i]);
break;
}
}
// iterate children
for (unsigned int i = 0; i < vNext.size(); i++)
vStack.push_back(make_pair(nCol+i, vNext[i]));
}
}
bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
{ {
// Map of disk positions for blocks with unknown parent (only used for reindex) // Map of disk positions for blocks with unknown parent (only used for reindex)
@ -3945,7 +3839,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->id, pfrom->cleanSubVer, pfrom->id, pfrom->cleanSubVer,
state.GetRejectReason()); state.GetRejectReason());
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
state.GetRejectReason(), inv.hash); state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
if (nDoS > 0) if (nDoS > 0)
Misbehaving(pfrom->GetId(), nDoS); Misbehaving(pfrom->GetId(), nDoS);
} }
@ -4019,7 +3913,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
int nDoS; int nDoS;
if (state.IsInvalid(nDoS)) { if (state.IsInvalid(nDoS)) {
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
state.GetRejectReason(), inv.hash); state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
if (nDoS > 0) { if (nDoS > 0) {
LOCK(cs_main); LOCK(cs_main);
Misbehaving(pfrom->GetId(), nDoS); Misbehaving(pfrom->GetId(), nDoS);
@ -4226,7 +4120,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (fDebug) { if (fDebug) {
try { try {
string strMsg; unsigned char ccode; string strReason; string strMsg; unsigned char ccode; string strReason;
vRecv >> LIMITED_STRING(strMsg, CMessageHeader::COMMAND_SIZE) >> ccode >> LIMITED_STRING(strReason, 111); vRecv >> LIMITED_STRING(strMsg, CMessageHeader::COMMAND_SIZE) >> ccode >> LIMITED_STRING(strReason, MAX_REJECT_MESSAGE_LENGTH);
ostringstream ss; ostringstream ss;
ss << strMsg << " code " << itostr(ccode) << ": " << strReason; ss << strMsg << " code " << itostr(ccode) << ": " << strReason;
@ -4641,11 +4535,6 @@ bool CBlockUndo::WriteToDisk(CDiskBlockPos &pos, const uint256 &hashBlock)
hasher << *this; hasher << *this;
fileout << hasher.GetHash(); fileout << hasher.GetHash();
// Flush stdio buffers and commit to disk before returning
fflush(fileout.Get());
if (!IsInitialBlockDownload())
FileCommit(fileout.Get());
return true; return true;
} }

View file

@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers // Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_MAIN_H #ifndef BITCOIN_MAIN_H
@ -14,8 +14,8 @@
#include "chain.h" #include "chain.h"
#include "chainparams.h" #include "chainparams.h"
#include "coins.h" #include "coins.h"
#include "core/block.h" #include "primitives/block.h"
#include "core/transaction.h" #include "primitives/transaction.h"
#include "net.h" #include "net.h"
#include "pow.h" #include "pow.h"
#include "script/script.h" #include "script/script.h"
@ -49,8 +49,6 @@ class CValidationState;
struct CBlockTemplate; struct CBlockTemplate;
struct CNodeStateStats; struct CNodeStateStats;
/** The maximum allowed size for a serialized block, in bytes (network rule) */
static const unsigned int MAX_BLOCK_SIZE = 1000000;
/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/ /** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/
static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000;
static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0; static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0;
@ -60,7 +58,7 @@ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000;
static const unsigned int MAX_STANDARD_TX_SIZE = 100000; static const unsigned int MAX_STANDARD_TX_SIZE = 100000;
/** The maximum allowed number of signature check operations in a block (network rule) */ /** The maximum allowed number of signature check operations in a block (network rule) */
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
/** Maxiumum number of signature check operations in an IsStandard() P2SH script */ /** Maximum number of signature check operations in an IsStandard() P2SH script */
static const unsigned int MAX_P2SH_SIGOPS = 15; static const unsigned int MAX_P2SH_SIGOPS = 15;
/** The maximum number of sigops we're willing to relay/mine in a single tx */ /** The maximum number of sigops we're willing to relay/mine in a single tx */
static const unsigned int MAX_TX_SIGOPS = MAX_BLOCK_SIGOPS/5; static const unsigned int MAX_TX_SIGOPS = MAX_BLOCK_SIGOPS/5;
@ -94,8 +92,12 @@ static const unsigned int MAX_HEADERS_RESULTS = 2000;
* degree of disordering of blocks on disk (which make reindexing and in the future perhaps pruning * degree of disordering of blocks on disk (which make reindexing and in the future perhaps pruning
* harder). We'll probably want to make this a per-peer adaptive value at some point. */ * harder). We'll probably want to make this a per-peer adaptive value at some point. */
static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024; static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
/** Time to wait (in seconds) between writing blockchain state to disk. */
static const unsigned int DATABASE_WRITE_INTERVAL = 3600;
/** Maximum length of reject messages. */
static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111;
/** "reject" message codes **/ /** "reject" message codes */
static const unsigned char REJECT_MALFORMED = 0x01; static const unsigned char REJECT_MALFORMED = 0x01;
static const unsigned char REJECT_INVALID = 0x10; static const unsigned char REJECT_INVALID = 0x10;
static const unsigned char REJECT_OBSOLETE = 0x11; static const unsigned char REJECT_OBSOLETE = 0x11;
@ -129,10 +131,10 @@ extern bool fIsBareMultisigStd;
extern unsigned int nCoinCacheSize; extern unsigned int nCoinCacheSize;
extern CFeeRate minRelayTxFee; extern CFeeRate minRelayTxFee;
// Best header we've seen so far (used for getheaders queries' starting points). /** Best header we've seen so far (used for getheaders queries' starting points). */
extern CBlockIndex *pindexBestHeader; extern CBlockIndex *pindexBestHeader;
// Minimum disk space required - used in CheckDiskSpace() /** Minimum disk space required - used in CheckDiskSpace() */
static const uint64_t nMinDiskSpace = 52428800; static const uint64_t nMinDiskSpace = 52428800;
/** Register a wallet to receive updates from core */ /** Register a wallet to receive updates from core */
@ -149,14 +151,16 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals);
/** Unregister a network node */ /** Unregister a network node */
void UnregisterNodeSignals(CNodeSignals& nodeSignals); void UnregisterNodeSignals(CNodeSignals& nodeSignals);
/** Process an incoming block. This only returns after the best known valid /**
block is made active. Note that it does not, however, guarantee that the * Process an incoming block. This only returns after the best known valid
specific block passed to it has been checked for validity! * block is made active. Note that it does not, however, guarantee that the
@param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state iff pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface - this will have its BlockChecked method called whenever *any* block completes validation. * specific block passed to it has been checked for validity!
@param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid. *
@param[in] pblock The block we want to process. * @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state if pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface - this will have its BlockChecked method called whenever *any* block completes validation.
@param[out] dbp If pblock is stored to disk (or already there), this will be set to its location. * @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid.
@return True if state.IsValid() * @param[in] pblock The block we want to process.
* @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location.
* @return True if state.IsValid()
*/ */
bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL); bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL);
/** Check whether enough disk space is available for an incoming block */ /** Check whether enough disk space is available for an incoming block */
@ -175,8 +179,6 @@ bool InitBlockIndex();
bool LoadBlockIndex(); bool LoadBlockIndex();
/** Unload database information */ /** Unload database information */
void UnloadBlockIndex(); void UnloadBlockIndex();
/** Print the loaded block tree */
void PrintBlockTree();
/** Process protocol messages received from a given node */ /** Process protocol messages received from a given node */
bool ProcessMessages(CNode* pfrom); bool ProcessMessages(CNode* pfrom);
/** Send queued protocol messages to be sent to a give node */ /** Send queued protocol messages to be sent to a give node */
@ -201,6 +203,8 @@ bool AbortNode(const std::string &msg, const std::string &userMessage="");
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats); bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats);
/** Increase a node's misbehavior score. */ /** Increase a node's misbehavior score. */
void Misbehaving(NodeId nodeid, int howmuch); void Misbehaving(NodeId nodeid, int howmuch);
/** Flush all state, indexes and buffers to disk. */
void FlushStateToDisk();
/** (try to) add transaction to memory pool **/ /** (try to) add transaction to memory pool **/
@ -243,53 +247,58 @@ struct CDiskTxPos : public CDiskBlockPos
CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree); CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree);
// /**
// Check transaction inputs, and make sure any * Check transaction inputs, and make sure any
// pay-to-script-hash transactions are evaluating IsStandard scripts * pay-to-script-hash transactions are evaluating IsStandard scripts
// *
// Why bother? To avoid denial-of-service attacks; an attacker * Why bother? To avoid denial-of-service attacks; an attacker
// can submit a standard HASH... OP_EQUAL transaction, * can submit a standard HASH... OP_EQUAL transaction,
// which will get accepted into blocks. The redemption * which will get accepted into blocks. The redemption
// script can be anything; an attacker could use a very * script can be anything; an attacker could use a very
// expensive-to-check-upon-redemption script like: * expensive-to-check-upon-redemption script like:
// DUP CHECKSIG DROP ... repeated 100 times... OP_1 * DUP CHECKSIG DROP ... repeated 100 times... OP_1
// */
/** Check for standard transaction types /**
@param[in] mapInputs Map of previous transactions that have outputs we're spending * Check for standard transaction types
@return True if all inputs (scriptSigs) use only standard transaction forms * @param[in] mapInputs Map of previous transactions that have outputs we're spending
* @return True if all inputs (scriptSigs) use only standard transaction forms
*/ */
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs); bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
/** Count ECDSA signature operations the old-fashioned (pre-0.6) way /**
@return number of sigops this transaction's outputs will produce when spent * Count ECDSA signature operations the old-fashioned (pre-0.6) way
@see CTransaction::FetchInputs * @return number of sigops this transaction's outputs will produce when spent
* @see CTransaction::FetchInputs
*/ */
unsigned int GetLegacySigOpCount(const CTransaction& tx); unsigned int GetLegacySigOpCount(const CTransaction& tx);
/** Count ECDSA signature operations in pay-to-script-hash inputs. /**
* Count ECDSA signature operations in pay-to-script-hash inputs.
@param[in] mapInputs Map of previous transactions that have outputs we're spending *
@return maximum number of sigops required to validate this transaction's inputs * @param[in] mapInputs Map of previous transactions that have outputs we're spending
@see CTransaction::FetchInputs * @return maximum number of sigops required to validate this transaction's inputs
* @see CTransaction::FetchInputs
*/ */
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs); unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs);
// Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts) /**
// This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it * Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
// instead of being performed inline. * This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
* instead of being performed inline.
*/
bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks, bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks,
unsigned int flags, bool cacheStore, std::vector<CScriptCheck> *pvChecks = NULL); unsigned int flags, bool cacheStore, std::vector<CScriptCheck> *pvChecks = NULL);
// Apply the effects of this transaction on the UTXO set represented by view /** Apply the effects of this transaction on the UTXO set represented by view */
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight); void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight);
// Context-independent validity checks /** Context-independent validity checks */
bool CheckTransaction(const CTransaction& tx, CValidationState& state); bool CheckTransaction(const CTransaction& tx, CValidationState& state);
/** Check for standard transaction types /** Check for standard transaction types
@return True if all outputs (scriptPubKeys) use only standard transaction forms * @return True if all outputs (scriptPubKeys) use only standard transaction forms
*/ */
bool IsStandardTx(const CTransaction& tx, std::string& reason); bool IsStandardTx(const CTransaction& tx, std::string& reason);
@ -313,8 +322,10 @@ public:
}; };
/** Closure representing one script verification /**
* Note that this stores references to the spending transaction */ * Closure representing one script verification
* Note that this stores references to the spending transaction
*/
class CScriptCheck class CScriptCheck
{ {
private: private:
@ -323,14 +334,15 @@ private:
unsigned int nIn; unsigned int nIn;
unsigned int nFlags; unsigned int nFlags;
bool cacheStore; bool cacheStore;
ScriptError error;
public: public:
CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false) {} CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) : CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) :
scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn) { } ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) { }
bool operator()() const; bool operator()();
void swap(CScriptCheck &check) { void swap(CScriptCheck &check) {
scriptPubKey.swap(check.scriptPubKey); scriptPubKey.swap(check.scriptPubKey);
@ -338,109 +350,12 @@ public:
std::swap(nIn, check.nIn); std::swap(nIn, check.nIn);
std::swap(nFlags, check.nFlags); std::swap(nFlags, check.nFlags);
std::swap(cacheStore, check.cacheStore); std::swap(cacheStore, check.cacheStore);
std::swap(error, check.error);
} }
ScriptError GetScriptError() const { return error; }
}; };
/** Data structure that represents a partial merkle tree.
*
* It respresents a subset of the txid's of a known block, in a way that
* allows recovery of the list of txid's and the merkle root, in an
* authenticated way.
*
* The encoding works as follows: we traverse the tree in depth-first order,
* storing a bit for each traversed node, signifying whether the node is the
* parent of at least one matched leaf txid (or a matched txid itself). In
* case we are at the leaf level, or this bit is 0, its merkle node hash is
* stored, and its children are not explorer further. Otherwise, no hash is
* stored, but we recurse into both (or the only) child branch. During
* decoding, the same depth-first traversal is performed, consuming bits and
* hashes as they written during encoding.
*
* The serialization is fixed and provides a hard guarantee about the
* encoded size:
*
* SIZE <= 10 + ceil(32.25*N)
*
* Where N represents the number of leaf nodes of the partial tree. N itself
* is bounded by:
*
* N <= total_transactions
* N <= 1 + matched_transactions*tree_height
*
* The serialization format:
* - uint32 total_transactions (4 bytes)
* - varint number of hashes (1-3 bytes)
* - uint256[] hashes in depth-first order (<= 32*N bytes)
* - varint number of bytes of flag bits (1-3 bytes)
* - byte[] flag bits, packed per 8 in a byte, least significant bit first (<= 2*N-1 bits)
* The size constraints follow from this.
*/
class CPartialMerkleTree
{
protected:
// the total number of transactions in the block
unsigned int nTransactions;
// node-is-parent-of-matched-txid bits
std::vector<bool> vBits;
// txids and internal hashes
std::vector<uint256> vHash;
// flag set when encountering invalid data
bool fBad;
// helper function to efficiently calculate the number of nodes at given height in the merkle tree
unsigned int CalcTreeWidth(int height) {
return (nTransactions+(1 << height)-1) >> height;
}
// calculate the hash of a node in the merkle tree (at leaf level: the txid's themself)
uint256 CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid);
// recursive function that traverses tree nodes, storing the data as bits and hashes
void TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
// recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild.
// it returns the hash of the respective node.
uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch);
public:
// serialization implementation
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(nTransactions);
READWRITE(vHash);
std::vector<unsigned char> vBytes;
if (ser_action.ForRead()) {
READWRITE(vBytes);
CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(this));
us.vBits.resize(vBytes.size() * 8);
for (unsigned int p = 0; p < us.vBits.size(); p++)
us.vBits[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0;
us.fBad = false;
} else {
vBytes.resize((vBits.size()+7)/8);
for (unsigned int p = 0; p < vBits.size(); p++)
vBytes[p / 8] |= vBits[p] << (p % 8);
READWRITE(vBytes);
}
}
// Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them
CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
CPartialMerkleTree();
// extract the matching txid's represented by this partial merkle tree.
// returns the merkle root, or 0 in case of failure
uint256 ExtractMatches(std::vector<uint256> &vMatch);
};
/** Functions for disk access for blocks */ /** Functions for disk access for blocks */
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos); bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos);
@ -456,22 +371,21 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
* of problems. Note that in any case, coins may be modified. */ * of problems. Note that in any case, coins may be modified. */
bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL); bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL);
// Apply the effects of this block (with given index) on the UTXO set represented by coins /** Apply the effects of this block (with given index) on the UTXO set represented by coins */
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false); bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false);
// Context-independent validity checks /** Context-independent validity checks */
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true); bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true);
bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true); bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
// Context-dependent validity checks /** Context-dependent validity checks */
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev); bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev);
bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev); bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev);
// Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) /** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */
bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex *pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true); bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex *pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
// Store block on disk /** Store block on disk. If dbp is provided, the file is known to already reside on disk */
// if dbp is provided, the file is known to already reside on disk
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, CDiskBlockPos* dbp = NULL); bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, CDiskBlockPos* dbp = NULL);
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL); bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL);
@ -480,13 +394,13 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
class CBlockFileInfo class CBlockFileInfo
{ {
public: public:
unsigned int nBlocks; // number of blocks stored in file unsigned int nBlocks; //! number of blocks stored in file
unsigned int nSize; // number of used bytes of block file unsigned int nSize; //! number of used bytes of block file
unsigned int nUndoSize; // number of used bytes in the undo file unsigned int nUndoSize; //! number of used bytes in the undo file
unsigned int nHeightFirst; // lowest height of block in file unsigned int nHeightFirst; //! lowest height of block in file
unsigned int nHeightLast; // highest height of block in file unsigned int nHeightLast; //! highest height of block in file
uint64_t nTimeFirst; // earliest time of block in file uint64_t nTimeFirst; //! earliest time of block in file
uint64_t nTimeLast; // latest time of block in file uint64_t nTimeLast; //! latest time of block in file
ADD_SERIALIZE_METHODS; ADD_SERIALIZE_METHODS;
@ -517,7 +431,7 @@ public:
std::string ToString() const; std::string ToString() const;
// update statistics (does not update nSize) /** update statistics (does not update nSize) */
void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) { void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) {
if (nBlocks==0 || nHeightFirst > nHeightIn) if (nBlocks==0 || nHeightFirst > nHeightIn)
nHeightFirst = nHeightIn; nHeightFirst = nHeightIn;
@ -535,9 +449,9 @@ public:
class CValidationState { class CValidationState {
private: private:
enum mode_state { enum mode_state {
MODE_VALID, // everything ok MODE_VALID, //! everything ok
MODE_INVALID, // network rule violation (DoS value may be set) MODE_INVALID, //! network rule violation (DoS value may be set)
MODE_ERROR, // run-time error MODE_ERROR, //! run-time error
} mode; } mode;
int nDoS; int nDoS;
std::string strRejectReason; std::string strRejectReason;
@ -605,6 +519,12 @@ public:
/** Find the last common block between the parameter chain and a locator. */ /** Find the last common block between the parameter chain and a locator. */
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator); CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator);
/** Mark a block as invalid. */
bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex);
/** Remove invalidity status from a block and its descendants. */
bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex);
/** The currently-connected chain of blocks. */ /** The currently-connected chain of blocks. */
extern CChain chainActive; extern CChain chainActive;
@ -626,36 +546,6 @@ struct CBlockTemplate
/** Used to relay blocks as header + vector<merkle branch>
* to filtered nodes.
*/
class CMerkleBlock
{
public:
// Public only for unit testing
CBlockHeader header;
CPartialMerkleTree txn;
public:
// Public only for unit testing and relay testing
// (not relayed)
std::vector<std::pair<unsigned int, uint256> > vMatchedTxn;
// Create from a CBlock, filtering transactions according to filter
// Note that this will call IsRelevantAndUpdate on the filter for each transaction,
// thus the filter will likely be modified.
CMerkleBlock(const CBlock& block, CBloomFilter& filter);
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(header);
READWRITE(txn);
}
};
class CValidationInterface { class CValidationInterface {
protected: protected:
virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) {}; virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) {};

152
src/merkleblock.cpp Normal file
View file

@ -0,0 +1,152 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "merkleblock.h"
#include "hash.h"
#include "primitives/block.h" // for MAX_BLOCK_SIZE
#include "utilstrencodings.h"
using namespace std;
CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
{
header = block.GetBlockHeader();
vector<bool> vMatch;
vector<uint256> vHashes;
vMatch.reserve(block.vtx.size());
vHashes.reserve(block.vtx.size());
for (unsigned int i = 0; i < block.vtx.size(); i++)
{
const uint256& hash = block.vtx[i].GetHash();
if (filter.IsRelevantAndUpdate(block.vtx[i]))
{
vMatch.push_back(true);
vMatchedTxn.push_back(make_pair(i, hash));
}
else
vMatch.push_back(false);
vHashes.push_back(hash);
}
txn = CPartialMerkleTree(vHashes, vMatch);
}
uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid) {
if (height == 0) {
// hash at height 0 is the txids themself
return vTxid[pos];
} else {
// calculate left hash
uint256 left = CalcHash(height-1, pos*2, vTxid), right;
// calculate right hash if not beyond the end of the array - copy left hash otherwise1
if (pos*2+1 < CalcTreeWidth(height-1))
right = CalcHash(height-1, pos*2+1, vTxid);
else
right = left;
// combine subhashes
return Hash(BEGIN(left), END(left), BEGIN(right), END(right));
}
}
void CPartialMerkleTree::TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch) {
// determine whether this node is the parent of at least one matched txid
bool fParentOfMatch = false;
for (unsigned int p = pos << height; p < (pos+1) << height && p < nTransactions; p++)
fParentOfMatch |= vMatch[p];
// store as flag bit
vBits.push_back(fParentOfMatch);
if (height==0 || !fParentOfMatch) {
// if at height 0, or nothing interesting below, store hash and stop
vHash.push_back(CalcHash(height, pos, vTxid));
} else {
// otherwise, don't store any hash, but descend into the subtrees
TraverseAndBuild(height-1, pos*2, vTxid, vMatch);
if (pos*2+1 < CalcTreeWidth(height-1))
TraverseAndBuild(height-1, pos*2+1, vTxid, vMatch);
}
}
uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch) {
if (nBitsUsed >= vBits.size()) {
// overflowed the bits array - failure
fBad = true;
return 0;
}
bool fParentOfMatch = vBits[nBitsUsed++];
if (height==0 || !fParentOfMatch) {
// if at height 0, or nothing interesting below, use stored hash and do not descend
if (nHashUsed >= vHash.size()) {
// overflowed the hash array - failure
fBad = true;
return 0;
}
const uint256 &hash = vHash[nHashUsed++];
if (height==0 && fParentOfMatch) // in case of height 0, we have a matched txid
vMatch.push_back(hash);
return hash;
} else {
// otherwise, descend into the subtrees to extract matched txids and hashes
uint256 left = TraverseAndExtract(height-1, pos*2, nBitsUsed, nHashUsed, vMatch), right;
if (pos*2+1 < CalcTreeWidth(height-1))
right = TraverseAndExtract(height-1, pos*2+1, nBitsUsed, nHashUsed, vMatch);
else
right = left;
// and combine them before returning
return Hash(BEGIN(left), END(left), BEGIN(right), END(right));
}
}
CPartialMerkleTree::CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch) : nTransactions(vTxid.size()), fBad(false) {
// reset state
vBits.clear();
vHash.clear();
// calculate height of tree
int nHeight = 0;
while (CalcTreeWidth(nHeight) > 1)
nHeight++;
// traverse the partial tree
TraverseAndBuild(nHeight, 0, vTxid, vMatch);
}
CPartialMerkleTree::CPartialMerkleTree() : nTransactions(0), fBad(true) {}
uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch) {
vMatch.clear();
// An empty set will not work
if (nTransactions == 0)
return 0;
// check for excessively high numbers of transactions
if (nTransactions > MAX_BLOCK_SIZE / 60) // 60 is the lower bound for the size of a serialized CTransaction
return 0;
// there can never be more hashes provided than one for every txid
if (vHash.size() > nTransactions)
return 0;
// there must be at least one bit per node in the partial tree, and at least one node per hash
if (vBits.size() < vHash.size())
return 0;
// calculate height of tree
int nHeight = 0;
while (CalcTreeWidth(nHeight) > 1)
nHeight++;
// traverse the partial tree
unsigned int nBitsUsed = 0, nHashUsed = 0;
uint256 hashMerkleRoot = TraverseAndExtract(nHeight, 0, nBitsUsed, nHashUsed, vMatch);
// verify that no problems occured during the tree traversal
if (fBad)
return 0;
// verify that all bits were consumed (except for the padding caused by serializing it as a byte sequence)
if ((nBitsUsed+7)/8 != (vBits.size()+7)/8)
return 0;
// verify that all hashes were consumed
if (nHashUsed != vHash.size())
return 0;
return hashMerkleRoot;
}

151
src/merkleblock.h Normal file
View file

@ -0,0 +1,151 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_MERKLEBLOCK_H
#define BITCOIN_MERKLEBLOCK_H
#include "serialize.h"
#include "uint256.h"
#include "primitives/block.h"
#include "bloom.h"
#include <vector>
/** Data structure that represents a partial merkle tree.
*
* It represents a subset of the txid's of a known block, in a way that
* allows recovery of the list of txid's and the merkle root, in an
* authenticated way.
*
* The encoding works as follows: we traverse the tree in depth-first order,
* storing a bit for each traversed node, signifying whether the node is the
* parent of at least one matched leaf txid (or a matched txid itself). In
* case we are at the leaf level, or this bit is 0, its merkle node hash is
* stored, and its children are not explorer further. Otherwise, no hash is
* stored, but we recurse into both (or the only) child branch. During
* decoding, the same depth-first traversal is performed, consuming bits and
* hashes as they written during encoding.
*
* The serialization is fixed and provides a hard guarantee about the
* encoded size:
*
* SIZE <= 10 + ceil(32.25*N)
*
* Where N represents the number of leaf nodes of the partial tree. N itself
* is bounded by:
*
* N <= total_transactions
* N <= 1 + matched_transactions*tree_height
*
* The serialization format:
* - uint32 total_transactions (4 bytes)
* - varint number of hashes (1-3 bytes)
* - uint256[] hashes in depth-first order (<= 32*N bytes)
* - varint number of bytes of flag bits (1-3 bytes)
* - byte[] flag bits, packed per 8 in a byte, least significant bit first (<= 2*N-1 bits)
* The size constraints follow from this.
*/
class CPartialMerkleTree
{
protected:
/** the total number of transactions in the block */
unsigned int nTransactions;
/** node-is-parent-of-matched-txid bits */
std::vector<bool> vBits;
/** txids and internal hashes */
std::vector<uint256> vHash;
/** flag set when encountering invalid data */
bool fBad;
/** helper function to efficiently calculate the number of nodes at given height in the merkle tree */
unsigned int CalcTreeWidth(int height) {
return (nTransactions+(1 << height)-1) >> height;
}
/** calculate the hash of a node in the merkle tree (at leaf level: the txid's themselves) */
uint256 CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid);
/** recursive function that traverses tree nodes, storing the data as bits and hashes */
void TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
/**
* recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild.
* it returns the hash of the respective node.
*/
uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch);
public:
/** serialization implementation */
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(nTransactions);
READWRITE(vHash);
std::vector<unsigned char> vBytes;
if (ser_action.ForRead()) {
READWRITE(vBytes);
CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(this));
us.vBits.resize(vBytes.size() * 8);
for (unsigned int p = 0; p < us.vBits.size(); p++)
us.vBits[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0;
us.fBad = false;
} else {
vBytes.resize((vBits.size()+7)/8);
for (unsigned int p = 0; p < vBits.size(); p++)
vBytes[p / 8] |= vBits[p] << (p % 8);
READWRITE(vBytes);
}
}
/** Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them */
CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
CPartialMerkleTree();
/**
* extract the matching txid's represented by this partial merkle tree.
* returns the merkle root, or 0 in case of failure
*/
uint256 ExtractMatches(std::vector<uint256> &vMatch);
};
/**
* Used to relay blocks as header + vector<merkle branch>
* to filtered nodes.
*/
class CMerkleBlock
{
public:
/** Public only for unit testing */
CBlockHeader header;
CPartialMerkleTree txn;
public:
/** Public only for unit testing and relay testing (not relayed) */
std::vector<std::pair<unsigned int, uint256> > vMatchedTxn;
/**
* Create from a CBlock, filtering transactions according to filter
* Note that this will call IsRelevantAndUpdate on the filter for each transaction,
* thus the filter will likely be modified.
*/
CMerkleBlock(const CBlock& block, CBloomFilter& filter);
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(header);
READWRITE(txn);
}
};
#endif // BITCOIN_MERKLEBLOCK_H

View file

@ -6,8 +6,8 @@
#include "miner.h" #include "miner.h"
#include "amount.h" #include "amount.h"
#include "core/block.h" #include "primitives/block.h"
#include "core/transaction.h" #include "primitives/transaction.h"
#include "hash.h" #include "hash.h"
#include "main.h" #include "main.h"
#include "net.h" #include "net.h"

View file

@ -12,7 +12,7 @@
#include "addrman.h" #include "addrman.h"
#include "chainparams.h" #include "chainparams.h"
#include "clientversion.h" #include "clientversion.h"
#include "core/transaction.h" #include "primitives/transaction.h"
#include "ui_interface.h" #include "ui_interface.h"
#ifdef WIN32 #ifdef WIN32
@ -399,7 +399,9 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
// Connect // Connect
SOCKET hSocket; SOCKET hSocket;
if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, Params().GetDefaultPort()) : ConnectSocket(addrConnect, hSocket)) bool proxyConnectionFailed = false;
if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, Params().GetDefaultPort(), nConnectTimeout, &proxyConnectionFailed) :
ConnectSocket(addrConnect, hSocket, nConnectTimeout, &proxyConnectionFailed))
{ {
addrman.Attempt(addrConnect); addrman.Attempt(addrConnect);
@ -415,6 +417,10 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
pnode->nTimeConnected = GetTime(); pnode->nTimeConnected = GetTime();
return pnode; return pnode;
} else if (!proxyConnectionFailed) {
// If connecting to the node failed, and failure is not caused by a problem connecting to
// the proxy, mark this as an attempt.
addrman.Attempt(addrConnect);
} }
return NULL; return NULL;
@ -1559,7 +1565,7 @@ void static Discover(boost::thread_group& threadGroup)
#ifdef WIN32 #ifdef WIN32
// Get local host IP // Get local host IP
char pszHostName[1000] = ""; char pszHostName[256] = "";
if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR) if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
{ {
vector<CNetAddr> vaddr; vector<CNetAddr> vaddr;
@ -1567,7 +1573,8 @@ void static Discover(boost::thread_group& threadGroup)
{ {
BOOST_FOREACH (const CNetAddr &addr, vaddr) BOOST_FOREACH (const CNetAddr &addr, vaddr)
{ {
AddLocal(addr, LOCAL_IF); if (AddLocal(addr, LOCAL_IF))
LogPrintf("%s: %s - %s\n", __func__, pszHostName, addr.ToString());
} }
} }
} }
@ -1587,20 +1594,19 @@ void static Discover(boost::thread_group& threadGroup)
struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr); struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
CNetAddr addr(s4->sin_addr); CNetAddr addr(s4->sin_addr);
if (AddLocal(addr, LOCAL_IF)) if (AddLocal(addr, LOCAL_IF))
LogPrintf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString()); LogPrintf("%s: IPv4 %s: %s\n", __func__, ifa->ifa_name, addr.ToString());
} }
else if (ifa->ifa_addr->sa_family == AF_INET6) else if (ifa->ifa_addr->sa_family == AF_INET6)
{ {
struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr); struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
CNetAddr addr(s6->sin6_addr); CNetAddr addr(s6->sin6_addr);
if (AddLocal(addr, LOCAL_IF)) if (AddLocal(addr, LOCAL_IF))
LogPrintf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString()); LogPrintf("%s: IPv6 %s: %s\n", __func__, ifa->ifa_name, addr.ToString());
} }
} }
freeifaddrs(myaddrs); freeifaddrs(myaddrs);
} }
#endif #endif
} }
void StartNode(boost::thread_group& threadGroup) void StartNode(boost::thread_group& threadGroup)

View file

@ -44,6 +44,8 @@ static const int PING_INTERVAL = 2 * 60;
static const int TIMEOUT_INTERVAL = 20 * 60; static const int TIMEOUT_INTERVAL = 20 * 60;
/** The maximum number of entries in an 'inv' protocol message */ /** The maximum number of entries in an 'inv' protocol message */
static const unsigned int MAX_INV_SZ = 50000; static const unsigned int MAX_INV_SZ = 50000;
/** The maximum number of new addresses to accumulate before announcing. */
static const unsigned int MAX_ADDR_TO_SEND = 1000;
/** -listen default */ /** -listen default */
static const bool DEFAULT_LISTEN = true; static const bool DEFAULT_LISTEN = true;
/** -upnp default */ /** -upnp default */
@ -368,9 +370,14 @@ public:
// Known checking here is only to save space from duplicates. // Known checking here is only to save space from duplicates.
// SendMessages will filter it again for knowns that were added // SendMessages will filter it again for knowns that were added
// after addresses were pushed. // after addresses were pushed.
if (addr.IsValid() && !setAddrKnown.count(addr)) if (addr.IsValid() && !setAddrKnown.count(addr)) {
if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) {
vAddrToSend[insecure_rand() % vAddrToSend.size()] = addr;
} else {
vAddrToSend.push_back(addr); vAddrToSend.push_back(addr);
} }
}
}
void AddInventoryKnown(const CInv& inv) void AddInventoryKnown(const CInv& inv)

View file

@ -4,7 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "bitcoin-config.h" #include "config/bitcoin-config.h"
#endif #endif
#include "netbase.h" #include "netbase.h"
@ -519,9 +519,11 @@ bool IsProxy(const CNetAddr &addr) {
return false; return false;
} }
bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout) bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
{ {
proxyType proxy; proxyType proxy;
if (outProxyConnectionFailed)
*outProxyConnectionFailed = false;
// no proxy needed (none set for target network) // no proxy needed (none set for target network)
if (!GetProxy(addrDest.GetNetwork(), proxy)) if (!GetProxy(addrDest.GetNetwork(), proxy))
return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout); return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout);
@ -529,8 +531,11 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
SOCKET hSocket = INVALID_SOCKET; SOCKET hSocket = INVALID_SOCKET;
// first connect to proxy server // first connect to proxy server
if (!ConnectSocketDirectly(proxy, hSocket, nTimeout)) if (!ConnectSocketDirectly(proxy, hSocket, nTimeout)) {
if (outProxyConnectionFailed)
*outProxyConnectionFailed = true;
return false; return false;
}
// do socks negotiation // do socks negotiation
if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket)) if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket))
return false; return false;
@ -539,10 +544,14 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
return true; return true;
} }
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout) bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed)
{ {
string strDest; string strDest;
int port = portDefault; int port = portDefault;
if (outProxyConnectionFailed)
*outProxyConnectionFailed = false;
SplitHostPort(string(pszDest), port, strDest); SplitHostPort(string(pszDest), port, strDest);
SOCKET hSocket = INVALID_SOCKET; SOCKET hSocket = INVALID_SOCKET;
@ -561,8 +570,11 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
if (!HaveNameProxy()) if (!HaveNameProxy())
return false; return false;
// first connect to name proxy server // first connect to name proxy server
if (!ConnectSocketDirectly(nameProxy, hSocket, nTimeout)) if (!ConnectSocketDirectly(nameProxy, hSocket, nTimeout)) {
if (outProxyConnectionFailed)
*outProxyConnectionFailed = true;
return false; return false;
}
// do socks negotiation // do socks negotiation
if (!Socks5(strDest, (unsigned short)port, hSocket)) if (!Socks5(strDest, (unsigned short)port, hSocket))
return false; return false;

View file

@ -182,8 +182,8 @@ bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nM
bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true); bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault = 0, bool fAllowLookup = true, unsigned int nMaxSolutions = 0); bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault = 0, bool fAllowLookup = true, unsigned int nMaxSolutions = 0);
bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0); bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout); bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0);
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault = 0, int nTimeout = nConnectTimeout); bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0);
/** Return readable error string for a network error code */ /** Return readable error string for a network error code */
std::string NetworkErrorString(int err); std::string NetworkErrorString(int err);
/** Close socket and set hSocket to INVALID_SOCKET */ /** Close socket and set hSocket to INVALID_SOCKET */

View file

@ -7,7 +7,7 @@
#include "chain.h" #include "chain.h"
#include "chainparams.h" #include "chainparams.h"
#include "core/block.h" #include "primitives/block.h"
#include "uint256.h" #include "uint256.h"
#include "util.h" #include "util.h"

View file

@ -3,7 +3,7 @@
// Distributed under the MIT/X11 software license, see the accompanying // Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "core/block.h" #include "primitives/block.h"
#include "hash.h" #include "hash.h"
#include "tinyformat.h" #include "tinyformat.h"

View file

@ -3,13 +3,16 @@
// Distributed under the MIT/X11 software license, see the accompanying // Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_CORE_BLOCK_H #ifndef BITCOIN_PRIMITIVES_BLOCK_H
#define BITCOIN_CORE_BLOCK_H #define BITCOIN_PRIMITIVES_BLOCK_H
#include "core/transaction.h" #include "primitives/transaction.h"
#include "serialize.h" #include "serialize.h"
#include "uint256.h" #include "uint256.h"
/** The maximum allowed size for a serialized block, in bytes (network rule) */
static const unsigned int MAX_BLOCK_SIZE = 1000000;
/** Nodes collect new transactions into a block, hash them into a hash tree, /** Nodes collect new transactions into a block, hash them into a hash tree,
* and scan through nonce values to make the block's hash satisfy proof-of-work * and scan through nonce values to make the block's hash satisfy proof-of-work
* requirements. When they solve the proof-of-work, they broadcast the block * requirements. When they solve the proof-of-work, they broadcast the block
@ -165,4 +168,4 @@ struct CBlockLocator
} }
}; };
#endif // BITCOIN_CORE_BLOCK_H #endif // BITCOIN_PRIMITIVES_BLOCK_H

View file

@ -3,7 +3,7 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "core/transaction.h" #include "primitives/transaction.h"
#include "hash.h" #include "hash.h"
#include "tinyformat.h" #include "tinyformat.h"

View file

@ -3,8 +3,8 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_CORE_TRANSACTION_H #ifndef BITCOIN_PRIMITIVES_TRANSACTION_H
#define BITCOIN_CORE_TRANSACTION_H #define BITCOIN_PRIMITIVES_TRANSACTION_H
#include "amount.h" #include "amount.h"
#include "script/script.h" #include "script/script.h"
@ -273,4 +273,4 @@ struct CMutableTransaction
uint256 GetHash() const; uint256 GetHash() const;
}; };
#endif // BITCOIN_CORE_TRANSACTION_H #endif // BITCOIN_PRIMITIVES_TRANSACTION_H

View file

@ -4,7 +4,6 @@
#include "pubkey.h" #include "pubkey.h"
#include "crypto/sha2.h"
#include "eccryptoverify.h" #include "eccryptoverify.h"
#ifdef USE_SECP256K1 #ifdef USE_SECP256K1

View file

@ -4,7 +4,7 @@
#include "bitcoinunits.h" #include "bitcoinunits.h"
#include "core/transaction.h" #include "primitives/transaction.h"
#include <QStringList> #include <QStringList>
@ -106,10 +106,8 @@ QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, Separator
QString quotient_str = QString::number(quotient); QString quotient_str = QString::number(quotient);
QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0'); QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');
// Use SI-stule separators as these are locale indendent and can't be // Use SI-style thin space separators as these are locale independent and can't be
// confused with the decimal marker. Rule is to use a thin space every // confused with the decimal marker.
// three digits on *both* sides of the decimal point - but only if there
// are five or more digits
QChar thin_sp(THIN_SP_CP); QChar thin_sp(THIN_SP_CP);
int q_size = quotient_str.size(); int q_size = quotient_str.size();
if (separators == separatorAlways || (separators == separatorStandard && q_size > 4)) if (separators == separatorAlways || (separators == separatorStandard && q_size > 4))

View file

@ -9,7 +9,7 @@
#include "qvalidatedlineedit.h" #include "qvalidatedlineedit.h"
#include "walletmodel.h" #include "walletmodel.h"
#include "core/transaction.h" #include "primitives/transaction.h"
#include "init.h" #include "init.h"
#include "main.h" #include "main.h"
#include "protocol.h" #include "protocol.h"

View file

@ -1,4 +1,4 @@
<TS language="ach" version="2.1"> <TS language="ach" version="2.0">
<context> <context>
<name>AddressBookPage</name> <name>AddressBookPage</name>
</context> </context>

View file

@ -1,4 +1,4 @@
<TS language="af_ZA" version="2.1"> <TS language="af_ZA" version="2.0">
<context> <context>
<name>AddressBookPage</name> <name>AddressBookPage</name>
<message> <message>
@ -200,10 +200,6 @@
<source>Amount</source> <source>Amount</source>
<translation>Bedrag</translation> <translation>Bedrag</translation>
</message> </message>
<message>
<source>Address</source>
<translation>Adres</translation>
</message>
<message> <message>
<source>Date</source> <source>Date</source>
<translation>Datum</translation> <translation>Datum</translation>

View file

@ -1,4 +1,4 @@
<TS language="ar" version="2.1"> <TS language="ar" version="2.0">
<context> <context>
<name>AddressBookPage</name> <name>AddressBookPage</name>
<message> <message>
@ -456,10 +456,6 @@
<source>Amount</source> <source>Amount</source>
<translation>المبلغ</translation> <translation>المبلغ</translation>
</message> </message>
<message>
<source>Address</source>
<translation>عنوان</translation>
</message>
<message> <message>
<source>Date</source> <source>Date</source>
<translation>التاريخ</translation> <translation>التاريخ</translation>
@ -524,6 +520,10 @@
<source>high</source> <source>high</source>
<translation>عالي</translation> <translation>عالي</translation>
</message> </message>
<message>
<source>medium-high</source>
<translation>متوسط-مرتفع</translation>
</message>
<message> <message>
<source>low</source> <source>low</source>
<translation>منخفض</translation> <translation>منخفض</translation>
@ -682,10 +682,6 @@
<source>&amp;Main</source> <source>&amp;Main</source>
<translation>&amp;الرئيسي</translation> <translation>&amp;الرئيسي</translation>
</message> </message>
<message>
<source>Pay transaction &amp;fee</source>
<translation>ادفع &amp;رسوم المعاملة</translation>
</message>
<message> <message>
<source>MB</source> <source>MB</source>
<translation>م ب</translation> <translation>م ب</translation>

View file

@ -1,4 +1,4 @@
<TS language="be_BY" version="2.1"> <TS language="be_BY" version="2.0">
<context> <context>
<name>AddressBookPage</name> <name>AddressBookPage</name>
<message> <message>
@ -352,10 +352,6 @@ Address: %4
<source>Amount</source> <source>Amount</source>
<translation>Колькасць</translation> <translation>Колькасць</translation>
</message> </message>
<message>
<source>Address</source>
<translation>Адрас</translation>
</message>
<message> <message>
<source>Date</source> <source>Date</source>
<translation>Дата</translation> <translation>Дата</translation>

View file

@ -1,4 +1,4 @@
<TS language="bg" version="2.1"> <TS language="bg" version="2.0">
<context> <context>
<name>AddressBookPage</name> <name>AddressBookPage</name>
<message> <message>
@ -364,10 +364,6 @@
<source>Amount</source> <source>Amount</source>
<translation>Сума</translation> <translation>Сума</translation>
</message> </message>
<message>
<source>Address</source>
<translation>Адрес</translation>
</message>
<message> <message>
<source>Date</source> <source>Date</source>
<translation>Дата</translation> <translation>Дата</translation>
@ -510,10 +506,6 @@
<source>&amp;Main</source> <source>&amp;Main</source>
<translation>&amp;Основни</translation> <translation>&amp;Основни</translation>
</message> </message>
<message>
<source>Pay transaction &amp;fee</source>
<translation>&amp;Такса за изходяща трансакция</translation>
</message>
<message> <message>
<source>&amp;Start Bitcoin on system login</source> <source>&amp;Start Bitcoin on system login</source>
<translation>&amp;Пускане на Биткоин при вход в системата</translation> <translation>&amp;Пускане на Биткоин при вход в системата</translation>

View file

@ -1,4 +1,4 @@
<TS language="bs" version="2.1"> <TS language="bs" version="2.0">
<context> <context>
<name>AddressBookPage</name> <name>AddressBookPage</name>
</context> </context>

View file

@ -1,4 +1,4 @@
<TS language="ca" version="2.1"> <TS language="ca" version="2.0">
<context> <context>
<name>AddressBookPage</name> <name>AddressBookPage</name>
<message> <message>
@ -516,10 +516,6 @@ Address: %4
</context> </context>
<context> <context>
<name>CoinControlDialog</name> <name>CoinControlDialog</name>
<message>
<source>Coin Control Address Selection</source>
<translation>Selecció de l'adreça de control de monedes</translation>
</message>
<message> <message>
<source>Quantity:</source> <source>Quantity:</source>
<translation>Quantitat:</translation> <translation>Quantitat:</translation>
@ -568,10 +564,6 @@ Address: %4
<source>Amount</source> <source>Amount</source>
<translation>Quantitat</translation> <translation>Quantitat</translation>
</message> </message>
<message>
<source>Address</source>
<translation>Adreça</translation>
</message>
<message> <message>
<source>Date</source> <source>Date</source>
<translation>Data</translation> <translation>Data</translation>
@ -938,14 +930,6 @@ Address: %4
<source>&amp;Main</source> <source>&amp;Main</source>
<translation>&amp;Principal</translation> <translation>&amp;Principal</translation>
</message> </message>
<message>
<source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source>
<translation>Comissió opcional de transacció per kB que ajuda a assegurar que les transaccions es processen ràpidament. La majoria de transaccions són d'1 kB.</translation>
</message>
<message>
<source>Pay transaction &amp;fee</source>
<translation>Paga &amp;comissió de transacció</translation>
</message>
<message> <message>
<source>Automatically start Bitcoin after logging in to the system.</source> <source>Automatically start Bitcoin after logging in to the system.</source>
<translation>Inicia automàticament el Bitcoin després de l'inici de sessió del sistema.</translation> <translation>Inicia automàticament el Bitcoin després de l'inici de sessió del sistema.</translation>
@ -974,14 +958,6 @@ Address: %4
<source>Allow incoming connections</source> <source>Allow incoming connections</source>
<translation>Permet connexions entrants</translation> <translation>Permet connexions entrants</translation>
</message> </message>
<message>
<source>Connect to the Bitcoin network through a SOCKS proxy.</source>
<translation>Connecta a la xarxa Bitcoin a través d'un proxy SOCKS.</translation>
</message>
<message>
<source>&amp;Connect through SOCKS proxy (default proxy):</source>
<translation>&amp;Connecta a través d'un proxy SOCKS (proxy per defecte):</translation>
</message>
<message> <message>
<source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
<translation>Adreça IP del proxy (p. ex. IPv4: 127.0.0.1 / IPv6: ::1)</translation> <translation>Adreça IP del proxy (p. ex. IPv4: 127.0.0.1 / IPv6: ::1)</translation>
@ -2929,10 +2905,6 @@ per exemple: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com
<source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source> <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
<translation>Crea fitxers nous amb els permisos per defecte del sistema, en comptes de l'umask 077 (només efectiu amb la funcionalitat de moneder inhabilitada)</translation> <translation>Crea fitxers nous amb els permisos per defecte del sistema, en comptes de l'umask 077 (només efectiu amb la funcionalitat de moneder inhabilitada)</translation>
</message> </message>
<message>
<source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</source>
<translation>Distribuït sota la llicència de programari MIT/X11. Vegeu el fitxer acompanyant COPYING o &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</translation>
</message>
<message> <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source> <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Error: ha fallat escoltar les connexions entrants (l'escoltament ha retornat l'error %s)</translation> <translation>Error: ha fallat escoltar les connexions entrants (l'escoltament ha retornat l'error %s)</translation>

View file

@ -1,4 +1,4 @@
<TS language="ca@valencia" version="2.1"> <TS language="ca@valencia" version="2.0">
<context> <context>
<name>AddressBookPage</name> <name>AddressBookPage</name>
<message> <message>
@ -496,10 +496,6 @@ Address: %4
</context> </context>
<context> <context>
<name>CoinControlDialog</name> <name>CoinControlDialog</name>
<message>
<source>Coin Control Address Selection</source>
<translation>Selecció de l'adreça de control de monedes</translation>
</message>
<message> <message>
<source>Quantity:</source> <source>Quantity:</source>
<translation>Quantitat:</translation> <translation>Quantitat:</translation>
@ -548,10 +544,6 @@ Address: %4
<source>Amount</source> <source>Amount</source>
<translation>Quantitat</translation> <translation>Quantitat</translation>
</message> </message>
<message>
<source>Address</source>
<translation>Adreça</translation>
</message>
<message> <message>
<source>Date</source> <source>Date</source>
<translation>Data</translation> <translation>Data</translation>
@ -918,14 +910,6 @@ Address: %4
<source>&amp;Main</source> <source>&amp;Main</source>
<translation>&amp;Principal</translation> <translation>&amp;Principal</translation>
</message> </message>
<message>
<source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source>
<translation>Comissió opcional de transacció per kB que ajuda a assegurar que les transaccions es processen ràpidament. La majoria de transaccions són d'1 kB.</translation>
</message>
<message>
<source>Pay transaction &amp;fee</source>
<translation>Paga &amp;comissió de transacció</translation>
</message>
<message> <message>
<source>Automatically start Bitcoin after logging in to the system.</source> <source>Automatically start Bitcoin after logging in to the system.</source>
<translation>Inicia automàticament el Bitcoin després de l'inici de sessió del sistema.</translation> <translation>Inicia automàticament el Bitcoin després de l'inici de sessió del sistema.</translation>
@ -954,14 +938,6 @@ Address: %4
<source>Allow incoming connections</source> <source>Allow incoming connections</source>
<translation>Permet connexions entrants</translation> <translation>Permet connexions entrants</translation>
</message> </message>
<message>
<source>Connect to the Bitcoin network through a SOCKS proxy.</source>
<translation>Connecta a la xarxa Bitcoin a través d'un proxy SOCKS.</translation>
</message>
<message>
<source>&amp;Connect through SOCKS proxy (default proxy):</source>
<translation>&amp;Connecta a través d'un proxy SOCKS (proxy per defecte):</translation>
</message>
<message> <message>
<source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
<translation>Adreça IP del proxy (p. ex. IPv4: 127.0.0.1 / IPv6: ::1)</translation> <translation>Adreça IP del proxy (p. ex. IPv4: 127.0.0.1 / IPv6: ::1)</translation>
@ -2893,10 +2869,6 @@ per exemple: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com
<source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source> <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
<translation>Crea fitxers nous amb els permisos per defecte del sistema, en comptes de l'umask 077 (només efectiu amb la funcionalitat de moneder inhabilitada)</translation> <translation>Crea fitxers nous amb els permisos per defecte del sistema, en comptes de l'umask 077 (només efectiu amb la funcionalitat de moneder inhabilitada)</translation>
</message> </message>
<message>
<source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</source>
<translation>Distribuït sota la llicència de programari MIT/X11. Vegeu el fitxer acompanyant COPYING o &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</translation>
</message>
<message> <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source> <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Error: ha fallat escoltar les connexions entrants (l'escoltament ha retornat l'error %s)</translation> <translation>Error: ha fallat escoltar les connexions entrants (l'escoltament ha retornat l'error %s)</translation>

View file

@ -1,4 +1,4 @@
<TS language="ca_ES" version="2.1"> <TS language="ca_ES" version="2.0">
<context> <context>
<name>AddressBookPage</name> <name>AddressBookPage</name>
<message> <message>
@ -516,10 +516,6 @@ Address: %4
</context> </context>
<context> <context>
<name>CoinControlDialog</name> <name>CoinControlDialog</name>
<message>
<source>Coin Control Address Selection</source>
<translation>Selecció de l'adreça de control de monedes</translation>
</message>
<message> <message>
<source>Quantity:</source> <source>Quantity:</source>
<translation>Quantitat:</translation> <translation>Quantitat:</translation>
@ -568,10 +564,6 @@ Address: %4
<source>Amount</source> <source>Amount</source>
<translation>Quantitat</translation> <translation>Quantitat</translation>
</message> </message>
<message>
<source>Address</source>
<translation>Adreça</translation>
</message>
<message> <message>
<source>Date</source> <source>Date</source>
<translation>Data</translation> <translation>Data</translation>
@ -938,14 +930,6 @@ Address: %4
<source>&amp;Main</source> <source>&amp;Main</source>
<translation>&amp;Principal</translation> <translation>&amp;Principal</translation>
</message> </message>
<message>
<source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source>
<translation>Comissió opcional de transacció per kB que ajuda a assegurar que les transaccions es processen ràpidament. La majoria de transaccions són d'1 kB.</translation>
</message>
<message>
<source>Pay transaction &amp;fee</source>
<translation>Paga &amp;comissió de transacció</translation>
</message>
<message> <message>
<source>Automatically start Bitcoin after logging in to the system.</source> <source>Automatically start Bitcoin after logging in to the system.</source>
<translation>Inicia automàticament el Bitcoin després de l'inici de sessió del sistema.</translation> <translation>Inicia automàticament el Bitcoin després de l'inici de sessió del sistema.</translation>
@ -974,14 +958,6 @@ Address: %4
<source>Allow incoming connections</source> <source>Allow incoming connections</source>
<translation>Permet connexions entrants</translation> <translation>Permet connexions entrants</translation>
</message> </message>
<message>
<source>Connect to the Bitcoin network through a SOCKS proxy.</source>
<translation>Connecta a la xarxa Bitcoin a través d'un proxy SOCKS.</translation>
</message>
<message>
<source>&amp;Connect through SOCKS proxy (default proxy):</source>
<translation>&amp;Connecta a través d'un proxy SOCKS (proxy per defecte):</translation>
</message>
<message> <message>
<source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
<translation>Adreça IP del proxy (p. ex. IPv4: 127.0.0.1 / IPv6: ::1)</translation> <translation>Adreça IP del proxy (p. ex. IPv4: 127.0.0.1 / IPv6: ::1)</translation>
@ -2929,10 +2905,6 @@ per exemple: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com
<source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source> <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
<translation>Crea fitxers nous amb els permisos per defecte del sistema, en comptes de l'umask 077 (només efectiu amb la funcionalitat de moneder inhabilitada)</translation> <translation>Crea fitxers nous amb els permisos per defecte del sistema, en comptes de l'umask 077 (només efectiu amb la funcionalitat de moneder inhabilitada)</translation>
</message> </message>
<message>
<source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</source>
<translation>Distribuït sota la llicència de programari MIT/X11. Vegeu el fitxer acompanyant COPYING o &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</translation>
</message>
<message> <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source> <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Error: ha fallat escoltar les connexions entrants (l'escoltament ha retornat l'error %s)</translation> <translation>Error: ha fallat escoltar les connexions entrants (l'escoltament ha retornat l'error %s)</translation>

View file

@ -1,4 +1,4 @@
<TS language="cmn" version="2.1"> <TS language="cmn" version="2.0">
<context> <context>
<name>AddressBookPage</name> <name>AddressBookPage</name>
</context> </context>

View file

@ -1,4 +1,4 @@
<TS language="cs" version="2.1"> <TS language="cs" version="2.0">
<context> <context>
<name>AddressBookPage</name> <name>AddressBookPage</name>
<message> <message>
@ -504,10 +504,6 @@ Adresa: %4
</context> </context>
<context> <context>
<name>CoinControlDialog</name> <name>CoinControlDialog</name>
<message>
<source>Coin Control Address Selection</source>
<translation>Volba adres v rámci ruční správy mincí</translation>
</message>
<message> <message>
<source>Quantity:</source> <source>Quantity:</source>
<translation>Počet:</translation> <translation>Počet:</translation>
@ -556,10 +552,6 @@ Adresa: %4
<source>Amount</source> <source>Amount</source>
<translation>Částka</translation> <translation>Částka</translation>
</message> </message>
<message>
<source>Address</source>
<translation>Adresa</translation>
</message>
<message> <message>
<source>Date</source> <source>Date</source>
<translation>Datum</translation> <translation>Datum</translation>
@ -926,14 +918,6 @@ Adresa: %4
<source>&amp;Main</source> <source>&amp;Main</source>
<translation>&amp;Hlavní</translation> <translation>&amp;Hlavní</translation>
</message> </message>
<message>
<source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source>
<translation>Dobrovolný transakční poplatek za každý započatý kB dopomáhá k rychlému zpracování tvých transakcí. Většina transakcí do 1 kB.</translation>
</message>
<message>
<source>Pay transaction &amp;fee</source>
<translation>Platit &amp;transakční poplatek</translation>
</message>
<message> <message>
<source>Automatically start Bitcoin after logging in to the system.</source> <source>Automatically start Bitcoin after logging in to the system.</source>
<translation>Automaticky spustí Bitcoin po přihlášení do systému.</translation> <translation>Automaticky spustí Bitcoin po přihlášení do systému.</translation>
@ -962,14 +946,6 @@ Adresa: %4
<source>Allow incoming connections</source> <source>Allow incoming connections</source>
<translation>Přijímat příchozí spojení</translation> <translation>Přijímat příchozí spojení</translation>
</message> </message>
<message>
<source>Connect to the Bitcoin network through a SOCKS proxy.</source>
<translation>Připojí se do Bitcoinové sítě přes SOCKS proxy.</translation>
</message>
<message>
<source>&amp;Connect through SOCKS proxy (default proxy):</source>
<translation>&amp;Připojit přes SOCKS proxy (výchozí proxy):</translation>
</message>
<message> <message>
<source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
<translation>IP adresa proxy (např. IPv4: 127.0.0.1/IPv6: ::1)</translation> <translation>IP adresa proxy (např. IPv4: 127.0.0.1/IPv6: ::1)</translation>
@ -2918,10 +2894,6 @@ například: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com
<source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source> <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
<translation>Vytvářet nové soubory s výchozími systémovými právy namísto umask 077 (uplatní se, pouze pokud je vypnutá funkce peněženky)</translation> <translation>Vytvářet nové soubory s výchozími systémovými právy namísto umask 077 (uplatní se, pouze pokud je vypnutá funkce peněženky)</translation>
</message> </message>
<message>
<source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</source>
<translation>Šířen pod licencí MIT/X11, viz přiložený soubor COPYING nebo &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</translation>
</message>
<message> <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source> <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Chyba: Nelze naslouchat příchozí spojení (listen vrátil chybu %s)</translation> <translation>Chyba: Nelze naslouchat příchozí spojení (listen vrátil chybu %s)</translation>

View file

@ -1,4 +1,4 @@
<TS language="cy" version="2.1"> <TS language="cy" version="2.0">
<context> <context>
<name>AddressBookPage</name> <name>AddressBookPage</name>
<message> <message>
@ -196,10 +196,6 @@
</context> </context>
<context> <context>
<name>CoinControlDialog</name> <name>CoinControlDialog</name>
<message>
<source>Address</source>
<translation>Cyfeiriad</translation>
</message>
<message> <message>
<source>Date</source> <source>Date</source>
<translation>Dyddiad</translation> <translation>Dyddiad</translation>

View file

@ -1,4 +1,4 @@
<TS language="da" version="2.1"> <TS language="da" version="2.0">
<context> <context>
<name>AddressBookPage</name> <name>AddressBookPage</name>
<message> <message>
@ -525,8 +525,8 @@ Adresse: %4
<context> <context>
<name>CoinControlDialog</name> <name>CoinControlDialog</name>
<message> <message>
<source>Coin Control Address Selection</source> <source>Coin Selection</source>
<translation>Adressevalg for coin-styring</translation> <translation>Coin-styring</translation>
</message> </message>
<message> <message>
<source>Quantity:</source> <source>Quantity:</source>
@ -577,8 +577,12 @@ Adresse: %4
<translation>Beløb</translation> <translation>Beløb</translation>
</message> </message>
<message> <message>
<source>Address</source> <source>Received with label</source>
<translation>Adresse</translation> <translation>Modtaget med mærke</translation>
</message>
<message>
<source>Received with address</source>
<translation>Modtaget med adresse</translation>
</message> </message>
<message> <message>
<source>Date</source> <source>Date</source>
@ -950,14 +954,6 @@ Adresse: %4
<source>&amp;Main</source> <source>&amp;Main</source>
<translation>&amp;Generelt</translation> <translation>&amp;Generelt</translation>
</message> </message>
<message>
<source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source>
<translation>Valgfrit transaktionsgebyr pr. kB, der hjælper dine transaktioner med at blive behandlet hurtigt. De fleste transaktioner er 1 kB.</translation>
</message>
<message>
<source>Pay transaction &amp;fee</source>
<translation>Betal transaktions&amp;gebyr</translation>
</message>
<message> <message>
<source>Automatically start Bitcoin after logging in to the system.</source> <source>Automatically start Bitcoin after logging in to the system.</source>
<translation>Start Bitcoin automatisk, når der logges ind systemet.</translation> <translation>Start Bitcoin automatisk, når der logges ind systemet.</translation>
@ -986,14 +982,6 @@ Adresse: %4
<source>Allow incoming connections</source> <source>Allow incoming connections</source>
<translation>Tillad indkommende forbindelser</translation> <translation>Tillad indkommende forbindelser</translation>
</message> </message>
<message>
<source>Connect to the Bitcoin network through a SOCKS proxy.</source>
<translation>Forbind til Bitcoin-netværket gennem en SOCKS-proxy.</translation>
</message>
<message>
<source>&amp;Connect through SOCKS proxy (default proxy):</source>
<translation>&amp;Forbind gennem SOCKS-proxy (standard-proxy):</translation>
</message>
<message> <message>
<source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
<translation>IP-adresse for proxyen (fx IPv4: 127.0.0.1 / IPv6: ::1)</translation> <translation>IP-adresse for proxyen (fx IPv4: 127.0.0.1 / IPv6: ::1)</translation>
@ -1054,6 +1042,14 @@ Adresse: %4
<source>Map port using &amp;UPnP</source> <source>Map port using &amp;UPnP</source>
<translation>Konfigurér port vha. &amp;UPnP</translation> <translation>Konfigurér port vha. &amp;UPnP</translation>
</message> </message>
<message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>Forbind til Bitcoin-netværket gennem en SOCKS5-proxy.</translation>
</message>
<message>
<source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
<translation>&amp;Forbind gennem SOCKS5-proxy (standard-proxy):</translation>
</message>
<message> <message>
<source>Proxy &amp;IP:</source> <source>Proxy &amp;IP:</source>
<translation>Proxy-&amp;IP:</translation> <translation>Proxy-&amp;IP:</translation>
@ -1844,6 +1840,78 @@ Adresse: %4
<source>Custom change address</source> <source>Custom change address</source>
<translation>Tilpasset byttepengeadresse</translation> <translation>Tilpasset byttepengeadresse</translation>
</message> </message>
<message>
<source>Transaction Fee:</source>
<translation>Transaktionsgebyr:</translation>
</message>
<message>
<source>Choose...</source>
<translation>Vælg </translation>
</message>
<message>
<source>collapse fee-settings</source>
<translation>sammenfold gebyropsætning</translation>
</message>
<message>
<source>Minimize</source>
<translation>Minimér</translation>
</message>
<message>
<source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
<translation>Hvis det brugertilpassede gebyr er sat til 1000 satoshis, og transaktionen kun fylder 250 byte, betaler "pr. kilobyte" kun 250 satoshis i gebyr, mens "mindst" betaler 1000 satoshis. For transaktioner større end en kilobyte betaler begge pr. kilobyte.</translation>
</message>
<message>
<source>per kilobyte</source>
<translation>pr. kilobyte</translation>
</message>
<message>
<source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
<translation>Hvis det brugertilpassede gebyr er sat til 1000 satoshis, og transaktionen kun fylder 250 byte, betaler "pr. kilobyte" kun 250 satoshis i gebyr, mens "total mindst" betaler 1000 satoshis. For transaktioner større end en kilobyte betaler begge pr. kilobyte.</translation>
</message>
<message>
<source>total at least</source>
<translation>total mindst</translation>
</message>
<message>
<source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
<translation>Det er helt fint kun at betale det minimale gebyr, længe den totale transaktionsvolumen er mindre end den plads, der er tilgængelig i blokkene. Men vær opmærksom , at dette kan ende ud i transaktioner, der aldrig bliver bekræftet, når der bliver større forespørgsel efter bitcoin-transaktioner, end hvad netværket kan bearbejde.</translation>
</message>
<message>
<source>(read the tooltip)</source>
<translation>(læs værktøjstippet)</translation>
</message>
<message>
<source>Recommended:</source>
<translation>Anbefalet:</translation>
</message>
<message>
<source>Custom:</source>
<translation>Brugertilpasset:</translation>
</message>
<message>
<source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
<translation>(Smart-gebyr er ikke initialiseret endnu. Dette tager typisk nogle blokke )</translation>
</message>
<message>
<source>Confirmation time:</source>
<translation>Bekræftelsestid:</translation>
</message>
<message>
<source>normal</source>
<translation>normal</translation>
</message>
<message>
<source>fast</source>
<translation>hurtig</translation>
</message>
<message>
<source>Send as zero-fee transaction if possible</source>
<translation>Send som nul-gebyr-transaktion hvis muligt</translation>
</message>
<message>
<source>(confirmation may take longer)</source>
<translation>(bekræftelse kan tage længere)</translation>
</message>
<message> <message>
<source>Send to multiple recipients at once</source> <source>Send to multiple recipients at once</source>
<translation>Send til flere modtagere en gang</translation> <translation>Send til flere modtagere en gang</translation>
@ -1948,6 +2016,18 @@ Adresse: %4
<source>The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.</source> <source>The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.</source>
<translation>Transaktionen blev afvist! Dette kan ske, hvis nogle af dine bitcoins i din tegnebog allerede er brugt, som hvis du brugte en kopi af wallet.dat og dine bitcoins er blevet brugt i kopien, men ikke er markeret som brugt her.</translation> <translation>Transaktionen blev afvist! Dette kan ske, hvis nogle af dine bitcoins i din tegnebog allerede er brugt, som hvis du brugte en kopi af wallet.dat og dine bitcoins er blevet brugt i kopien, men ikke er markeret som brugt her.</translation>
</message> </message>
<message>
<source>A fee higher than %1 is considered an insanely high fee.</source>
<translation>Et gebyr højere end %1 anses som et vanvittigt højt gebyr.</translation>
</message>
<message>
<source>Pay only the minimum fee of %1</source>
<translation>Betal kun det minimale gebyr %1</translation>
</message>
<message>
<source>Estimated to begin confirmation within %1 block(s).</source>
<translation>Bekræftelse vurderes at begynde inden for %1 blok(ke).</translation>
</message>
<message> <message>
<source>Warning: Invalid Bitcoin address</source> <source>Warning: Invalid Bitcoin address</source>
<translation>Advarsel: Ugyldig Bitcoin-adresse</translation> <translation>Advarsel: Ugyldig Bitcoin-adresse</translation>
@ -2754,6 +2834,10 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com
<source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source> <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
<translation>Slet alle transaktioner i tegnebogen og genskab kun disse dele af blokkæden gennem -rescan under opstart</translation> <translation>Slet alle transaktioner i tegnebogen og genskab kun disse dele af blokkæden gennem -rescan under opstart</translation>
</message> </message>
<message>
<source>Distributed under the MIT software license, see the accompanying file COPYING or &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</source>
<translation>Distribueret under MIT-softwarelicensen; se den vedlagte fil COPYING eller &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</translation>
</message>
<message> <message>
<source>Enter regression test mode, which uses a special chain in which blocks can be solved instantly.</source> <source>Enter regression test mode, which uses a special chain in which blocks can be solved instantly.</source>
<translation>Start regressionstesttilstand, som bruger en speciel kæde, hvor blokke kan løses med det samme.</translation> <translation>Start regressionstesttilstand, som bruger en speciel kæde, hvor blokke kan løses med det samme.</translation>
@ -2986,10 +3070,6 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com
<source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source> <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
<translation>Opret nye filer med systemstandard for rettigheder i stedet for umask 077 (kun virksomt med tegnebogsfunktionalitet slået fra)</translation> <translation>Opret nye filer med systemstandard for rettigheder i stedet for umask 077 (kun virksomt med tegnebogsfunktionalitet slået fra)</translation>
</message> </message>
<message>
<source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</source>
<translation>Distribueret under MIT/X11-softwarelicensen. Se medfølgende fil COPYING eller &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</translation>
</message>
<message> <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source> <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Fejl: Lytning efter indkommende forbindelser mislykkedes (lytning resultarede i fejl %s)</translation> <translation>Fejl: Lytning efter indkommende forbindelser mislykkedes (lytning resultarede i fejl %s)</translation>
@ -3010,6 +3090,10 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com
<source>Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)</source> <source>Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)</source>
<translation>Gebyrer (i BTC/Kb) mindre end dette opfattes som nulgebyr for oprettelse af transaktion (standard: %s)</translation> <translation>Gebyrer (i BTC/Kb) mindre end dette opfattes som nulgebyr for oprettelse af transaktion (standard: %s)</translation>
</message> </message>
<message>
<source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
<translation>Maksimal størrelse data i transaktioner til dataoverførsel, som vi videresender og miner (standard: %u)</translation>
</message>
<message> <message>
<source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)</source> <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)</source>
<translation>Forespørgsel</translation> <translation>Forespørgsel</translation>
@ -3018,6 +3102,10 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com
<source>Set maximum size of high-priority/low-fee transactions in bytes (default: %d)</source> <source>Set maximum size of high-priority/low-fee transactions in bytes (default: %d)</source>
<translation>Sæt maksimumstørrelse for højprioritet/lavgebyr-transaktioner i byte (standard: %d)</translation> <translation>Sæt maksimumstørrelse for højprioritet/lavgebyr-transaktioner i byte (standard: %d)</translation>
</message> </message>
<message>
<source>Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)</source>
<translation>Sæt antaller af tråde for coin-generering, hvis aktiveret (-1 = alle kerner, standard: %d)</translation>
</message>
<message> <message>
<source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit &lt;https://www.openssl.org/&gt; and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source> <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit &lt;https://www.openssl.org/&gt; and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
<translation>Dette produkt indeholder software, der er udviklet af OpenSSL-projektet for brug i OpenSSL-værktøjskassen &lt;https://www.openssl.org/&gt;, samt kryptografisk software, der er skrevet af Eric Young, samt UPnP-software, der er skrevet af Thomas Bernard.</translation> <translation>Dette produkt indeholder software, der er udviklet af OpenSSL-projektet for brug i OpenSSL-værktøjskassen &lt;https://www.openssl.org/&gt;, samt kryptografisk software, der er skrevet af Eric Young, samt UPnP-software, der er skrevet af Thomas Bernard.</translation>
@ -3122,6 +3210,10 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com
<source>Send trace/debug info to console instead of debug.log file</source> <source>Send trace/debug info to console instead of debug.log file</source>
<translation>Send sporings-/fejlsøgningsinformation til konsollen i stedet for debug.log filen</translation> <translation>Send sporings-/fejlsøgningsinformation til konsollen i stedet for debug.log filen</translation>
</message> </message>
<message>
<source>Send transactions as zero-fee transactions if possible (default: %u)</source>
<translation>Send transaktioner som nul-gebyr-transaktioner hvis muligt (standard: %u)</translation>
</message>
<message> <message>
<source>Show all debugging options (usage: --help -help-debug)</source> <source>Show all debugging options (usage: --help -help-debug)</source>
<translation>Vis alle tilvalg for fejlsøgning (brug: --help -help-debug)</translation> <translation>Vis alle tilvalg for fejlsøgning (brug: --help -help-debug)</translation>
@ -3262,10 +3354,6 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com
<source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source> <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
<translation>Udskriv fejlsøgningsinformation (standard: %u, angivelse af &lt;kategori&gt; er valgfri)</translation> <translation>Udskriv fejlsøgningsinformation (standard: %u, angivelse af &lt;kategori&gt; er valgfri)</translation>
</message> </message>
<message>
<source>Set the processor limit for when generation is on (-1 = unlimited, default: %d)</source>
<translation>Sæt processorbegrænsning for når generering er slået til (-1 = ubegrænset, standard: %d)</translation>
</message>
<message> <message>
<source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source> <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
<translation>Brug separat SOCS5-proxy for at andre knuder via Tor skjulte tjenester (standard: %s)</translation> <translation>Brug separat SOCS5-proxy for at andre knuder via Tor skjulte tjenester (standard: %s)</translation>

Some files were not shown because too many files have changed in this diff Show more