diff options
43 files changed, 888 insertions, 268 deletions
diff --git a/configure.ac b/configure.ac index 88c20cdce..973f4398d 100644 --- a/configure.ac +++ b/configure.ac @@ -24,6 +24,12 @@ m4_include([pkg.m4]) dnl faketime breaks configure and is only needed for make. Disable it here. unset FAKETIME +if test "x${CXXFLAGS+set}" = "xset"; then + CXXFLAGS_overridden=yes +else + CXXFLAGS_overridden=no +fi + dnl ============================================================== dnl Setup for automake dnl ============================================================== @@ -92,7 +98,7 @@ AC_ARG_ENABLE([hardening], AC_ARG_ENABLE([ccache], [AS_HELP_STRING([--enable-ccache], - [enable building with ccache (default is yes if ccache is found)])], + [use ccache for building (default is yes if ccache is found)])], [use_ccache=$enableval], [use_ccache=auto]) @@ -134,7 +140,9 @@ PKG_PROG_PKG_CONFIG ## TODO: Remove these hard-coded paths and flags. They are here for the sake of ## compatibility with the legacy buildsystem. ## -CXXFLAGS="$CXXFLAGS -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter" +if test "x$CXXFLAGS_overridden" = "xno"; then + CXXFLAGS="$CXXFLAGS -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter" +fi CPPFLAGS="$CPPFLAGS -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS" AC_LANG_PUSH([C++]) @@ -182,7 +190,9 @@ case $host in CPPFLAGS="$CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -D__USE_MINGW_ANSI_STDIO" LEVELDB_TARGET_FLAGS="TARGET_OS=OS_WINDOWS_CROSSCOMPILE" - CXXFLAGS="$CXXFLAGS -w" + if test "x$CXXFLAGS_overridden" = "xno"; then + CXXFLAGS="$CXXFLAGS -w" + fi ;; *darwin*) TARGET_OS=darwin @@ -207,10 +217,8 @@ case $host in fi CPPFLAGS="$CPPFLAGS -DMAC_OSX" - TESTDEFS="-DBOOST_TEST_DYN_LINK" ;; *) - TESTDEFS="-DBOOST_TEST_DYN_LINK" ;; esac @@ -278,7 +286,12 @@ if test x$use_hardening != xno; then AX_CHECK_COMPILE_FLAG([-Wstack-protector],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -Wstack-protector"]) AX_CHECK_COMPILE_FLAG([-fPIE],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fPIE"]) - AX_CHECK_PREPROC_FLAG([-D_FORTIFY_SOURCE=2],[HARDENED_CPPFLAGS="$HARDENED_CPPFLAGS -D_FORTIFY_SOURCE=2"]) + AX_CHECK_PREPROC_FLAG([-D_FORTIFY_SOURCE=2],[ + AX_CHECK_PREPROC_FLAG([-U_FORTIFY_SOURCE],[ + HARDENED_CPPFLAGS="$HARDENED_CPPFLAGS -U_FORTIFY_SOURCE" + ]) + HARDENED_CPPFLAGS="$HARDENED_CPPFLAGS -D_FORTIFY_SOURCE=2" + ]) AX_CHECK_LINK_FLAG([[-Wl,--dynamicbase]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--dynamicbase"]) AX_CHECK_LINK_FLAG([[-Wl,--nxcompat]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--nxcompat"]) @@ -315,6 +328,14 @@ AC_TRY_COMPILE([#include <sys/socket.h>], [ AC_MSG_RESULT(no)] ) +LEVELDB_CPPFLAGS= +LIBLEVELDB= +LIBMEMENV= +AM_CONDITIONAL([EMBEDDED_LEVELDB],[true]) +AC_SUBST(LEVELDB_CPPFLAGS) +AC_SUBST(LIBLEVELDB) +AC_SUBST(LIBMEMENV) + if test x$enable_wallet != xno; then dnl Check for libdb_cxx only if wallet enabled BITCOIN_FIND_BDB48 @@ -345,6 +366,24 @@ if test x$use_tests = xyes; then AX_BOOST_UNIT_TEST_FRAMEWORK + + dnl Determine if -DBOOST_TEST_DYN_LINK is needed + AC_MSG_CHECKING([for dynamic linked boost test]) + TEMP_LIBS="$LIBS" + LIBS="$LIBS $BOOST_UNIT_TEST_FRAMEWORK_LIB" + TEMP_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" + AC_LINK_IFELSE([AC_LANG_SOURCE([ + #define BOOST_TEST_DYN_LINK + #define BOOST_TEST_MAIN + #include <boost/test/unit_test.hpp> + + ])], + [AC_MSG_RESULT(yes)] + [TESTDEFS="$TESTDEFS -DBOOST_TEST_DYN_LINK"], + [AC_MSG_RESULT(no)]) + LIBS="$TEMP_LIBS" + CPPFLAGS="$TEMP_CPPFLAGS" fi BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_PROGRAM_OPTIONS_LIB $BOOST_THREAD_LIB" @@ -357,8 +396,13 @@ dnl after 1.56. dnl If neither is available, abort. dnl If sleep_for is used, boost_chrono becomes a requirement. if test x$ax_cv_boost_chrono = xyes; then +dnl Allow passing extra needed dependency libraries for boost-chrono from static gitian build +BOOST_CHRONO_LIB="$BOOST_CHRONO_LIB $BOOST_CHRONO_EXTRALIBS" + TEMP_LIBS="$LIBS" LIBS="$LIBS $BOOST_LIBS $BOOST_CHRONO_LIB" +TEMP_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" AC_TRY_LINK([ #include <boost/thread/thread.hpp> #include <boost/version.hpp> @@ -373,11 +417,14 @@ AC_TRY_LINK([ AC_DEFINE(HAVE_WORKING_BOOST_SLEEP_FOR, 1, [Define this symbol if boost sleep_for works])], [boost_sleep=no]) LIBS="$TEMP_LIBS" +CPPFLAGS="$TEMP_CPPFLAGS" fi if test x$boost_sleep != xyes; then TEMP_LIBS="$LIBS" LIBS="$LIBS $BOOST_LIBS" +TEMP_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" AC_TRY_LINK([ #include <boost/version.hpp> #include <boost/thread.hpp> @@ -392,12 +439,25 @@ AC_TRY_LINK([ [boost_sleep=yes; AC_DEFINE(HAVE_WORKING_BOOST_SLEEP, 1, [Define this symbol if boost sleep works])], [boost_sleep=no]) LIBS="$TEMP_LIBS" +CPPFLAGS="$TEMP_CPPFLAGS" fi if test x$boost_sleep != xyes; then AC_MSG_ERROR(No working boost sleep implementation found. If on ubuntu 13.10 with libboost1.54-all-dev remove libboost.1.54-all-dev and use libboost1.53-all-dev) fi +AC_ARG_WITH([cli], + [AS_HELP_STRING([--with-cli], + [with CLI (default is yes)])], + [build_bitcoin_cli=$withval], + [build_bitcoin_cli=yes]) + +AC_ARG_WITH([daemon], + [AS_HELP_STRING([--with-daemon], + [with daemon (default is yes)])], + [build_bitcoind=$withval], + [build_bitcoind=yes]) + BITCOIN_QT_INIT if test x$use_pkgconfig = xyes; then @@ -434,13 +494,21 @@ fi BITCOIN_QT_PATH_PROGS([PROTOC], [protoc],$protoc_bin_path) +AC_MSG_CHECKING([whether to build bitcoind]) +AM_CONDITIONAL([BUILD_BITCOIND], [test x$build_bitcoind = xyes]) +AC_MSG_RESULT($build_bitcoind) + +AC_MSG_CHECKING([whether to build bitcoin-cli]) +AM_CONDITIONAL([BUILD_BITCOIN_CLI], [test x$build_bitcoin_cli = xyes]) +AC_MSG_RESULT($build_bitcoin_cli) + dnl sets $bitcoin_enable_qt, $bitcoin_enable_qt_test, $bitcoin_enable_qt_dbus BITCOIN_QT_CONFIGURE([$use_pkgconfig], [qt4]) if test x$use_ipv6 = xyes; then dnl Check for ipv6 build requirements - AC_MSG_CHECKING(for IPV6 build support) + AC_MSG_CHECKING(for operating system IPv6 support) AC_TRY_LINK([ #if defined(_WINDOWS) #include <winsock2.h> @@ -455,18 +523,17 @@ if test x$use_ipv6 = xyes; then struct sockaddr_in6 addr; #endif int temp = socket(AF_INET6, SOCK_STREAM, 0);], - [AC_MSG_RESULT(yes); have_ipv6=yes; AC_DEFINE(HAVE_IPV6, 1, [Define this symbol if you have ipv6 build support])], + [AC_MSG_RESULT(yes); have_ipv6=yes; AC_DEFINE(HAVE_IPV6, 1, [Define this symbol if you have operating system IPv6 support])], [AC_MSG_RESULT(no)]; have_ipv6=no) fi AC_LANG_POP if test "x$use_ccache" != "xno"; then - AC_MSG_CHECKING(if ccache should be enabled) + AC_MSG_CHECKING(if ccache should be used) if test x$CCACHE = x; then if test "x$use_ccache" = "xyes"; then AC_MSG_ERROR([ccache not found.]); else - AC_MSG_NOTICE([ccache not found. Falling back to default CC]) use_ccache=no fi else @@ -488,32 +555,32 @@ else fi dnl enable ipv6 support -AC_MSG_CHECKING([if ipv6 should be enabled]) +AC_MSG_CHECKING([whether to build with support for IPv6]) if test x$have_ipv6 = xno; then if test x$use_ipv6 = xyes; then - AC_MSG_ERROR("ipv6 requested but cannot be built. use --disable-ipv6") + AC_MSG_ERROR([IPv6 requested, but cannot be built. use --disable-ipv6]) fi AC_MSG_RESULT(no) else if test x$use_ipv6 = xyes; then AC_MSG_RESULT(yes) - AC_DEFINE([USE_IPV6],[1],[Define if ipv6 support should be compiled in]) + AC_DEFINE([USE_IPV6],[1],[Define if IPv6 support should be compiled in]) else AC_MSG_RESULT(no) fi fi dnl enable upnp support -AC_MSG_CHECKING([if upnp should be enabled]) +AC_MSG_CHECKING([whether to build with support for UPnP]) if test x$have_miniupnpc = xno; then if test x$use_upnp = xyes; then - AC_MSG_ERROR("upnp requested but cannot be built. use --without-miniupnpc") + AC_MSG_ERROR("UPnP requested but cannot be built. use --without-miniupnpc") fi AC_MSG_RESULT(no) else if test x$use_upnp != xno; then AC_MSG_RESULT(yes) - AC_MSG_CHECKING([if upnp should be on by default]) + AC_MSG_CHECKING([whether to build with UPnP enabled by default]) use_upnp=yes upnp_setting=0 if test x$use_upnp_default != xno; then @@ -521,7 +588,7 @@ else upnp_setting=1 fi AC_MSG_RESULT($use_upnp_default) - AC_DEFINE_UNQUOTED([USE_UPNP],[$upnp_setting],[Define to 1 for upnp runtime support]) + AC_DEFINE_UNQUOTED([USE_UPNP],[$upnp_setting],[UPnP support not compiled if undefined, otherwise value (0 or 1) determines default state]) if test x$TARGET_OS = xwindows; then CPPFLAGS="$CPPFLAGS -DSTATICLIB" fi @@ -534,14 +601,14 @@ dnl these are only used when qt is enabled if test x$bitcoin_enable_qt != xno; then BUILD_QT=qt dnl enable dbus support - AC_MSG_CHECKING([if dbus should be enabled]) + AC_MSG_CHECKING([whether to build GUI with support for D-Bus]) if test x$bitcoin_enable_qt_dbus != xno; then AC_DEFINE([USE_DBUS],[1],[Define if dbus support should be compiled in]) fi AC_MSG_RESULT($bitcoin_enable_qt_dbus) dnl enable qr support - AC_MSG_CHECKING([if qr should be enabled]) + AC_MSG_CHECKING([whether to build GUI with support for QR codes]) if test x$have_qrencode = xno; then if test x$use_qr == xyes; then AC_MSG_ERROR("QR support requested but cannot be built. use --without-qrencode") @@ -561,16 +628,25 @@ if test x$bitcoin_enable_qt != xno; then AC_MSG_WARN("xgettext is required to update qt translations") fi - if test x$use_tests = xyes; then + AC_MSG_CHECKING([whether to build test_bitcoin-qt]) + if test x$use_tests$bitcoin_enable_qt_test = xyesyes; then + AC_MSG_RESULT([yes]) BUILD_TEST_QT="test" - if test x$bitcoin_enable_qt_test != xyes; then - AC_MSG_ERROR("QT Test lib not found. Use --disable-tests or --without-qt.") - fi + else + AC_MSG_RESULT([no]) fi fi +AC_MSG_CHECKING([whether to build test_bitcoin]) if test x$use_tests = xyes; then + AC_MSG_RESULT([yes]) BUILD_TEST="test" +else + AC_MSG_RESULT([no]) +fi + +if test "x$use_tests$build_bitcoind$use_qt" = "xnonono"; then + AC_MSG_ERROR([No targets! Please specify at least one of: --enable-cli --enable-daemon --enable-gui or --enable-tests]) fi AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin]) diff --git a/contrib/bitcoin-qt.pro b/contrib/bitcoin-qt.pro index 8bfa4a18a..3a72d10f4 100644 --- a/contrib/bitcoin-qt.pro +++ b/contrib/bitcoin-qt.pro @@ -4,6 +4,7 @@ FORMS += \ ../src/qt/forms/askpassphrasedialog.ui \ ../src/qt/forms/coincontroldialog.ui \ ../src/qt/forms/editaddressdialog.ui \ + ../src/qt/forms/helpmessagedialog.ui \ ../src/qt/forms/intro.ui \ ../src/qt/forms/openuridialog.ui \ ../src/qt/forms/optionsdialog.ui \ diff --git a/contrib/gitian-descriptors/boost-linux.yml b/contrib/gitian-descriptors/boost-linux.yml new file mode 100644 index 000000000..5d22294dd --- /dev/null +++ b/contrib/gitian-descriptors/boost-linux.yml @@ -0,0 +1,42 @@ +--- +name: "boost" +suites: +- "precise" +architectures: +- "i386" +- "amd64" +packages: +- "unzip" +- "pkg-config" +- "libtool" +- "faketime" +- "bsdmainutils" +- "zip" +reference_datetime: "2011-01-30 00:00:00" +remotes: [] +files: +- "boost_1_55_0.tar.bz2" +script: | + STAGING="$HOME/install" + export LIBRARY_PATH="$STAGING/lib" + # Input Integrity Check + echo "fff00023dd79486d444c8e29922f4072e1d451fc5a4d2b6075852ead7f2b7b52 boost_1_55_0.tar.bz2" | shasum -c + + mkdir -p "$STAGING" + tar xjf boost_1_55_0.tar.bz2 + cd boost_1_55_0 + GCCVERSION=$(g++ -E -dM $(mktemp --suffix=.h) | grep __VERSION__ | cut -d ' ' -f 3 | cut -d '"' -f 2) + # note: bjam with -d+2 reveals that -O3 is implied by default, no need to provide it in cxxflags + echo "using gcc : $GCCVERSION : g++ + : + <cxxflags>\"-frandom-seed=boost1 -fPIC\" + ;" > user-config.jam + + ./bootstrap.sh --without-icu + + ./bjam toolset=gcc threadapi=pthread threading=multi variant=release link=static runtime-link=shared --user-config=user-config.jam --without-mpi --without-python -sNO_BZIP2=1 --layout=tagged --build-type=complete --prefix="$STAGING" $MAKEOPTS install + + cd "$STAGING" + export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 + export FAKETIME=$REFERENCE_DATETIME + zip -r $OUTDIR/boost-linux${GBUILD_BITS}-1.55.0-gitian-r1.zip * diff --git a/contrib/gitian-descriptors/boost-win32.yml b/contrib/gitian-descriptors/boost-win32.yml index b14cd1f6c..55e74ce3e 100644 --- a/contrib/gitian-descriptors/boost-win32.yml +++ b/contrib/gitian-descriptors/boost-win32.yml @@ -16,7 +16,7 @@ files: - "boost-mingw-gas-cross-compile-2013-03-03.patch" script: | # Defines - INSTALLPREFIX="$OUTDIR/staging/boost" + INSTALLPREFIX="$HOME/install" HOST=i686-w64-mingw32 # Input Integrity Check echo "fff00023dd79486d444c8e29922f4072e1d451fc5a4d2b6075852ead7f2b7b52 boost_1_55_0.tar.bz2" | shasum -c @@ -57,10 +57,9 @@ script: | # Note: Might need these options in the future for 64bit builds. # "Please note that address-model=64 must be given to bjam command line on 64bit Windows for 64bit build; otherwise 32bit code will be generated." # "For cross-compiling the lib you must specify certain additional properties at bjam command line: target-os, abi, binary-format, architecture and address-model." - ./bjam toolset=gcc binary-format=pe target-os=windows threadapi=win32 threading=multi variant=release link=static --user-config=user-config.jam --without-mpi --without-python -sNO_BZIP2=1 -sNO_ZLIB=1 --layout=tagged --build-type=complete --prefix="$INSTALLPREFIX" $MAKEOPTS install + ./bjam toolset=gcc binary-format=pe target-os=windows threadapi=win32 threading=multi variant=release link=static runtime-link=static --user-config=user-config.jam --without-mpi --without-python -sNO_BZIP2=1 -sNO_ZLIB=1 --layout=tagged --build-type=complete --prefix="$INSTALLPREFIX" $MAKEOPTS install cd "$INSTALLPREFIX" export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 export FAKETIME=$REFERENCE_DATETIME - zip -r boost-win32-1.55.0-gitian-r6.zip * - cp boost-win32-1.55.0-gitian-r6.zip $OUTDIR + zip -r $OUTDIR/boost-win32-1.55.0-gitian-r6.zip * diff --git a/contrib/gitian-descriptors/deps-linux.yml b/contrib/gitian-descriptors/deps-linux.yml index 4ebf5c53a..41d8d65fb 100644 --- a/contrib/gitian-descriptors/deps-linux.yml +++ b/contrib/gitian-descriptors/deps-linux.yml @@ -15,6 +15,7 @@ packages: reference_datetime: "2013-06-01 00:00:00" remotes: [] files: +- "openssl-1.0.1e.tar.gz" - "miniupnpc-1.8.tar.gz" - "qrencode-3.4.3.tar.bz2" - "protobuf-2.5.0.tar.bz2" @@ -24,11 +25,21 @@ script: | OPTFLAGS='-O2' export LIBRARY_PATH="$STAGING/lib" # Integrity Check + echo "f74f15e8c8ff11aa3d5bb5f276d202ec18d7246e95f961db76054199c69c1ae3 openssl-1.0.1e.tar.gz" | sha256sum -c echo "bc5f73c7b0056252c1888a80e6075787a1e1e9112b808f863a245483ff79859c miniupnpc-1.8.tar.gz" | sha256sum -c echo "dfd71487513c871bad485806bfd1fdb304dedc84d2b01a8fb8e0940b50597a98 qrencode-3.4.3.tar.bz2" | sha256sum -c echo "13bfc5ae543cf3aa180ac2485c0bc89495e3ae711fc6fab4f8ffe90dfb4bb677 protobuf-2.5.0.tar.bz2" | sha256sum -c echo "12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz" | sha256sum -c + # + tar xzf openssl-1.0.1e.tar.gz + cd openssl-1.0.1e + # need -fPIC to avoid relocation error in 64 bit builds + ./config no-shared no-zlib no-dso no-krb5 --openssldir=$STAGING -fPIC + make + make install_sw + cd .. + # tar xzfm miniupnpc-1.8.tar.gz cd miniupnpc-1.8 # miniupnpc is always built with -fPIC @@ -60,4 +71,4 @@ script: | cd ../.. # cd $STAGING - zip -r $OUTDIR/bitcoin-deps-linux${GBUILD_BITS}-gitian-r1.zip include lib bin host + zip -r $OUTDIR/bitcoin-deps-linux${GBUILD_BITS}-gitian-r2.zip include lib bin host diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index b0fe86e25..417f31e27 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -6,14 +6,7 @@ architectures: - "i386" - "amd64" packages: -- "qt4-qmake" - "libqt4-dev" -- "libboost-system-dev" -- "libboost-filesystem-dev" -- "libboost-program-options-dev" -- "libboost-thread-dev" -- "libboost-test-dev" -- "libssl-dev" - "git-core" - "unzip" - "pkg-config" @@ -27,8 +20,10 @@ remotes: - "url": "https://github.com/bitcoin/bitcoin.git" "dir": "bitcoin" files: -- "bitcoin-deps-linux32-gitian-r1.zip" -- "bitcoin-deps-linux64-gitian-r1.zip" +- "bitcoin-deps-linux32-gitian-r2.zip" +- "bitcoin-deps-linux64-gitian-r2.zip" +- "boost-linux32-1.55.0-gitian-r1.zip" +- "boost-linux64-1.55.0-gitian-r1.zip" script: | STAGING="$HOME/install" OPTFLAGS='-O2' @@ -38,18 +33,19 @@ script: | # mkdir -p $STAGING cd $STAGING - unzip ../build/bitcoin-deps-linux${GBUILD_BITS}-gitian-r1.zip + unzip ../build/bitcoin-deps-linux${GBUILD_BITS}-gitian-r2.zip + unzip ../build/boost-linux${GBUILD_BITS}-1.55.0-gitian-r1.zip cd ../build # cd bitcoin export TAR_OPTIONS=--mtime=`echo $REFERENCE_DATETIME | awk '{ print $1 }'` ./autogen.sh - ./configure --prefix=$STAGING --bindir=$BINDIR --with-protoc-bindir=$STAGING/host/bin --disable-maintainer-mode --disable-dependency-tracking PKG_CONFIG_PATH="$STAGING/lib/pkgconfig" CPPFLAGS="-I$STAGING/include ${OPTFLAGS}" LDFLAGS="-L$STAGING/lib ${OPTFLAGS}" CXXFLAGS="-frandom-seed=bitcoin ${OPTFLAGS}" + ./configure --prefix=$STAGING --bindir=$BINDIR --with-protoc-bindir=$STAGING/host/bin --with-boost=$STAGING --disable-maintainer-mode --disable-dependency-tracking PKG_CONFIG_PATH="$STAGING/lib/pkgconfig" CPPFLAGS="-I$STAGING/include ${OPTFLAGS}" LDFLAGS="-L$STAGING/lib ${OPTFLAGS}" CXXFLAGS="-frandom-seed=bitcoin ${OPTFLAGS}" BOOST_CHRONO_EXTRALIBS="-lrt" make dist mkdir -p distsrc cd distsrc tar --strip-components=1 -xf ../bitcoin-*.tar.* - ./configure --prefix=$STAGING --bindir=$BINDIR --with-protoc-bindir=$STAGING/host/bin --disable-maintainer-mode --disable-dependency-tracking PKG_CONFIG_PATH="$STAGING/lib/pkgconfig" CPPFLAGS="-I$STAGING/include ${OPTFLAGS}" LDFLAGS="-L$STAGING/lib ${OPTFLAGS}" CXXFLAGS="-frandom-seed=bitcoin ${OPTFLAGS}" + ./configure --prefix=$STAGING --bindir=$BINDIR --with-protoc-bindir=$STAGING/host/bin --with-boost=$STAGING --disable-maintainer-mode --disable-dependency-tracking PKG_CONFIG_PATH="$STAGING/lib/pkgconfig" CPPFLAGS="-I$STAGING/include ${OPTFLAGS}" LDFLAGS="-L$STAGING/lib ${OPTFLAGS}" CXXFLAGS="-frandom-seed=bitcoin ${OPTFLAGS}" BOOST_CHRONO_EXTRALIBS="-lrt" make $MAKEOPTS make $MAKEOPTS install-strip mkdir -p $OUTDIR/src diff --git a/contrib/gitian-descriptors/gitian-win32.yml b/contrib/gitian-descriptors/gitian-win32.yml index 794fa27f1..eac74272c 100644 --- a/contrib/gitian-descriptors/gitian-win32.yml +++ b/contrib/gitian-descriptors/gitian-win32.yml @@ -25,7 +25,7 @@ files: - "qt-win32-5.2.0-gitian-r1.zip" - "boost-win32-1.55.0-gitian-r6.zip" - "bitcoin-deps-win32-gitian-r10.zip" -- "protobuf-win32-2.5.0-gitian-r3.zip" +- "protobuf-win32-2.5.0-gitian-r4.zip" script: | # STAGING=$HOME/staging @@ -37,7 +37,7 @@ script: | unzip ../build/qt-win32-5.2.0-gitian-r1.zip unzip ../build/boost-win32-1.55.0-gitian-r6.zip unzip ../build/bitcoin-deps-win32-gitian-r10.zip - unzip ../build/protobuf-win32-2.5.0-gitian-r3.zip + unzip ../build/protobuf-win32-2.5.0-gitian-r4.zip cd $HOME/build/ # cd bitcoin diff --git a/contrib/gitian-descriptors/protobuf-win32.yml b/contrib/gitian-descriptors/protobuf-win32.yml index b2e3d0b46..e93f92bbf 100644 --- a/contrib/gitian-descriptors/protobuf-win32.yml +++ b/contrib/gitian-descriptors/protobuf-win32.yml @@ -18,6 +18,7 @@ script: | export TZ=UTC export INSTALLPREFIX=$OUTDIR/staging/deps export HOST=i686-w64-mingw32 + OPTFLAGS="-O2" # Integrity Check echo "13bfc5ae543cf3aa180ac2485c0bc89495e3ae711fc6fab4f8ffe90dfb4bb677 protobuf-2.5.0.tar.bz2" | sha256sum -c @@ -33,12 +34,12 @@ script: | cp src/protoc $INSTALLPREFIX/host/bin # Now recompile with the mingw cross-compiler: make distclean - ./configure --prefix=$INSTALLPREFIX --enable-shared=no --disable-dependency-tracking --with-protoc=$INSTALLPREFIX/host/bin/protoc --host=$HOST CXXFLAGS=-frandom-seed=11 + ./configure --prefix=$INSTALLPREFIX --enable-shared=no --disable-dependency-tracking --with-protoc=$INSTALLPREFIX/host/bin/protoc --host=$HOST CXXFLAGS="-frandom-seed=11 ${OPTFLAGS}" make make install cd $INSTALLPREFIX export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 export FAKETIME=$REFERENCE_DATETIME - zip -r $OUTDIR/protobuf-win32-2.5.0-gitian-r3.zip include lib host + zip -r $OUTDIR/protobuf-win32-2.5.0-gitian-r4.zip include lib host unset LD_PRELOAD unset FAKETIME diff --git a/contrib/linearize/example-linearize.cfg b/contrib/linearize/example-linearize.cfg index 9e5aa404c..65bba712a 100644 --- a/contrib/linearize/example-linearize.cfg +++ b/contrib/linearize/example-linearize.cfg @@ -7,6 +7,6 @@ port=8332 # bootstrap.dat settings netmagic=f9beb4d9 -max_height=250000 +max_height=279000 output=bootstrap.dat diff --git a/contrib/linearize/linearize.py b/contrib/linearize/linearize.py index 12049100d..ea3814ab7 100644 --- a/contrib/linearize/linearize.py +++ b/contrib/linearize/linearize.py @@ -117,7 +117,7 @@ if __name__ == '__main__': if 'min_height' not in settings: settings['min_height'] = 0 if 'max_height' not in settings: - settings['max_height'] = 250000 + settings['max_height'] = 279000 if 'rpcuser' not in settings or 'rpcpass' not in settings: print "Missing username and/or password in cfg file" sys.exit(1) diff --git a/doc/build-osx.md b/doc/build-osx.md index 381e8b6f0..dd343dca5 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -5,7 +5,7 @@ This guide will show you how to build bitcoind(headless client) for OSX. Notes ----- -* Tested on OS X 10.5 through 10.8 on Intel processors only. PPC is not +* Tested on OS X 10.5 through 10.9 on Intel processors only. PPC is not supported because it is big-endian. * All of the commands should be executed in a Terminal application. The built-in one is located in `/Applications/Utilities`. @@ -27,7 +27,7 @@ not, it's the path of least resistance to install [Github for Mac](https://mac.g [Git for OS X](https://code.google.com/p/git-osx-installer/). It is also available via Homebrew or MacPorts. -You will also need to install [Homebrew](http://mxcl.github.io/homebrew/) +You will also need to install [Homebrew](http://brew.sh) or [MacPorts](https://www.macports.org/) in order to install library dependencies. It's largely a religious decision which to choose, but, as of December 2012, MacPorts is a little easier because you can just install the @@ -64,20 +64,20 @@ Installing the dependencies using MacPorts is very straightforward. make check -Instructions: HomeBrew +Instructions: Homebrew ---------------------- #### Install dependencies using Homebrew - brew install boost miniupnpc openssl berkeley-db4 + brew install autoconf automake berkeley-db4 boost miniupnpc openssl pkg-config protobuf -Note: After you have installed the dependencies, you should check that the Brew installed version of OpenSSL is the one available for compilation. You can check this by typing +Note: After you have installed the dependencies, you should check that the Homebrew installed version of OpenSSL is the one available for compilation. You can check this by typing openssl version -into Terminal. You should see OpenSSL 1.0.1e 11 Feb 2013. +into Terminal. You should see OpenSSL 1.0.1f 6 Jan 2014. -If not, you can ensure that the Brew OpenSSL is correctly linked by running +If not, you can ensure that the Homebrew OpenSSL is correctly linked by running brew link openssl --force diff --git a/doc/build-unix.md b/doc/build-unix.md index 5124205a3..d3a0536b1 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -87,12 +87,18 @@ Dependencies for the GUI: Ubuntu & Debian ----------------------------------------- If you want to build Bitcoin-Qt, make sure that the required packages for Qt development -are installed. Qt 4 is currently necessary to build the GUI. +are installed. Either Qt 4 or Qt 5 are necessary to build the GUI. +If both Qt 4 and Qt 5 are installed, Qt 4 will be used. Pass `--with-gui=qt5` to configure to choose Qt5. +To build without GUI pass `--without-gui`. To build with Qt 4 you need the following: apt-get install libqt4-dev libprotobuf-dev protobuf-compiler +For Qt 5 you need the following: + + apt-get install libqt5gui5 libqt5core5 libqt5dbus5 qttools5-dev-tools libprotobuf-dev + libqrencode (optional) can be installed with: apt-get install libqrencode-dev diff --git a/doc/release-process.md b/doc/release-process.md index 428193681..7fccf2172 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -53,6 +53,8 @@ Release Process cd .. ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/deps-linux.yml mv build/out/bitcoin-deps-*.zip inputs/ + ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/boost-linux.yml + mv build/out/boost-linux-*.zip inputs/ ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/boost-win32.yml mv build/out/boost-win32-*.zip inputs/ ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/deps-win32.yml diff --git a/src/Makefile.am b/src/Makefile.am index 9917be248..f27f16ab9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,6 @@ include Makefile.include -AM_CPPFLAGS += -I$(top_srcdir)/src/leveldb/helpers/memenv \ - -I$(builddir) +AM_CPPFLAGS += -I$(builddir) noinst_LIBRARIES = \ libbitcoin_server.a \ @@ -11,7 +10,15 @@ if ENABLE_WALLET noinst_LIBRARIES += libbitcoin_wallet.a endif -bin_PROGRAMS = bitcoind bitcoin-cli +bin_PROGRAMS = + +if BUILD_BITCOIND + bin_PROGRAMS += bitcoind +endif + +if BUILD_BITCOIN_CLI + bin_PROGRAMS += bitcoin-cli +endif SUBDIRS = . $(BUILD_QT) $(BUILD_TEST) DIST_SUBDIRS = . qt test @@ -140,8 +147,8 @@ bitcoind_LDADD = \ libbitcoin_server.a \ libbitcoin_cli.a \ libbitcoin_common.a \ - leveldb/libleveldb.a \ - leveldb/libmemenv.a + $(LIBLEVELDB) \ + $(LIBMEMENV) if ENABLE_WALLET bitcoind_LDADD += libbitcoin_wallet.a endif @@ -167,6 +174,7 @@ if TARGET_WINDOWS bitcoin_cli_SOURCES += bitcoin-cli-res.rc endif +# NOTE: This dependency is not strictly necessary, but without it make may try to build both in parallel, which breaks the LevelDB build system in a race leveldb/libleveldb.a: leveldb/libmemenv.a leveldb/%.a: diff --git a/src/Makefile.include b/src/Makefile.include index b9e6c262c..01b47d1aa 100644 --- a/src/Makefile.include +++ b/src/Makefile.include @@ -1,23 +1,30 @@ +if EMBEDDED_LEVELDB +LEVELDB_CPPFLAGS += -I$(top_srcdir)/src/leveldb/include +LEVELDB_CPPFLAGS += -I$(top_srcdir)/src/leveldb/helpers/memenv +LIBLEVELDB += $(top_builddir)/src/leveldb/libleveldb.a +LIBMEMENV += $(top_builddir)/src/leveldb/libmemenv.a +endif + AM_CPPFLAGS = $(INCLUDES) \ -I$(top_builddir)/src/obj \ - -I$(top_srcdir)/src/leveldb/include \ $(BDB_CPPFLAGS) \ - $(BOOST_INCLUDES) + $(BOOST_CPPFLAGS) $(BOOST_INCLUDES) +AM_CPPFLAGS += $(LEVELDB_CPPFLAGS) AM_LDFLAGS = $(PTHREAD_CFLAGS) LIBBITCOIN_SERVER=$(top_builddir)/src/libbitcoin_server.a LIBBITCOIN_WALLET=$(top_builddir)/src/libbitcoin_wallet.a LIBBITCOIN_COMMON=$(top_builddir)/src/libbitcoin_common.a LIBBITCOIN_CLI=$(top_builddir)/src/libbitcoin_cli.a -LIBLEVELDB=$(top_builddir)/src/leveldb/libleveldb.a -LIBMEMENV=$(top_builddir)/src/leveldb/libmemenv.a LIBBITCOINQT=$(top_builddir)/src/qt/libbitcoinqt.a $(LIBBITCOIN): $(MAKE) -C $(top_builddir)/src $(@F) +if EMBEDDED_LEVELDB $(LIBLEVELDB) $(LIBMEMENV): $(MAKE) -C $(top_builddir)/src leveldb/$(@F) +endif $(LIBBITCOINQT): $(MAKE) -C $(top_builddir)/src/qt $(@F) diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 40dd30d1a..9db1f5e10 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -50,11 +50,12 @@ namespace Checkpoints (216116, uint256("0x00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e")) (225430, uint256("0x00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932")) (250000, uint256("0x000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214")) + (279000, uint256("0x0000000000000001ae8c72a0b0c301f67e3afca10e819efa9041e458e9bd7e40")) ; static const CCheckpointData data = { &mapCheckpoints, - 1375533383, // * UNIX timestamp of last checkpoint block - 21491097, // * total number of transactions between genesis and last checkpoint + 1389047471, // * UNIX timestamp of last checkpoint block + 30549816, // * total number of transactions between genesis and last checkpoint // (the tx=... number in the SetBestChain debug.log lines) 60000.0 // * estimated number of transactions per day after checkpoint }; @@ -111,7 +112,7 @@ namespace Checkpoints double fWorkBefore = 0.0; // Amount of work done before pindex double fWorkAfter = 0.0; // Amount of work left after pindex (estimated) - // Work is defined as: 1.0 per transaction before the last checkoint, and + // Work is defined as: 1.0 per transaction before the last checkpoint, and // fSigcheckVerificationFactor per transaction after. const CCheckpointData &data = Checkpoints(); diff --git a/src/leveldb/db/filename.cc b/src/leveldb/db/filename.cc index da32946d9..27d750697 100644 --- a/src/leveldb/db/filename.cc +++ b/src/leveldb/db/filename.cc @@ -29,14 +29,19 @@ std::string LogFileName(const std::string& name, uint64_t number) { return MakeFileName(name, number, "log"); } +// TableFileName returns the filenames we usually write to, while +// SSTTableFileName returns the alternative filenames we also try to read from +// for backward compatibility. For now, swap them around. +// TODO: when compatibility is no longer necessary, swap them back +// (TableFileName to use "ldb" and SSTTableFileName to use "sst"). std::string TableFileName(const std::string& name, uint64_t number) { assert(number > 0); - return MakeFileName(name, number, "ldb"); + return MakeFileName(name, number, "sst"); } std::string SSTTableFileName(const std::string& name, uint64_t number) { assert(number > 0); - return MakeFileName(name, number, "sst"); + return MakeFileName(name, number, "ldb"); } std::string DescriptorFileName(const std::string& dbname, uint64_t number) { diff --git a/src/m4/bitcoin_qt.m4 b/src/m4/bitcoin_qt.m4 index 758aea349..5ed969218 100644 --- a/src/m4/bitcoin_qt.m4 +++ b/src/m4/bitcoin_qt.m4 @@ -22,7 +22,7 @@ AC_DEFUN([BITCOIN_QT_CHECK],[ ]) dnl BITCOIN_QT_PATH_PROGS([FOO], [foo foo2], [/path/to/search/first], [continue if missing]) -dnl Helper for finding the path of programs needed for QT. +dnl Helper for finding the path of programs needed for Qt. dnl Inputs: $1: Variable to be set dnl Inputs: $2: List of programs to search for dnl Inputs: $3: Look for $2 here before $PATH @@ -47,9 +47,9 @@ dnl input variables are set correctly. dnl CAUTION: Do not use this inside of a conditional. AC_DEFUN([BITCOIN_QT_INIT],[ dnl enable qt support - AC_ARG_WITH([qt], - [AS_HELP_STRING([--with-qt], - [with qt (no|qt4|qt5|auto. default is auto, qt4 tried first.)])], + AC_ARG_WITH([gui], + [AS_HELP_STRING([--with-gui], + [with GUI (no|qt4|qt5|auto. default is auto, qt4 tried first.)])], [ bitcoin_qt_want_version=$withval if test x$bitcoin_qt_want_version = xyes; then @@ -59,10 +59,10 @@ AC_DEFUN([BITCOIN_QT_INIT],[ ], [bitcoin_qt_want_version=auto]) - AC_ARG_WITH([qt-incdir],[AS_HELP_STRING([--with-qt-incdir=INC_DIR],[specify qt include path (overridden by pkgconfig)])], [qt_include_path=$withval], []) - AC_ARG_WITH([qt-libdir],[AS_HELP_STRING([--with-qt-libdir=LIB_DIR],[specify qt lib path (overridden by pkgconfig)])], [qt_lib_path=$withval], []) - AC_ARG_WITH([qt-plugindir],[AS_HELP_STRING([--with-qt-plugindir=PLUGIN_DIR],[specify qt plugin path (overridden by pkgconfig)])], [qt_plugin_path=$withval], []) - AC_ARG_WITH([qt-bindir],[AS_HELP_STRING([--with-qt-bindir=BIN_DIR],[specify qt bin path])], [qt_bin_path=$withval], []) + AC_ARG_WITH([qt-incdir],[AS_HELP_STRING([--with-gui-incdir=INC_DIR],[specify qt include path (overridden by pkgconfig)])], [qt_include_path=$withval], []) + AC_ARG_WITH([qt-libdir],[AS_HELP_STRING([--with-gui-libdir=LIB_DIR],[specify qt lib path (overridden by pkgconfig)])], [qt_lib_path=$withval], []) + AC_ARG_WITH([qt-plugindir],[AS_HELP_STRING([--with-gui-plugindir=PLUGIN_DIR],[specify qt plugin path (overridden by pkgconfig)])], [qt_plugin_path=$withval], []) + AC_ARG_WITH([qt-bindir],[AS_HELP_STRING([--with-gui-bindir=BIN_DIR],[specify qt bin path])], [qt_bin_path=$withval], []) AC_ARG_WITH([qtdbus], [AS_HELP_STRING([--with-qtdbus], @@ -73,7 +73,7 @@ AC_DEFUN([BITCOIN_QT_INIT],[ dnl Find the appropriate version of Qt libraries and includes. dnl Inputs: $1: Whether or not pkg-config should be used. yes|no. Default: yes. -dnl Inputs: $2: If $1 is "yes" and --with-qt=auto, which qt version should be +dnl Inputs: $2: If $1 is "yes" and --with-gui=auto, which qt version should be dnl tried first. dnl Outputs: See _BITCOIN_QT_FIND_LIBS_* dnl Outputs: Sets variables for all qt-related tools. @@ -113,7 +113,7 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ dnl enable qt support - AC_MSG_CHECKING(if QT should be enabled) + AC_MSG_CHECKING(whether to build Bitcoin Core GUI) BITCOIN_QT_CHECK([ bitcoin_enable_qt=yes bitcoin_enable_qt_test=yes @@ -149,11 +149,11 @@ dnl All macros below are internal and should _not_ be used from the main dnl configure.ac. dnl ---- -dnl Internal. Check if the included version of QT is Qt5. +dnl Internal. Check if the included version of Qt is Qt5. dnl Requires: INCLUDES must be populated as necessary. dnl Output: bitcoin_cv_qt5=yes|no AC_DEFUN([_BITCOIN_QT_CHECK_QT5],[ - AC_CACHE_CHECK(for QT 5, bitcoin_cv_qt5,[ + AC_CACHE_CHECK(for Qt 5, bitcoin_cv_qt5,[ AC_TRY_COMPILE( [#include <QtCore>], [ @@ -167,13 +167,13 @@ AC_DEFUN([_BITCOIN_QT_CHECK_QT5],[ bitcoin_cv_qt5=no) ])]) -dnl Internal. Check if the linked version of QT was built as static libs. +dnl Internal. Check if the linked version of Qt was built as static libs. dnl Requires: Qt5. This check cannot determine if Qt4 is static. dnl Requires: INCLUDES and LIBS must be populated as necessary. dnl Output: bitcoin_cv_static_qt=yes|no dnl Output: Defines QT_STATICPLUGIN if plugins are static. AC_DEFUN([_BITCOIN_QT_IS_STATIC],[ - AC_CACHE_CHECK(for static QT, bitcoin_cv_static_qt,[ + AC_CACHE_CHECK(for static Qt, bitcoin_cv_static_qt,[ AC_TRY_COMPILE( [#include <QtCore>], [ @@ -187,7 +187,7 @@ AC_DEFUN([_BITCOIN_QT_IS_STATIC],[ [bitcoin_cv_static_qt=no]) ]) if test xbitcoin_cv_static_qt = xyes; then - AC_DEFINE(QT_STATICPLUGIN, 1, [Define this symbol for static QT plugins]) + AC_DEFINE(QT_STATICPLUGIN, 1, [Define this symbol for static Qt plugins]) fi ]) @@ -197,7 +197,7 @@ dnl Inputs: $1: A series of Q_IMPORT_PLUGIN(). dnl Inputs: $2: The libraries that resolve $1. dnl Output: QT_LIBS is prepended or configure exits. AC_DEFUN([_BITCOIN_QT_CHECK_STATIC_PLUGINS],[ - AC_MSG_CHECKING(for static QT plugins: $2) + AC_MSG_CHECKING(for static Qt plugins: $2) CHECK_STATIC_PLUGINS_TEMP_LIBS="$LIBS" LIBS="$2 $QT_LIBS $LIBS" AC_TRY_LINK([ @@ -211,7 +211,7 @@ AC_DEFUN([_BITCOIN_QT_CHECK_STATIC_PLUGINS],[ ]) dnl Internal. Find Qt libraries using pkg-config. -dnl Inputs: bitcoin_qt_want_version (from --with-qt=). The version to check +dnl Inputs: bitcoin_qt_want_version (from --with-gui=). The version to check dnl first. dnl Inputs: $1: If bitcoin_qt_want_version is "auto", check for this version dnl first. @@ -265,7 +265,7 @@ AC_DEFUN([_BITCOIN_QT_FIND_LIBS_WITH_PKGCONFIG],[ dnl Internal. Find Qt libraries without using pkg-config. Version is deduced dnl from the discovered headers. -dnl Inputs: bitcoin_qt_want_version (from --with-qt=). The version to use. +dnl Inputs: bitcoin_qt_want_version (from --with-gui=). The version to use. dnl If "auto", the version will be discovered by _BITCOIN_QT_CHECK_QT5. dnl Outputs: All necessary QT_* variables are set. dnl Outputs: bitcoin_qt_got_major_vers is set to "4" or "5". diff --git a/src/main.cpp b/src/main.cpp index 9c6c1ba0c..3ff1fd3a9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -883,11 +883,11 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock fseek(file, postx.nTxOffset, SEEK_CUR); file >> txOut; } catch (std::exception &e) { - return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__); + return error("%s : Deserialize or I/O error - %s", __PRETTY_FUNCTION__, e.what()); } hashBlock = header.GetHash(); if (txOut.GetHash() != hash) - return error("%s() : txid mismatch", __PRETTY_FUNCTION__); + return error("%s : txid mismatch", __PRETTY_FUNCTION__); return true; } } @@ -936,7 +936,7 @@ bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos) // Open history file to append CAutoFile fileout = CAutoFile(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION); if (!fileout) - return error("WriteBlockToDisk() : OpenBlockFile failed"); + return error("WriteBlockToDisk : OpenBlockFile failed"); // Write index header unsigned int nSize = fileout.GetSerializeSize(block); @@ -945,7 +945,7 @@ bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos) // Write block long fileOutPos = ftell(fileout); if (fileOutPos < 0) - return error("WriteBlockToDisk() : ftell failed"); + return error("WriteBlockToDisk : ftell failed"); pos.nPos = (unsigned int)fileOutPos; fileout << block; @@ -964,19 +964,19 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos) // Open history file to read CAutoFile filein = CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION); if (!filein) - return error("ReadBlockFromDisk(CBlock&, CDiskBlockPos&) : OpenBlockFile failed"); + return error("ReadBlockFromDisk : OpenBlockFile failed"); // Read block try { filein >> block; } catch (std::exception &e) { - return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__); + return error("%s : Deserialize or I/O error - %s", __PRETTY_FUNCTION__, e.what()); } // Check the header if (!CheckProofOfWork(block.GetHash(), block.nBits)) - return error("ReadBlockFromDisk(CBlock&, CDiskBlockPos&) : errors in block header"); + return error("ReadBlockFromDisk : Errors in block header"); return true; } @@ -2876,7 +2876,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) break; } } catch (std::exception &e) { - LogPrintf("%s() : Deserialize or I/O error caught during load\n", __PRETTY_FUNCTION__); + LogPrintf("%s : Deserialize or I/O error - %s", __PRETTY_FUNCTION__, e.what()); } } fclose(fileIn); diff --git a/src/main.h b/src/main.h index f3f9acb63..60e733b23 100644 --- a/src/main.h +++ b/src/main.h @@ -336,7 +336,7 @@ public: // Open history file to append CAutoFile fileout = CAutoFile(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION); if (!fileout) - return error("CBlockUndo::WriteToDisk() : OpenUndoFile failed"); + return error("CBlockUndo::WriteToDisk : OpenUndoFile failed"); // Write index header unsigned int nSize = fileout.GetSerializeSize(*this); @@ -345,7 +345,7 @@ public: // Write undo data long fileOutPos = ftell(fileout); if (fileOutPos < 0) - return error("CBlockUndo::WriteToDisk() : ftell failed"); + return error("CBlockUndo::WriteToDisk : ftell failed"); pos.nPos = (unsigned int)fileOutPos; fileout << *this; @@ -368,7 +368,7 @@ public: // Open history file to read CAutoFile filein = CAutoFile(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION); if (!filein) - return error("CBlockUndo::ReadFromDisk() : OpenBlockFile failed"); + return error("CBlockUndo::ReadFromDisk : OpenBlockFile failed"); // Read block uint256 hashChecksum; @@ -377,7 +377,7 @@ public: filein >> hashChecksum; } catch (std::exception &e) { - return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__); + return error("%s : Deserialize or I/O error - %s", __PRETTY_FUNCTION__, e.what()); } // Verify checksum @@ -385,7 +385,7 @@ public: hasher << hashBlock; hasher << *this; if (hashChecksum != hasher.GetHash()) - return error("CBlockUndo::ReadFromDisk() : checksum mismatch"); + return error("CBlockUndo::ReadFromDisk : Checksum mismatch"); return true; } diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index 274cebcf3..cac603966 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -80,6 +80,7 @@ QT_FORMS_UI = \ forms/askpassphrasedialog.ui \ forms/coincontroldialog.ui \ forms/editaddressdialog.ui \ + forms/helpmessagedialog.ui \ forms/intro.ui \ forms/openuridialog.ui \ forms/optionsdialog.ui \ @@ -93,7 +94,6 @@ QT_FORMS_UI = \ forms/transactiondescdialog.ui QT_MOC_CPP = \ - moc_aboutdialog.cpp \ moc_addressbookpage.cpp \ moc_addresstablemodel.cpp \ moc_askpassphrasedialog.cpp \ @@ -133,6 +133,7 @@ QT_MOC_CPP = \ moc_transactionfilterproxy.cpp \ moc_transactiontablemodel.cpp \ moc_transactionview.cpp \ + moc_utilitydialog.cpp \ moc_walletframe.cpp \ moc_walletmodel.cpp \ moc_walletview.cpp @@ -155,7 +156,6 @@ PROTOBUF_H = paymentrequest.pb.h PROTOBUF_PROTO = paymentrequest.proto BITCOIN_QT_H = \ - aboutdialog.h \ addressbookpage.h \ addresstablemodel.h \ askpassphrasedialog.h \ @@ -198,6 +198,7 @@ BITCOIN_QT_H = \ transactionrecord.h \ transactiontablemodel.h \ transactionview.h \ + utilitydialog.h \ walletframe.h \ walletmodel.h \ walletmodeltransaction.h \ @@ -248,7 +249,6 @@ RES_ICONS = \ res/icons/tx_mined.png BITCOIN_QT_CPP = \ - aboutdialog.cpp \ bitcoin.cpp \ bitcoinaddressvalidator.cpp \ bitcoinamountfield.cpp \ @@ -267,7 +267,8 @@ BITCOIN_QT_CPP = \ rpcconsole.cpp \ signverifymessagedialog.cpp \ splashscreen.cpp \ - trafficgraphwidget.cpp + trafficgraphwidget.cpp \ + utilitydialog.cpp if ENABLE_WALLET BITCOIN_QT_CPP += \ diff --git a/src/qt/aboutdialog.cpp b/src/qt/aboutdialog.cpp deleted file mode 100644 index 6581a19c1..000000000 --- a/src/qt/aboutdialog.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2011-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "aboutdialog.h" -#include "ui_aboutdialog.h" - -#include "clientmodel.h" - -#include "clientversion.h" - -AboutDialog::AboutDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::AboutDialog) -{ - ui->setupUi(this); - - // Set current copyright year - ui->copyrightLabel->setText(tr("Copyright") + QString(" © 2009-%1 ").arg(COPYRIGHT_YEAR) + tr("The Bitcoin Core developers")); -} - -void AboutDialog::setModel(ClientModel *model) -{ - if(model) - { - ui->versionLabel->setText(model->formatFullVersion()); - } -} - -AboutDialog::~AboutDialog() -{ - delete ui; -} - -void AboutDialog::on_buttonBox_accepted() -{ - close(); -} diff --git a/src/qt/aboutdialog.h b/src/qt/aboutdialog.h deleted file mode 100644 index 1b131c4dc..000000000 --- a/src/qt/aboutdialog.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2011-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef ABOUTDIALOG_H -#define ABOUTDIALOG_H - -#include <QDialog> - -class ClientModel; - -namespace Ui { - class AboutDialog; -} - -/** "About" dialog box */ -class AboutDialog : public QDialog -{ - Q_OBJECT - -public: - explicit AboutDialog(QWidget *parent); - ~AboutDialog(); - - void setModel(ClientModel *model); - -private: - Ui::AboutDialog *ui; - -private slots: - void on_buttonBox_accepted(); -}; - -#endif // ABOUTDIALOG_H diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 3cf7e53c0..848e50deb 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -14,6 +14,7 @@ #include "intro.h" #include "optionsmodel.h" #include "splashscreen.h" +#include "utilitydialog.h" #ifdef ENABLE_WALLET #include "paymentserver.h" #include "walletmodel.h" @@ -36,8 +37,6 @@ #include <QTimer> #include <QTranslator> #include <QThread> -#include <QVBoxLayout> -#include <QLabel> #if defined(QT_STATICPLUGIN) #include <QtPlugin> @@ -356,17 +355,7 @@ void BitcoinApplication::requestShutdown() clientModel = 0; // Show a simple window indicating shutdown status - QWidget *shutdownWindow = new QWidget(); - QVBoxLayout *layout = new QVBoxLayout(); - layout->addWidget(new QLabel( - tr("Bitcoin Core is shutting down...") + "<br /><br />" + - tr("Do not shut down the computer until this window disappears."))); - shutdownWindow->setLayout(layout); - - // Center shutdown window at where main window was - const QPoint global = window->mapToGlobal(window->rect().center()); - shutdownWindow->move(global.x() - shutdownWindow->width() / 2, global.y() - shutdownWindow->height() / 2); - shutdownWindow->show(); + ShutdownWindow::showShutdownWindow(window); // Request shutdown from core thread emit requestedShutdown(); @@ -503,7 +492,7 @@ int main(int argc, char *argv[]) // but before showing splash screen. if (mapArgs.count("-?") || mapArgs.count("--help")) { - GUIUtil::HelpMessageBox help; + HelpMessageDialog help(NULL); help.showOrPrint(); return 1; } diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 692fb6dc1..1008ef2b0 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -4,7 +4,6 @@ #include "bitcoingui.h" -#include "aboutdialog.h" #include "bitcoinunits.h" #include "clientmodel.h" #include "guiconstants.h" @@ -14,6 +13,7 @@ #include "optionsdialog.h" #include "optionsmodel.h" #include "rpcconsole.h" +#include "utilitydialog.h" #ifdef ENABLE_WALLET #include "walletframe.h" #include "walletmodel.h" diff --git a/src/qt/forms/aboutdialog.ui b/src/qt/forms/aboutdialog.ui index 10a5857ca..3ab4675bf 100644 --- a/src/qt/forms/aboutdialog.ui +++ b/src/qt/forms/aboutdialog.ui @@ -160,12 +160,12 @@ This product includes software developed by the OpenSSL Project for use in the O <slot>accept()</slot> <hints> <hint type="sourcelabel"> - <x>360</x> - <y>308</y> + <x>20</x> + <y>20</y> </hint> <hint type="destinationlabel"> - <x>157</x> - <y>274</y> + <x>20</x> + <y>20</y> </hint> </hints> </connection> @@ -176,12 +176,12 @@ This product includes software developed by the OpenSSL Project for use in the O <slot>reject()</slot> <hints> <hint type="sourcelabel"> - <x>428</x> - <y>308</y> + <x>20</x> + <y>20</y> </hint> <hint type="destinationlabel"> - <x>286</x> - <y>274</y> + <x>20</x> + <y>20</y> </hint> </hints> </connection> diff --git a/src/qt/forms/helpmessagedialog.ui b/src/qt/forms/helpmessagedialog.ui new file mode 100644 index 000000000..f68fea7e6 --- /dev/null +++ b/src/qt/forms/helpmessagedialog.ui @@ -0,0 +1,128 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>HelpMessageDialog</class> + <widget class="QDialog" name="HelpMessageDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>800</width> + <height>400</height> + </rect> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="windowTitle"> + <string>Bitcoin Core - Command-line options</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="graphic"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Ignored"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="pixmap"> + <pixmap resource="../bitcoin.qrc">:/images/about</pixmap> + </property> + </widget> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QScrollArea" name="scrollArea"> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOn</enum> + </property> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <widget class="QWidget" name="scrollAreaWidgetContents"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>659</width> + <height>348</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QLabel" name="helpMessageLabel"> + <property name="font"> + <font> + <family>Terminal</family> + </font> + </property> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="okButton"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources> + <include location="../bitcoin.qrc"/> + </resources> + <connections> + <connection> + <sender>okButton</sender> + <signal>accepted()</signal> + <receiver>HelpMessageDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>20</x> + <y>20</y> + </hint> + <hint type="destinationlabel"> + <x>20</x> + <y>20</y> + </hint> + </hints> + </connection> + <connection> + <sender>okButton</sender> + <signal>rejected()</signal> + <receiver>HelpMessageDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>20</x> + <y>20</y> + </hint> + <hint type="destinationlabel"> + <x>20</x> + <y>20</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/qt/forms/receivecoinsdialog.ui b/src/qt/forms/receivecoinsdialog.ui index 8242763e7..7bf01224e 100644 --- a/src/qt/forms/receivecoinsdialog.ui +++ b/src/qt/forms/receivecoinsdialog.ui @@ -207,7 +207,11 @@ </widget> </item> <item> - <widget class="QTableView" name="recentRequestsView"/> + <widget class="QTableView" name="recentRequestsView"> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + </widget> </item> <item> <layout class="QHBoxLayout" name="horizontalLayout_2"> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index b87498402..2d8a6afe2 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -591,47 +591,6 @@ void restoreWindowGeometry(const QString& strSetting, const QSize& defaultSize, parent->move(pos); } -HelpMessageBox::HelpMessageBox(QWidget *parent) : - QMessageBox(parent) -{ - header = tr("Bitcoin Core") + " " + tr("version") + " " + - QString::fromStdString(FormatFullVersion()) + "\n\n" + - tr("Usage:") + "\n" + - " bitcoin-qt [" + tr("command-line options") + "] " + "\n"; - - coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT)); - - uiOptions = tr("UI options") + ":\n" + - " -lang=<lang> " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" + - " -min " + tr("Start minimized") + "\n" + - " -splash " + tr("Show splash screen on startup (default: 1)") + "\n" + - " -choosedatadir " + tr("Choose data directory on startup (default: 0)") + "\n"; - - setWindowTitle(tr("Bitcoin Core")); - setTextFormat(Qt::PlainText); - // setMinimumWidth is ignored for QMessageBox so put in non-breaking spaces to make it wider. - setText(header + QString(QChar(0x2003)).repeated(50)); - setDetailedText(coreOptions + "\n" + uiOptions); -} - -void HelpMessageBox::printToConsole() -{ - // On other operating systems, the expected action is to print the message to the console. - QString strUsage = header + "\n" + coreOptions + "\n" + uiOptions; - fprintf(stdout, "%s", strUsage.toStdString().c_str()); -} - -void HelpMessageBox::showOrPrint() -{ -#if defined(WIN32) - // On Windows, show a message box, as there is no stderr/stdout in windowed applications - exec(); -#else - // On other operating systems, print help text to console - printToConsole(); -#endif -} - void setClipboard(const QString& str) { QApplication::clipboard()->setText(str, QClipboard::Clipboard); diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 14d4ff17c..c894850a9 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -123,26 +123,6 @@ namespace GUIUtil /** Restore window size and position */ void restoreWindowGeometry(const QString& strSetting, const QSize &defaultSizeIn, QWidget *parent); - /** Help message for Bitcoin-Qt, shown with --help. */ - class HelpMessageBox : public QMessageBox - { - Q_OBJECT - - public: - HelpMessageBox(QWidget *parent = 0); - - /** Show message box or print help message to standard output, based on operating system. */ - void showOrPrint(); - - /** Print help message to console */ - void printToConsole(); - - private: - QString header; - QString coreOptions; - QString uiOptions; - }; - } // namespace GUIUtil #endif // GUIUTIL_H diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 075a16dab..38dc88f63 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -55,6 +55,8 @@ void ReceiveCoinsDialog::setModel(WalletModel *model) ui->recentRequestsView->horizontalHeader()->setSectionResizeMode(RecentRequestsTableModel::Message, QHeaderView::Stretch); #endif ui->recentRequestsView->horizontalHeader()->resizeSection(RecentRequestsTableModel::Amount, 100); + + model->getRecentRequestsTableModel()->sort(RecentRequestsTableModel::Date, Qt::DescendingOrder); } } diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp index 86c29dd02..74b43f1d2 100644 --- a/src/qt/recentrequeststablemodel.cpp +++ b/src/qt/recentrequeststablemodel.cpp @@ -12,6 +12,13 @@ RecentRequestsTableModel::RecentRequestsTableModel(CWallet *wallet, WalletModel walletModel(parent) { Q_UNUSED(wallet); + nReceiveRequestsMaxId = 0; + + // Load entries from wallet + std::vector<std::string> vReceiveRequests; + parent->loadReceiveRequests(vReceiveRequests); + BOOST_FOREACH(const std::string& request, vReceiveRequests) + addNewRequest(request); /* These columns must match the indices in the ColumnIndex enumeration */ columns << tr("Date") << tr("Label") << tr("Message") << tr("Amount"); @@ -104,6 +111,14 @@ bool RecentRequestsTableModel::removeRows(int row, int count, const QModelIndex if(count > 0 && row >= 0 && (row+count) <= list.size()) { + const RecentRequestEntry *rec; + for (int i = 0; i < count; ++i) + { + rec = &list[row+i]; + if (!walletModel->saveReceiveRequest(rec->recipient.address.toStdString(), rec->id, "")) + return false; + } + beginRemoveRows(parent, row, row + count - 1); list.erase(list.begin() + row, list.begin() + row + count); endRemoveRows(); @@ -118,12 +133,73 @@ Qt::ItemFlags RecentRequestsTableModel::flags(const QModelIndex &index) const return Qt::ItemIsSelectable | Qt::ItemIsEnabled; } +// called when adding a request from the GUI void RecentRequestsTableModel::addNewRequest(const SendCoinsRecipient &recipient) { RecentRequestEntry newEntry; + newEntry.id = ++nReceiveRequestsMaxId; newEntry.date = QDateTime::currentDateTime(); newEntry.recipient = recipient; + + CDataStream ss(SER_DISK, CLIENT_VERSION); + ss << newEntry; + + if (!walletModel->saveReceiveRequest(recipient.address.toStdString(), newEntry.id, ss.str())) + return; + + addNewRequest(newEntry); +} + +// called from ctor when loading from wallet +void RecentRequestsTableModel::addNewRequest(const std::string &recipient) +{ + std::vector<char> data(recipient.begin(), recipient.end()); + CDataStream ss(data, SER_DISK, CLIENT_VERSION); + + RecentRequestEntry entry; + ss >> entry; + + if (entry.id == 0) // should not happen + return; + + if (entry.id > nReceiveRequestsMaxId) + nReceiveRequestsMaxId = entry.id; + + addNewRequest(entry); +} + +// actually add to table in GUI +void RecentRequestsTableModel::addNewRequest(RecentRequestEntry &recipient) +{ beginInsertRows(QModelIndex(), 0, 0); - list.prepend(newEntry); + list.prepend(recipient); endInsertRows(); } + +void RecentRequestsTableModel::sort(int column, Qt::SortOrder order) +{ + qSort(list.begin(), list.end(), RecentRequestEntryLessThan(column, order)); + emit dataChanged(index(0, 0, QModelIndex()), index(list.size() - 1, NUMBER_OF_COLUMNS - 1, QModelIndex())); +} + +bool RecentRequestEntryLessThan::operator()(RecentRequestEntry &left, RecentRequestEntry &right) const +{ + RecentRequestEntry *pLeft = &left; + RecentRequestEntry *pRight = &right; + if (order == Qt::DescendingOrder) + std::swap(pLeft, pRight); + + switch(column) + { + case RecentRequestsTableModel::Date: + return pLeft->date.toTime_t() < pRight->date.toTime_t(); + case RecentRequestsTableModel::Label: + return pLeft->recipient.label < pRight->recipient.label; + case RecentRequestsTableModel::Message: + return pLeft->recipient.message < pRight->recipient.message; + case RecentRequestsTableModel::Amount: + return pLeft->recipient.amount < pRight->recipient.amount; + default: + return pLeft->id < pRight->id; + } +} diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h index 3aab7b0a4..6b20402f7 100644 --- a/src/qt/recentrequeststablemodel.h +++ b/src/qt/recentrequeststablemodel.h @@ -13,10 +13,44 @@ class CWallet; -struct RecentRequestEntry +class RecentRequestEntry { +public: + RecentRequestEntry() : nVersion(RecentRequestEntry::CURRENT_VERSION), id(0) { } + + static const int CURRENT_VERSION=1; + int nVersion; + int64_t id; QDateTime date; SendCoinsRecipient recipient; + + IMPLEMENT_SERIALIZE + ( + RecentRequestEntry* pthis = const_cast<RecentRequestEntry*>(this); + + unsigned int nDate = date.toTime_t(); + + READWRITE(pthis->nVersion); + nVersion = pthis->nVersion; + READWRITE(id); + READWRITE(nDate); + READWRITE(recipient); + + if (fRead) + pthis->date = QDateTime::fromTime_t(nDate); + ) +}; + +class RecentRequestEntryLessThan +{ +public: + RecentRequestEntryLessThan(int nColumn, Qt::SortOrder fOrder): + column(nColumn), order(fOrder) {} + bool operator()(RecentRequestEntry &left, RecentRequestEntry &right ) const; + +private: + int column; + Qt::SortOrder order; }; /** Model for list of recently generated payment requests / bitcoin URIs. @@ -34,7 +68,8 @@ public: Date = 0, Label = 1, Message = 2, - Amount = 3 + Amount = 3, + NUMBER_OF_COLUMNS }; /** @name Methods overridden from QAbstractTableModel @@ -51,11 +86,17 @@ public: const RecentRequestEntry &entry(int row) const { return list[row]; } void addNewRequest(const SendCoinsRecipient &recipient); + void addNewRequest(const std::string &recipient); + void addNewRequest(RecentRequestEntry &recipient); + +public slots: + void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); private: WalletModel *walletModel; QStringList columns; QList<RecentRequestEntry> list; + int64_t nReceiveRequestsMaxId; }; #endif diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index a8470572d..abb6ceb13 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -7,6 +7,7 @@ #include "clientmodel.h" #include "guiutil.h" +#include "utilitydialog.h" #include "rpcserver.h" #include "rpcclient.h" @@ -443,8 +444,8 @@ void RPCConsole::scrollToEnd() void RPCConsole::on_showCLOptionsButton_clicked() { - GUIUtil::HelpMessageBox help; - help.exec(); + HelpMessageDialog *help = new HelpMessageDialog(this); + help->show(); } void RPCConsole::on_sldGraphRange_valueChanged(int value) diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp new file mode 100644 index 000000000..05a01c744 --- /dev/null +++ b/src/qt/utilitydialog.cpp @@ -0,0 +1,125 @@ +// Copyright (c) 2011-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "utilitydialog.h" + +#include "ui_aboutdialog.h" +#include "ui_helpmessagedialog.h" + +#include "bitcoingui.h" +#include "clientmodel.h" +#include "guiutil.h" + +#include "clientversion.h" +#include "init.h" +#include "util.h" + +#include <QLabel> +#include <QVBoxLayout> + +/** "About" dialog box */ +AboutDialog::AboutDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::AboutDialog) +{ + ui->setupUi(this); + + // Set current copyright year + ui->copyrightLabel->setText(tr("Copyright") + QString(" © 2009-%1 ").arg(COPYRIGHT_YEAR) + tr("The Bitcoin Core developers")); +} + +void AboutDialog::setModel(ClientModel *model) +{ + if(model) + { + ui->versionLabel->setText(model->formatFullVersion()); + } +} + +AboutDialog::~AboutDialog() +{ + delete ui; +} + +void AboutDialog::on_buttonBox_accepted() +{ + close(); +} + +/** "Help message" dialog box */ +HelpMessageDialog::HelpMessageDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::HelpMessageDialog) +{ + ui->setupUi(this); + GUIUtil::restoreWindowGeometry("nHelpMessageDialogWindow", this->size(), this); + + header = tr("Bitcoin Core") + " " + tr("version") + " " + + QString::fromStdString(FormatFullVersion()) + "\n\n" + + tr("Usage:") + "\n" + + " bitcoin-qt [" + tr("command-line options") + "] " + "\n"; + + coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT)); + + uiOptions = tr("UI options") + ":\n" + + " -lang=<lang> " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" + + " -min " + tr("Start minimized") + "\n" + + " -splash " + tr("Show splash screen on startup (default: 1)") + "\n" + + " -choosedatadir " + tr("Choose data directory on startup (default: 0)"); + + ui->helpMessageLabel->setFont(GUIUtil::bitcoinAddressFont()); + + // Set help message text + ui->helpMessageLabel->setText(header + "\n" + coreOptions + "\n" + uiOptions); +} + +HelpMessageDialog::~HelpMessageDialog() +{ + GUIUtil::saveWindowGeometry("nHelpMessageDialogWindow", this); + delete ui; +} + +void HelpMessageDialog::printToConsole() +{ + // On other operating systems, the expected action is to print the message to the console. + QString strUsage = header + "\n" + coreOptions + "\n" + uiOptions; + fprintf(stdout, "%s", strUsage.toStdString().c_str()); +} + +void HelpMessageDialog::showOrPrint() +{ +#if defined(WIN32) + // On Windows, show a message box, as there is no stderr/stdout in windowed applications + exec(); +#else + // On other operating systems, print help text to console + printToConsole(); +#endif +} + +void HelpMessageDialog::on_okButton_accepted() +{ + close(); +} + + +/** "Shutdown" window */ +void ShutdownWindow::showShutdownWindow(BitcoinGUI *window) +{ + if (!window) + return; + + // Show a simple window indicating shutdown status + QWidget *shutdownWindow = new QWidget(); + QVBoxLayout *layout = new QVBoxLayout(); + layout->addWidget(new QLabel( + tr("Bitcoin Core is shutting down...") + "<br /><br />" + + tr("Do not shut down the computer until this window disappears."))); + shutdownWindow->setLayout(layout); + + // Center shutdown window at where main window was + const QPoint global = window->mapToGlobal(window->rect().center()); + shutdownWindow->move(global.x() - shutdownWindow->width() / 2, global.y() - shutdownWindow->height() / 2); + shutdownWindow->show(); +} diff --git a/src/qt/utilitydialog.h b/src/qt/utilitydialog.h new file mode 100644 index 000000000..874daf6a7 --- /dev/null +++ b/src/qt/utilitydialog.h @@ -0,0 +1,69 @@ +// Copyright (c) 2011-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef UTILITYDIALOG_H +#define UTILITYDIALOG_H + +#include <QDialog> +#include <QObject> + +class BitcoinGUI; +class ClientModel; + +namespace Ui { + class AboutDialog; + class HelpMessageDialog; +} + +/** "About" dialog box */ +class AboutDialog : public QDialog +{ + Q_OBJECT + +public: + explicit AboutDialog(QWidget *parent); + ~AboutDialog(); + + void setModel(ClientModel *model); + +private: + Ui::AboutDialog *ui; + +private slots: + void on_buttonBox_accepted(); +}; + +/** "Help message" dialog box */ +class HelpMessageDialog : public QDialog +{ + Q_OBJECT + +public: + explicit HelpMessageDialog(QWidget *parent); + ~HelpMessageDialog(); + + void printToConsole(); + void showOrPrint(); + +private: + Ui::HelpMessageDialog *ui; + QString header; + QString coreOptions; + QString uiOptions; + +private slots: + void on_okButton_accepted(); +}; + + +/** "Shutdown" window */ +class ShutdownWindow : public QObject +{ + Q_OBJECT + +public: + static void showShutdownWindow(BitcoinGUI *window); +}; + +#endif // UTILITYDIALOG_H diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 14f29c933..01f5a304a 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -554,3 +554,27 @@ void WalletModel::listLockedCoins(std::vector<COutPoint>& vOutpts) LOCK(wallet->cs_wallet); wallet->ListLockedCoins(vOutpts); } + +void WalletModel::loadReceiveRequests(std::vector<std::string>& vReceiveRequests) +{ + LOCK(wallet->cs_wallet); + BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, wallet->mapAddressBook) + BOOST_FOREACH(const PAIRTYPE(std::string, std::string)& item2, item.second.destdata) + if (item2.first.size() > 2 && item2.first.substr(0,2) == "rr") // receive request + vReceiveRequests.push_back(item2.second); +} + +bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest) +{ + CTxDestination dest = CBitcoinAddress(sAddress).Get(); + + std::stringstream ss; + ss << nId; + std::string key = "rr" + ss.str(); // "rr" prefix = "receive request" in destdata + + LOCK(wallet->cs_wallet); + if (sRequest.empty()) + return wallet->EraseDestData(dest, key); + else + return wallet->AddDestData(dest, key, sRequest); +} diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 1a4d25615..600bef346 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -36,9 +36,9 @@ QT_END_NAMESPACE class SendCoinsRecipient { public: - explicit SendCoinsRecipient() : amount(0) { } + explicit SendCoinsRecipient() : amount(0), nVersion(SendCoinsRecipient::CURRENT_VERSION) { } explicit SendCoinsRecipient(const QString &addr, const QString &label, quint64 amount, const QString &message): - address(addr), label(label), amount(amount), message(message) {} + address(addr), label(label), amount(amount), message(message), nVersion(SendCoinsRecipient::CURRENT_VERSION) {} // If from an insecure payment request, this is used for storing // the addresses, e.g. address-A<br />address-B<br />address-C. @@ -55,6 +55,41 @@ public: PaymentRequestPlus paymentRequest; // Empty if no authentication or invalid signature/cert/etc. QString authenticatedMerchant; + + static const int CURRENT_VERSION=1; + int nVersion; + + IMPLEMENT_SERIALIZE + ( + SendCoinsRecipient* pthis = const_cast<SendCoinsRecipient*>(this); + + std::string sAddress = pthis->address.toStdString(); + std::string sLabel = pthis->label.toStdString(); + std::string sMessage = pthis->message.toStdString(); + std::string sPaymentRequest; + if (!fRead && pthis->paymentRequest.IsInitialized()) + pthis->paymentRequest.SerializeToString(&sPaymentRequest); + std::string sAuthenticatedMerchant = pthis->authenticatedMerchant.toStdString(); + + READWRITE(pthis->nVersion); + nVersion = pthis->nVersion; + READWRITE(sAddress); + READWRITE(sLabel); + READWRITE(amount); + READWRITE(sMessage); + READWRITE(sPaymentRequest); + READWRITE(sAuthenticatedMerchant); + + if (fRead) + { + pthis->address = QString::fromStdString(sAddress); + pthis->label = QString::fromStdString(sLabel); + pthis->message = QString::fromStdString(sMessage); + if (!sPaymentRequest.empty()) + pthis->paymentRequest.parse(QByteArray::fromRawData(sPaymentRequest.data(), sPaymentRequest.size())); + pthis->authenticatedMerchant = QString::fromStdString(sAuthenticatedMerchant); + } + ) }; /** Interface to Bitcoin wallet from Qt view code. */ @@ -152,6 +187,9 @@ public: void unlockCoin(COutPoint& output); void listLockedCoins(std::vector<COutPoint>& vOutpts); + void loadReceiveRequests(std::vector<std::string>& vReceiveRequests); + bool saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest); + private: CWallet *wallet; diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index c801b284c..18c8bb6e6 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -116,9 +116,14 @@ Value importprivkey(const Array& params, bool fHelp) if (pwalletMain->HaveKey(vchAddress)) return Value::null; + pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = 1; + if (!pwalletMain->AddKeyPubKey(key, pubkey)) throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); + // whenever a key is imported, we need to scan the whole chain + pwalletMain->nTimeFirstKey = 1; // 0 would be considered 'no value' + if (fRescan) { pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true); pwalletMain->ReacceptWalletTransactions(); diff --git a/src/wallet.cpp b/src/wallet.cpp index 9065ba848..84642bee6 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1534,7 +1534,19 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const string& strNam bool CWallet::DelAddressBook(const CTxDestination& address) { + AssertLockHeld(cs_wallet); // mapAddressBook + + if(fFileBacked) + { + // Delete destdata tuples associated with address + std::string strAddress = CBitcoinAddress(address).ToString(); + BOOST_FOREACH(const PAIRTYPE(string, string) &item, mapAddressBook[address].destdata) + { + CWalletDB(strWalletFile).EraseDestData(strAddress, item.first); + } + } + mapAddressBook.erase(address); NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), "", CT_DELETED); if (!fFileBacked) @@ -2008,3 +2020,45 @@ void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const { for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++) mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off } + +bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value) +{ + if (boost::get<CNoDestination>(&dest)) + return false; + + mapAddressBook[dest].destdata.insert(std::make_pair(key, value)); + if (!fFileBacked) + return true; + return CWalletDB(strWalletFile).WriteDestData(CBitcoinAddress(dest).ToString(), key, value); +} + +bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key) +{ + if (!mapAddressBook[dest].destdata.erase(key)) + return false; + if (!fFileBacked) + return true; + return CWalletDB(strWalletFile).EraseDestData(CBitcoinAddress(dest).ToString(), key); +} + +bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value) +{ + mapAddressBook[dest].destdata.insert(std::make_pair(key, value)); + return true; +} + +bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const +{ + std::map<CTxDestination, CAddressBookData>::const_iterator i = mapAddressBook.find(dest); + if(i != mapAddressBook.end()) + { + CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key); + if(j != i->second.destdata.end()) + { + if(value) + *value = j->second; + return true; + } + } + return false; +} diff --git a/src/wallet.h b/src/wallet.h index e4452a309..dc8c007ac 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -83,6 +83,9 @@ public: { purpose = "unknown"; } + + typedef std::map<std::string, std::string> StringMap; + StringMap destdata; }; /** A CWallet is an extension of a keystore, which also maintains a set of transactions and balances, @@ -189,6 +192,15 @@ public: bool AddCScript(const CScript& redeemScript); bool LoadCScript(const CScript& redeemScript) { return CCryptoKeyStore::AddCScript(redeemScript); } + /// Adds a destination data tuple to the store, and saves it to disk + bool AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value); + /// Erases a destination data tuple in the store and on disk + bool EraseDestData(const CTxDestination &dest, const std::string &key); + /// Adds a destination data tuple to the store, without saving it to disk + bool LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value); + /// Look up a destination data tuple in the store, return true if found false otherwise + bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const; + bool Unlock(const SecureString& strWalletPassphrase); bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase); bool EncryptWallet(const SecureString& strWalletPassphrase); diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 9c5bddba6..2e61c6cd5 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -564,6 +564,18 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, { ssValue >> pwallet->nOrderPosNext; } + else if (strType == "destdata") + { + std::string strAddress, strKey, strValue; + ssKey >> strAddress; + ssKey >> strKey; + ssValue >> strValue; + if (!pwallet->LoadDestData(CBitcoinAddress(strAddress).Get(), strKey, strValue)) + { + strErr = "Error reading wallet database: LoadDestData failed"; + return false; + } + } } catch (...) { return false; @@ -865,3 +877,15 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename) { return CWalletDB::Recover(dbenv, filename, false); } + +bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value) +{ + nWalletDBUpdated++; + return Write(boost::make_tuple(std::string("destdata"), address, key), value); +} + +bool CWalletDB::EraseDestData(const std::string &address, const std::string &key) +{ + nWalletDBUpdated++; + return Erase(boost::make_tuple(string("destdata"), address, key)); +} diff --git a/src/walletdb.h b/src/walletdb.h index 88ba89f9d..15af28724 100644 --- a/src/walletdb.h +++ b/src/walletdb.h @@ -124,6 +124,11 @@ public: bool ReadAccount(const std::string& strAccount, CAccount& account); bool WriteAccount(const std::string& strAccount, const CAccount& account); + + /// Write destination data key,value tuple to database + bool WriteDestData(const std::string &address, const std::string &key, const std::string &value); + /// Erase destination data tuple from wallet database + bool EraseDestData(const std::string &address, const std::string &key); private: bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry); public: |