Rename CClaimTrieCache to CClaimTrieUpdateBuffer #156

Closed
kaykurokawa wants to merge 276 commits from cclaimtriecache_change into master
171 changed files with 2633 additions and 1514 deletions
Showing only changes of commit 361c99b104 - Show all commits

View file

@ -10,6 +10,7 @@ env:
global: global:
- MAKEJOBS=-j3 - MAKEJOBS=-j3
- RUN_TESTS=false - RUN_TESTS=false
- BOOST_TEST_RANDOM=1$TRAVIS_BUILD_ID
- CCACHE_SIZE=100M - CCACHE_SIZE=100M
- CCACHE_TEMPDIR=/tmp/.ccache-temp - CCACHE_TEMPDIR=/tmp/.ccache-temp
- CCACHE_COMPRESS=1 - CCACHE_COMPRESS=1
@ -25,19 +26,19 @@ matrix:
fast_finish: true fast_finish: true
include: include:
- compiler: ": ARM" - compiler: ": ARM"
env: HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat" env: HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports"
- compiler: ": bitcoind"
env: HOST=x86_64-unknown-linux-gnu PACKAGES="bc" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat CPPFLAGS=-DDEBUG_LOCKORDER"
- compiler: ": No wallet"
env: HOST=x86_64-unknown-linux-gnu DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat"
- compiler: ": 32-bit + dash"
env: HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat" USE_SHELL="/bin/dash"
- compiler: ": Cross-Mac"
env: HOST=x86_64-apple-darwin11 PACKAGES="cmake libcap-dev libz-dev libbz2-dev" OSX_SDK=10.9 GOAL="deploy"
- compiler: ": Win64"
env: HOST=x86_64-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64 mingw-w64-dev wine bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui" MAKEJOBS="-j2"
- compiler: ": Win32" - compiler: ": Win32"
env: HOST=i686-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-i686 g++-mingw-w64-i686 binutils-mingw-w64-i686 mingw-w64-dev wine bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui" MAKEJOBS="-j2" env: HOST=i686-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-i686 g++-mingw-w64-i686 binutils-mingw-w64-i686 mingw-w64-dev wine bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" MAKEJOBS="-j2"
- compiler: ": 32-bit + dash"
env: HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash"
- compiler: ": Win64"
env: HOST=x86_64-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64 mingw-w64-dev wine bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" MAKEJOBS="-j2"
- compiler: ": bitcoind"
env: HOST=x86_64-unknown-linux-gnu PACKAGES="bc" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER"
- compiler: ": No wallet"
env: HOST=x86_64-unknown-linux-gnu DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports"
- compiler: ": Cross-Mac"
env: HOST=x86_64-apple-darwin11 PACKAGES="cmake libcap-dev libz-dev libbz2-dev" BITCOIN_CONFIG="--enable-reduce-exports" OSX_SDK=10.9 GOAL="deploy"
install: install:
- if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get update; fi - if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get update; fi
- if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES; fi - if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES; fi

View file

@ -115,9 +115,9 @@ AC_ARG_ENABLE([hardening],
AC_ARG_ENABLE([reduce-exports], AC_ARG_ENABLE([reduce-exports],
[AS_HELP_STRING([--enable-reduce-exports], [AS_HELP_STRING([--enable-reduce-exports],
[attempt to reduce exported symbols in the resulting executables (default is yes)])], [attempt to reduce exported symbols in the resulting executables (default is no)])],
[use_reduce_exports=$enableval], [use_reduce_exports=$enableval],
[use_reduce_exports=auto]) [use_reduce_exports=no])
AC_ARG_ENABLE([ccache], AC_ARG_ENABLE([ccache],
[AS_HELP_STRING([--enable-ccache], [AS_HELP_STRING([--enable-ccache],
@ -133,7 +133,7 @@ AC_ARG_ENABLE([lcov],
AC_ARG_ENABLE([glibc-back-compat], AC_ARG_ENABLE([glibc-back-compat],
[AS_HELP_STRING([--enable-glibc-back-compat], [AS_HELP_STRING([--enable-glibc-back-compat],
[enable backwards compatibility with glibc and libstdc++])], [enable backwards compatibility with glibc])],
[use_glibc_compat=$enableval], [use_glibc_compat=$enableval],
[use_glibc_compat=no]) [use_glibc_compat=no])
@ -350,8 +350,8 @@ if test x$use_lcov = xyes; then
[AC_MSG_ERROR("lcov testing requested but --coverage flag does not work")]) [AC_MSG_ERROR("lcov testing requested but --coverage flag does not work")])
fi fi
dnl Require little endian dnl Check for endianness
AC_C_BIGENDIAN([AC_MSG_ERROR("Big Endian not supported")]) AC_C_BIGENDIAN
dnl Check for pthread compile/link requirements dnl Check for pthread compile/link requirements
AX_PTHREAD AX_PTHREAD
@ -438,17 +438,22 @@ if test x$TARGET_OS = xdarwin; then
AX_CHECK_LINK_FLAG([[-Wl,-dead_strip]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip"]) AX_CHECK_LINK_FLAG([[-Wl,-dead_strip]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip"])
fi fi
AC_CHECK_HEADERS([endian.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h sys/prctl.h]) AC_CHECK_HEADERS([endian.h byteswap.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h sys/prctl.h])
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([strnlen])
AC_CHECK_DECLS([le32toh, le64toh, htole32, htole64, be32toh, be64toh, htobe32, htobe64],,, AC_CHECK_DECLS([le16toh, le32toh, le64toh, htole16, htole32, htole64, be16toh, be32toh, be64toh, htobe16, htobe32, htobe64],,,
[#if HAVE_ENDIAN_H [#if HAVE_ENDIAN_H
#include <endian.h> #include <endian.h>
#endif]) #endif])
AC_CHECK_DECLS([bswap_16, bswap_32, bswap_64],,,
[#if HAVE_BYTESWAP_H
#include <byteswap.h>
#endif])
dnl Check for MSG_NOSIGNAL dnl Check for MSG_NOSIGNAL
AC_MSG_CHECKING(for MSG_NOSIGNAL) AC_MSG_CHECKING(for MSG_NOSIGNAL)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/socket.h>]], AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/socket.h>]],
@ -471,22 +476,14 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([
[ [
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
if test x$use_reduce_exports = xyes; then if test x$use_reduce_exports = xyes; then
AC_MSG_ERROR([Cannot find a working visibility attribute. Use --disable-reduced-exports.]) AC_MSG_ERROR([Cannot find a working visibility attribute. Use --disable-reduce-exports.])
fi fi
AC_MSG_WARN([Cannot find a working visibility attribute. Disabling reduced exports.])
use_reduce_exports=no
] ]
) )
if test x$use_reduce_exports != xno; then if test x$use_reduce_exports = xyes; then
AX_CHECK_COMPILE_FLAG([-fvisibility=hidden],[RE_CXXFLAGS="-fvisibility=hidden"], AX_CHECK_COMPILE_FLAG([-fvisibility=hidden],[RE_CXXFLAGS="-fvisibility=hidden"],
[ [AC_MSG_ERROR([Cannot set default symbol visibility. Use --disable-reduce-exports.])])
if test x$use_reduce_exports = xyes; then
AC_MSG_ERROR([Cannot set default symbol visibility. Use --disable-reduced-exports.])
fi
AC_MSG_WARN([Cannot set default symbol visibility. Disabling reduced exports.])
use_reduce_exports=no
])
fi fi
LEVELDB_CPPFLAGS= LEVELDB_CPPFLAGS=
@ -533,7 +530,7 @@ AX_BOOST_THREAD
AX_BOOST_CHRONO AX_BOOST_CHRONO
if test x$use_reduce_exports != xno; then if test x$use_reduce_exports = xyes; then
AC_MSG_CHECKING([for working boost reduced exports]) AC_MSG_CHECKING([for working boost reduced exports])
TEMP_CPPFLAGS="$CPPFLAGS" TEMP_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS" CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS"
@ -547,25 +544,14 @@ if test x$use_reduce_exports != xno; then
#endif #endif
]])],[ ]])],[
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
],[: ],[
if test x$use_reduce_exports = xauto; then AC_MSG_ERROR([boost versions < 1.49 are known to be broken with reduced exports. Use --disable-reduce-exports.])
use_reduce_exports=no
else
if test x$use_reduce_exports = xyes; then
AC_MSG_ERROR([boost versions < 1.49 are known to be broken with reduced exports. Use --disable-reduced-exports.])
fi
fi
AC_MSG_RESULT(no)
AC_MSG_WARN([boost versions < 1.49 are known to have symbol visibility issues. Disabling reduced exports.])
]) ])
CPPFLAGS="$TEMP_CPPFLAGS" CPPFLAGS="$TEMP_CPPFLAGS"
fi fi
elif test x$use_reduce_exports = xauto; then
use_reduce_exports=yes
fi fi
if test x$use_reduce_exports != xno; then if test x$use_reduce_exports = xyes; then
CXXFLAGS="$CXXFLAGS $RE_CXXFLAGS" CXXFLAGS="$CXXFLAGS $RE_CXXFLAGS"
AX_CHECK_LINK_FLAG([[-Wl,--exclude-libs,ALL]], [RELDFLAGS="-Wl,--exclude-libs,ALL"]) AX_CHECK_LINK_FLAG([[-Wl,--exclude-libs,ALL]], [RELDFLAGS="-Wl,--exclude-libs,ALL"])
fi fi
@ -827,7 +813,7 @@ else
fi fi
AC_MSG_CHECKING([whether to reduce exports]) AC_MSG_CHECKING([whether to reduce exports])
if test x$use_reduce_exports != xno; then if test x$use_reduce_exports = xyes; then
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
else else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
@ -849,7 +835,6 @@ AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes])
AM_CONDITIONAL([USE_COMPARISON_TOOL],[test x$use_comparison_tool != xno]) AM_CONDITIONAL([USE_COMPARISON_TOOL],[test x$use_comparison_tool != xno])
AM_CONDITIONAL([USE_COMPARISON_TOOL_REORG_TESTS],[test x$use_comparison_tool_reorg_test != xno]) AM_CONDITIONAL([USE_COMPARISON_TOOL_REORG_TESTS],[test x$use_comparison_tool_reorg_test != xno])
AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes]) AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes])
AM_CONDITIONAL([USE_LIBSECP256K1],[test x$use_libsecp256k1 = xyes])
AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version]) AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version])
AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version]) AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version])

View file

@ -16,6 +16,9 @@ Repository Tools
Specific tools for developers working on this repository. Specific tools for developers working on this repository.
Contains the script `github-merge.sh` for merging github pull requests securely and signing them using GPG. Contains the script `github-merge.sh` for merging github pull requests securely and signing them using GPG.
### [Verify-Commits](/contrib/verify-commits) ###
Tool to verify that every merge commit was signed by a developer using the above `github-merge.sh` script.
### [Linearize](/contrib/linearize) ### ### [Linearize](/contrib/linearize) ###
Construct a linear, no-fork, best version of the blockchain. Construct a linear, no-fork, best version of the blockchain.

View file

@ -20,8 +20,8 @@ if cmd == "backupwallet":
try: try:
path = raw_input("Enter destination path/filename: ") path = raw_input("Enter destination path/filename: ")
print access.backupwallet(path) print access.backupwallet(path)
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "encryptwallet": elif cmd == "encryptwallet":
try: try:
@ -32,29 +32,29 @@ elif cmd == "encryptwallet":
print "\n---Wallet encrypted. Server stopping, restart to run with encrypted wallet---\n" print "\n---Wallet encrypted. Server stopping, restart to run with encrypted wallet---\n"
else: else:
print "\n---Passphrases do not match---\n" print "\n---Passphrases do not match---\n"
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "getaccount": elif cmd == "getaccount":
try: try:
addr = raw_input("Enter a Bitcoin address: ") addr = raw_input("Enter a Bitcoin address: ")
print access.getaccount(addr) print access.getaccount(addr)
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "getaccountaddress": elif cmd == "getaccountaddress":
try: try:
acct = raw_input("Enter an account name: ") acct = raw_input("Enter an account name: ")
print access.getaccountaddress(acct) print access.getaccountaddress(acct)
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "getaddressesbyaccount": elif cmd == "getaddressesbyaccount":
try: try:
acct = raw_input("Enter an account name: ") acct = raw_input("Enter an account name: ")
print access.getaddressesbyaccount(acct) print access.getaddressesbyaccount(acct)
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "getbalance": elif cmd == "getbalance":
try: try:
@ -64,57 +64,57 @@ elif cmd == "getbalance":
print access.getbalance(acct, mc) print access.getbalance(acct, mc)
except: except:
print access.getbalance() print access.getbalance()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "getblockbycount": elif cmd == "getblockbycount":
try: try:
height = raw_input("Height: ") height = raw_input("Height: ")
print access.getblockbycount(height) print access.getblockbycount(height)
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "getblockcount": elif cmd == "getblockcount":
try: try:
print access.getblockcount() print access.getblockcount()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "getblocknumber": elif cmd == "getblocknumber":
try: try:
print access.getblocknumber() print access.getblocknumber()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "getconnectioncount": elif cmd == "getconnectioncount":
try: try:
print access.getconnectioncount() print access.getconnectioncount()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "getdifficulty": elif cmd == "getdifficulty":
try: try:
print access.getdifficulty() print access.getdifficulty()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "getgenerate": elif cmd == "getgenerate":
try: try:
print access.getgenerate() print access.getgenerate()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "gethashespersec": elif cmd == "gethashespersec":
try: try:
print access.gethashespersec() print access.gethashespersec()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "getinfo": elif cmd == "getinfo":
try: try:
print access.getinfo() print access.getinfo()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "getnewaddress": elif cmd == "getnewaddress":
try: try:
@ -123,8 +123,8 @@ elif cmd == "getnewaddress":
print access.getnewaddress(acct) print access.getnewaddress(acct)
except: except:
print access.getnewaddress() print access.getnewaddress()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "getreceivedbyaccount": elif cmd == "getreceivedbyaccount":
try: try:
@ -134,8 +134,8 @@ elif cmd == "getreceivedbyaccount":
print access.getreceivedbyaccount(acct, mc) print access.getreceivedbyaccount(acct, mc)
except: except:
print access.getreceivedbyaccount() print access.getreceivedbyaccount()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "getreceivedbyaddress": elif cmd == "getreceivedbyaddress":
try: try:
@ -145,15 +145,15 @@ elif cmd == "getreceivedbyaddress":
print access.getreceivedbyaddress(addr, mc) print access.getreceivedbyaddress(addr, mc)
except: except:
print access.getreceivedbyaddress() print access.getreceivedbyaddress()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "gettransaction": elif cmd == "gettransaction":
try: try:
txid = raw_input("Enter a transaction ID: ") txid = raw_input("Enter a transaction ID: ")
print access.gettransaction(txid) print access.gettransaction(txid)
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "getwork": elif cmd == "getwork":
try: try:
@ -162,8 +162,8 @@ elif cmd == "getwork":
print access.gettransaction(data) print access.gettransaction(data)
except: except:
print access.gettransaction() print access.gettransaction()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "help": elif cmd == "help":
try: try:
@ -172,8 +172,8 @@ elif cmd == "help":
print access.help(cmd) print access.help(cmd)
except: except:
print access.help() print access.help()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "listaccounts": elif cmd == "listaccounts":
try: try:
@ -182,8 +182,8 @@ elif cmd == "listaccounts":
print access.listaccounts(mc) print access.listaccounts(mc)
except: except:
print access.listaccounts() print access.listaccounts()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "listreceivedbyaccount": elif cmd == "listreceivedbyaccount":
try: try:
@ -193,8 +193,8 @@ elif cmd == "listreceivedbyaccount":
print access.listreceivedbyaccount(mc, incemp) print access.listreceivedbyaccount(mc, incemp)
except: except:
print access.listreceivedbyaccount() print access.listreceivedbyaccount()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "listreceivedbyaddress": elif cmd == "listreceivedbyaddress":
try: try:
@ -204,8 +204,8 @@ elif cmd == "listreceivedbyaddress":
print access.listreceivedbyaddress(mc, incemp) print access.listreceivedbyaddress(mc, incemp)
except: except:
print access.listreceivedbyaddress() print access.listreceivedbyaddress()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "listtransactions": elif cmd == "listtransactions":
try: try:
@ -216,8 +216,8 @@ elif cmd == "listtransactions":
print access.listtransactions(acct, count, frm) print access.listtransactions(acct, count, frm)
except: except:
print access.listtransactions() print access.listtransactions()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "move": elif cmd == "move":
try: try:
@ -230,8 +230,8 @@ elif cmd == "move":
print access.move(frm, to, amt, mc, comment) print access.move(frm, to, amt, mc, comment)
except: except:
print access.move(frm, to, amt) print access.move(frm, to, amt)
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "sendfrom": elif cmd == "sendfrom":
try: try:
@ -245,8 +245,8 @@ elif cmd == "sendfrom":
print access.sendfrom(frm, to, amt, mc, comment, commentto) print access.sendfrom(frm, to, amt, mc, comment, commentto)
except: except:
print access.sendfrom(frm, to, amt) print access.sendfrom(frm, to, amt)
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "sendmany": elif cmd == "sendmany":
try: try:
@ -258,8 +258,8 @@ elif cmd == "sendmany":
print access.sendmany(frm,to,mc,comment) print access.sendmany(frm,to,mc,comment)
except: except:
print access.sendmany(frm,to) print access.sendmany(frm,to)
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "sendtoaddress": elif cmd == "sendtoaddress":
try: try:
@ -271,16 +271,16 @@ elif cmd == "sendtoaddress":
print access.sendtoaddress(to,amt,comment,commentto) print access.sendtoaddress(to,amt,comment,commentto)
except: except:
print access.sendtoaddress(to,amt) print access.sendtoaddress(to,amt)
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "setaccount": elif cmd == "setaccount":
try: try:
addr = raw_input("Address: ") addr = raw_input("Address: ")
acct = raw_input("Account:") acct = raw_input("Account:")
print access.setaccount(addr,acct) print access.setaccount(addr,acct)
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "setgenerate": elif cmd == "setgenerate":
try: try:
@ -290,36 +290,36 @@ elif cmd == "setgenerate":
print access.setgenerate(gen, cpus) print access.setgenerate(gen, cpus)
except: except:
print access.setgenerate(gen) print access.setgenerate(gen)
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "settxfee": elif cmd == "settxfee":
try: try:
amt = raw_input("Amount:") amt = raw_input("Amount:")
print access.settxfee(amt) print access.settxfee(amt)
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "stop": elif cmd == "stop":
try: try:
print access.stop() print access.stop()
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "validateaddress": elif cmd == "validateaddress":
try: try:
addr = raw_input("Address: ") addr = raw_input("Address: ")
print access.validateaddress(addr) print access.validateaddress(addr)
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "walletpassphrase": elif cmd == "walletpassphrase":
try: try:
pwd = getpass.getpass(prompt="Enter wallet passphrase: ") pwd = getpass.getpass(prompt="Enter wallet passphrase: ")
access.walletpassphrase(pwd, 60) access.walletpassphrase(pwd, 60)
print "\n---Wallet unlocked---\n" print "\n---Wallet unlocked---\n"
except: except Exception as inst:
print "\n---An error occurred---\n" print inst
elif cmd == "walletpassphrasechange": elif cmd == "walletpassphrasechange":
try: try:
@ -328,10 +328,8 @@ elif cmd == "walletpassphrasechange":
access.walletpassphrasechange(pwd, pwd2) access.walletpassphrasechange(pwd, pwd2)
print print
print "\n---Passphrase changed---\n" print "\n---Passphrase changed---\n"
except: except Exception as inst:
print print inst
print "\n---An error occurred---\n"
print
else: else:
print "Command not found or not supported" print "Command not found or not supported"

View file

@ -1,2 +1,3 @@
debian/manpages/bitcoind.1 debian/manpages/bitcoind.1
debian/manpages/bitcoin.conf.5 debian/manpages/bitcoin.conf.5
debian/manpages/bitcoin-cli.1

View file

@ -0,0 +1,48 @@
.TH BITCOIN-CLI "1" "February 2015" "bitcoin-cli 0.10"
.SH NAME
bitcoin-cli \- a remote procedure call client for Bitcoin Core.
.SH SYNOPSIS
bitcoin-cli [options] <command> [params] \- Send command to Bitcoin Core.
.TP
bitcoin-cli [options] help \- Asks Bitcoin Core for a list of supported commands.
.SH DESCRIPTION
This manual page documents the bitcoin-cli program. bitcoin-cli is an RPC client used to send commands to Bitcoin Core.
.SH OPTIONS
.TP
\fB\-?\fR
Show the help message.
.TP
\fB\-conf=\fR<file>
Specify configuration file (default: bitcoin.conf).
.TP
\fB\-datadir=\fR<dir>
Specify data directory.
.TP
\fB\-testnet\fR
Connect to a Bitcoin Core instance running in testnet mode.
.TP
\fB\-regtest\fR
Connect to a Bitcoin Core instance running in regtest mode (see documentation for -regtest on bitcoind).
.TP
\fB\-rpcuser=\fR<user>
Username for JSON\-RPC connections.
.TP
\fB\-rpcpassword=\fR<pw>
Password for JSON\-RPC connections.
.TP
\fB\-rpcport=\fR<port>
Listen for JSON\-RPC connections on <port> (default: 8332 or testnet: 18332).
.TP
\fB\-rpcconnect=\fR<ip>
Send commands to node running on <ip> (default: 127.0.0.1).
.TP
\fB\-rpcssl\fR=\fI1\fR
Use OpenSSL (https) for JSON\-RPC connections (see the Bitcoin Wiki for SSL setup instructions).
.SH "SEE ALSO"
\fBbitcoind\fP, \fBbitcoin.conf\fP
.SH AUTHOR
This manual page was written by Ciemon Dunville <ciemon@gmail.com>. Permission is granted to copy, distribute and/or modify this document under the terms of the MIT License.
The complete text of the MIT License can be found on the web at \fIhttp://opensource.org/licenses/MIT\fP.

View file

@ -15,6 +15,7 @@ packages:
- "faketime" - "faketime"
- "bsdmainutils" - "bsdmainutils"
- "binutils-gold" - "binutils-gold"
- "libstdc++6-4.6-pic"
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"
@ -23,7 +24,7 @@ files: []
script: | script: |
WRAP_DIR=$HOME/wrapped WRAP_DIR=$HOME/wrapped
HOSTS="i686-pc-linux-gnu x86_64-unknown-linux-gnu" HOSTS="i686-pc-linux-gnu x86_64-unknown-linux-gnu"
CONFIGFLAGS="--enable-upnp-default --enable-glibc-back-compat" CONFIGFLAGS="--enable-upnp-default --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++"
FAKETIME_HOST_PROGS="" FAKETIME_HOST_PROGS=""
FAKETIME_PROGS="date ar ranlib nm strip" FAKETIME_PROGS="date ar ranlib nm strip"
@ -69,6 +70,14 @@ script: |
make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}"
done done
# Ubuntu precise hack: Not an issue in later versions.
# Precise's libstdc++.a is non-pic. There's an optional libstdc++6-4.6-pic
# package which provides libstdc++_pic.a, but the linker can't find it.
# Symlink it to a path that will be included in our link-line so that the
# linker picks it up before the default libstdc++.a.
# This is only necessary for 64bit.
ln -s /usr/lib/gcc/x86_64-linux-gnu/4.6/libstdc++_pic.a ${BASEPREFIX}/x86_64-unknown-linux-gnu/lib/libstdc++.a
# Create the release tarball using (arbitrarily) the first host # Create the release tarball using (arbitrarily) the first host
./autogen.sh ./autogen.sh
./configure --prefix=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'` ./configure --prefix=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`

View file

@ -27,7 +27,7 @@ files:
script: | script: |
WRAP_DIR=$HOME/wrapped WRAP_DIR=$HOME/wrapped
HOSTS="x86_64-apple-darwin11" HOSTS="x86_64-apple-darwin11"
CONFIGFLAGS="--enable-upnp-default GENISOIMAGE=$WRAP_DIR/genisoimage" CONFIGFLAGS="--enable-upnp-default --enable-reduce-exports GENISOIMAGE=$WRAP_DIR/genisoimage"
FAKETIME_HOST_PROGS="" FAKETIME_HOST_PROGS=""
FAKETIME_PROGS="ar ranlib date dmg genisoimage" FAKETIME_PROGS="ar ranlib date dmg genisoimage"

View file

@ -26,7 +26,7 @@ files: []
script: | script: |
WRAP_DIR=$HOME/wrapped WRAP_DIR=$HOME/wrapped
HOSTS="x86_64-w64-mingw32 i686-w64-mingw32" HOSTS="x86_64-w64-mingw32 i686-w64-mingw32"
CONFIGFLAGS="--enable-upnp-default" CONFIGFLAGS="--enable-upnp-default --enable-reduce-exports"
FAKETIME_HOST_PROGS="g++ ar ranlib nm windres strip" FAKETIME_HOST_PROGS="g++ ar ranlib nm windres strip"
FAKETIME_PROGS="date makensis zip" FAKETIME_PROGS="date makensis zip"

View file

@ -4,6 +4,7 @@ SystemD: bitcoind.service
Upstart: bitcoind.conf Upstart: bitcoind.conf
OpenRC: bitcoind.openrc OpenRC: bitcoind.openrc
bitcoind.openrcconf bitcoind.openrcconf
CentOS: bitcoind.init
have been made available to assist packagers in creating node packages here. have been made available to assist packagers in creating node packages here.

View file

@ -0,0 +1,67 @@
#!/bin/bash
#
# bitcoind The bitcoin core server.
#
#
# chkconfig: 345 80 20
# description: bitcoind
# processname: bitcoind
#
# Source function library.
. /etc/init.d/functions
# you can override defaults in /etc/sysconfig/bitcoind, see below
if [ -f /etc/sysconfig/bitcoind ]; then
. /etc/sysconfig/bitcoind
fi
RETVAL=0
prog=bitcoind
# you can override the lockfile via BITCOIND_LOCKFILE in /etc/sysconfig/bitcoind
lockfile=${BITCOIND_LOCKFILE-/var/lock/subsys/bitcoind}
# bitcoind defaults to /usr/bin/bitcoind, override with BITCOIND_BIN
bitcoind=${BITCOIND_BIN-/usr/bin/bitcoind}
# bitcoind opts default to -disablewallet, override with BITCOIND_OPTS
bitcoind_opts=${BITCOIND_OPTS--disablewallet}
start() {
echo -n $"Starting $prog: "
daemon $DAEMONOPTS $bitcoind $bitcoind_opts
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch $lockfile
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
killproc $prog
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f $lockfile
return $RETVAL
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status $prog
;;
restart)
stop
start
;;
*)
echo "Usage: service $prog {start|stop|status|restart}"
exit 1
;;
esac

View file

@ -12,9 +12,11 @@ BITCOIND_CONFIGFILE=${BITCOIND_CONFIGFILE:-/etc/bitcoin/bitcoin.conf}
BITCOIND_PIDDIR=${BITCOIND_PIDDIR:-/var/run/bitcoind} BITCOIND_PIDDIR=${BITCOIND_PIDDIR:-/var/run/bitcoind}
BITCOIND_PIDFILE=${BITCOIND_PIDFILE:-${BITCOIND_PIDDIR}/bitcoind.pid} BITCOIND_PIDFILE=${BITCOIND_PIDFILE:-${BITCOIND_PIDDIR}/bitcoind.pid}
BITCOIND_DATADIR=${BITCOIND_DATADIR:-${BITCOIND_DEFAULT_DATADIR}} BITCOIND_DATADIR=${BITCOIND_DATADIR:-${BITCOIND_DEFAULT_DATADIR}}
BITCOIND_USER=${BITCOIND_USER:-bitcoin} BITCOIND_USER=${BITCOIND_USER:-${BITCOIN_USER:-bitcoin}}
BITCOIND_GROUP=${BITCOIND_GROUP:-bitcoin} BITCOIND_GROUP=${BITCOIND_GROUP:-bitcoin}
BITCOIND_BIN=${BITCOIND_BIN:-/usr/bin/bitcoind} BITCOIND_BIN=${BITCOIND_BIN:-/usr/bin/bitcoind}
BITCOIND_NICE=${BITCOIND_NICE:-${NICELEVEL:-0}}
BITCOIND_OPTS="${BITCOIND_OPTS:-${BITCOIN_OPTS}}"
name="Bitcoin Core Daemon" name="Bitcoin Core Daemon"
description="Bitcoin crypto-currency p2p network daemon" description="Bitcoin crypto-currency p2p network daemon"
@ -28,7 +30,7 @@ command_args="-pid=\"${BITCOIND_PIDFILE}\" \
required_files="${BITCOIND_CONFIGFILE}" required_files="${BITCOIND_CONFIGFILE}"
start_stop_daemon_args="-u ${BITCOIND_USER} \ start_stop_daemon_args="-u ${BITCOIND_USER} \
-N ${BITCOIND_NICE:-0} -w 2000" -N ${BITCOIND_NICE} -w 2000"
pidfile="${BITCOIND_PIDFILE}" pidfile="${BITCOIND_PIDFILE}"
retry=60 retry=60

15
contrib/verify-commits/gpg.sh Executable file
View file

@ -0,0 +1,15 @@
#!/bin/sh
INPUT=$(</dev/stdin)
VALID=false
IFS=$'\n'
for LINE in $(echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null); do
case "$LINE" in "[GNUPG:] VALIDSIG"*)
while read KEY; do
case "$LINE" in "[GNUPG:] VALIDSIG $KEY "*) VALID=true;; esac
done < ./contrib/verify-commits/trusted-keys
esac
done
if ! $VALID; then
exit 1
fi
echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null

View file

@ -0,0 +1,16 @@
#!/bin/bash
if ! [[ "$2" =~ [git@]?[www.]?github.com[:|/]bitcoin/bitcoin[.git]? ]]; then
exit 0
fi
while read LINE; do
set -- A $LINE
if [ "$4" != "refs/heads/master" ]; then
continue
fi
if ! ./contrib/verify-commits/verify-commits.sh $3 > /dev/null 2>&1; then
echo "ERROR: A commit is not signed, can't push"
./contrib/verify-commits/verify-commits.sh
exit 1
fi
done < /dev/stdin

View file

@ -0,0 +1 @@
053038e5ba116cb319fb85f3cb3e062cf1b3df15

View file

@ -0,0 +1,5 @@
71A3B16735405025D447E8F274810B012346C9A6
1F4410F6A89268CE3197A84C57896D2FF8F0B657
01CDF4627A3B88AAE4A571C87588242FBE38D3A8
AF8BE07C7049F3A26B239D5325B3083201782B2F
81291FA67D2C379A006A053FEAB5AF94D9E9ABE7

View file

@ -0,0 +1,51 @@
#!/bin/sh
DIR=$(dirname "$0")
echo "Please verify all commits in the following list are not evil:"
git log "$DIR"
VERIFIED_ROOT=$(cat "${DIR}/trusted-git-root")
HAVE_FAILED=false
IS_SIGNED () {
if [ $1 = $VERIFIED_ROOT ]; then
return 0;
fi
if ! git -c "gpg.program=${DIR}/gpg.sh" verify-commit $1 > /dev/null 2>&1; then
return 1;
fi
local PARENTS=$(git show -s --format=format:%P $1)
for PARENT in $PARENTS; do
if IS_SIGNED $PARENT > /dev/null; then
return 0;
fi
done
if ! "$HAVE_FAILED"; then
echo "No parent of $1 was signed with a trusted key!" > /dev/stderr
echo "Parents are:" > /dev/stderr
for PARENT in $PARENTS; do
git show -s $PARENT > /dev/stderr
done
HAVE_FAILED=true
fi
return 1;
}
if [ x"$1" = "x" ]; then
TEST_COMMIT="HEAD"
else
TEST_COMMIT="$1"
fi
IS_SIGNED "$TEST_COMMIT"
RES=$?
if [ "$RES" = 1 ]; then
if ! "$HAVE_FAILED"; then
echo "$TEST_COMMIT was not signed with a trusted key!"
fi
else
echo "There is a valid path from $TEST_COMMIT to $VERIFIED_ROOT where all commits are signed!"
fi
exit $RES

View file

@ -6,7 +6,6 @@ SDK_PATH ?= $(BASEDIR)/SDKs
NO_QT ?= NO_QT ?=
NO_WALLET ?= NO_WALLET ?=
NO_UPNP ?= NO_UPNP ?=
USE_LINUX_STATIC_QT5 ?=
FALLBACK_DOWNLOAD_PATH ?= https://bitcoincore.org/depends-sources FALLBACK_DOWNLOAD_PATH ?= https://bitcoincore.org/depends-sources
BUILD = $(shell ./config.guess) BUILD = $(shell ./config.guess)

View file

@ -23,7 +23,6 @@ NO_QT: Don't download/build/cache qt and its dependencies
NO_WALLET: Don't download/build/cache libs needed to enable the wallet NO_WALLET: Don't download/build/cache libs needed to enable the wallet
NO_UPNP: Don't download/build/cache packages needed for enabling upnp NO_UPNP: Don't download/build/cache packages needed for enabling upnp
DEBUG: disable some optimizations and enable more runtime checking DEBUG: disable some optimizations and enable more runtime checking
USE_LINUX_STATIC_QT5: Build a static qt5 rather than shared qt4. Linux only.
If some packages are not built, for example 'make NO_WALLET=1', the appropriate If some packages are not built, for example 'make NO_WALLET=1', the appropriate
options will be passed to bitcoin's configure. In this case, --disable-wallet. options will be passed to bitcoin's configure. In this case, --disable-wallet.

View file

@ -13,8 +13,13 @@ define $(package)_preprocess_cmds
sed "s/pthread-stubs//" -i configure sed "s/pthread-stubs//" -i configure
endef endef
# Don't install xcb headers to the default path in order to work around a qt
# build issue: https://bugreports.qt.io/browse/QTBUG-34748
# When using qt's internal libxcb, it may end up finding the real headers in
# depends staging. Use a non-default path to avoid that.
define $(package)_config_cmds define $(package)_config_cmds
$($(package)_autoconf) $($(package)_autoconf) --includedir=$(host_prefix)/include/xcb-shared
endef endef
define $(package)_build_cmds define $(package)_build_cmds

View file

@ -4,15 +4,10 @@ native_packages := native_ccache native_comparisontool
qt_native_packages = native_protobuf qt_native_packages = native_protobuf
qt_packages = qrencode protobuf qt_packages = qrencode protobuf
qt46_linux_packages = qt46 expat dbus libxcb xcb_proto libXau xproto freetype libX11 xextproto libXext xtrans libICE libSM qt_linux_packages= qt expat dbus libxcb xcb_proto libXau xproto freetype fontconfig libX11 xextproto libXext xtrans
qt5_linux_packages= qt expat dbus libxcb xcb_proto libXau xproto freetype fontconfig libX11 xextproto libXext xtrans
qt_darwin_packages=qt qt_darwin_packages=qt
qt_mingw32_packages=qt qt_mingw32_packages=qt
qt_linux_$(USE_LINUX_STATIC_QT5):=$(qt5_linux_packages)
qt_linux_:=$(qt46_linux_packages)
qt_linux_packages:=$(qt_linux_$(USE_LINUX_STATIC_QT5))
wallet_packages=bdb wallet_packages=bdb

View file

@ -1,21 +1,31 @@
--- old/qtbase/src/plugins/platforms/xcb/xcb-plugin.pro 2014-07-30 18:17:27.384458441 -0400 --- old/qtbase/src/plugins/platforms/xcb/xcb-plugin.pro 2015-03-17 02:06:42.705930685 +0000
+++ new/qtbase/src/plugins/platforms/xcb/xcb-plugin.pro 2014-07-30 18:18:28.620459303 -0400 +++ new/qtbase/src/plugins/platforms/xcb/xcb-plugin.pro 2015-03-17 02:08:41.281926351 +0000
@@ -101,10 +101,6 @@ @@ -103,7 +103,6 @@
}
}
-DEFINES += $$QMAKE_DEFINES_XCB DEFINES += $$QMAKE_DEFINES_XCB
-LIBS += $$QMAKE_LIBS_XCB LIBS += $$QMAKE_LIBS_XCB
-QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XCB -QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XCB
-
CONFIG += qpa/genericunixfontdatabase CONFIG += qpa/genericunixfontdatabase
contains(QT_CONFIG, dbus) { @@ -118,7 +117,8 @@
@@ -141,3 +137,7 @@ contains(QT_CONFIG, xcb-qt) {
INCLUDEPATH += ../../../3rdparty/xkbcommon/xkbcommon/ DEFINES += XCB_USE_RENDER
} XCB_DIR = ../../../3rdparty/xcb
} - INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/sysinclude
+ + QMAKE_CFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/sysinclude $$QMAKE_CFLAGS_XCB
+DEFINES += $$QMAKE_DEFINES_XCB + QMAKE_CXXFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/sysinclude $$QMAKE_CFLAGS_XCB
+LIBS += $$QMAKE_LIBS_XCB LIBS += -lxcb -L$$OUT_PWD/xcb-static -lxcb-static
+INCLUDEPATH += $$QMAKE_CFLAGS_XCB } else {
LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr
--- old/qtbase/src/plugins/platforms/xcb/xcb-static/xcb-static.pro 2015-03-17 02:07:04.641929383 +0000
+++ new/qtbase/src/plugins/platforms/xcb/xcb-static/xcb-static.pro 2015-03-17 02:10:15.485922059 +0000
@@ -8,7 +8,7 @@
XCB_DIR = ../../../../3rdparty/xcb
-INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/include/xcb $$XCB_DIR/sysinclude
+QMAKE_CFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/include/xcb -I$$XCB_DIR/sysinclude $$QMAKE_CFLAGS_XCB
# ignore compiler warnings in 3rdparty code
QMAKE_CFLAGS_STATIC_LIB+=-w

View file

@ -8,6 +8,7 @@ can be found in the contrib/init folder.
contrib/init/bitcoind.openrc: OpenRC compatible SysV style init script contrib/init/bitcoind.openrc: OpenRC compatible SysV style init script
contrib/init/bitcoind.openrcconf: OpenRC conf.d file contrib/init/bitcoind.openrcconf: OpenRC conf.d file
contrib/init/bitcoind.conf: Upstart service configuration file contrib/init/bitcoind.conf: Upstart service configuration file
contrib/init/bitcoind.init: CentOS compatible SysV style init script
1. Service User 1. Service User
--------------------------------- ---------------------------------
@ -49,6 +50,7 @@ Configuration file: /etc/bitcoin/bitcoin.conf
Data directory: /var/lib/bitcoind Data directory: /var/lib/bitcoind
PID file: /var/run/bitcoind/bitcoind.pid (OpenRC and Upstart) PID file: /var/run/bitcoind/bitcoind.pid (OpenRC and Upstart)
/var/lib/bitcoind/bitcoind.pid (systemd) /var/lib/bitcoind/bitcoind.pid (systemd)
Lock file: /var/lock/subsys/bitcoind (CentOS)
The configuration file, PID directory (if applicable) and data directory The configuration file, PID directory (if applicable) and data directory
should all be owned by the bitcoin user and group. It is advised for security should all be owned by the bitcoin user and group. It is advised for security
@ -81,7 +83,15 @@ Drop bitcoind.conf in /etc/init. Test by running "service bitcoind start"
it will automatically start on reboot. it will automatically start on reboot.
NOTE: This script is incompatible with CentOS 5 and Amazon Linux 2014 as they NOTE: This script is incompatible with CentOS 5 and Amazon Linux 2014 as they
use old versions of Upstart and do not supply the start-stop-daemon uitility. use old versions of Upstart and do not supply the start-stop-daemon utility.
4d) CentOS
Copy bitcoind.init to /etc/init.d/bitcoind. Test by running "service bitcoind start".
Using this script, you can adjust the path and flags to the bitcoind program by
setting the BITCOIND and FLAGS environment variables in the file
/etc/sysconfig/bitcoind. You can also use the DAEMONOPTS environment variable here.
5. Auto-respawn 5. Auto-respawn
----------------------------------- -----------------------------------

76
qa/rpc-tests/invalidateblock.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 InvalidateBlock code
#
from test_framework import BitcoinTestFramework
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
from util import *
class InvalidateTest(BitcoinTestFramework):
def setup_chain(self):
print("Initializing test directory "+self.options.tmpdir)
initialize_chain_clean(self.options.tmpdir, 3)
def setup_network(self):
self.nodes = []
self.is_network_split = False
self.nodes.append(start_node(0, self.options.tmpdir, ["-debug"]))
self.nodes.append(start_node(1, self.options.tmpdir, ["-debug"]))
self.nodes.append(start_node(2, self.options.tmpdir, ["-debug"]))
def run_test(self):
print "Make sure we repopulate setBlockIndexCandidates after InvalidateBlock:"
print "Mine 4 blocks on Node 0"
self.nodes[0].setgenerate(True, 4)
assert(self.nodes[0].getblockcount() == 4)
besthash = self.nodes[0].getbestblockhash()
print "Mine competing 6 blocks on Node 1"
self.nodes[1].setgenerate(True, 6)
assert(self.nodes[1].getblockcount() == 6)
print "Connect nodes to force a reorg"
connect_nodes_bi(self.nodes,0,1)
sync_blocks(self.nodes[0:2])
assert(self.nodes[0].getblockcount() == 6)
badhash = self.nodes[1].getblockhash(2)
print "Invalidate block 2 on node 0 and verify we reorg to node 0's original chain"
self.nodes[0].invalidateblock(badhash)
newheight = self.nodes[0].getblockcount()
newhash = self.nodes[0].getbestblockhash()
if (newheight != 4 or newhash != besthash):
raise AssertionError("Wrong tip for node0, hash %s, height %d"%(newhash,newheight))
print "\nMake sure we won't reorg to a lower work chain:"
connect_nodes_bi(self.nodes,1,2)
print "Sync node 2 to node 1 so both have 6 blocks"
sync_blocks(self.nodes[1:3])
assert(self.nodes[2].getblockcount() == 6)
print "Invalidate block 5 on node 1 so its tip is now at 4"
self.nodes[1].invalidateblock(self.nodes[1].getblockhash(5))
assert(self.nodes[1].getblockcount() == 4)
print "Invalidate block 3 on node 2, so its tip is now 2"
self.nodes[2].invalidateblock(self.nodes[2].getblockhash(3))
assert(self.nodes[2].getblockcount() == 2)
print "..and then mine a block"
self.nodes[2].setgenerate(True, 1)
print "Verify all nodes are at the right height"
time.sleep(5)
for i in xrange(3):
print i,self.nodes[i].getblockcount()
assert(self.nodes[2].getblockcount() == 3)
assert(self.nodes[0].getblockcount() == 4)
node1height = self.nodes[1].getblockcount()
if node1height < 4:
raise AssertionError("Node 1 reorged to a lower height: %d"%node1height)
if __name__ == '__main__':
InvalidateTest().main()

View file

@ -102,6 +102,35 @@ class WalletTest (BitcoinTestFramework):
assert_equal(self.nodes[2].getbalance(), 100) assert_equal(self.nodes[2].getbalance(), 100)
assert_equal(self.nodes[2].getbalance("from1"), 100-21) assert_equal(self.nodes[2].getbalance("from1"), 100-21)
# Send 10 BTC normal
address = self.nodes[0].getnewaddress("test")
self.nodes[2].settxfee(Decimal('0.001'))
txid = self.nodes[2].sendtoaddress(address, 10, "", "", False)
self.nodes[2].setgenerate(True, 1)
self.sync_all()
assert_equal(self.nodes[2].getbalance(), Decimal('89.99900000'))
assert_equal(self.nodes[0].getbalance(), Decimal('10.00000000'))
# Send 10 BTC with subtract fee from amount
txid = self.nodes[2].sendtoaddress(address, 10, "", "", True)
self.nodes[2].setgenerate(True, 1)
self.sync_all()
assert_equal(self.nodes[2].getbalance(), Decimal('79.99900000'))
assert_equal(self.nodes[0].getbalance(), Decimal('19.99900000'))
# Sendmany 10 BTC
txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "", [])
self.nodes[2].setgenerate(True, 1)
self.sync_all()
assert_equal(self.nodes[2].getbalance(), Decimal('69.99800000'))
assert_equal(self.nodes[0].getbalance(), Decimal('29.99900000'))
# Sendmany 10 BTC with subtract fee from amount
txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "", [address])
self.nodes[2].setgenerate(True, 1)
self.sync_all()
assert_equal(self.nodes[2].getbalance(), Decimal('59.99800000'))
assert_equal(self.nodes[0].getbalance(), Decimal('39.99800000'))
if __name__ == '__main__': if __name__ == '__main__':
WalletTest ().main () WalletTest ().main ()

View file

@ -72,7 +72,6 @@ endif
BITCOIN_CORE_H = \ BITCOIN_CORE_H = \
addrman.h \ addrman.h \
alert.h \ alert.h \
allocators.h \
amount.h \ amount.h \
arith_uint256.h \ arith_uint256.h \
base58.h \ base58.h \
@ -89,8 +88,7 @@ BITCOIN_CORE_H = \
compat.h \ compat.h \
compressor.h \ compressor.h \
core_io.h \ core_io.h \
crypter.h \ wallet/db.h \
db.h \
eccryptoverify.h \ eccryptoverify.h \
ecwrapper.h \ ecwrapper.h \
hash.h \ hash.h \
@ -125,7 +123,10 @@ BITCOIN_CORE_H = \
script/standard.h \ script/standard.h \
serialize.h \ serialize.h \
streams.h \ streams.h \
support/allocators/secure.h \
support/allocators/zeroafterfree.h \
support/cleanse.h \ support/cleanse.h \
support/pagelocker.h \
sync.h \ sync.h \
threadsafety.h \ threadsafety.h \
timedata.h \ timedata.h \
@ -139,10 +140,14 @@ BITCOIN_CORE_H = \
utilmoneystr.h \ utilmoneystr.h \
utilstrencodings.h \ utilstrencodings.h \
utiltime.h \ utiltime.h \
validationinterface.h \
version.h \ version.h \
walletdb.h \ wallet/crypter.h \
wallet.h \ wallet/walletdb.h \
wallet_ismine.h \ wallet/wallet.h \
wallet/wallet_ismine.h \
compat/byteswap.h \
compat/endian.h \
compat/sanity.h compat/sanity.h
JSON_H = \ JSON_H = \
@ -191,6 +196,7 @@ libbitcoin_server_a_SOURCES = \
timedata.cpp \ timedata.cpp \
txdb.cpp \ txdb.cpp \
txmempool.cpp \ txmempool.cpp \
validationinterface.cpp \
$(JSON_H) \ $(JSON_H) \
$(BITCOIN_CORE_H) $(BITCOIN_CORE_H)
@ -198,13 +204,13 @@ libbitcoin_server_a_SOURCES = \
# when wallet enabled # when wallet enabled
libbitcoin_wallet_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_wallet_a_CPPFLAGS = $(BITCOIN_INCLUDES)
libbitcoin_wallet_a_SOURCES = \ libbitcoin_wallet_a_SOURCES = \
db.cpp \ wallet/crypter.cpp \
crypter.cpp \ wallet/db.cpp \
rpcdump.cpp \ wallet/rpcdump.cpp \
rpcwallet.cpp \ wallet/rpcwallet.cpp \
wallet.cpp \ wallet/wallet.cpp \
wallet_ismine.cpp \ wallet/wallet_ismine.cpp \
walletdb.cpp \ wallet/walletdb.cpp \
$(BITCOIN_CORE_H) $(BITCOIN_CORE_H)
# crypto primitives library # crypto primitives library
@ -235,7 +241,6 @@ univalue_libbitcoin_univalue_a_SOURCES = \
# common: shared between bitcoind, and bitcoin-qt and non-server tools # common: shared between bitcoind, and bitcoin-qt and non-server tools
libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES)
libbitcoin_common_a_SOURCES = \ libbitcoin_common_a_SOURCES = \
allocators.cpp \
arith_uint256.cpp \ arith_uint256.cpp \
amount.cpp \ amount.cpp \
base58.cpp \ base58.cpp \
@ -267,6 +272,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 = \
support/pagelocker.cpp \
chainparamsbase.cpp \ chainparamsbase.cpp \
clientversion.cpp \ clientversion.cpp \
compat/glibc_sanity.cpp \ compat/glibc_sanity.cpp \
@ -285,7 +291,6 @@ libbitcoin_util_a_SOURCES = \
if GLIBC_BACK_COMPAT if GLIBC_BACK_COMPAT
libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp
libbitcoin_util_a_SOURCES += compat/glibcxx_compat.cpp
endif endif
# cli: shared between bitcoin-cli and bitcoin-qt # cli: shared between bitcoin-cli and bitcoin-qt
@ -377,16 +382,12 @@ libbitcoinconsensus_la_SOURCES = \
if GLIBC_BACK_COMPAT if GLIBC_BACK_COMPAT
libbitcoinconsensus_la_SOURCES += compat/glibc_compat.cpp libbitcoinconsensus_la_SOURCES += compat/glibc_compat.cpp
libbitcoinconsensus_la_SOURCES += compat/glibcxx_compat.cpp
endif endif
libbitcoinconsensus_la_LDFLAGS = -no-undefined $(RELDFLAGS) libbitcoinconsensus_la_LDFLAGS = -no-undefined $(RELDFLAGS)
libbitcoinconsensus_la_LIBADD = $(CRYPTO_LIBS) libbitcoinconsensus_la_LIBADD = $(CRYPTO_LIBS)
libbitcoinconsensus_la_CPPFLAGS = $(CRYPTO_CFLAGS) -I$(builddir)/obj -DBUILD_BITCOIN_INTERNAL libbitcoinconsensus_la_CPPFLAGS = $(CRYPTO_CFLAGS) -I$(builddir)/obj -DBUILD_BITCOIN_INTERNAL
if USE_LIBSECP256K1
libbitcoinconsensus_la_LIBADD += secp256k1/libsecp256k1.la
endif
endif endif
# #

View file

@ -56,6 +56,7 @@ BITCOIN_TESTS =\
test/ncctrie_tests.cpp \ test/ncctrie_tests.cpp \
test/netbase_tests.cpp \ test/netbase_tests.cpp \
test/pmt_tests.cpp \ test/pmt_tests.cpp \
test/pow_tests.cpp \
test/rpc_tests.cpp \ test/rpc_tests.cpp \
test/sanity_tests.cpp \ test/sanity_tests.cpp \
test/script_P2SH_tests.cpp \ test/script_P2SH_tests.cpp \
@ -66,6 +67,7 @@ BITCOIN_TESTS =\
test/sigopcount_tests.cpp \ test/sigopcount_tests.cpp \
test/skiplist_tests.cpp \ test/skiplist_tests.cpp \
test/test_bitcoin.cpp \ test/test_bitcoin.cpp \
test/test_bitcoin.h \
test/timedata_tests.cpp \ test/timedata_tests.cpp \
test/transaction_tests.cpp \ test/transaction_tests.cpp \
test/uint256_tests.cpp \ test/uint256_tests.cpp \
@ -75,7 +77,7 @@ BITCOIN_TESTS =\
if ENABLE_WALLET if ENABLE_WALLET
BITCOIN_TESTS += \ BITCOIN_TESTS += \
test/accounting_tests.cpp \ test/accounting_tests.cpp \
test/wallet_tests.cpp \ wallet/test/wallet_tests.cpp \
test/rpc_wallet_tests.cpp test/rpc_wallet_tests.cpp
endif endif

View file

@ -272,8 +272,9 @@ void CAddrMan::Good_(const CService& addr, int64_t nTime)
// update info // update info
info.nLastSuccess = nTime; info.nLastSuccess = nTime;
info.nLastTry = nTime; info.nLastTry = nTime;
info.nTime = nTime;
info.nAttempts = 0; info.nAttempts = 0;
// nTime is not updated here, to avoid leaking information about
// currently-connected peers.
// if it is already in the tried set, don't do anything else // if it is already in the tried set, don't do anything else
if (info.fInTried) if (info.fInTried)

View file

@ -7,6 +7,7 @@
#include "uint256.h" #include "uint256.h"
#include "utilstrencodings.h" #include "utilstrencodings.h"
#include "crypto/common.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -246,14 +247,14 @@ uint32_t arith_uint256::GetCompact(bool fNegative) const
uint256 ArithToUint256(const arith_uint256 &a) uint256 ArithToUint256(const arith_uint256 &a)
{ {
uint256 b; uint256 b;
// TODO: needs bswap32 on big-endian for(int x=0; x<a.WIDTH; ++x)
memcpy(b.begin(), a.pn, a.size()); WriteLE32(b.begin() + x*4, a.pn[x]);
return b; return b;
} }
arith_uint256 UintToArith256(const uint256 &a) arith_uint256 UintToArith256(const uint256 &a)
{ {
arith_uint256 b; arith_uint256 b;
// TODO: needs bswap32 on big-endian for(int x=0; x<b.WIDTH; ++x)
memcpy(b.pn, a.begin(), a.size()); b.pn[x] = ReadLE32(a.begin() + x*4);
return b; return b;
} }

View file

@ -19,6 +19,7 @@
#include "pubkey.h" #include "pubkey.h"
#include "script/script.h" #include "script/script.h"
#include "script/standard.h" #include "script/standard.h"
#include "support/allocators/zeroafterfree.h"
#include <string> #include <string>
#include <vector> #include <vector>

View file

@ -20,21 +20,21 @@ using namespace json_spirit;
std::string HelpMessageCli() std::string HelpMessageCli()
{ {
string strUsage; string strUsage;
strUsage += _("Options:") + "\n"; strUsage += HelpMessageGroup(_("Options:"));
strUsage += " -? " + _("This help message") + "\n"; strUsage += HelpMessageOpt("-?", _("This help message"));
strUsage += " -conf=<file> " + strprintf(_("Specify configuration file (default: %s)"), "bitcoin.conf") + "\n"; strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), "bitcoin.conf"));
strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n"; strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
strUsage += " -testnet " + _("Use the test network") + "\n"; strUsage += HelpMessageOpt("-testnet", _("Use the test network"));
strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be " strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be "
"solved instantly. This is intended for regression testing tools and app development.") + "\n"; "solved instantly. This is intended for regression testing tools and app development."));
strUsage += " -rpcconnect=<ip> " + strprintf(_("Send commands to node running on <ip> (default: %s)"), "127.0.0.1") + "\n"; strUsage += HelpMessageOpt("-rpcconnect=<ip>", strprintf(_("Send commands to node running on <ip> (default: %s)"), "127.0.0.1"));
strUsage += " -rpcport=<port> " + strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), 8332, 18332) + "\n"; strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), 8332, 18332));
strUsage += " -rpcwait " + _("Wait for RPC server to start") + "\n"; strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start"));
strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n"; strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections"));
strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n"; strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
strUsage += "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n"; strUsage += HelpMessageGroup(_("SSL options: (see the Bitcoin Wiki for SSL setup instructions)"));
strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n"; strUsage += HelpMessageOpt("-rpcssl", _("Use OpenSSL (https) for JSON-RPC connections"));
return strUsage; return strUsage;
} }

View file

@ -54,38 +54,34 @@ static bool AppInitRawTx(int argc, char* argv[])
fprintf(stdout, "%s", strUsage.c_str()); fprintf(stdout, "%s", strUsage.c_str());
strUsage = _("Options:") + "\n"; strUsage = HelpMessageGroup(_("Options:"));
strUsage += " -? " + _("This help message") + "\n"; strUsage += HelpMessageOpt("-?", _("This help message"));
strUsage += " -create " + _("Create new, empty TX.") + "\n"; strUsage += HelpMessageOpt("-create", _("Create new, empty TX."));
strUsage += " -json " + _("Select JSON output") + "\n"; strUsage += HelpMessageOpt("-json", _("Select JSON output"));
strUsage += " -txid " + _("Output only the hex-encoded transaction id of the resultant transaction.") + "\n"; strUsage += HelpMessageOpt("-txid", _("Output only the hex-encoded transaction id of the resultant transaction."));
strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n"; strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly."));
strUsage += " -testnet " + _("Use the test network") + "\n"; strUsage += HelpMessageOpt("-testnet", _("Use the test network"));
strUsage += "\n";
fprintf(stdout, "%s", strUsage.c_str()); fprintf(stdout, "%s", strUsage.c_str());
strUsage = HelpMessageGroup(_("Commands:"));
strUsage = _("Commands:") + "\n"; strUsage += HelpMessageOpt("delin=N", _("Delete input N from TX"));
strUsage += " delin=N " + _("Delete input N from TX") + "\n"; strUsage += HelpMessageOpt("delout=N", _("Delete output N from TX"));
strUsage += " delout=N " + _("Delete output N from TX") + "\n"; strUsage += HelpMessageOpt("in=TXID:VOUT", _("Add input to TX"));
strUsage += " in=TXID:VOUT " + _("Add input to TX") + "\n"; strUsage += HelpMessageOpt("locktime=N", _("Set TX lock time to N"));
strUsage += " locktime=N " + _("Set TX lock time to N") + "\n"; strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N"));
strUsage += " nversion=N " + _("Set TX version to N") + "\n"; strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", _("Add address-based output to TX"));
strUsage += " outaddr=VALUE:ADDRESS " + _("Add address-based output to TX") + "\n"; strUsage += HelpMessageOpt("outscript=VALUE:SCRIPT", _("Add raw script output to TX"));
strUsage += " outscript=VALUE:SCRIPT " + _("Add raw script output to TX") + "\n"; strUsage += HelpMessageOpt("sign=SIGHASH-FLAGS", _("Add zero or more signatures to transaction") + ". " +
strUsage += " sign=SIGHASH-FLAGS " + _("Add zero or more signatures to transaction") + "\n"; _("This command requires JSON registers:") +
strUsage += " This command requires JSON registers:\n"; _("prevtxs=JSON object") + ", " +
strUsage += " prevtxs=JSON object\n"; _("privatekeys=JSON object") + ". " +
strUsage += " privatekeys=JSON object\n"; _("See signrawtransaction docs for format of sighash flags, JSON objects."));
strUsage += " See signrawtransaction docs for format of sighash flags, JSON objects.\n";
strUsage += "\n";
fprintf(stdout, "%s", strUsage.c_str()); fprintf(stdout, "%s", strUsage.c_str());
strUsage = _("Register Commands:") + "\n"; strUsage = HelpMessageGroup(_("Register Commands:"));
strUsage += " load=NAME:FILENAME " + _("Load JSON file FILENAME into register NAME") + "\n"; strUsage += HelpMessageOpt("load=NAME:FILENAME", _("Load JSON file FILENAME into register NAME"));
strUsage += " set=NAME:JSON-STRING " + _("Set register NAME to given JSON-STRING") + "\n"; strUsage += HelpMessageOpt("set=NAME:JSON-STRING", _("Set register NAME to given JSON-STRING"));
strUsage += "\n";
fprintf(stdout, "%s", strUsage.c_str()); fprintf(stdout, "%s", strUsage.c_str());
return false; return false;

View file

@ -200,7 +200,6 @@ public:
fAllowMinDifficultyBlocks = false; fAllowMinDifficultyBlocks = false;
fRequireStandard = true; fRequireStandard = true;
fMineBlocksOnDemand = false; fMineBlocksOnDemand = false;
fSkipProofOfWorkCheck = false;
fTestnetToBeDeprecatedFieldRPC = false; fTestnetToBeDeprecatedFieldRPC = false;
} }
@ -311,51 +310,8 @@ public:
}; };
static CRegTestParams regTestParams; static CRegTestParams regTestParams;
/**
* Unit test
*/
class CUnitTestParams : public CMainParams, public CModifiableParams {
public:
CUnitTestParams() {
strNetworkID = "unittest";
nDefaultPort = 18445;
vFixedSeeds.clear(); //! Unit test mode doesn't have any fixed seeds.
vSeeds.clear(); //! Unit test mode doesn't have any DNS seeds.
fRequireRPCPassword = false;
fMiningRequiresPeers = false;
fDefaultCheckMemPool = true;
fAllowMinDifficultyBlocks = false;
fMineBlocksOnDemand = true;
}
const Checkpoints::CCheckpointData& Checkpoints() const
{
// UnitTest share the same checkpoints as MAIN
return data;
}
//! Published setters to allow changing values in unit test cases
virtual void setSubsidyHalvingInterval(int anSubsidyHalvingInterval) { nSubsidyHalvingInterval=anSubsidyHalvingInterval; }
virtual void setEnforceBlockUpgradeMajority(int anEnforceBlockUpgradeMajority) { nEnforceBlockUpgradeMajority=anEnforceBlockUpgradeMajority; }
virtual void setRejectBlockOutdatedMajority(int anRejectBlockOutdatedMajority) { nRejectBlockOutdatedMajority=anRejectBlockOutdatedMajority; }
virtual void setToCheckBlockUpgradeMajority(int anToCheckBlockUpgradeMajority) { nToCheckBlockUpgradeMajority=anToCheckBlockUpgradeMajority; }
virtual void setDefaultCheckMemPool(bool afDefaultCheckMemPool) { fDefaultCheckMemPool=afDefaultCheckMemPool; }
virtual void setAllowMinDifficultyBlocks(bool afAllowMinDifficultyBlocks) { fAllowMinDifficultyBlocks=afAllowMinDifficultyBlocks; }
virtual void setSkipProofOfWorkCheck(bool afSkipProofOfWorkCheck) { fSkipProofOfWorkCheck = afSkipProofOfWorkCheck; }
};
static CUnitTestParams unitTestParams;
static CChainParams *pCurrentParams = 0; static CChainParams *pCurrentParams = 0;
CModifiableParams *ModifiableParams()
{
assert(pCurrentParams);
assert(pCurrentParams==&unitTestParams);
return (CModifiableParams*)&unitTestParams;
}
const CChainParams &Params() { const CChainParams &Params() {
assert(pCurrentParams); assert(pCurrentParams);
return *pCurrentParams; return *pCurrentParams;
@ -369,8 +325,6 @@ CChainParams &Params(CBaseChainParams::Network network) {
return testNetParams; return testNetParams;
case CBaseChainParams::REGTEST: case CBaseChainParams::REGTEST:
return regTestParams; return regTestParams;
case CBaseChainParams::UNITTEST:
return unitTestParams;
default: default:
assert(false && "Unimplemented network"); assert(false && "Unimplemented network");
return mainParams; return mainParams;

View file

@ -14,8 +14,6 @@
#include <vector> #include <vector>
typedef unsigned char MessageStartChars[MESSAGE_START_SIZE];
struct CDNSSeedData { struct CDNSSeedData {
std::string name, host; std::string name, host;
CDNSSeedData(const std::string &strName, const std::string &strHost) : name(strName), host(strHost) {} CDNSSeedData(const std::string &strName, const std::string &strHost) : name(strName), host(strHost) {}
@ -42,7 +40,7 @@ public:
}; };
const uint256& HashGenesisBlock() const { return hashGenesisBlock; } const uint256& HashGenesisBlock() const { return hashGenesisBlock; }
const MessageStartChars& MessageStart() const { return pchMessageStart; } const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; }
const std::vector<unsigned char>& AlertKey() const { return vAlertPubKey; } const std::vector<unsigned char>& AlertKey() const { return vAlertPubKey; }
int GetDefaultPort() const { return nDefaultPort; } int GetDefaultPort() const { return nDefaultPort; }
const arith_uint256& ProofOfWorkLimit() const { return bnProofOfWorkLimit; } const arith_uint256& ProofOfWorkLimit() const { return bnProofOfWorkLimit; }
@ -62,8 +60,6 @@ public:
bool DefaultCheckMemPool() const { return fDefaultCheckMemPool; } bool DefaultCheckMemPool() const { return fDefaultCheckMemPool; }
/** Allow mining of a min-difficulty block */ /** Allow mining of a min-difficulty block */
bool AllowMinDifficultyBlocks() const { return fAllowMinDifficultyBlocks; } bool AllowMinDifficultyBlocks() const { return fAllowMinDifficultyBlocks; }
/** Skip proof-of-work check: allow mining of any difficulty block */
bool SkipProofOfWorkCheck() const { return fSkipProofOfWorkCheck; }
/** Make standard checks */ /** Make standard checks */
bool RequireStandard() const { return fRequireStandard; } bool RequireStandard() const { return fRequireStandard; }
int64_t TargetTimespan() const { return nTargetTimespan; } int64_t TargetTimespan() const { return nTargetTimespan; }
@ -83,7 +79,7 @@ protected:
CChainParams() {} CChainParams() {}
uint256 hashGenesisBlock; uint256 hashGenesisBlock;
MessageStartChars pchMessageStart; CMessageHeader::MessageStartChars pchMessageStart;
//! Raw pub key bytes for the broadcast alert signing key. //! Raw pub key bytes for the broadcast alert signing key.
std::vector<unsigned char> vAlertPubKey; std::vector<unsigned char> vAlertPubKey;
int nDefaultPort; int nDefaultPort;
@ -106,29 +102,9 @@ protected:
bool fAllowMinDifficultyBlocks; bool fAllowMinDifficultyBlocks;
bool fRequireStandard; bool fRequireStandard;
bool fMineBlocksOnDemand; bool fMineBlocksOnDemand;
bool fSkipProofOfWorkCheck;
bool fTestnetToBeDeprecatedFieldRPC; bool fTestnetToBeDeprecatedFieldRPC;
}; };
/**
* Modifiable parameters interface is used by test cases to adapt the parameters in order
* to test specific features more easily. Test cases should always restore the previous
* values after finalization.
*/
class CModifiableParams {
public:
//! Published setters to allow changing values in unit test cases
virtual void setSubsidyHalvingInterval(int anSubsidyHalvingInterval) =0;
virtual void setEnforceBlockUpgradeMajority(int anEnforceBlockUpgradeMajority)=0;
virtual void setRejectBlockOutdatedMajority(int anRejectBlockOutdatedMajority)=0;
virtual void setToCheckBlockUpgradeMajority(int anToCheckBlockUpgradeMajority)=0;
virtual void setDefaultCheckMemPool(bool aDefaultCheckMemPool)=0;
virtual void setAllowMinDifficultyBlocks(bool aAllowMinDifficultyBlocks)=0;
virtual void setSkipProofOfWorkCheck(bool aSkipProofOfWorkCheck)=0;
};
/** /**
* Return the currently selected parameters. This won't change after app startup * Return the currently selected parameters. This won't change after app startup
* outside of the unit tests. * outside of the unit tests.
@ -138,9 +114,6 @@ const CChainParams &Params();
/** Return parameters for the given network. */ /** Return parameters for the given network. */
CChainParams &Params(CBaseChainParams::Network network); CChainParams &Params(CBaseChainParams::Network network);
/** Get modifiable network parameters (UNITTEST only) */
CModifiableParams *ModifiableParams();
/** Sets the params returned by Params() to those for the given network. */ /** Sets the params returned by Params() to those for the given network. */
void SelectParams(CBaseChainParams::Network network); void SelectParams(CBaseChainParams::Network network);

View file

@ -82,9 +82,6 @@ void SelectBaseParams(CBaseChainParams::Network network)
case CBaseChainParams::REGTEST: case CBaseChainParams::REGTEST:
pCurrentBaseParams = &regTestParams; pCurrentBaseParams = &regTestParams;
break; break;
case CBaseChainParams::UNITTEST:
pCurrentBaseParams = &unitTestParams;
break;
default: default:
assert(false && "Unimplemented network"); assert(false && "Unimplemented network");
return; return;

View file

@ -19,7 +19,6 @@ public:
MAIN, MAIN,
TESTNET, TESTNET,
REGTEST, REGTEST,
UNITTEST,
MAX_NETWORK_TYPES MAX_NETWORK_TYPES
}; };

47
src/compat/byteswap.h Normal file
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.
#ifndef BITCOIN_COMPAT_BYTESWAP_H
#define BITCOIN_COMPAT_BYTESWAP_H
#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif
#include <stdint.h>
#if defined(HAVE_BYTESWAP_H)
#include <byteswap.h>
#endif
#if HAVE_DECL_BSWAP_16 == 0
inline uint16_t bswap_16(uint16_t x)
{
return (x >> 8) | ((x & 0x00ff) << 8);
}
#endif // HAVE_DECL_BSWAP16
#if HAVE_DECL_BSWAP_32 == 0
inline uint32_t bswap_32(uint32_t x)
{
return (((x & 0xff000000U) >> 24) | ((x & 0x00ff0000U) >> 8) |
((x & 0x0000ff00U) << 8) | ((x & 0x000000ffU) << 24));
}
#endif // HAVE_DECL_BSWAP32
#if HAVE_DECL_BSWAP_64 == 0
inline uint64_t bswap_64(uint64_t x)
{
return (((x & 0xff00000000000000ull) >> 56)
| ((x & 0x00ff000000000000ull) >> 40)
| ((x & 0x0000ff0000000000ull) >> 24)
| ((x & 0x000000ff00000000ull) >> 8)
| ((x & 0x00000000ff000000ull) << 8)
| ((x & 0x0000000000ff0000ull) << 24)
| ((x & 0x000000000000ff00ull) << 40)
| ((x & 0x00000000000000ffull) << 56));
}
#endif // HAVE_DECL_BSWAP64
#endif // BITCOIN_COMPAT_BYTESWAP_H

194
src/compat/endian.h Normal file
View file

@ -0,0 +1,194 @@
// 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_COMPAT_ENDIAN_H
#define BITCOIN_COMPAT_ENDIAN_H
#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif
#include <stdint.h>
#include "compat/byteswap.h"
#if defined(HAVE_ENDIAN_H)
#include <endian.h>
#endif
#if defined(WORDS_BIGENDIAN)
#if HAVE_DECL_HTOBE16 == 0
inline uint16_t htobe16(uint16_t host_16bits)
{
return host_16bits;
}
#endif // HAVE_DECL_HTOBE16
#if HAVE_DECL_HTOLE16 == 0
inline uint16_t htole16(uint16_t host_16bits)
{
return bswap_16(host_16bits);
}
#endif // HAVE_DECL_HTOLE16
#if HAVE_DECL_BE16TOH == 0
inline uint16_t be16toh(uint16_t big_endian_16bits)
{
return big_endian_16bits;
}
#endif // HAVE_DECL_BE16TOH
#if HAVE_DECL_LE16TOH == 0
inline uint16_t le16toh(uint16_t little_endian_16bits)
{
return bswap_16(little_endian_16bits);
}
#endif // HAVE_DECL_LE16TOH
#if HAVE_DECL_HTOBE32 == 0
inline uint32_t htobe32(uint32_t host_32bits)
{
return host_32bits;
}
#endif // HAVE_DECL_HTOBE32
#if HAVE_DECL_HTOLE32 == 0
inline uint32_t htole32(uint32_t host_32bits)
{
return bswap_32(host_32bits);
}
#endif // HAVE_DECL_HTOLE32
#if HAVE_DECL_BE32TOH == 0
inline uint32_t be32toh(uint32_t big_endian_32bits)
{
return big_endian_32bits;
}
#endif // HAVE_DECL_BE32TOH
#if HAVE_DECL_LE32TOH == 0
inline uint32_t le32toh(uint32_t little_endian_32bits)
{
return bswap_32(little_endian_32bits);
}
#endif // HAVE_DECL_LE32TOH
#if HAVE_DECL_HTOBE64 == 0
inline uint64_t htobe64(uint64_t host_64bits)
{
return host_64bits;
}
#endif // HAVE_DECL_HTOBE64
#if HAVE_DECL_HTOLE64 == 0
inline uint64_t htole64(uint64_t host_64bits)
{
return bswap_64(host_64bits);
}
#endif // HAVE_DECL_HTOLE64
#if HAVE_DECL_BE64TOH == 0
inline uint64_t be64toh(uint64_t big_endian_64bits)
{
return big_endian_64bits;
}
#endif // HAVE_DECL_BE64TOH
#if HAVE_DECL_LE64TOH == 0
inline uint64_t le64toh(uint64_t little_endian_64bits)
{
return bswap_64(little_endian_64bits);
}
#endif // HAVE_DECL_LE64TOH
#else // WORDS_BIGENDIAN
#if HAVE_DECL_HTOBE16 == 0
inline uint16_t htobe16(uint16_t host_16bits)
{
return bswap_16(host_16bits);
}
#endif // HAVE_DECL_HTOBE16
#if HAVE_DECL_HTOLE16 == 0
inline uint16_t htole16(uint16_t host_16bits)
{
return host_16bits;
}
#endif // HAVE_DECL_HTOLE16
#if HAVE_DECL_BE16TOH == 0
inline uint16_t be16toh(uint16_t big_endian_16bits)
{
return bswap_16(big_endian_16bits);
}
#endif // HAVE_DECL_BE16TOH
#if HAVE_DECL_LE16TOH == 0
inline uint16_t le16toh(uint16_t little_endian_16bits)
{
return little_endian_16bits;
}
#endif // HAVE_DECL_LE16TOH
#if HAVE_DECL_HTOBE32 == 0
inline uint32_t htobe32(uint32_t host_32bits)
{
return bswap_32(host_32bits);
}
#endif // HAVE_DECL_HTOBE32
#if HAVE_DECL_HTOLE32 == 0
inline uint32_t htole32(uint32_t host_32bits)
{
return host_32bits;
}
#endif // HAVE_DECL_HTOLE32
#if HAVE_DECL_BE32TOH == 0
inline uint32_t be32toh(uint32_t big_endian_32bits)
{
return bswap_32(big_endian_32bits);
}
#endif // HAVE_DECL_BE32TOH
#if HAVE_DECL_LE32TOH == 0
inline uint32_t le32toh(uint32_t little_endian_32bits)
{
return little_endian_32bits;
}
#endif // HAVE_DECL_LE32TOH
#if HAVE_DECL_HTOBE64 == 0
inline uint64_t htobe64(uint64_t host_64bits)
{
return bswap_64(host_64bits);
}
#endif // HAVE_DECL_HTOBE64
#if HAVE_DECL_HTOLE64 == 0
inline uint64_t htole64(uint64_t host_64bits)
{
return host_64bits;
}
#endif // HAVE_DECL_HTOLE64
#if HAVE_DECL_BE64TOH == 0
inline uint64_t be64toh(uint64_t big_endian_64bits)
{
return bswap_64(big_endian_64bits);
}
#endif // HAVE_DECL_BE64TOH
#if HAVE_DECL_LE64TOH == 0
inline uint64_t le64toh(uint64_t little_endian_64bits)
{
return little_endian_64bits;
}
#endif // HAVE_DECL_LE64TOH
#endif // WORDS_BIGENDIAN
#endif // BITCOIN_COMPAT_ENDIAN_H

View file

@ -1,94 +0,0 @@
// Copyright (c) 2009-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.
#include <cstddef>
#include <istream>
#include <stdexcept>
#include <typeinfo>
#ifndef _GLIBCXX_USE_NOEXCEPT
#define _GLIBCXX_USE_NOEXCEPT throw()
#endif
namespace std
{
const char* bad_exception::what() const throw()
{
return "std::bad_exception";
}
const char* bad_cast::what() const throw()
{
return "std::bad_cast";
}
const char* bad_alloc::what() const throw()
{
return "std::bad_alloc";
}
namespace __detail
{
struct _List_node_base {
void _M_hook(std::__detail::_List_node_base* const __position) throw() __attribute__((used))
{
_M_next = __position;
_M_prev = __position->_M_prev;
__position->_M_prev->_M_next = this;
__position->_M_prev = this;
}
void _M_unhook() __attribute__((used))
{
_List_node_base* const __next_node = _M_next;
_List_node_base* const __prev_node = _M_prev;
__prev_node->_M_next = __next_node;
__next_node->_M_prev = __prev_node;
}
_List_node_base* _M_next;
_List_node_base* _M_prev;
};
} // namespace detail
template ostream& ostream::_M_insert(bool);
template ostream& ostream::_M_insert(long);
template ostream& ostream::_M_insert(double);
template ostream& ostream::_M_insert(unsigned long);
template ostream& ostream::_M_insert(const void*);
template ostream& __ostream_insert(ostream&, const char*, streamsize);
template istream& istream::_M_extract(long&);
template istream& istream::_M_extract(unsigned short&);
out_of_range::~out_of_range() _GLIBCXX_USE_NOEXCEPT {}
length_error::~length_error() _GLIBCXX_USE_NOEXCEPT {}
// Used with permission.
// See: https://github.com/madlib/madlib/commit/c3db418c0d34d6813608f2137fef1012ce03043d
void ctype<char>::_M_widen_init() const
{
char __tmp[sizeof(_M_widen)];
for (unsigned __i = 0; __i < sizeof(_M_widen); ++__i)
__tmp[__i] = __i;
do_widen(__tmp, __tmp + sizeof(__tmp), _M_widen);
_M_widen_ok = 1;
// Set _M_widen_ok to 2 if memcpy can't be used.
for (unsigned __i = 0; __i < sizeof(_M_widen); ++__i)
if (__tmp[__i] != _M_widen[__i]) {
_M_widen_ok = 2;
break;
}
}
void __throw_out_of_range_fmt(const char*, ...) __attribute__((__noreturn__));
void __throw_out_of_range_fmt(const char* err, ...)
{
// Safe and over-simplified version. Ignore the format and print it as-is.
__throw_out_of_range(err);
}
} // namespace std

View file

@ -11,110 +11,56 @@
#include <stdint.h> #include <stdint.h>
#if defined(HAVE_ENDIAN_H) #include "compat/endian.h"
#include <endian.h>
#endif uint16_t static inline ReadLE16(const unsigned char* ptr)
{
return le16toh(*((uint16_t*)ptr));
}
uint32_t static inline ReadLE32(const unsigned char* ptr) uint32_t static inline ReadLE32(const unsigned char* ptr)
{ {
#if HAVE_DECL_LE32TOH == 1
return le32toh(*((uint32_t*)ptr)); return le32toh(*((uint32_t*)ptr));
#elif !defined(WORDS_BIGENDIAN)
return *((uint32_t*)ptr);
#else
return ((uint32_t)ptr[3] << 24 | (uint32_t)ptr[2] << 16 | (uint32_t)ptr[1] << 8 | (uint32_t)ptr[0]);
#endif
} }
uint64_t static inline ReadLE64(const unsigned char* ptr) uint64_t static inline ReadLE64(const unsigned char* ptr)
{ {
#if HAVE_DECL_LE64TOH == 1
return le64toh(*((uint64_t*)ptr)); return le64toh(*((uint64_t*)ptr));
#elif !defined(WORDS_BIGENDIAN) }
return *((uint64_t*)ptr);
#else void static inline WriteLE16(unsigned char* ptr, uint16_t x)
return ((uint64_t)ptr[7] << 56 | (uint64_t)ptr[6] << 48 | (uint64_t)ptr[5] << 40 | (uint64_t)ptr[4] << 32 | {
(uint64_t)ptr[3] << 24 | (uint64_t)ptr[2] << 16 | (uint64_t)ptr[1] << 8 | (uint64_t)ptr[0]); *((uint16_t*)ptr) = htole16(x);
#endif
} }
void static inline WriteLE32(unsigned char* ptr, uint32_t x) void static inline WriteLE32(unsigned char* ptr, uint32_t x)
{ {
#if HAVE_DECL_HTOLE32 == 1
*((uint32_t*)ptr) = htole32(x); *((uint32_t*)ptr) = htole32(x);
#elif !defined(WORDS_BIGENDIAN)
*((uint32_t*)ptr) = x;
#else
ptr[3] = x >> 24;
ptr[2] = x >> 16;
ptr[1] = x >> 8;
ptr[0] = x;
#endif
} }
void static inline WriteLE64(unsigned char* ptr, uint64_t x) void static inline WriteLE64(unsigned char* ptr, uint64_t x)
{ {
#if HAVE_DECL_HTOLE64 == 1
*((uint64_t*)ptr) = htole64(x); *((uint64_t*)ptr) = htole64(x);
#elif !defined(WORDS_BIGENDIAN)
*((uint64_t*)ptr) = x;
#else
ptr[7] = x >> 56;
ptr[6] = x >> 48;
ptr[5] = x >> 40;
ptr[4] = x >> 32;
ptr[3] = x >> 24;
ptr[2] = x >> 16;
ptr[1] = x >> 8;
ptr[0] = x;
#endif
} }
uint32_t static inline ReadBE32(const unsigned char* ptr) uint32_t static inline ReadBE32(const unsigned char* ptr)
{ {
#if HAVE_DECL_BE32TOH == 1
return be32toh(*((uint32_t*)ptr)); return be32toh(*((uint32_t*)ptr));
#else
return ((uint32_t)ptr[0] << 24 | (uint32_t)ptr[1] << 16 | (uint32_t)ptr[2] << 8 | (uint32_t)ptr[3]);
#endif
} }
uint64_t static inline ReadBE64(const unsigned char* ptr) uint64_t static inline ReadBE64(const unsigned char* ptr)
{ {
#if HAVE_DECL_BE64TOH == 1
return be64toh(*((uint64_t*)ptr)); return be64toh(*((uint64_t*)ptr));
#else
return ((uint64_t)ptr[0] << 56 | (uint64_t)ptr[1] << 48 | (uint64_t)ptr[2] << 40 | (uint64_t)ptr[3] << 32 |
(uint64_t)ptr[4] << 24 | (uint64_t)ptr[5] << 16 | (uint64_t)ptr[6] << 8 | (uint64_t)ptr[7]);
#endif
} }
void static inline WriteBE32(unsigned char* ptr, uint32_t x) void static inline WriteBE32(unsigned char* ptr, uint32_t x)
{ {
#if HAVE_DECL_HTOBE32 == 1
*((uint32_t*)ptr) = htobe32(x); *((uint32_t*)ptr) = htobe32(x);
#else
ptr[0] = x >> 24;
ptr[1] = x >> 16;
ptr[2] = x >> 8;
ptr[3] = x;
#endif
} }
void static inline WriteBE64(unsigned char* ptr, uint64_t x) void static inline WriteBE64(unsigned char* ptr, uint64_t x)
{ {
#if HAVE_DECL_HTOBE64 == 1
*((uint64_t*)ptr) = htobe64(x); *((uint64_t*)ptr) = htobe64(x);
#else
ptr[0] = x >> 56;
ptr[1] = x >> 48;
ptr[2] = x >> 40;
ptr[3] = x >> 32;
ptr[4] = x >> 24;
ptr[5] = x >> 16;
ptr[6] = x >> 8;
ptr[7] = x;
#endif
} }
#endif // BITCOIN_CRYPTO_COMMON_H #endif // BITCOIN_CRYPTO_COMMON_H

View file

@ -3,8 +3,10 @@
// 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/common.h"
#include "crypto/hmac_sha512.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)
{ {
return (x << r) | (x >> (32 - r)); return (x << r) | (x >> (32 - r));
@ -23,10 +25,10 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char
//---------- //----------
// body // body
const uint32_t* blocks = (const uint32_t*)(&vDataToHash[0] + nblocks * 4); const uint8_t* blocks = &vDataToHash[0] + nblocks * 4;
for (int i = -nblocks; i; i++) { for (int i = -nblocks; i; i++) {
uint32_t k1 = blocks[i]; uint32_t k1 = ReadLE32(blocks + i*4);
k1 *= c1; k1 *= c1;
k1 = ROTL32(k1, 15); k1 = ROTL32(k1, 15);

View file

@ -23,10 +23,10 @@
#include "ui_interface.h" #include "ui_interface.h"
#include "util.h" #include "util.h"
#include "utilmoneystr.h" #include "utilmoneystr.h"
#include "validationinterface.h"
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#include "db.h" #include "wallet/wallet.h"
#include "wallet.h" #include "wallet/walletdb.h"
#include "walletdb.h"
#endif #endif
#include <stdint.h> #include <stdint.h>
@ -151,7 +151,7 @@ void Shutdown()
StopRPCThreads(); StopRPCThreads();
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
if (pwalletMain) if (pwalletMain)
bitdb.Flush(false); pwalletMain->Flush(false);
GenerateBitcoins(false, NULL, 0); GenerateBitcoins(false, NULL, 0);
#endif #endif
StopNode(); StopNode();
@ -186,7 +186,7 @@ void Shutdown()
} }
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
if (pwalletMain) if (pwalletMain)
bitdb.Flush(true); pwalletMain->Flush(true);
#endif #endif
#ifndef WIN32 #ifndef WIN32
boost::filesystem::remove(GetPidFile()); boost::filesystem::remove(GetPidFile());
@ -258,157 +258,174 @@ void OnRPCPreCommand(const CRPCCommand& cmd)
std::string HelpMessage(HelpMessageMode mode) std::string HelpMessage(HelpMessageMode mode)
{ {
// When adding new options to the categories, please keep and ensure alphabetical ordering. // When adding new options to the categories, please keep and ensure alphabetical ordering.
string strUsage = _("Options:") + "\n"; string strUsage = HelpMessageGroup(_("Options:"));
strUsage += " -? " + _("This help message") + "\n"; strUsage += HelpMessageOpt("-?", _("This help message"));
strUsage += " -alertnotify=<cmd> " + _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)") + "\n"; strUsage += HelpMessageOpt("-alertnotify=<cmd>", _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)"));
strUsage += " -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n"; strUsage += HelpMessageOpt("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)"));
strUsage += " -checkblocks=<n> " + strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), 288) + "\n"; strUsage += HelpMessageOpt("-checkblocks=<n>", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), 288));
strUsage += " -checklevel=<n> " + strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), 3) + "\n"; strUsage += HelpMessageOpt("-checklevel=<n>", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), 3));
strUsage += " -conf=<file> " + strprintf(_("Specify configuration file (default: %s)"), "bitcoin.conf") + "\n"; strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), "bitcoin.conf"));
if (mode == HMM_BITCOIND) if (mode == HMM_BITCOIND)
{ {
#if !defined(WIN32) #if !defined(WIN32)
strUsage += " -daemon " + _("Run in the background as a daemon and accept commands") + "\n"; strUsage += HelpMessageOpt("-daemon", _("Run in the background as a daemon and accept commands"));
#endif #endif
} }
strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n"; strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
strUsage += " -dbcache=<n> " + strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache) + "\n"; strUsage += HelpMessageOpt("-dbcache=<n>", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache));
strUsage += " -loadblock=<file> " + _("Imports blocks from external blk000??.dat file") + " " + _("on startup") + "\n"; strUsage += HelpMessageOpt("-loadblock=<file>", _("Imports blocks from external blk000??.dat file") + " " + _("on startup"));
strUsage += " -maxorphantx=<n> " + strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS) + "\n"; strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS));
strUsage += " -par=<n> " + strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), -(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS) + "\n"; strUsage += HelpMessageOpt("-par=<n>", strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"),
-(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS));
#ifndef WIN32 #ifndef WIN32
strUsage += " -pid=<file> " + strprintf(_("Specify pid file (default: %s)"), "bitcoind.pid") + "\n"; strUsage += HelpMessageOpt("-pid=<file>", strprintf(_("Specify pid file (default: %s)"), "bitcoind.pid"));
#endif #endif
strUsage += " -reindex " + _("Rebuild block chain index from current blk000??.dat files") + " " + _("on startup") + "\n"; strUsage += HelpMessageOpt("-reindex", _("Rebuild block chain index from current blk000??.dat files") + " " + _("on startup"));
#if !defined(WIN32) #if !defined(WIN32)
strUsage += " -sysperms " + _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)") + "\n"; strUsage += HelpMessageOpt("-sysperms", _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)"));
#endif #endif
strUsage += " -txindex " + strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"), 0) + "\n"; strUsage += HelpMessageOpt("-txindex", strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"), 0));
strUsage += "\n" + _("Connection options:") + "\n"; strUsage += HelpMessageGroup(_("Connection options:"));
strUsage += " -addnode=<ip> " + _("Add a node to connect to and attempt to keep the connection open") + "\n"; strUsage += HelpMessageOpt("-addnode=<ip>", _("Add a node to connect to and attempt to keep the connection open"));
strUsage += " -banscore=<n> " + strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), 100) + "\n"; strUsage += HelpMessageOpt("-banscore=<n>", strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), 100));
strUsage += " -bantime=<n> " + strprintf(_("Number of seconds to keep misbehaving peers from reconnecting (default: %u)"), 86400) + "\n"; strUsage += HelpMessageOpt("-bantime=<n>", strprintf(_("Number of seconds to keep misbehaving peers from reconnecting (default: %u)"), 86400));
strUsage += " -bind=<addr> " + _("Bind to given address and always listen on it. Use [host]:port notation for IPv6") + "\n"; strUsage += HelpMessageOpt("-bind=<addr>", _("Bind to given address and always listen on it. Use [host]:port notation for IPv6"));
strUsage += " -connect=<ip> " + _("Connect only to the specified node(s)") + "\n"; strUsage += HelpMessageOpt("-connect=<ip>", _("Connect only to the specified node(s)"));
strUsage += " -discover " + _("Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)") + "\n"; strUsage += HelpMessageOpt("-discover", _("Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)"));
strUsage += " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + " " + _("(default: 1)") + "\n"; strUsage += HelpMessageOpt("-dns", _("Allow DNS lookups for -addnode, -seednode and -connect") + " " + _("(default: 1)"));
strUsage += " -dnsseed " + _("Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)") + "\n"; strUsage += HelpMessageOpt("-dnsseed", _("Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)"));
strUsage += " -externalip=<ip> " + _("Specify your own public address") + "\n"; strUsage += HelpMessageOpt("-externalip=<ip>", _("Specify your own public address"));
strUsage += " -forcednsseed " + strprintf(_("Always query for peer addresses via DNS lookup (default: %u)"), 0) + "\n"; strUsage += HelpMessageOpt("-forcednsseed", strprintf(_("Always query for peer addresses via DNS lookup (default: %u)"), 0));
strUsage += " -listen " + _("Accept connections from outside (default: 1 if no -proxy or -connect)") + "\n"; strUsage += HelpMessageOpt("-listen", _("Accept connections from outside (default: 1 if no -proxy or -connect)"));
strUsage += " -maxconnections=<n> " + strprintf(_("Maintain at most <n> connections to peers (default: %u)"), 125) + "\n"; strUsage += HelpMessageOpt("-maxconnections=<n>", strprintf(_("Maintain at most <n> connections to peers (default: %u)"), 125));
strUsage += " -maxreceivebuffer=<n> " + strprintf(_("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)"), 5000) + "\n"; strUsage += HelpMessageOpt("-maxreceivebuffer=<n>", strprintf(_("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)"), 5000));
strUsage += " -maxsendbuffer=<n> " + strprintf(_("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)"), 1000) + "\n"; strUsage += HelpMessageOpt("-maxsendbuffer=<n>", strprintf(_("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)"), 1000));
strUsage += " -onion=<ip:port> " + strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy") + "\n"; strUsage += HelpMessageOpt("-onion=<ip:port>", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy"));
strUsage += " -onlynet=<net> " + _("Only connect to nodes in network <net> (ipv4, ipv6 or onion)") + "\n"; strUsage += HelpMessageOpt("-onlynet=<net>", _("Only connect to nodes in network <net> (ipv4, ipv6 or onion)"));
strUsage += " -permitbaremultisig " + strprintf(_("Relay non-P2SH multisig (default: %u)"), 1) + "\n"; strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), 1));
strUsage += " -port=<port> " + strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), 8333, 18333) + "\n"; strUsage += HelpMessageOpt("-port=<port>", strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), 8333, 18333));
strUsage += " -proxy=<ip:port> " + _("Connect through SOCKS5 proxy") + "\n"; strUsage += HelpMessageOpt("-proxy=<ip:port>", _("Connect through SOCKS5 proxy"));
strUsage += " -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n"; strUsage += HelpMessageOpt("-seednode=<ip>", _("Connect to a node to retrieve peer addresses, and disconnect"));
strUsage += " -timeout=<n> " + strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT) + "\n"; strUsage += HelpMessageOpt("-timeout=<n>", strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT));
#ifdef USE_UPNP #ifdef USE_UPNP
#if USE_UPNP #if USE_UPNP
strUsage += " -upnp " + _("Use UPnP to map the listening port (default: 1 when listening)") + "\n"; strUsage += HelpMessageOpt("-upnp", _("Use UPnP to map the listening port (default: 1 when listening)"));
#else #else
strUsage += " -upnp " + strprintf(_("Use UPnP to map the listening port (default: %u)"), 0) + "\n"; strUsage += HelpMessageOpt("-upnp", strprintf(_("Use UPnP to map the listening port (default: %u)"), 0));
#endif #endif
#endif #endif
strUsage += " -whitebind=<addr> " + _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6") + "\n"; strUsage += HelpMessageOpt("-whitebind=<addr>", _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6"));
strUsage += " -whitelist=<netmask> " + _("Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.") + "\n"; strUsage += HelpMessageOpt("-whitelist=<netmask>", _("Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.") +
strUsage += " " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway") + "\n"; " " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway"));
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
strUsage += "\n" + _("Wallet options:") + "\n"; strUsage += HelpMessageGroup(_("Wallet options:"));
strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n"; strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls"));
strUsage += " -keypool=<n> " + strprintf(_("Set key pool size to <n> (default: %u)"), 100) + "\n"; strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), 100));
if (GetBoolArg("-help-debug", false)) if (GetBoolArg("-help-debug", false))
strUsage += " -mintxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)"), FormatMoney(CWallet::minTxFee.GetFeePerK())) + "\n"; strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)"),
strUsage += " -paytxfee=<amt> " + strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())) + "\n"; FormatMoney(CWallet::minTxFee.GetFeePerK())));
strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + " " + _("on startup") + "\n"; strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())));
strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup") + "\n"; strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions") + " " + _("on startup"));
strUsage += " -sendfreetransactions " + strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0) + "\n"; strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup"));
strUsage += " -spendzeroconfchange " + strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1) + "\n"; strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0));
strUsage += " -txconfirmtarget=<n> " + strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), 1) + "\n"; strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1));
strUsage += " -maxtxfee=<amt> " + strprintf(_("Maximum total fees to use in a single wallet transaction, setting too low may abort large transactions (default: %s)"), FormatMoney(maxTxFee)) + "\n"; strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), 1));
strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n"; strUsage += HelpMessageOpt("-maxtxfee=<amt>", strprintf(_("Maximum total fees to use in a single wallet transaction, setting too low may abort large transactions (default: %s)"),
strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), "wallet.dat") + "\n"; FormatMoney(maxTxFee)));
strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n"; strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format") + " " + _("on startup"));
strUsage += " -zapwallettxes=<mode> " + _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") + "\n"; strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), "wallet.dat"));
strUsage += " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)") + "\n"; strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") +
" " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)"));
#endif #endif
strUsage += "\n" + _("Debugging/Testing options:") + "\n"; strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
if (GetBoolArg("-help-debug", false)) if (GetBoolArg("-help-debug", false))
{ {
strUsage += " -checkpoints " + strprintf(_("Only accept block chain matching built-in checkpoints (default: %u)"), 1) + "\n"; strUsage += HelpMessageOpt("-checkpoints", strprintf(_("Only accept block chain matching built-in checkpoints (default: %u)"), 1));
strUsage += " -dblogsize=<n> " + strprintf(_("Flush database activity from memory pool to disk log every <n> megabytes (default: %u)"), 100) + "\n"; strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf(_("Flush database activity from memory pool to disk log every <n> megabytes (default: %u)"), 100));
strUsage += " -disablesafemode " + strprintf(_("Disable safemode, override a real safe mode event (default: %u)"), 0) + "\n"; strUsage += HelpMessageOpt("-disablesafemode", strprintf(_("Disable safemode, override a real safe mode event (default: %u)"), 0));
strUsage += " -testsafemode " + strprintf(_("Force safe mode (default: %u)"), 0) + "\n"; strUsage += HelpMessageOpt("-testsafemode", strprintf(_("Force safe mode (default: %u)"), 0));
strUsage += " -dropmessagestest=<n> " + _("Randomly drop 1 of every <n> network messages") + "\n"; strUsage += HelpMessageOpt("-dropmessagestest=<n>", _("Randomly drop 1 of every <n> network messages"));
strUsage += " -fuzzmessagestest=<n> " + _("Randomly fuzz 1 of every <n> network messages") + "\n"; strUsage += HelpMessageOpt("-fuzzmessagestest=<n>", _("Randomly fuzz 1 of every <n> network messages"));
strUsage += " -flushwallet " + strprintf(_("Run a thread to flush wallet periodically (default: %u)"), 1) + "\n"; strUsage += HelpMessageOpt("-flushwallet", strprintf(_("Run a thread to flush wallet periodically (default: %u)"), 1));
strUsage += " -stopafterblockimport " + strprintf(_("Stop running after importing blocks from disk (default: %u)"), 0) + "\n"; strUsage += HelpMessageOpt("-stopafterblockimport", strprintf(_("Stop running after importing blocks from disk (default: %u)"), 0));
} }
strUsage += " -debug=<category> " + strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + "\n"; string debugCategories = "addrman, alert, bench, coindb, db, lock, rand, rpc, selectcoins, mempool, net"; // Don't translate these and qt below
strUsage += " " + _("If <category> is not supplied, output all debugging information.") + "\n";
strUsage += " " + _("<category> can be:");
strUsage += " addrman, alert, bench, coindb, db, lock, rand, rpc, selectcoins, mempool, net"; // Don't translate these and qt below
if (mode == HMM_BITCOIN_QT) if (mode == HMM_BITCOIN_QT)
strUsage += ", qt"; debugCategories += ", qt";
strUsage += ".\n"; strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " +
_("If <category> is not supplied, output all debugging information.") + _("<category> can be:") + " " + debugCategories + ".");
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
strUsage += " -gen " + strprintf(_("Generate coins (default: %u)"), 0) + "\n"; strUsage += HelpMessageOpt("-gen", strprintf(_("Generate coins (default: %u)"), 0));
strUsage += " -genproclimit=<n> " + strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), 1) + "\n"; strUsage += HelpMessageOpt("-genproclimit=<n>", strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), 1));
#endif #endif
strUsage += " -help-debug " + _("Show all debugging options (usage: --help -help-debug)") + "\n"; strUsage += HelpMessageOpt("-help-debug", _("Show all debugging options (usage: --help -help-debug)"));
strUsage += " -logips " + strprintf(_("Include IP addresses in debug output (default: %u)"), 0) + "\n"; strUsage += HelpMessageOpt("-logips", strprintf(_("Include IP addresses in debug output (default: %u)"), 0));
strUsage += " -logtimestamps " + strprintf(_("Prepend debug output with timestamp (default: %u)"), 1) + "\n"; strUsage += HelpMessageOpt("-logtimestamps", strprintf(_("Prepend debug output with timestamp (default: %u)"), 1));
if (GetBoolArg("-help-debug", false)) if (GetBoolArg("-help-debug", false))
{ {
strUsage += " -limitfreerelay=<n> " + strprintf(_("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:%u)"), 15) + "\n"; strUsage += HelpMessageOpt("-limitfreerelay=<n>", strprintf(_("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:%u)"), 15));
strUsage += " -relaypriority " + strprintf(_("Require high priority for relaying free or low-fee transactions (default:%u)"), 1) + "\n"; strUsage += HelpMessageOpt("-relaypriority", strprintf(_("Require high priority for relaying free or low-fee transactions (default:%u)"), 1));
strUsage += " -maxsigcachesize=<n> " + strprintf(_("Limit size of signature cache to <n> entries (default: %u)"), 50000) + "\n"; strUsage += HelpMessageOpt("-maxsigcachesize=<n>", strprintf(_("Limit size of signature cache to <n> entries (default: %u)"), 50000));
} }
strUsage += " -minrelaytxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK())) + "\n"; strUsage += HelpMessageOpt("-minrelaytxfee=<amt>", strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK())));
strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n"; strUsage += HelpMessageOpt("-printtoconsole", _("Send trace/debug info to console instead of debug.log file"));
if (GetBoolArg("-help-debug", false)) if (GetBoolArg("-help-debug", false))
{ {
strUsage += " -printpriority " + strprintf(_("Log transaction priority and fee per kB when mining blocks (default: %u)"), 0) + "\n"; strUsage += HelpMessageOpt("-printpriority", strprintf(_("Log transaction priority and fee per kB when mining blocks (default: %u)"), 0));
strUsage += " -privdb " + strprintf(_("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)"), 1) + "\n"; strUsage += HelpMessageOpt("-privdb", strprintf(_("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)"), 1));
strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n"; strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + " " +
strUsage += " " + _("This is intended for regression testing tools and app development.") + "\n"; _("This is intended for regression testing tools and app development.") + " " +
strUsage += " " + _("In this mode -genproclimit controls how many blocks are generated immediately.") + "\n"; _("In this mode -genproclimit controls how many blocks are generated immediately."));
} }
strUsage += " -shrinkdebugfile " + _("Shrink debug.log file on client startup (default: 1 when no -debug)") + "\n"; strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)"));
strUsage += " -testnet " + _("Use the test network") + "\n"; strUsage += HelpMessageOpt("-testnet", _("Use the test network"));
strUsage += "\n" + _("Node relay options:") + "\n"; strUsage += HelpMessageGroup(_("Node relay options:"));
strUsage += " -datacarrier " + strprintf(_("Relay and mine data carrier transactions (default: %u)"), 1) + "\n"; strUsage += HelpMessageOpt("-datacarrier", strprintf(_("Relay and mine data carrier transactions (default: %u)"), 1));
strUsage += " -datacarriersize " + strprintf(_("Maximum size of data in data carrier transactions we relay and mine (default: %u)"), MAX_OP_RETURN_RELAY) + "\n"; strUsage += HelpMessageOpt("-datacarriersize", strprintf(_("Maximum size of data in data carrier transactions we relay and mine (default: %u)"), MAX_OP_RETURN_RELAY));
strUsage += "\n" + _("Block creation options:") + "\n"; strUsage += HelpMessageGroup(_("Block creation options:"));
strUsage += " -blockminsize=<n> " + strprintf(_("Set minimum block size in bytes (default: %u)"), 0) + "\n"; strUsage += HelpMessageOpt("-blockminsize=<n>", strprintf(_("Set minimum block size in bytes (default: %u)"), 0));
strUsage += " -blockmaxsize=<n> " + strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE) + "\n"; strUsage += HelpMessageOpt("-blockmaxsize=<n>", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE));
strUsage += " -blockprioritysize=<n> " + strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE) + "\n"; strUsage += HelpMessageOpt("-blockprioritysize=<n>", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE));
strUsage += "\n" + _("RPC server options:") + "\n"; strUsage += HelpMessageGroup(_("RPC server options:"));
strUsage += " -server " + _("Accept command line and JSON-RPC commands") + "\n"; strUsage += HelpMessageOpt("-server", _("Accept command line and JSON-RPC commands"));
strUsage += " -rest " + strprintf(_("Accept public REST requests (default: %u)"), 0) + "\n"; strUsage += HelpMessageOpt("-rest", strprintf(_("Accept public REST requests (default: %u)"), 0));
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 += HelpMessageOpt("-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)"));
strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n"; strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections"));
strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n"; strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
strUsage += " -rpcport=<port> " + strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), 8332, 18332) + "\n"; strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), 8332, 18332));
strUsage += " -rpcallowip=<ip> " + _("Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times") + "\n"; strUsage += HelpMessageOpt("-rpcallowip=<ip>", _("Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times"));
strUsage += " -rpcthreads=<n> " + strprintf(_("Set the number of threads to service RPC calls (default: %d)"), 4) + "\n"; strUsage += HelpMessageOpt("-rpcthreads=<n>", strprintf(_("Set the number of threads to service RPC calls (default: %d)"), 4));
strUsage += " -rpckeepalive " + strprintf(_("RPC support for HTTP persistent connections (default: %d)"), 1) + "\n"; strUsage += HelpMessageOpt("-rpckeepalive", strprintf(_("RPC support for HTTP persistent connections (default: %d)"), 1));
strUsage += "\n" + _("RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n"; strUsage += HelpMessageGroup(_("RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions)"));
strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n"; strUsage += HelpMessageOpt("-rpcssl", _("Use OpenSSL (https) for JSON-RPC connections"));
strUsage += " -rpcsslcertificatechainfile=<file.cert> " + strprintf(_("Server certificate file (default: %s)"), "server.cert") + "\n"; strUsage += HelpMessageOpt("-rpcsslcertificatechainfile=<file.cert>", strprintf(_("Server certificate file (default: %s)"), "server.cert"));
strUsage += " -rpcsslprivatekeyfile=<file.pem> " + strprintf(_("Server private key (default: %s)"), "server.pem") + "\n"; strUsage += HelpMessageOpt("-rpcsslprivatekeyfile=<file.pem>", strprintf(_("Server private key (default: %s)"), "server.pem"));
strUsage += " -rpcsslciphers=<ciphers> " + strprintf(_("Acceptable ciphers (default: %s)"), "TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH") + "\n"; strUsage += HelpMessageOpt("-rpcsslciphers=<ciphers>", strprintf(_("Acceptable ciphers (default: %s)"), "TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH"));
if (mode == HMM_BITCOIN_QT)
{
strUsage += HelpMessageGroup(_("UI Options:"));
if (GetBoolArg("-help-debug", false)) {
strUsage += HelpMessageOpt("-allowselfsignedrootcertificates", _("Allow self signed root certificates (default: 0)"));
}
strUsage += HelpMessageOpt("-choosedatadir", _("Choose data directory on startup (default: 0)"));
strUsage += HelpMessageOpt("-lang=<lang>", _("Set language, for example \"de_DE\" (default: system locale)"));
strUsage += HelpMessageOpt("-min", _("Start minimized"));
strUsage += HelpMessageOpt("-rootcertificates=<file>", _("Set SSL root certificates for payment request (default: -system-)"));
strUsage += HelpMessageOpt("-splash", _("Show splash screen on startup (default: 1)"));
}
return strUsage; return strUsage;
} }
@ -837,47 +854,17 @@ bool AppInit2(boost::thread_group& threadGroup)
LogPrintf("Using wallet %s\n", strWalletFile); LogPrintf("Using wallet %s\n", strWalletFile);
uiInterface.InitMessage(_("Verifying wallet...")); uiInterface.InitMessage(_("Verifying wallet..."));
if (!bitdb.Open(GetDataDir())) std::string warningString;
{ std::string errorString;
// try moving the database env out of the way
boost::filesystem::path pathDatabase = GetDataDir() / "database";
boost::filesystem::path pathDatabaseBak = GetDataDir() / strprintf("database.%d.bak", GetTime());
try {
boost::filesystem::rename(pathDatabase, pathDatabaseBak);
LogPrintf("Moved old %s to %s. Retrying.\n", pathDatabase.string(), pathDatabaseBak.string());
} catch (const boost::filesystem::filesystem_error&) {
// failure is ok (well, not really, but it's not worse than what we started with)
}
// try again if (!CWallet::Verify(strWalletFile, warningString, errorString))
if (!bitdb.Open(GetDataDir())) { return false;
// if it still fails, it probably means we can't even create the database env
string msg = strprintf(_("Error initializing wallet database environment %s!"), strDataDir);
return InitError(msg);
}
}
if (GetBoolArg("-salvagewallet", false)) if (!warningString.empty())
{ InitWarning(warningString);
// Recover readable keypairs: if (!errorString.empty())
if (!CWalletDB::Recover(bitdb, strWalletFile, true)) return InitError(warningString);
return false;
}
if (boost::filesystem::exists(GetDataDir() / strWalletFile))
{
CDBEnv::VerifyResult r = bitdb.Verify(strWalletFile, CWalletDB::Recover);
if (r == CDBEnv::RECOVER_OK)
{
string msg = strprintf(_("Warning: wallet.dat corrupt, data salvaged!"
" Original wallet.dat saved as wallet.{timestamp}.bak in %s; if"
" your balance or transactions are incorrect you should"
" restore from a backup."), strDataDir);
InitWarning(msg);
}
if (r == CDBEnv::RECOVER_FAIL)
return InitError(_("wallet.dat corrupt, salvage failed"));
}
} // (!fDisableWallet) } // (!fDisableWallet)
#endif // ENABLE_WALLET #endif // ENABLE_WALLET
// ********************************************************* Step 6: network initialization // ********************************************************* Step 6: network initialization

View file

@ -208,11 +208,9 @@ void CExtKey::Decode(const unsigned char code[74]) {
} }
bool ECC_InitSanityCheck() { bool ECC_InitSanityCheck() {
#if !defined(USE_SECP256K1)
if (!CECKey::SanityCheck()) { if (!CECKey::SanityCheck()) {
return false; return false;
} }
#endif
CKey key; CKey key;
key.MakeNewKey(true); key.MakeNewKey(true);
CPubKey pubkey = key.GetPubKey(); CPubKey pubkey = key.GetPubKey();

View file

@ -6,8 +6,8 @@
#ifndef BITCOIN_KEY_H #ifndef BITCOIN_KEY_H
#define BITCOIN_KEY_H #define BITCOIN_KEY_H
#include "allocators.h"
#include "serialize.h" #include "serialize.h"
#include "support/allocators/secure.h"
#include "uint256.h" #include "uint256.h"
#include <stdexcept> #include <stdexcept>

View file

@ -5,7 +5,6 @@
#include "keystore.h" #include "keystore.h"
#include "crypter.h"
#include "key.h" #include "key.h"
#include "util.h" #include "util.h"

View file

@ -5,9 +5,9 @@
#include "main.h" #include "main.h"
#include "arith_uint256.h"
#include "addrman.h" #include "addrman.h"
#include "alert.h" #include "alert.h"
#include "arith_uint256.h"
#include "chainparams.h" #include "chainparams.h"
#include "checkpoints.h" #include "checkpoints.h"
#include "checkqueue.h" #include "checkqueue.h"
@ -23,6 +23,7 @@
#include "util.h" #include "util.h"
#include "utilmoneystr.h" #include "utilmoneystr.h"
#include "ncc.h" #include "ncc.h"
#include "validationinterface.h"
#include <sstream> #include <sstream>
@ -56,7 +57,6 @@ bool fTxIndex = false;
bool fIsBareMultisigStd = true; bool fIsBareMultisigStd = true;
unsigned int nCoinCacheSize = 5000; unsigned int nCoinCacheSize = 5000;
/** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */ /** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */
CFeeRate minRelayTxFee = CFeeRate(1000); CFeeRate minRelayTxFee = CFeeRate(1000);
@ -159,68 +159,6 @@ namespace {
set<int> setDirtyFileInfo; set<int> setDirtyFileInfo;
} // anon namespace } // anon namespace
//////////////////////////////////////////////////////////////////////////////
//
// dispatching functions
//
// These functions dispatch to one or all registered wallets
namespace {
struct CMainSignals {
/** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */
boost::signals2::signal<void (const CTransaction &, const CBlock *)> SyncTransaction;
/** Notifies listeners of an erased transaction (currently disabled, requires transaction replacement). */
boost::signals2::signal<void (const uint256 &)> EraseTransaction;
/** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */
boost::signals2::signal<void (const uint256 &)> UpdatedTransaction;
/** Notifies listeners of a new active block chain. */
boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
/** Notifies listeners about an inventory item being seen on the network. */
boost::signals2::signal<void (const uint256 &)> Inventory;
/** Tells listeners to broadcast their data. */
boost::signals2::signal<void ()> Broadcast;
/** Notifies listeners of a block validation result */
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
} g_signals;
} // anon namespace
void RegisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.SyncTransaction.connect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2));
g_signals.EraseTransaction.connect(boost::bind(&CValidationInterface::EraseFromWallet, pwalletIn, _1));
g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn));
g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
}
void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn));
g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
g_signals.EraseTransaction.disconnect(boost::bind(&CValidationInterface::EraseFromWallet, pwalletIn, _1));
g_signals.SyncTransaction.disconnect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2));
}
void UnregisterAllValidationInterfaces() {
g_signals.BlockChecked.disconnect_all_slots();
g_signals.Broadcast.disconnect_all_slots();
g_signals.Inventory.disconnect_all_slots();
g_signals.SetBestChain.disconnect_all_slots();
g_signals.UpdatedTransaction.disconnect_all_slots();
g_signals.EraseTransaction.disconnect_all_slots();
g_signals.SyncTransaction.disconnect_all_slots();
}
void SyncWithWallets(const CTransaction &tx, const CBlock *pblock) {
g_signals.SyncTransaction(tx, pblock);
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// Registration of network node signals. // Registration of network node signals.
@ -241,6 +179,10 @@ struct CBlockReject {
* and we're no longer holding the node's locks. * and we're no longer holding the node's locks.
*/ */
struct CNodeState { struct CNodeState {
//! The peer's address
CService address;
//! Whether we have a fully established connection.
bool fCurrentlyConnected;
//! 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).
@ -265,6 +207,7 @@ struct CNodeState {
bool fPreferredDownload; bool fPreferredDownload;
CNodeState() { CNodeState() {
fCurrentlyConnected = false;
nMisbehavior = 0; nMisbehavior = 0;
fShouldBan = false; fShouldBan = false;
pindexBestKnownBlock = NULL; pindexBestKnownBlock = NULL;
@ -308,6 +251,7 @@ void InitializeNode(NodeId nodeid, const CNode *pnode) {
LOCK(cs_main); LOCK(cs_main);
CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second; CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second;
state.name = pnode->addrName; state.name = pnode->addrName;
state.address = pnode->addr;
} }
void FinalizeNode(NodeId nodeid) { void FinalizeNode(NodeId nodeid) {
@ -317,6 +261,10 @@ void FinalizeNode(NodeId nodeid) {
if (state->fSyncStarted) if (state->fSyncStarted)
nSyncStarted--; nSyncStarted--;
if (state->nMisbehavior == 0 && state->fCurrentlyConnected) {
AddressCurrentlyConnected(state->address);
}
BOOST_FOREACH(const QueuedBlock& entry, state->vBlocksInFlight) BOOST_FOREACH(const QueuedBlock& entry, state->vBlocksInFlight)
mapBlocksInFlight.erase(entry.hash); mapBlocksInFlight.erase(entry.hash);
EraseOrphansFor(nodeid); EraseOrphansFor(nodeid);
@ -2026,7 +1974,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
// Watch for changes to the previous coinbase transaction. // Watch for changes to the previous coinbase transaction.
static uint256 hashPrevBestCoinBase; static uint256 hashPrevBestCoinBase;
g_signals.UpdatedTransaction(hashPrevBestCoinBase); GetMainSignals().UpdatedTransaction(hashPrevBestCoinBase);
hashPrevBestCoinBase = block.vtx[0].GetHash(); hashPrevBestCoinBase = block.vtx[0].GetHash();
int64_t nTime4 = GetTimeMicros(); nTimeCallbacks += nTime4 - nTime3; int64_t nTime4 = GetTimeMicros(); nTimeCallbacks += nTime4 - nTime3;
@ -2087,7 +2035,7 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) {
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). // Update best block in wallet (so we can detect restored wallets).
if (mode != FLUSH_STATE_IF_NEEDED) { if (mode != FLUSH_STATE_IF_NEEDED) {
g_signals.SetBestChain(chainActive.GetLocator()); GetMainSignals().SetBestChain(chainActive.GetLocator());
} }
nLastWrite = GetTimeMicros(); nLastWrite = GetTimeMicros();
} }
@ -2215,7 +2163,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
CNCCTrieCache trieCache(pnccTrie); CNCCTrieCache trieCache(pnccTrie);
CInv inv(MSG_BLOCK, pindexNew->GetBlockHash()); CInv inv(MSG_BLOCK, pindexNew->GetBlockHash());
bool rv = ConnectBlock(*pblock, state, pindexNew, view, trieCache); bool rv = ConnectBlock(*pblock, state, pindexNew, view, trieCache);
g_signals.BlockChecked(*pblock, state); GetMainSignals().BlockChecked(*pblock, state);
if (!rv) { if (!rv) {
if (state.IsInvalid()) if (state.IsInvalid())
InvalidBlockFound(pindexNew, state); InvalidBlockFound(pindexNew, state);
@ -2456,8 +2404,8 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) {
// add them again. // add them again.
BlockMap::iterator it = mapBlockIndex.begin(); BlockMap::iterator it = mapBlockIndex.begin();
while (it != mapBlockIndex.end()) { while (it != mapBlockIndex.end()) {
if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) { if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && !setBlockIndexCandidates.value_comp()(it->second, chainActive.Tip())) {
setBlockIndexCandidates.insert(pindex); setBlockIndexCandidates.insert(it->second);
} }
it++; it++;
} }
@ -2600,8 +2548,11 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd
} }
nLastBlockFile = nFile; nLastBlockFile = nFile;
vinfoBlockFile[nFile].nSize += nAddSize;
vinfoBlockFile[nFile].AddBlock(nHeight, nTime); vinfoBlockFile[nFile].AddBlock(nHeight, nTime);
if (fKnown)
vinfoBlockFile[nFile].nSize = std::max(pos.nPos + nAddSize, vinfoBlockFile[nFile].nSize);
else
vinfoBlockFile[nFile].nSize += nAddSize;
if (!fKnown) { if (!fKnown) {
unsigned int nOldChunks = (pos.nPos + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE; unsigned int nOldChunks = (pos.nPos + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE;
@ -2739,8 +2690,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
int nHeight = pindexPrev->nHeight+1; int nHeight = pindexPrev->nHeight+1;
// Check proof of work // Check proof of work
if ((!Params().SkipProofOfWorkCheck()) && if ((block.nBits != GetNextWorkRequired(pindexPrev, &block)))
(block.nBits != GetNextWorkRequired(pindexPrev, &block)))
return state.DoS(100, error("%s: incorrect proof of work", __func__), return state.DoS(100, error("%s: incorrect proof of work", __func__),
REJECT_INVALID, "bad-diffbits"); REJECT_INVALID, "bad-diffbits");
@ -3232,10 +3182,31 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
void UnloadBlockIndex() void UnloadBlockIndex()
{ {
mapBlockIndex.clear(); LOCK(cs_main);
setBlockIndexCandidates.clear(); setBlockIndexCandidates.clear();
chainActive.SetTip(NULL); chainActive.SetTip(NULL);
pindexBestInvalid = NULL; pindexBestInvalid = NULL;
pindexBestHeader = NULL;
mempool.clear();
mapOrphanTransactions.clear();
mapOrphanTransactionsByPrev.clear();
nSyncStarted = 0;
mapBlocksUnlinked.clear();
vinfoBlockFile.clear();
nLastBlockFile = 0;
nBlockSequenceId = 1;
mapBlockSource.clear();
mapBlocksInFlight.clear();
nQueuedValidatedHeaders = 0;
nPreferredDownload = 0;
setDirtyBlockIndex.clear();
setDirtyFileInfo.clear();
mapNodeState.clear();
BOOST_FOREACH(BlockMap::value_type& entry, mapBlockIndex) {
delete entry.second;
}
mapBlockIndex.clear();
} }
bool LoadBlockIndex() bool LoadBlockIndex()
@ -3502,19 +3473,17 @@ void static ProcessGetData(CNode* pfrom)
BlockMap::iterator mi = mapBlockIndex.find(inv.hash); BlockMap::iterator mi = mapBlockIndex.find(inv.hash);
if (mi != mapBlockIndex.end()) if (mi != mapBlockIndex.end())
{ {
// If the requested block is at a height below our last if (chainActive.Contains(mi->second)) {
// checkpoint, only serve it if it's in the checkpointed chain
int nHeight = mi->second->nHeight;
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint();
if (pcheckpoint && nHeight < pcheckpoint->nHeight) {
if (!chainActive.Contains(mi->second))
{
LogPrintf("ProcessGetData(): ignoring request for old block that isn't in the main chain\n");
} else {
send = true;
}
} else {
send = true; send = true;
} else {
// To prevent fingerprinting attacks, only send blocks outside of the active
// chain if they are valid, and no more than a month older than the best header
// chain we know about.
send = mi->second->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != NULL) &&
(mi->second->GetBlockTime() > pindexBestHeader->GetBlockTime() - 30 * 24 * 60 * 60);
if (!send) {
LogPrintf("ProcessGetData(): ignoring request from peer=%i for old block that isn't in the main chain\n", pfrom->GetId());
}
} }
} }
if (send) if (send)
@ -3588,7 +3557,7 @@ void static ProcessGetData(CNode* pfrom)
} }
// Track requests for our stuff. // Track requests for our stuff.
g_signals.Inventory(inv.hash); GetMainSignals().Inventory(inv.hash);
if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK) if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK)
break; break;
@ -3754,6 +3723,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
else if (strCommand == "verack") else if (strCommand == "verack")
{ {
pfrom->SetRecvVersion(min(pfrom->nVersion, PROTOCOL_VERSION)); pfrom->SetRecvVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
// Mark this node as currently connected, so we update its timestamp later.
if (pfrom->fNetworkNode) {
LOCK(cs_main);
State(pfrom->GetId())->fCurrentlyConnected = true;
}
} }
@ -3876,7 +3851,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
} }
// Track requests for our stuff // Track requests for our stuff
g_signals.Inventory(inv.hash); GetMainSignals().Inventory(inv.hash);
if (pfrom->nSendSize > (SendBufferSize() * 2)) { if (pfrom->nSendSize > (SendBufferSize() * 2)) {
Misbehaving(pfrom->GetId(), 50); Misbehaving(pfrom->GetId(), 50);
@ -4170,7 +4145,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
} }
else if (strCommand == "getaddr") // This asymmetric behavior for inbound and outbound connections was introduced
// to prevent a fingerprinting attack: an attacker can send specific fake addresses
// to users' AddrMan and later request them by sending getaddr messages.
// Making users (which are behind NAT and can only make outgoing connections) ignore
// getaddr message mitigates the attack.
else if ((strCommand == "getaddr") && (pfrom->fInbound))
{ {
pfrom->vAddrToSend.clear(); pfrom->vAddrToSend.clear();
vector<CAddress> vAddr = addrman.GetAddr(); vector<CAddress> vAddr = addrman.GetAddr();
@ -4393,11 +4373,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
} }
// Update the last seen time for this node's address
if (pfrom->fNetworkNode)
if (strCommand == "version" || strCommand == "addr" || strCommand == "inv" || strCommand == "getdata" || strCommand == "ping")
AddressCurrentlyConnected(pfrom->addr);
return true; return true;
} }
@ -4454,7 +4429,7 @@ bool ProcessMessages(CNode* pfrom)
// Read header // Read header
CMessageHeader& hdr = msg.hdr; CMessageHeader& hdr = msg.hdr;
if (!hdr.IsValid()) if (!hdr.IsValid(Params().MessageStart()))
{ {
LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id); LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id);
continue; continue;
@ -4467,8 +4442,7 @@ bool ProcessMessages(CNode* pfrom)
// Checksum // Checksum
CDataStream& vRecv = msg.vRecv; CDataStream& vRecv = msg.vRecv;
uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize); uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize);
unsigned int nChecksum = 0; unsigned int nChecksum = ReadLE32((unsigned char*)&hash);
memcpy(&nChecksum, &hash, sizeof(nChecksum));
if (nChecksum != hdr.nChecksum) if (nChecksum != hdr.nChecksum)
{ {
LogPrintf("ProcessMessages(%s, %u bytes): CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n", LogPrintf("ProcessMessages(%s, %u bytes): CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
@ -4648,7 +4622,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
// transactions become unconfirmed and spams other nodes. // transactions become unconfirmed and spams other nodes.
if (!fReindex && !fImporting && !IsInitialBlockDownload()) if (!fReindex && !fImporting && !IsInitialBlockDownload())
{ {
g_signals.Broadcast(); GetMainSignals().Broadcast();
} }
// //

View file

@ -134,15 +134,6 @@ 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 */
void RegisterValidationInterface(CValidationInterface* pwalletIn);
/** Unregister a wallet from core */
void UnregisterValidationInterface(CValidationInterface* pwalletIn);
/** Unregister all wallets from core */
void UnregisterAllValidationInterfaces();
/** Push an updated transaction to all registered wallets */
void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL);
/** Register with a network node to receive its signals */ /** Register with a network node to receive its signals */
void RegisterNodeSignals(CNodeSignals& nodeSignals); void RegisterNodeSignals(CNodeSignals& nodeSignals);
/** Unregister a network node */ /** Unregister a network node */
@ -153,7 +144,7 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals);
* block is made active. Note that it does not, however, guarantee that the * block is made active. Note that it does not, however, guarantee that the
* specific block passed to it has been checked for validity! * specific block passed to it has been checked for validity!
* *
* @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] 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 (see validationinterface.h) - this will have its BlockChecked method called whenever *any* block completes validation.
* @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] 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[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. * @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location.
@ -517,19 +508,4 @@ extern CNCCTrie *pnccTrie;
/** Global variable that points to the active block tree (protected by cs_main) */ /** Global variable that points to the active block tree (protected by cs_main) */
extern CBlockTreeDB *pblocktree; extern CBlockTreeDB *pblocktree;
class CValidationInterface {
protected:
virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) {};
virtual void EraseFromWallet(const uint256 &hash) {};
virtual void SetBestChain(const CBlockLocator &locator) {};
virtual void UpdatedTransaction(const uint256 &hash) {};
virtual void Inventory(const uint256 &hash) {};
virtual void ResendWalletTransactions() {};
virtual void BlockChecked(const CBlock&, const CValidationState&) {};
friend void ::RegisterValidationInterface(CValidationInterface*);
friend void ::UnregisterValidationInterface(CValidationInterface*);
friend void ::UnregisterAllValidationInterfaces();
};
#endif // BITCOIN_MAIN_H #endif // BITCOIN_MAIN_H

View file

@ -17,7 +17,7 @@
#include "util.h" #include "util.h"
#include "utilmoneystr.h" #include "utilmoneystr.h"
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#include "wallet.h" #include "wallet/wallet.h"
#endif #endif
#include <boost/thread.hpp> #include <boost/thread.hpp>

View file

@ -109,6 +109,20 @@ bool CNCCTrie::queueEmpty() const
return valueQueue.empty(); return valueQueue.empty();
} }
void CNCCTrie::clear()
{
clear(&root);
}
void CNCCTrie::clear(CNCCTrieNode* current)
{
for (nodeMapType::const_iterator itchildren = current->children.begin(); itchildren != current->children.end(); ++itchildren)
{
clear(itchildren->second);
delete itchildren->second;
}
}
bool CNCCTrie::haveClaim(const std::string& name, const uint256& txhash, uint32_t nOut) const bool CNCCTrie::haveClaim(const std::string& name, const uint256& txhash, uint32_t nOut) const
{ {
const CNCCTrieNode* current = &root; const CNCCTrieNode* current = &root;

View file

@ -152,6 +152,7 @@ public:
uint256 getMerkleHash(); uint256 getMerkleHash();
CLevelDBWrapper db; CLevelDBWrapper db;
bool empty() const; bool empty() const;
void clear();
bool checkConsistency(); bool checkConsistency();
bool WriteToDisk(); bool WriteToDisk();
bool ReadFromDisk(bool check = false); bool ReadFromDisk(bool check = false);
@ -162,6 +163,7 @@ public:
bool haveClaim(const std::string& name, const uint256& txhash, uint32_t nOut) const; bool haveClaim(const std::string& name, const uint256& txhash, uint32_t nOut) const;
friend class CNCCTrieCache; friend class CNCCTrieCache;
private: private:
void clear(CNCCTrieNode* current);
bool update(nodeCacheType& cache, hashMapType& hashes, const uint256& hashBlock, valueQueueType& queueCache, int nNewHeight); bool update(nodeCacheType& cache, hashMapType& hashes, const uint256& hashBlock, valueQueueType& queueCache, int nNewHeight);
bool updateName(const std::string& name, CNCCTrieNode* updatedNode); bool updateName(const std::string& name, CNCCTrieNode* updatedNode);
bool updateHash(const std::string& name, uint256& hash); bool updateHash(const std::string& name, uint256& hash);

View file

@ -14,6 +14,7 @@
#include "clientversion.h" #include "clientversion.h"
#include "primitives/transaction.h" #include "primitives/transaction.h"
#include "ui_interface.h" #include "ui_interface.h"
#include "crypto/common.h"
#ifdef WIN32 #ifdef WIN32
#include <string.h> #include <string.h>
@ -509,7 +510,7 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes)
// get current incomplete message, or create a new one // get current incomplete message, or create a new one
if (vRecvMsg.empty() || if (vRecvMsg.empty() ||
vRecvMsg.back().complete()) vRecvMsg.back().complete())
vRecvMsg.push_back(CNetMessage(SER_NETWORK, nRecvVersion)); vRecvMsg.push_back(CNetMessage(Params().MessageStart(), SER_NETWORK, nRecvVersion));
CNetMessage& msg = vRecvMsg.back(); CNetMessage& msg = vRecvMsg.back();
@ -523,6 +524,11 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes)
if (handled < 0) if (handled < 0)
return false; return false;
if (msg.in_data && msg.hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) {
LogPrint("net", "Oversized message from peer=%i, disconnecting", GetId());
return false;
}
pch += handled; pch += handled;
nBytes -= handled; nBytes -= handled;
@ -1970,7 +1976,7 @@ void CNode::BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSen
{ {
ENTER_CRITICAL_SECTION(cs_vSend); ENTER_CRITICAL_SECTION(cs_vSend);
assert(ssSend.size() == 0); assert(ssSend.size() == 0);
ssSend << CMessageHeader(pszCommand, 0); ssSend << CMessageHeader(Params().MessageStart(), pszCommand, 0);
LogPrint("net", "sending: %s ", SanitizeString(pszCommand)); LogPrint("net", "sending: %s ", SanitizeString(pszCommand));
} }
@ -2002,7 +2008,7 @@ void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend)
// Set the size // Set the size
unsigned int nSize = ssSend.size() - CMessageHeader::HEADER_SIZE; unsigned int nSize = ssSend.size() - CMessageHeader::HEADER_SIZE;
memcpy((char*)&ssSend[CMessageHeader::MESSAGE_SIZE_OFFSET], &nSize, sizeof(nSize)); WriteLE32((uint8_t*)&ssSend[CMessageHeader::MESSAGE_SIZE_OFFSET], nSize);
// Set the checksum // Set the checksum
uint256 hash = Hash(ssSend.begin() + CMessageHeader::HEADER_SIZE, ssSend.end()); uint256 hash = Hash(ssSend.begin() + CMessageHeader::HEADER_SIZE, ssSend.end());

View file

@ -46,6 +46,8 @@ static const int TIMEOUT_INTERVAL = 20 * 60;
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. */ /** The maximum number of new addresses to accumulate before announcing. */
static const unsigned int MAX_ADDR_TO_SEND = 1000; static const unsigned int MAX_ADDR_TO_SEND = 1000;
/** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 2 * 1024 * 1024;
/** -listen default */ /** -listen default */
static const bool DEFAULT_LISTEN = true; static const bool DEFAULT_LISTEN = true;
/** -upnp default */ /** -upnp default */
@ -76,12 +78,27 @@ void SocketSendData(CNode *pnode);
typedef int NodeId; typedef int NodeId;
struct CombinerAll
{
typedef bool result_type;
template<typename I>
bool operator()(I first, I last) const
{
while (first != last) {
if (!(*first)) return false;
++first;
}
return true;
}
};
// Signals for message handling // Signals for message handling
struct CNodeSignals struct CNodeSignals
{ {
boost::signals2::signal<int ()> GetHeight; boost::signals2::signal<int ()> GetHeight;
boost::signals2::signal<bool (CNode*)> ProcessMessages; boost::signals2::signal<bool (CNode*), CombinerAll> ProcessMessages;
boost::signals2::signal<bool (CNode*, bool)> SendMessages; boost::signals2::signal<bool (CNode*, bool), CombinerAll> SendMessages;
boost::signals2::signal<void (NodeId, const CNode*)> InitializeNode; boost::signals2::signal<void (NodeId, const CNode*)> InitializeNode;
boost::signals2::signal<void (NodeId)> FinalizeNode; boost::signals2::signal<void (NodeId)> FinalizeNode;
}; };
@ -183,7 +200,7 @@ public:
int64_t nTime; // time (in microseconds) of message receipt. int64_t nTime; // time (in microseconds) of message receipt.
CNetMessage(int nTypeIn, int nVersionIn) : hdrbuf(nTypeIn, nVersionIn), vRecv(nTypeIn, nVersionIn) { CNetMessage(const CMessageHeader::MessageStartChars& pchMessageStartIn, int nTypeIn, int nVersionIn) : hdrbuf(nTypeIn, nVersionIn), hdr(pchMessageStartIn), vRecv(nTypeIn, nVersionIn) {
hdrbuf.resize(24); hdrbuf.resize(24);
in_data = false; in_data = false;
nHdrPos = 0; nHdrPos = 0;
@ -570,9 +587,6 @@ public:
} }
} }
bool IsSubscribed(unsigned int nChannel);
void Subscribe(unsigned int nChannel, unsigned int nHops=0);
void CancelSubscribe(unsigned int nChannel);
void CloseSocketDisconnect(); void CloseSocketDisconnect();
// Denial-of-service detection/prevention // Denial-of-service detection/prevention

View file

@ -162,7 +162,7 @@ class CService : public CNetAddr
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(FLATDATA(ip)); READWRITE(FLATDATA(ip));
unsigned short portN = htons(port); unsigned short portN = htons(port);
READWRITE(portN); READWRITE(FLATDATA(portN));
if (ser_action.ForRead()) if (ser_action.ForRead())
port = ntohs(portN); port = ntohs(portN);
} }

View file

@ -48,8 +48,13 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
pindexFirst = pindexFirst->pprev; pindexFirst = pindexFirst->pprev;
assert(pindexFirst); assert(pindexFirst);
return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime());
}
unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime)
{
// Limit adjustment step // Limit adjustment step
int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime(); int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan); LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan);
if (nActualTimespan < Params().TargetTimespan()/4) if (nActualTimespan < Params().TargetTimespan()/4)
nActualTimespan = Params().TargetTimespan()/4; nActualTimespan = Params().TargetTimespan()/4;
@ -82,9 +87,6 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits)
bool fOverflow; bool fOverflow;
arith_uint256 bnTarget; arith_uint256 bnTarget;
if (Params().SkipProofOfWorkCheck())
return true;
bnTarget.SetCompact(nBits, &fNegative, &fOverflow); bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
// Check range // Check range

View file

@ -14,6 +14,7 @@ class uint256;
class arith_uint256; class arith_uint256;
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock); unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock);
unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime);
/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
bool CheckProofOfWork(uint256 hash, unsigned int nBits); bool CheckProofOfWork(uint256 hash, unsigned int nBits);

View file

@ -8,10 +8,11 @@
#include "hash.h" #include "hash.h"
#include "tinyformat.h" #include "tinyformat.h"
#include "utilstrencodings.h" #include "utilstrencodings.h"
#include "crypto/common.h"
uint256 CBlockHeader::GetHash() const uint256 CBlockHeader::GetHash() const
{ {
return Hash(BEGIN(nVersion), END(nNonce)); return SerializeHash(*this);
} }
uint256 CBlock::BuildMerkleTree(bool* fMutated) const uint256 CBlock::BuildMerkleTree(bool* fMutated) const

View file

@ -25,7 +25,8 @@ public:
template <typename Stream, typename Operation> template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(FLATDATA(*this)); READWRITE(hash);
READWRITE(n);
} }
void SetNull() { hash.SetNull(); n = (uint32_t) -1; } void SetNull() { hash.SetNull(); n = (uint32_t) -1; }
@ -134,7 +135,7 @@ public:
uint256 GetHash() const; uint256 GetHash() const;
bool IsDust(CFeeRate minRelayTxFee) const CAmount GetDustThreshold(const CFeeRate &minRelayTxFee) const
{ {
// "Dust" is defined in terms of CTransaction::minRelayTxFee, // "Dust" is defined in terms of CTransaction::minRelayTxFee,
// which has units satoshis-per-kilobyte. // which has units satoshis-per-kilobyte.
@ -145,7 +146,12 @@ public:
// so dust is a txout less than 546 satoshis // so dust is a txout less than 546 satoshis
// with default minRelayTxFee. // with default minRelayTxFee.
size_t nSize = GetSerializeSize(SER_DISK,0)+148u; size_t nSize = GetSerializeSize(SER_DISK,0)+148u;
return (nValue < 3*minRelayTxFee.GetFee(nSize)); return 3*minRelayTxFee.GetFee(nSize);
}
bool IsDust(const CFeeRate &minRelayTxFee) const
{
return (nValue < GetDustThreshold(minRelayTxFee));
} }
friend bool operator==(const CTxOut& a, const CTxOut& b) friend bool operator==(const CTxOut& a, const CTxOut& b)

View file

@ -5,7 +5,6 @@
#include "protocol.h" #include "protocol.h"
#include "chainparams.h"
#include "util.h" #include "util.h"
#include "utilstrencodings.h" #include "utilstrencodings.h"
@ -21,17 +20,17 @@ static const char* ppszTypeName[] =
"filtered block" "filtered block"
}; };
CMessageHeader::CMessageHeader() CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn)
{ {
memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE); memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
memset(pchCommand, 0, sizeof(pchCommand)); memset(pchCommand, 0, sizeof(pchCommand));
nMessageSize = -1; nMessageSize = -1;
nChecksum = 0; nChecksum = 0;
} }
CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn) CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn)
{ {
memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE); memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
memset(pchCommand, 0, sizeof(pchCommand)); memset(pchCommand, 0, sizeof(pchCommand));
strncpy(pchCommand, pszCommand, COMMAND_SIZE); strncpy(pchCommand, pszCommand, COMMAND_SIZE);
nMessageSize = nMessageSizeIn; nMessageSize = nMessageSizeIn;
@ -43,10 +42,10 @@ std::string CMessageHeader::GetCommand() const
return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE)); return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));
} }
bool CMessageHeader::IsValid() const bool CMessageHeader::IsValid(const MessageStartChars& pchMessageStartIn) const
{ {
// Check start string // Check start string
if (memcmp(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0) if (memcmp(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE) != 0)
return false; return false;
// Check the command string for errors // Check the command string for errors

View file

@ -29,11 +29,13 @@
class CMessageHeader class CMessageHeader
{ {
public: public:
CMessageHeader(); typedef unsigned char MessageStartChars[MESSAGE_START_SIZE];
CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn);
CMessageHeader(const MessageStartChars& pchMessageStartIn);
CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn);
std::string GetCommand() const; std::string GetCommand() const;
bool IsValid() const; bool IsValid(const MessageStartChars& messageStart) const;
ADD_SERIALIZE_METHODS; ADD_SERIALIZE_METHODS;

View file

@ -6,25 +6,16 @@
#include "eccryptoverify.h" #include "eccryptoverify.h"
#ifdef USE_SECP256K1
#include <secp256k1.h>
#else
#include "ecwrapper.h" #include "ecwrapper.h"
#endif
bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const { bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
if (!IsValid()) if (!IsValid())
return false; return false;
#ifdef USE_SECP256K1
if (secp256k1_ecdsa_verify((const unsigned char*)&hash, &vchSig[0], vchSig.size(), begin(), size()) != 1)
return false;
#else
CECKey key; CECKey key;
if (!key.SetPubKey(begin(), size())) if (!key.SetPubKey(begin(), size()))
return false; return false;
if (!key.Verify(hash, vchSig)) if (!key.Verify(hash, vchSig))
return false; return false;
#endif
return true; return true;
} }
@ -33,52 +24,33 @@ bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned cha
return false; return false;
int recid = (vchSig[0] - 27) & 3; int recid = (vchSig[0] - 27) & 3;
bool fComp = ((vchSig[0] - 27) & 4) != 0; bool fComp = ((vchSig[0] - 27) & 4) != 0;
#ifdef USE_SECP256K1
int pubkeylen = 65;
if (!secp256k1_ecdsa_recover_compact((const unsigned char*)&hash, &vchSig[1], (unsigned char*)begin(), &pubkeylen, fComp, recid))
return false;
assert((int)size() == pubkeylen);
#else
CECKey key; CECKey key;
if (!key.Recover(hash, &vchSig[1], recid)) if (!key.Recover(hash, &vchSig[1], recid))
return false; return false;
std::vector<unsigned char> pubkey; std::vector<unsigned char> pubkey;
key.GetPubKey(pubkey, fComp); key.GetPubKey(pubkey, fComp);
Set(pubkey.begin(), pubkey.end()); Set(pubkey.begin(), pubkey.end());
#endif
return true; return true;
} }
bool CPubKey::IsFullyValid() const { bool CPubKey::IsFullyValid() const {
if (!IsValid()) if (!IsValid())
return false; return false;
#ifdef USE_SECP256K1
if (!secp256k1_ecdsa_pubkey_verify(begin(), size()))
return false;
#else
CECKey key; CECKey key;
if (!key.SetPubKey(begin(), size())) if (!key.SetPubKey(begin(), size()))
return false; return false;
#endif
return true; return true;
} }
bool CPubKey::Decompress() { bool CPubKey::Decompress() {
if (!IsValid()) if (!IsValid())
return false; return false;
#ifdef USE_SECP256K1
int clen = size();
int ret = secp256k1_ecdsa_pubkey_decompress((unsigned char*)begin(), &clen);
assert(ret);
assert(clen == (int)size());
#else
CECKey key; CECKey key;
if (!key.SetPubKey(begin(), size())) if (!key.SetPubKey(begin(), size()))
return false; return false;
std::vector<unsigned char> pubkey; std::vector<unsigned char> pubkey;
key.GetPubKey(pubkey, false); key.GetPubKey(pubkey, false);
Set(pubkey.begin(), pubkey.end()); Set(pubkey.begin(), pubkey.end());
#endif
return true; return true;
} }
@ -89,17 +61,12 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned i
unsigned char out[64]; unsigned char out[64];
BIP32Hash(cc, nChild, *begin(), begin()+1, out); BIP32Hash(cc, nChild, *begin(), begin()+1, out);
memcpy(ccChild, out+32, 32); memcpy(ccChild, out+32, 32);
#ifdef USE_SECP256K1
pubkeyChild = *this;
bool ret = secp256k1_ecdsa_pubkey_tweak_add((unsigned char*)pubkeyChild.begin(), pubkeyChild.size(), out);
#else
CECKey key; CECKey key;
bool ret = key.SetPubKey(begin(), size()); bool ret = key.SetPubKey(begin(), size());
ret &= key.TweakPublic(out); ret &= key.TweakPublic(out);
std::vector<unsigned char> pubkey; std::vector<unsigned char> pubkey;
key.GetPubKey(pubkey, true); key.GetPubKey(pubkey, true);
pubkeyChild.Set(pubkey.begin(), pubkey.end()); pubkeyChild.Set(pubkey.begin(), pubkey.end());
#endif
return ret; return ret;
} }

View file

@ -8,7 +8,9 @@
#include "walletmodel.h" #include "walletmodel.h"
#include "base58.h" #include "base58.h"
#include "wallet.h" #include "wallet/wallet.h"
#include <boost/foreach.hpp>
#include <QFont> #include <QFont>
#include <QDebug> #include <QDebug>

View file

@ -8,7 +8,7 @@
#include "guiconstants.h" #include "guiconstants.h"
#include "walletmodel.h" #include "walletmodel.h"
#include "allocators.h" #include "support/allocators/secure.h"
#include <QKeyEvent> #include <QKeyEvent>
#include <QMessageBox> #include <QMessageBox>

View file

@ -30,7 +30,7 @@
#include "util.h" #include "util.h"
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#include "wallet.h" #include "wallet/wallet.h"
#endif #endif
#include <stdint.h> #include <stdint.h>

View file

@ -151,7 +151,7 @@ BitcoinGUI::BitcoinGUI(const NetworkStyle *networkStyle, QWidget *parent) :
// Create actions for the toolbar, menu bar and tray/dock icon // Create actions for the toolbar, menu bar and tray/dock icon
// Needs walletFrame to be initialized // Needs walletFrame to be initialized
createActions(networkStyle); createActions();
// Create application menu bar // Create application menu bar
createMenuBar(); createMenuBar();
@ -237,13 +237,13 @@ BitcoinGUI::~BitcoinGUI()
trayIcon->hide(); trayIcon->hide();
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
delete appMenuBar; delete appMenuBar;
MacDockIconHandler::instance()->setMainWindow(NULL); MacDockIconHandler::cleanup();
#endif #endif
delete rpcConsole; delete rpcConsole;
} }
void BitcoinGUI::createActions(const NetworkStyle *networkStyle) void BitcoinGUI::createActions()
{ {
QActionGroup *tabGroup = new QActionGroup(this); QActionGroup *tabGroup = new QActionGroup(this);
@ -340,6 +340,7 @@ void BitcoinGUI::createActions(const NetworkStyle *networkStyle)
openAction->setStatusTip(tr("Open a bitcoin: URI or payment request")); openAction->setStatusTip(tr("Open a bitcoin: URI or payment request"));
showHelpMessageAction = new QAction(TextColorIcon(":/icons/info"), tr("&Command-line options"), this); showHelpMessageAction = new QAction(TextColorIcon(":/icons/info"), tr("&Command-line options"), this);
showHelpMessageAction->setMenuRole(QAction::NoRole);
showHelpMessageAction->setStatusTip(tr("Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options")); showHelpMessageAction->setStatusTip(tr("Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options"));
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
@ -435,8 +436,8 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
setNumConnections(clientModel->getNumConnections()); setNumConnections(clientModel->getNumConnections());
connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
setNumBlocks(clientModel->getNumBlocks()); setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate());
connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int))); connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(setNumBlocks(int,QDateTime)));
// Receive and report messages from client model // Receive and report messages from client model
connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int))); connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
@ -652,7 +653,7 @@ void BitcoinGUI::setNumConnections(int count)
labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count)); labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count));
} }
void BitcoinGUI::setNumBlocks(int count) void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate)
{ {
if(!clientModel) if(!clientModel)
return; return;
@ -680,9 +681,8 @@ void BitcoinGUI::setNumBlocks(int count)
QString tooltip; QString tooltip;
QDateTime lastBlockDate = clientModel->getLastBlockDate();
QDateTime currentDate = QDateTime::currentDateTime(); QDateTime currentDate = QDateTime::currentDateTime();
int secs = lastBlockDate.secsTo(currentDate); qint64 secs = blockDate.secsTo(currentDate);
tooltip = tr("Processed %n blocks of transaction history.", "", count); tooltip = tr("Processed %n blocks of transaction history.", "", count);
@ -722,8 +722,8 @@ void BitcoinGUI::setNumBlocks(int count)
} }
else else
{ {
int years = secs / YEAR_IN_SECONDS; qint64 years = secs / YEAR_IN_SECONDS;
int remainder = secs % YEAR_IN_SECONDS; qint64 remainder = secs % YEAR_IN_SECONDS;
timeBehindText = tr("%1 and %2").arg(tr("%n year(s)", "", years)).arg(tr("%n week(s)","", remainder/WEEK_IN_SECONDS)); timeBehindText = tr("%1 and %2").arg(tr("%n year(s)", "", years)).arg(tr("%n week(s)","", remainder/WEEK_IN_SECONDS));
} }

View file

@ -118,7 +118,7 @@ private:
int spinnerFrame; int spinnerFrame;
/** Create the main UI actions. */ /** Create the main UI actions. */
void createActions(const NetworkStyle *networkStyle); void createActions();
/** Create the menu bar and sub-menus. */ /** Create the menu bar and sub-menus. */
void createMenuBar(); void createMenuBar();
/** Create the toolbars */ /** Create the toolbars */
@ -143,8 +143,8 @@ signals:
public slots: public slots:
/** Set number of connections shown in the UI */ /** Set number of connections shown in the UI */
void setNumConnections(int count); void setNumConnections(int count);
/** Set number of blocks shown in the UI */ /** Set number of blocks and last block date shown in the UI */
void setNumBlocks(int count); void setNumBlocks(int count, const QDateTime& blockDate);
/** Notify the user of an event from the core network or transaction handling code. /** Notify the user of an event from the core network or transaction handling code.
@param[in] title the message box / notification title @param[in] title the message box / notification title

View file

@ -18,7 +18,6 @@
#include <stdint.h> #include <stdint.h>
#include <QDateTime>
#include <QDebug> #include <QDebug>
#include <QTimer> #include <QTimer>
@ -29,8 +28,10 @@ ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
optionsModel(optionsModel), optionsModel(optionsModel),
peerTableModel(0), peerTableModel(0),
cachedNumBlocks(0), cachedNumBlocks(0),
cachedReindexing(0), cachedImporting(0), cachedBlockDate(QDateTime()),
numBlocksAtStartup(-1), pollTimer(0) cachedReindexing(0),
cachedImporting(0),
pollTimer(0)
{ {
peerTableModel = new PeerTableModel(this); peerTableModel = new PeerTableModel(this);
pollTimer = new QTimer(this); pollTimer = new QTimer(this);
@ -65,12 +66,6 @@ int ClientModel::getNumBlocks() const
return chainActive.Height(); return chainActive.Height();
} }
int ClientModel::getNumBlocksAtStartup()
{
if (numBlocksAtStartup == -1) numBlocksAtStartup = getNumBlocks();
return numBlocksAtStartup;
}
quint64 ClientModel::getTotalBytesRecv() const quint64 ClientModel::getTotalBytesRecv() const
{ {
return CNode::GetTotalBytesRecv(); return CNode::GetTotalBytesRecv();
@ -84,10 +79,11 @@ quint64 ClientModel::getTotalBytesSent() const
QDateTime ClientModel::getLastBlockDate() const QDateTime ClientModel::getLastBlockDate() const
{ {
LOCK(cs_main); LOCK(cs_main);
if (chainActive.Tip()) if (chainActive.Tip())
return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime()); return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime());
else
return QDateTime::fromTime_t(Params().GenesisBlock().GetBlockTime()); // Genesis block's time of current network return QDateTime::fromTime_t(Params().GenesisBlock().GetBlockTime()); // Genesis block's time of current network
} }
double ClientModel::getVerificationProgress() const double ClientModel::getVerificationProgress() const
@ -102,21 +98,26 @@ void ClientModel::updateTimer()
// periodical polls if the core is holding the locks for a longer time - // periodical polls if the core is holding the locks for a longer time -
// for example, during a wallet rescan. // for example, during a wallet rescan.
TRY_LOCK(cs_main, lockMain); TRY_LOCK(cs_main, lockMain);
if(!lockMain) if (!lockMain)
return; return;
// Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change. // Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change.
// Periodically check and update with a timer. // Periodically check and update with a timer.
int newNumBlocks = getNumBlocks(); int newNumBlocks = getNumBlocks();
QDateTime newBlockDate = getLastBlockDate();
// check for changed number of blocks we have, number of blocks peers claim to have, reindexing state and importing state // check for changed number of blocks we have, number of blocks peers claim to have, reindexing state and importing state
if (cachedNumBlocks != newNumBlocks || if (cachedNumBlocks != newNumBlocks ||
cachedReindexing != fReindex || cachedImporting != fImporting) cachedBlockDate != newBlockDate ||
cachedReindexing != fReindex ||
cachedImporting != fImporting)
{ {
cachedNumBlocks = newNumBlocks; cachedNumBlocks = newNumBlocks;
cachedBlockDate = newBlockDate;
cachedReindexing = fReindex; cachedReindexing = fReindex;
cachedImporting = fImporting; cachedImporting = fImporting;
emit numBlocksChanged(newNumBlocks); emit numBlocksChanged(newNumBlocks, newBlockDate);
} }
emit bytesChanged(getTotalBytesRecv(), getTotalBytesSent()); emit bytesChanged(getTotalBytesRecv(), getTotalBytesSent());

View file

@ -6,6 +6,7 @@
#define BITCOIN_QT_CLIENTMODEL_H #define BITCOIN_QT_CLIENTMODEL_H
#include <QObject> #include <QObject>
#include <QDateTime>
class AddressTableModel; class AddressTableModel;
class OptionsModel; class OptionsModel;
@ -15,7 +16,6 @@ class TransactionTableModel;
class CWallet; class CWallet;
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QDateTime;
class QTimer; class QTimer;
QT_END_NAMESPACE QT_END_NAMESPACE
@ -48,7 +48,6 @@ public:
//! Return number of connections, default is in- and outbound (total) //! Return number of connections, default is in- and outbound (total)
int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const; int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const;
int getNumBlocks() const; int getNumBlocks() const;
int getNumBlocksAtStartup();
quint64 getTotalBytesRecv() const; quint64 getTotalBytesRecv() const;
quint64 getTotalBytesSent() const; quint64 getTotalBytesSent() const;
@ -74,11 +73,10 @@ private:
PeerTableModel *peerTableModel; PeerTableModel *peerTableModel;
int cachedNumBlocks; int cachedNumBlocks;
QDateTime cachedBlockDate;
bool cachedReindexing; bool cachedReindexing;
bool cachedImporting; bool cachedImporting;
int numBlocksAtStartup;
QTimer *pollTimer; QTimer *pollTimer;
void subscribeToCoreSignals(); void subscribeToCoreSignals();
@ -86,7 +84,7 @@ private:
signals: signals:
void numConnectionsChanged(int count); void numConnectionsChanged(int count);
void numBlocksChanged(int count); void numBlocksChanged(int count, const QDateTime& blockDate);
void alertsChanged(const QString &warnings); void alertsChanged(const QString &warnings);
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut); void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut);

View file

@ -15,7 +15,7 @@
#include "coincontrol.h" #include "coincontrol.h"
#include "main.h" #include "main.h"
#include "wallet.h" #include "wallet/wallet.h"
#include <boost/assign/list_of.hpp> // for 'map_list_of()' #include <boost/assign/list_of.hpp> // for 'map_list_of()'
@ -33,6 +33,7 @@
using namespace std; using namespace std;
QList<CAmount> CoinControlDialog::payAmounts; QList<CAmount> CoinControlDialog::payAmounts;
CCoinControl* CoinControlDialog::coinControl = new CCoinControl(); CCoinControl* CoinControlDialog::coinControl = new CCoinControl();
bool CoinControlDialog::fSubtractFeeFromAmount = false;
CoinControlDialog::CoinControlDialog(QWidget *parent) : CoinControlDialog::CoinControlDialog(QWidget *parent) :
QDialog(parent), QDialog(parent),
@ -541,6 +542,11 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
dPriority = dPriorityInputs / (nBytes - nBytesInputs + (nQuantityUncompressed * 29)); // 29 = 180 - 151 (uncompressed public keys are over the limit. max 151 bytes of the input are ignored for priority) dPriority = dPriorityInputs / (nBytes - nBytesInputs + (nQuantityUncompressed * 29)); // 29 = 180 - 151 (uncompressed public keys are over the limit. max 151 bytes of the input are ignored for priority)
sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority, mempoolEstimatePriority); sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority, mempoolEstimatePriority);
// in the subtract fee from amount case, we can tell if zero change already and subtract the bytes, so that fee calculation afterwards is accurate
if (CoinControlDialog::fSubtractFeeFromAmount)
if (nAmount - nPayAmount == 0)
nBytes -= 34;
// Fee // Fee
nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool); nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
@ -556,7 +562,9 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
if (nPayAmount > 0) if (nPayAmount > 0)
{ {
nChange = nAmount - nPayFee - nPayAmount; nChange = nAmount - nPayAmount;
if (!CoinControlDialog::fSubtractFeeFromAmount)
nChange -= nPayFee;
// Never create dust outputs; if we would, just add the dust to the fee. // Never create dust outputs; if we would, just add the dust to the fee.
if (nChange > 0 && nChange < CENT) if (nChange > 0 && nChange < CENT)
@ -564,12 +572,17 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
CTxOut txout(nChange, (CScript)vector<unsigned char>(24, 0)); CTxOut txout(nChange, (CScript)vector<unsigned char>(24, 0));
if (txout.IsDust(::minRelayTxFee)) if (txout.IsDust(::minRelayTxFee))
{ {
nPayFee += nChange; if (CoinControlDialog::fSubtractFeeFromAmount) // dust-change will be raised until no dust
nChange = 0; nChange = txout.GetDustThreshold(::minRelayTxFee);
else
{
nPayFee += nChange;
nChange = 0;
}
} }
} }
if (nChange == 0) if (nChange == 0 && !CoinControlDialog::fSubtractFeeFromAmount)
nBytes -= 34; nBytes -= 34;
} }
@ -612,7 +625,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
{ {
l3->setText(ASYMP_UTF8 + l3->text()); l3->setText(ASYMP_UTF8 + l3->text());
l4->setText(ASYMP_UTF8 + l4->text()); l4->setText(ASYMP_UTF8 + l4->text());
if (nChange > 0) if (nChange > 0 && !CoinControlDialog::fSubtractFeeFromAmount)
l8->setText(ASYMP_UTF8 + l8->text()); l8->setText(ASYMP_UTF8 + l8->text());
} }

View file

@ -43,6 +43,7 @@ public:
static QList<CAmount> payAmounts; static QList<CAmount> payAmounts;
static CCoinControl *coinControl; static CCoinControl *coinControl;
static bool fSubtractFeeFromAmount;
private: private:
Ui::CoinControlDialog *ui; Ui::CoinControlDialog *ui;

View file

@ -771,16 +771,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="buttonMinimizeFee">
<property name="toolTip">
<string>collapse fee-settings</string>
</property>
<property name="text">
<string>Minimize</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@ -811,6 +801,16 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item>
<widget class="QPushButton" name="buttonMinimizeFee">
<property name="toolTip">
<string>collapse fee-settings</string>
</property>
<property name="text">
<string>Minimize</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>

View file

@ -157,7 +157,21 @@
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="2" column="1">
<widget class="BitcoinAmountField" name="payAmount"/> <layout class="QHBoxLayout" name="horizontalLayoutAmount" stretch="0,1">
<item>
<widget class="BitcoinAmountField" name="payAmount"/>
</item>
<item>
<widget class="QCheckBox" name="checkboxSubtractFeeFromAmount">
<property name="toolTip">
<string>The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</string>
</property>
<property name="text">
<string>S&amp;ubtract fee from amount</string>
</property>
</widget>
</item>
</layout>
</item> </item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="messageLabel"> <widget class="QLabel" name="messageLabel">

View file

@ -40,6 +40,7 @@
#if BOOST_FILESYSTEM_VERSION >= 3 #if BOOST_FILESYSTEM_VERSION >= 3
#include <boost/filesystem/detail/utf8_codecvt_facet.hpp> #include <boost/filesystem/detail/utf8_codecvt_facet.hpp>
#endif #endif
#include <boost/scoped_array.hpp>
#include <QAbstractItemView> #include <QAbstractItemView>
#include <QApplication> #include <QApplication>
@ -567,12 +568,17 @@ TableViewLastColumnResizingFixer::TableViewLastColumnResizingFixer(QTableView* t
#ifdef WIN32 #ifdef WIN32
boost::filesystem::path static StartupShortcutPath() boost::filesystem::path static StartupShortcutPath()
{ {
if (GetBoolArg("-testnet", false))
return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin (testnet).lnk";
else if (GetBoolArg("-regtest", false))
return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin (regtest).lnk";
return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin.lnk"; return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin.lnk";
} }
bool GetStartOnSystemStartup() bool GetStartOnSystemStartup()
{ {
// check for Bitcoin.lnk // check for Bitcoin*.lnk
return boost::filesystem::exists(StartupShortcutPath()); return boost::filesystem::exists(StartupShortcutPath());
} }
@ -588,8 +594,8 @@ bool SetStartOnSystemStartup(bool fAutoStart)
// Get a pointer to the IShellLink interface. // Get a pointer to the IShellLink interface.
IShellLink* psl = NULL; IShellLink* psl = NULL;
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_IShellLink, CLSCTX_INPROC_SERVER, IID_IShellLink,
reinterpret_cast<void**>(&psl)); reinterpret_cast<void**>(&psl));
if (SUCCEEDED(hres)) if (SUCCEEDED(hres))
{ {
@ -597,20 +603,34 @@ bool SetStartOnSystemStartup(bool fAutoStart)
TCHAR pszExePath[MAX_PATH]; TCHAR pszExePath[MAX_PATH];
GetModuleFileName(NULL, pszExePath, sizeof(pszExePath)); GetModuleFileName(NULL, pszExePath, sizeof(pszExePath));
TCHAR pszArgs[5] = TEXT("-min"); // Start client minimized
QString strArgs = "-min";
// Set -testnet /-regtest options
strArgs += QString::fromStdString(strprintf(" -testnet=%d -regtest=%d", GetBoolArg("-testnet", false), GetBoolArg("-regtest", false)));
#ifdef UNICODE
boost::scoped_array<TCHAR> args(new TCHAR[strArgs.length() + 1]);
// Convert the QString to TCHAR*
strArgs.toWCharArray(args.get());
// Add missing '\0'-termination to string
args[strArgs.length()] = '\0';
#endif
// Set the path to the shortcut target // Set the path to the shortcut target
psl->SetPath(pszExePath); psl->SetPath(pszExePath);
PathRemoveFileSpec(pszExePath); PathRemoveFileSpec(pszExePath);
psl->SetWorkingDirectory(pszExePath); psl->SetWorkingDirectory(pszExePath);
psl->SetShowCmd(SW_SHOWMINNOACTIVE); psl->SetShowCmd(SW_SHOWMINNOACTIVE);
psl->SetArguments(pszArgs); #ifndef UNICODE
psl->SetArguments(strArgs.toStdString().c_str());
#else
psl->SetArguments(args.get());
#endif
// Query IShellLink for the IPersistFile interface for // Query IShellLink for the IPersistFile interface for
// saving the shortcut in persistent storage. // saving the shortcut in persistent storage.
IPersistFile* ppf = NULL; IPersistFile* ppf = NULL;
hres = psl->QueryInterface(IID_IPersistFile, hres = psl->QueryInterface(IID_IPersistFile, reinterpret_cast<void**>(&ppf));
reinterpret_cast<void**>(&ppf));
if (SUCCEEDED(hres)) if (SUCCEEDED(hres))
{ {
WCHAR pwsz[MAX_PATH]; WCHAR pwsz[MAX_PATH];
@ -630,11 +650,10 @@ bool SetStartOnSystemStartup(bool fAutoStart)
} }
return true; return true;
} }
#elif defined(Q_OS_LINUX) #elif defined(Q_OS_LINUX)
// Follow the Desktop Application Autostart Spec: // Follow the Desktop Application Autostart Spec:
// http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html // http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
boost::filesystem::path static GetAutostartDir() boost::filesystem::path static GetAutostartDir()
{ {
@ -690,8 +709,13 @@ bool SetStartOnSystemStartup(bool fAutoStart)
// Write a bitcoin.desktop file to the autostart directory: // Write a bitcoin.desktop file to the autostart directory:
optionFile << "[Desktop Entry]\n"; optionFile << "[Desktop Entry]\n";
optionFile << "Type=Application\n"; optionFile << "Type=Application\n";
optionFile << "Name=Bitcoin\n"; if (GetBoolArg("-testnet", false))
optionFile << "Exec=" << pszExePath << " -min\n"; optionFile << "Name=Bitcoin (testnet)\n";
else if (GetBoolArg("-regtest", false))
optionFile << "Name=Bitcoin (regtest)\n";
else
optionFile << "Name=Bitcoin\n";
optionFile << "Exec=" << pszExePath << strprintf(" -min -testnet=%d -regtest=%d\n", GetBoolArg("-testnet", false), GetBoolArg("-regtest", false));
optionFile << "Terminal=false\n"; optionFile << "Terminal=false\n";
optionFile << "Hidden=false\n"; optionFile << "Hidden=false\n";
optionFile.close(); optionFile.close();

View file

@ -14,12 +14,6 @@ class QMenu;
class QWidget; class QWidget;
QT_END_NAMESPACE QT_END_NAMESPACE
#ifdef __OBJC__
@class DockIconClickEventHandler;
#else
class DockIconClickEventHandler;
#endif
/** Macintosh-specific dock icon handler. /** Macintosh-specific dock icon handler.
*/ */
class MacDockIconHandler : public QObject class MacDockIconHandler : public QObject
@ -33,7 +27,7 @@ public:
void setIcon(const QIcon &icon); void setIcon(const QIcon &icon);
void setMainWindow(QMainWindow *window); void setMainWindow(QMainWindow *window);
static MacDockIconHandler *instance(); static MacDockIconHandler *instance();
static void cleanup();
void handleDockIconClickEvent(); void handleDockIconClickEvent();
signals: signals:
@ -42,7 +36,6 @@ signals:
private: private:
MacDockIconHandler(); MacDockIconHandler();
DockIconClickEventHandler *m_dockIconClickEventHandler;
QWidget *m_dummyWidget; QWidget *m_dummyWidget;
QMenu *m_dockMenu; QMenu *m_dockMenu;
QMainWindow *mainWindow; QMainWindow *mainWindow;

View file

@ -11,52 +11,46 @@
#undef slots #undef slots
#include <Cocoa/Cocoa.h> #include <Cocoa/Cocoa.h>
#include <objc/objc.h>
#include <objc/message.h>
#if QT_VERSION < 0x050000 #if QT_VERSION < 0x050000
extern void qt_mac_set_dock_menu(QMenu *); extern void qt_mac_set_dock_menu(QMenu *);
#endif #endif
@interface DockIconClickEventHandler : NSObject static MacDockIconHandler *s_instance = NULL;
{
MacDockIconHandler* dockIconHandler; bool dockClickHandler(id self,SEL _cmd,...) {
Q_UNUSED(self)
Q_UNUSED(_cmd)
s_instance->handleDockIconClickEvent();
// Return NO (false) to suppress the default OS X actions
return false;
} }
@end void setupDockClickHandler() {
Class cls = objc_getClass("NSApplication");
id appInst = objc_msgSend((id)cls, sel_registerName("sharedApplication"));
@implementation DockIconClickEventHandler if (appInst != NULL) {
id delegate = objc_msgSend(appInst, sel_registerName("delegate"));
- (id)initWithDockIconHandler:(MacDockIconHandler *)aDockIconHandler Class delClass = (Class)objc_msgSend(delegate, sel_registerName("class"));
{ SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:");
self = [super init]; if (class_getInstanceMethod(delClass, shouldHandle))
if (self) { class_replaceMethod(delClass, shouldHandle, (IMP)dockClickHandler, "B@:");
dockIconHandler = aDockIconHandler; else
class_addMethod(delClass, shouldHandle, (IMP)dockClickHandler,"B@:");
[[NSAppleEventManager sharedAppleEventManager]
setEventHandler:self
andSelector:@selector(handleDockClickEvent:withReplyEvent:)
forEventClass:kCoreEventClass
andEventID:kAEReopenApplication];
}
return self;
}
- (void)handleDockClickEvent:(NSAppleEventDescriptor*)event withReplyEvent:(NSAppleEventDescriptor*)replyEvent
{
Q_UNUSED(event)
Q_UNUSED(replyEvent)
if (dockIconHandler) {
dockIconHandler->handleDockIconClickEvent();
} }
} }
@end
MacDockIconHandler::MacDockIconHandler() : QObject() MacDockIconHandler::MacDockIconHandler() : QObject()
{ {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
this->m_dockIconClickEventHandler = [[DockIconClickEventHandler alloc] initWithDockIconHandler:this]; setupDockClickHandler();
this->m_dummyWidget = new QWidget(); this->m_dummyWidget = new QWidget();
this->m_dockMenu = new QMenu(this->m_dummyWidget); this->m_dockMenu = new QMenu(this->m_dummyWidget);
this->setMainWindow(NULL); this->setMainWindow(NULL);
@ -74,7 +68,6 @@ void MacDockIconHandler::setMainWindow(QMainWindow *window) {
MacDockIconHandler::~MacDockIconHandler() MacDockIconHandler::~MacDockIconHandler()
{ {
[this->m_dockIconClickEventHandler release];
delete this->m_dummyWidget; delete this->m_dummyWidget;
this->setMainWindow(NULL); this->setMainWindow(NULL);
} }
@ -119,12 +112,16 @@ void MacDockIconHandler::setIcon(const QIcon &icon)
MacDockIconHandler *MacDockIconHandler::instance() MacDockIconHandler *MacDockIconHandler::instance()
{ {
static MacDockIconHandler *s_instance = NULL;
if (!s_instance) if (!s_instance)
s_instance = new MacDockIconHandler(); s_instance = new MacDockIconHandler();
return s_instance; return s_instance;
} }
void MacDockIconHandler::cleanup()
{
delete s_instance;
}
void MacDockIconHandler::handleDockIconClickEvent() void MacDockIconHandler::handleDockIconClickEvent()
{ {
if (this->mainWindow) if (this->mainWindow)

View file

@ -18,7 +18,7 @@
#include "txdb.h" // for -dbcache defaults #include "txdb.h" // for -dbcache defaults
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#include "wallet.h" // for CWallet::minTxFee #include "wallet/wallet.h" // for CWallet::minTxFee
#endif #endif
#include <boost/thread.hpp> #include <boost/thread.hpp>
@ -38,7 +38,6 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
fProxyIpValid(true) fProxyIpValid(true)
{ {
ui->setupUi(this); ui->setupUi(this);
GUIUtil::restoreWindowGeometry("nOptionsDialogWindow", this->size(), this);
/* Main elements init */ /* Main elements init */
ui->databaseCache->setMinimum(nMinDbCache); ui->databaseCache->setMinimum(nMinDbCache);
@ -117,7 +116,6 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
OptionsDialog::~OptionsDialog() OptionsDialog::~OptionsDialog()
{ {
GUIUtil::saveWindowGeometry("nOptionsDialogWindow", this);
delete ui; delete ui;
} }

View file

@ -18,8 +18,8 @@
#include "txdb.h" // for -dbcache defaults #include "txdb.h" // for -dbcache defaults
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#include "wallet.h" #include "wallet/wallet.h"
#include "walletdb.h" #include "wallet/walletdb.h"
#endif #endif
#include <QNetworkProxy> #include <QNetworkProxy>

View file

@ -10,9 +10,10 @@
#include "base58.h" #include "base58.h"
#include "chainparams.h" #include "chainparams.h"
#include "main.h"
#include "ui_interface.h" #include "ui_interface.h"
#include "util.h" #include "util.h"
#include "wallet.h" #include "wallet/wallet.h"
#include <cstdlib> #include <cstdlib>

View file

@ -293,8 +293,8 @@ void RPCConsole::setClientModel(ClientModel *model)
setNumConnections(model->getNumConnections()); setNumConnections(model->getNumConnections());
connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
setNumBlocks(model->getNumBlocks()); setNumBlocks(model->getNumBlocks(), model->getLastBlockDate());
connect(model, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int))); connect(model, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(setNumBlocks(int,QDateTime)));
updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent()); updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent());
connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64))); connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64)));
@ -404,11 +404,10 @@ void RPCConsole::setNumConnections(int count)
ui->numberOfConnections->setText(connections); ui->numberOfConnections->setText(connections);
} }
void RPCConsole::setNumBlocks(int count) void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate)
{ {
ui->numberOfBlocks->setText(QString::number(count)); ui->numberOfBlocks->setText(QString::number(count));
if(clientModel) ui->lastBlockTime->setText(blockDate.toString());
ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString());
} }
void RPCConsole::on_lineEdit_returnPressed() void RPCConsole::on_lineEdit_returnPressed()

View file

@ -63,8 +63,8 @@ public slots:
void message(int category, const QString &message, bool html = false); void message(int category, const QString &message, bool html = false);
/** Set number of connections shown in the UI */ /** Set number of connections shown in the UI */
void setNumConnections(int count); void setNumConnections(int count);
/** Set number of blocks shown in the UI */ /** Set number of blocks and last block date shown in the UI */
void setNumBlocks(int count); void setNumBlocks(int count, const QDateTime& blockDate);
/** Go forward or back in history */ /** Go forward or back in history */
void browseHistory(int offset); void browseHistory(int offset);
/** Scroll console view to end */ /** Scroll console view to end */

View file

@ -17,8 +17,9 @@
#include "base58.h" #include "base58.h"
#include "coincontrol.h" #include "coincontrol.h"
#include "main.h"
#include "ui_interface.h" #include "ui_interface.h"
#include "wallet.h" #include "wallet/wallet.h"
#include <QMessageBox> #include <QMessageBox>
#include <QScrollBar> #include <QScrollBar>
@ -121,7 +122,7 @@ void SendCoinsDialog::setClientModel(ClientModel *clientModel)
this->clientModel = clientModel; this->clientModel = clientModel;
if (clientModel) { if (clientModel) {
connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(updateSmartFeeLabel())); connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(updateSmartFeeLabel()));
} }
} }
@ -220,9 +221,37 @@ void SendCoinsDialog::on_sendButton_clicked()
return; return;
} }
fNewRecipientAllowed = false;
WalletModel::UnlockContext ctx(model->requestUnlock());
if(!ctx.isValid())
{
// Unlock wallet was cancelled
fNewRecipientAllowed = true;
return;
}
// prepare transaction for getting txFee earlier
WalletModelTransaction currentTransaction(recipients);
WalletModel::SendCoinsReturn prepareStatus;
if (model->getOptionsModel()->getCoinControlFeatures()) // coin control enabled
prepareStatus = model->prepareTransaction(currentTransaction, CoinControlDialog::coinControl);
else
prepareStatus = model->prepareTransaction(currentTransaction);
// process prepareStatus and on error generate message shown to user
processSendCoinsReturn(prepareStatus,
BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), currentTransaction.getTransactionFee()));
if(prepareStatus.status != WalletModel::OK) {
fNewRecipientAllowed = true;
return;
}
CAmount txFee = currentTransaction.getTransactionFee();
// Format confirmation message // Format confirmation message
QStringList formatted; QStringList formatted;
foreach(const SendCoinsRecipient &rcp, recipients) foreach(const SendCoinsRecipient &rcp, currentTransaction.getRecipients())
{ {
// generate bold amount string // generate bold amount string
QString amount = "<b>" + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount); QString amount = "<b>" + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount);
@ -257,35 +286,6 @@ void SendCoinsDialog::on_sendButton_clicked()
formatted.append(recipientElement); formatted.append(recipientElement);
} }
fNewRecipientAllowed = false;
WalletModel::UnlockContext ctx(model->requestUnlock());
if(!ctx.isValid())
{
// Unlock wallet was cancelled
fNewRecipientAllowed = true;
return;
}
// prepare transaction for getting txFee earlier
WalletModelTransaction currentTransaction(recipients);
WalletModel::SendCoinsReturn prepareStatus;
if (model->getOptionsModel()->getCoinControlFeatures()) // coin control enabled
prepareStatus = model->prepareTransaction(currentTransaction, CoinControlDialog::coinControl);
else
prepareStatus = model->prepareTransaction(currentTransaction);
// process prepareStatus and on error generate message shown to user
processSendCoinsReturn(prepareStatus,
BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), currentTransaction.getTransactionFee()));
if(prepareStatus.status != WalletModel::OK) {
fNewRecipientAllowed = true;
return;
}
CAmount txFee = currentTransaction.getTransactionFee();
QString questionString = tr("Are you sure you want to send?"); QString questionString = tr("Are you sure you want to send?");
questionString.append("<br /><br />%1"); questionString.append("<br /><br />%1");
@ -368,6 +368,7 @@ SendCoinsEntry *SendCoinsDialog::addEntry()
ui->entries->addWidget(entry); ui->entries->addWidget(entry);
connect(entry, SIGNAL(removeEntry(SendCoinsEntry*)), this, SLOT(removeEntry(SendCoinsEntry*))); connect(entry, SIGNAL(removeEntry(SendCoinsEntry*)), this, SLOT(removeEntry(SendCoinsEntry*)));
connect(entry, SIGNAL(payAmountChanged()), this, SLOT(coinControlUpdateLabels())); connect(entry, SIGNAL(payAmountChanged()), this, SLOT(coinControlUpdateLabels()));
connect(entry, SIGNAL(subtractFeeFromAmountChanged()), this, SLOT(coinControlUpdateLabels()));
updateTabsAndLabels(); updateTabsAndLabels();
@ -783,11 +784,17 @@ void SendCoinsDialog::coinControlUpdateLabels()
// set pay amounts // set pay amounts
CoinControlDialog::payAmounts.clear(); CoinControlDialog::payAmounts.clear();
CoinControlDialog::fSubtractFeeFromAmount = false;
for(int i = 0; i < ui->entries->count(); ++i) for(int i = 0; i < ui->entries->count(); ++i)
{ {
SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget()); SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
if(entry) if(entry)
CoinControlDialog::payAmounts.append(entry->getValue().amount); {
SendCoinsRecipient rcp = entry->getValue();
CoinControlDialog::payAmounts.append(rcp.amount);
if (rcp.fSubtractFeeFromAmount)
CoinControlDialog::fSubtractFeeFromAmount = true;
}
} }
if (CoinControlDialog::coinControl->HasSelected()) if (CoinControlDialog::coinControl->HasSelected())

View file

@ -44,6 +44,7 @@ SendCoinsEntry::SendCoinsEntry(QWidget *parent) :
// Connect signals // Connect signals
connect(ui->payAmount, SIGNAL(valueChanged()), this, SIGNAL(payAmountChanged())); connect(ui->payAmount, SIGNAL(valueChanged()), this, SIGNAL(payAmountChanged()));
connect(ui->checkboxSubtractFeeFromAmount, SIGNAL(toggled(bool)), this, SIGNAL(subtractFeeFromAmountChanged()));
connect(ui->deleteButton, SIGNAL(clicked()), this, SLOT(deleteClicked())); connect(ui->deleteButton, SIGNAL(clicked()), this, SLOT(deleteClicked()));
connect(ui->deleteButton_is, SIGNAL(clicked()), this, SLOT(deleteClicked())); connect(ui->deleteButton_is, SIGNAL(clicked()), this, SLOT(deleteClicked()));
connect(ui->deleteButton_s, SIGNAL(clicked()), this, SLOT(deleteClicked())); connect(ui->deleteButton_s, SIGNAL(clicked()), this, SLOT(deleteClicked()));
@ -94,6 +95,7 @@ void SendCoinsEntry::clear()
ui->payTo->clear(); ui->payTo->clear();
ui->addAsLabel->clear(); ui->addAsLabel->clear();
ui->payAmount->clear(); ui->payAmount->clear();
ui->checkboxSubtractFeeFromAmount->setCheckState(Qt::Unchecked);
ui->messageTextLabel->clear(); ui->messageTextLabel->clear();
ui->messageTextLabel->hide(); ui->messageTextLabel->hide();
ui->messageLabel->hide(); ui->messageLabel->hide();
@ -165,6 +167,7 @@ SendCoinsRecipient SendCoinsEntry::getValue()
recipient.label = ui->addAsLabel->text(); recipient.label = ui->addAsLabel->text();
recipient.amount = ui->payAmount->value(); recipient.amount = ui->payAmount->value();
recipient.message = ui->messageTextLabel->text(); recipient.message = ui->messageTextLabel->text();
recipient.fSubtractFeeFromAmount = (ui->checkboxSubtractFeeFromAmount->checkState() == Qt::Checked);
return recipient; return recipient;
} }
@ -174,7 +177,8 @@ QWidget *SendCoinsEntry::setupTabChain(QWidget *prev)
QWidget::setTabOrder(prev, ui->payTo); QWidget::setTabOrder(prev, ui->payTo);
QWidget::setTabOrder(ui->payTo, ui->addAsLabel); QWidget::setTabOrder(ui->payTo, ui->addAsLabel);
QWidget *w = ui->payAmount->setupTabChain(ui->addAsLabel); QWidget *w = ui->payAmount->setupTabChain(ui->addAsLabel);
QWidget::setTabOrder(w, ui->addressBookButton); QWidget::setTabOrder(w, ui->checkboxSubtractFeeFromAmount);
QWidget::setTabOrder(ui->checkboxSubtractFeeFromAmount, ui->addressBookButton);
QWidget::setTabOrder(ui->addressBookButton, ui->pasteButton); QWidget::setTabOrder(ui->addressBookButton, ui->pasteButton);
QWidget::setTabOrder(ui->pasteButton, ui->deleteButton); QWidget::setTabOrder(ui->pasteButton, ui->deleteButton);
return ui->deleteButton; return ui->deleteButton;

View file

@ -51,6 +51,7 @@ public slots:
signals: signals:
void removeEntry(SendCoinsEntry *entry); void removeEntry(SendCoinsEntry *entry);
void payAmountChanged(); void payAmountChanged();
void subtractFeeFromAmountChanged();
private slots: private slots:
void deleteClicked(); void deleteClicked();

View file

@ -12,7 +12,8 @@
#include "base58.h" #include "base58.h"
#include "init.h" #include "init.h"
#include "wallet.h" #include "main.h" // For strMessageMagic
#include "wallet/wallet.h"
#include <string> #include <string>
#include <vector> #include <vector>

View file

@ -12,7 +12,7 @@
#include "version.h" #include "version.h"
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#include "wallet.h" #include "wallet/wallet.h"
#endif #endif
#include <QApplication> #include <QApplication>

View file

@ -10,13 +10,13 @@
#include "transactionrecord.h" #include "transactionrecord.h"
#include "base58.h" #include "base58.h"
#include "db.h" #include "wallet/db.h"
#include "main.h" #include "main.h"
#include "script/script.h" #include "script/script.h"
#include "timedata.h" #include "timedata.h"
#include "ui_interface.h" #include "ui_interface.h"
#include "util.h" #include "util.h"
#include "wallet.h" #include "wallet/wallet.h"
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>

View file

@ -5,11 +5,14 @@
#include "transactionrecord.h" #include "transactionrecord.h"
#include "base58.h" #include "base58.h"
#include "main.h"
#include "timedata.h" #include "timedata.h"
#include "wallet.h" #include "wallet/wallet.h"
#include <stdint.h> #include <stdint.h>
#include <boost/foreach.hpp>
/* Return positive answer if transaction should be shown in list. /* Return positive answer if transaction should be shown in list.
*/ */
bool TransactionRecord::showTransaction(const CWalletTx &wtx) bool TransactionRecord::showTransaction(const CWalletTx &wtx)

View file

@ -17,7 +17,7 @@
#include "sync.h" #include "sync.h"
#include "uint256.h" #include "uint256.h"
#include "util.h" #include "util.h"
#include "wallet.h" #include "wallet/wallet.h"
#include <QColor> #include <QColor>
#include <QDateTime> #include <QDateTime>

View file

@ -29,7 +29,6 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) :
ui(new Ui::HelpMessageDialog) ui(new Ui::HelpMessageDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
GUIUtil::restoreWindowGeometry("nHelpMessageDialogWindow", this->size(), this);
QString version = tr("Bitcoin Core") + " " + tr("version") + " " + QString::fromStdString(FormatFullVersion()); QString version = tr("Bitcoin Core") + " " + tr("version") + " " + QString::fromStdString(FormatFullVersion());
/* On x86 add a bit specifier to the version so that users can distinguish between /* On x86 add a bit specifier to the version so that users can distinguish between
@ -63,13 +62,17 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) :
ui->helpMessage->setVisible(false); ui->helpMessage->setVisible(false);
} else { } else {
setWindowTitle(tr("Command-line options")); setWindowTitle(tr("Command-line options"));
QString header = tr("Usage:") + "\n" +
" bitcoin-qt [" + tr("command-line options") + "] " + "\n";
QTextCursor cursor(ui->helpMessage->document()); QTextCursor cursor(ui->helpMessage->document());
cursor.insertText(version); cursor.insertText(version);
cursor.insertBlock(); cursor.insertBlock();
cursor.insertText(tr("Usage:") + '\n' + cursor.insertText(header);
" bitcoin-qt [" + tr("command-line options") + "]\n");
cursor.insertBlock(); cursor.insertBlock();
QString coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT));
text = version + "\n" + header + "\n" + coreOptions;
QTextTableFormat tf; QTextTableFormat tf;
tf.setBorderStyle(QTextFrameFormat::BorderStyle_None); tf.setBorderStyle(QTextFrameFormat::BorderStyle_None);
tf.setCellPadding(2); tf.setCellPadding(2);
@ -77,64 +80,30 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) :
widths << QTextLength(QTextLength::PercentageLength, 35); widths << QTextLength(QTextLength::PercentageLength, 35);
widths << QTextLength(QTextLength::PercentageLength, 65); widths << QTextLength(QTextLength::PercentageLength, 65);
tf.setColumnWidthConstraints(widths); tf.setColumnWidthConstraints(widths);
QTextTable *table = cursor.insertTable(2, 2, tf);
QString coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT));
bool first = true;
QTextCharFormat bold; QTextCharFormat bold;
bold.setFontWeight(QFont::Bold); bold.setFontWeight(QFont::Bold);
// note that coreOptions is not translated.
foreach (const QString &line, coreOptions.split('\n')) { foreach (const QString &line, coreOptions.split("\n")) {
if (!first) { if (line.startsWith(" -"))
table->appendRows(1); {
cursor.currentTable()->appendRows(1);
cursor.movePosition(QTextCursor::PreviousCell);
cursor.movePosition(QTextCursor::NextRow); cursor.movePosition(QTextCursor::NextRow);
cursor.insertText(line.trimmed());
cursor.movePosition(QTextCursor::NextCell);
} else if (line.startsWith(" ")) {
cursor.insertText(line.trimmed()+' ');
} else if (line.size() > 0) {
//Title of a group
if (cursor.currentTable())
cursor.currentTable()->appendRows(1);
cursor.movePosition(QTextCursor::Down);
cursor.insertText(line.trimmed(), bold);
cursor.insertTable(1, 2, tf);
} }
first = false;
if (line.startsWith(" ")) {
int index = line.indexOf(' ', 3);
if (index > 0) {
cursor.insertText(line.left(index).trimmed());
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText(line.mid(index).trimmed());
continue;
}
}
cursor.movePosition(QTextCursor::NextCell, QTextCursor::KeepAnchor);
table->mergeCells(cursor);
cursor.insertText(line.trimmed(), bold);
} }
table->appendRows(6);
cursor.movePosition(QTextCursor::NextRow);
cursor.insertText(tr("UI options") + ":", bold);
cursor.movePosition(QTextCursor::NextRow);
if (GetBoolArg("-help-debug", false)) {
cursor.insertText("-allowselfsignedrootcertificates");
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText(tr("Allow self signed root certificates (default: 0)"));
cursor.movePosition(QTextCursor::NextCell);
}
cursor.insertText("-choosedatadir");
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText(tr("Choose data directory on startup (default: 0)"));
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText("-lang=<lang>");
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText(tr("Set language, for example \"de_DE\" (default: system locale)"));
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText("-min");
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText(tr("Start minimized"));
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText("-rootcertificates=<file>");
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText(tr("Set SSL root certificates for payment request (default: -system-)"));
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText("-splash");
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText(tr("Show splash screen on startup (default: 1)"));
ui->helpMessage->moveCursor(QTextCursor::Start); ui->helpMessage->moveCursor(QTextCursor::Start);
ui->scrollArea->setVisible(false); ui->scrollArea->setVisible(false);
ui->aboutLogo->setVisible(false); ui->aboutLogo->setVisible(false);
@ -143,7 +112,6 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) :
HelpMessageDialog::~HelpMessageDialog() HelpMessageDialog::~HelpMessageDialog()
{ {
GUIUtil::saveWindowGeometry("nHelpMessageDialogWindow", this);
delete ui; delete ui;
} }

View file

@ -6,18 +6,19 @@
#include "addresstablemodel.h" #include "addresstablemodel.h"
#include "guiconstants.h" #include "guiconstants.h"
#include "guiutil.h"
#include "paymentserver.h" #include "paymentserver.h"
#include "recentrequeststablemodel.h" #include "recentrequeststablemodel.h"
#include "transactiontablemodel.h" #include "transactiontablemodel.h"
#include "base58.h" #include "base58.h"
#include "db.h" #include "wallet/db.h"
#include "keystore.h" #include "keystore.h"
#include "main.h" #include "main.h"
#include "sync.h" #include "sync.h"
#include "ui_interface.h" #include "ui_interface.h"
#include "wallet.h" #include "wallet/wallet.h"
#include "walletdb.h" // for BackupWallet #include "wallet/walletdb.h" // for BackupWallet
#include <stdint.h> #include <stdint.h>
@ -192,8 +193,9 @@ bool WalletModel::validateAddress(const QString &address)
WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl) WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl)
{ {
CAmount total = 0; CAmount total = 0;
bool fSubtractFeeFromAmount = false;
QList<SendCoinsRecipient> recipients = transaction.getRecipients(); QList<SendCoinsRecipient> recipients = transaction.getRecipients();
std::vector<std::pair<CScript, CAmount> > vecSend; std::vector<CRecipient> vecSend;
if(recipients.empty()) if(recipients.empty())
{ {
@ -206,6 +208,9 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
// Pre-check input data for validity // Pre-check input data for validity
foreach(const SendCoinsRecipient &rcp, recipients) foreach(const SendCoinsRecipient &rcp, recipients)
{ {
if (rcp.fSubtractFeeFromAmount)
fSubtractFeeFromAmount = true;
if (rcp.paymentRequest.IsInitialized()) if (rcp.paymentRequest.IsInitialized())
{ // PaymentRequest... { // PaymentRequest...
CAmount subtotal = 0; CAmount subtotal = 0;
@ -217,7 +222,9 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
subtotal += out.amount(); subtotal += out.amount();
const unsigned char* scriptStr = (const unsigned char*)out.script().data(); const unsigned char* scriptStr = (const unsigned char*)out.script().data();
CScript scriptPubKey(scriptStr, scriptStr+out.script().size()); CScript scriptPubKey(scriptStr, scriptStr+out.script().size());
vecSend.push_back(std::pair<CScript, CAmount>(scriptPubKey, out.amount())); CAmount nAmount = out.amount();
CRecipient recipient = {scriptPubKey, nAmount, rcp.fSubtractFeeFromAmount};
vecSend.push_back(recipient);
} }
if (subtotal <= 0) if (subtotal <= 0)
{ {
@ -239,7 +246,8 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
++nAddresses; ++nAddresses;
CScript scriptPubKey = GetScriptForDestination(CBitcoinAddress(rcp.address.toStdString()).Get()); CScript scriptPubKey = GetScriptForDestination(CBitcoinAddress(rcp.address.toStdString()).Get());
vecSend.push_back(std::pair<CScript, CAmount>(scriptPubKey, rcp.amount)); CRecipient recipient = {scriptPubKey, rcp.amount, rcp.fSubtractFeeFromAmount};
vecSend.push_back(recipient);
total += rcp.amount; total += rcp.amount;
} }
@ -260,17 +268,21 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
LOCK2(cs_main, wallet->cs_wallet); LOCK2(cs_main, wallet->cs_wallet);
transaction.newPossibleKeyChange(wallet); transaction.newPossibleKeyChange(wallet);
CAmount nFeeRequired = 0; CAmount nFeeRequired = 0;
int nChangePosRet = -1;
std::string strFailReason; std::string strFailReason;
CWalletTx *newTx = transaction.getTransaction(); CWalletTx *newTx = transaction.getTransaction();
CReserveKey *keyChange = transaction.getPossibleKeyChange(); CReserveKey *keyChange = transaction.getPossibleKeyChange();
bool fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, strFailReason, coinControl); bool fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, nChangePosRet, strFailReason, coinControl);
transaction.setTransactionFee(nFeeRequired); transaction.setTransactionFee(nFeeRequired);
if (fSubtractFeeFromAmount && fCreated)
transaction.reassignAmounts(nChangePosRet);
if(!fCreated) if(!fCreated)
{ {
if((total + nFeeRequired) > nBalance) if(!fSubtractFeeFromAmount && (total + nFeeRequired) > nBalance)
{ {
return SendCoinsReturn(AmountWithFeeExceedsBalance); return SendCoinsReturn(AmountWithFeeExceedsBalance);
} }

View file

@ -8,7 +8,7 @@
#include "paymentrequestplus.h" #include "paymentrequestplus.h"
#include "walletmodeltransaction.h" #include "walletmodeltransaction.h"
#include "allocators.h" /* for SecureString */ #include "support/allocators/secure.h"
#include <map> #include <map>
#include <vector> #include <vector>
@ -36,9 +36,9 @@ QT_END_NAMESPACE
class SendCoinsRecipient class SendCoinsRecipient
{ {
public: public:
explicit SendCoinsRecipient() : amount(0), nVersion(SendCoinsRecipient::CURRENT_VERSION) { } explicit SendCoinsRecipient() : amount(0), fSubtractFeeFromAmount(false), nVersion(SendCoinsRecipient::CURRENT_VERSION) { }
explicit SendCoinsRecipient(const QString &addr, const QString &label, const CAmount& amount, const QString &message): explicit SendCoinsRecipient(const QString &addr, const QString &label, const CAmount& amount, const QString &message):
address(addr), label(label), amount(amount), message(message), nVersion(SendCoinsRecipient::CURRENT_VERSION) {} address(addr), label(label), amount(amount), message(message), fSubtractFeeFromAmount(false), nVersion(SendCoinsRecipient::CURRENT_VERSION) {}
// If from an unauthenticated payment request, this is used for storing // If from an unauthenticated payment request, this is used for storing
// the addresses, e.g. address-A<br />address-B<br />address-C. // the addresses, e.g. address-A<br />address-B<br />address-C.
@ -56,6 +56,8 @@ public:
// Empty if no authentication or invalid signature/cert/etc. // Empty if no authentication or invalid signature/cert/etc.
QString authenticatedMerchant; QString authenticatedMerchant;
bool fSubtractFeeFromAmount; // memory only
static const int CURRENT_VERSION = 1; static const int CURRENT_VERSION = 1;
int nVersion; int nVersion;

View file

@ -4,7 +4,7 @@
#include "walletmodeltransaction.h" #include "walletmodeltransaction.h"
#include "wallet.h" #include "wallet/wallet.h"
WalletModelTransaction::WalletModelTransaction(const QList<SendCoinsRecipient> &recipients) : WalletModelTransaction::WalletModelTransaction(const QList<SendCoinsRecipient> &recipients) :
recipients(recipients), recipients(recipients),
@ -46,6 +46,38 @@ void WalletModelTransaction::setTransactionFee(const CAmount& newFee)
fee = newFee; fee = newFee;
} }
void WalletModelTransaction::reassignAmounts(int nChangePosRet)
{
int i = 0;
for (QList<SendCoinsRecipient>::iterator it = recipients.begin(); it != recipients.end(); ++it)
{
SendCoinsRecipient& rcp = (*it);
if (rcp.paymentRequest.IsInitialized())
{
CAmount subtotal = 0;
const payments::PaymentDetails& details = rcp.paymentRequest.getDetails();
for (int j = 0; j < details.outputs_size(); j++)
{
const payments::Output& out = details.outputs(j);
if (out.amount() <= 0) continue;
if (i == nChangePosRet)
i++;
subtotal += walletTransaction->vout[i].nValue;
i++;
}
rcp.amount = subtotal;
}
else // normal recipient (no payment request)
{
if (i == nChangePosRet)
i++;
rcp.amount = walletTransaction->vout[i].nValue;
i++;
}
}
}
CAmount WalletModelTransaction::getTotalTransactionAmount() CAmount WalletModelTransaction::getTotalTransactionAmount()
{ {
CAmount totalTransactionAmount = 0; CAmount totalTransactionAmount = 0;

View file

@ -35,8 +35,10 @@ public:
void newPossibleKeyChange(CWallet *wallet); void newPossibleKeyChange(CWallet *wallet);
CReserveKey *getPossibleKeyChange(); CReserveKey *getPossibleKeyChange();
void reassignAmounts(int nChangePosRet); // needed for the subtract-fee-from-amount feature
private: private:
const QList<SendCoinsRecipient> recipients; QList<SendCoinsRecipient> recipients;
CWalletTx *walletTransaction; CWalletTx *walletTransaction;
CReserveKey *keyChange; CReserveKey *keyChange;
CAmount fee; CAmount fee;

View file

@ -47,15 +47,16 @@ void RandAddSeedPerfmon()
{ {
RandAddSeed(); RandAddSeed();
#ifdef WIN32
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
// Seed with the entire set of perfmon data
// This can take up to 2 seconds, so only do it every 10 minutes // This can take up to 2 seconds, so only do it every 10 minutes
static int64_t nLastPerfmon; static int64_t nLastPerfmon;
if (GetTime() < nLastPerfmon + 10 * 60) if (GetTime() < nLastPerfmon + 10 * 60)
return; return;
nLastPerfmon = GetTime(); nLastPerfmon = GetTime();
#ifdef WIN32
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
// Seed with the entire set of perfmon data
std::vector<unsigned char> vData(250000, 0); std::vector<unsigned char> vData(250000, 0);
long ret = 0; long ret = 0;
unsigned long nSize = 0; unsigned long nSize = 0;

View file

@ -32,6 +32,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getnetworkhashps", 0 }, { "getnetworkhashps", 0 },
{ "getnetworkhashps", 1 }, { "getnetworkhashps", 1 },
{ "sendtoaddress", 1 }, { "sendtoaddress", 1 },
{ "sendtoaddress", 4 },
{ "settxfee", 0 }, { "settxfee", 0 },
{ "getreceivedbyaddress", 1 }, { "getreceivedbyaddress", 1 },
{ "getreceivedbyaccount", 1 }, { "getreceivedbyaccount", 1 },
@ -59,6 +60,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "listsinceblock", 2 }, { "listsinceblock", 2 },
{ "sendmany", 1 }, { "sendmany", 1 },
{ "sendmany", 2 }, { "sendmany", 2 },
{ "sendmany", 4 },
{ "addmultisigaddress", 0 }, { "addmultisigaddress", 0 },
{ "addmultisigaddress", 1 }, { "addmultisigaddress", 1 },
{ "createmultisig", 0 }, { "createmultisig", 0 },

View file

@ -13,9 +13,10 @@
#include "pow.h" #include "pow.h"
#include "rpcserver.h" #include "rpcserver.h"
#include "util.h" #include "util.h"
#include "validationinterface.h"
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#include "db.h" #include "wallet/db.h"
#include "wallet.h" #include "wallet/wallet.h"
#endif #endif
#include <stdint.h> #include <stdint.h>

View file

@ -13,8 +13,8 @@
#include "timedata.h" #include "timedata.h"
#include "util.h" #include "util.h"
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#include "wallet.h" #include "wallet/wallet.h"
#include "walletdb.h" #include "wallet/walletdb.h"
#endif #endif
#include <stdint.h> #include <stdint.h>

View file

@ -16,7 +16,7 @@
#include "script/standard.h" #include "script/standard.h"
#include "uint256.h" #include "uint256.h"
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#include "wallet.h" #include "wallet/wallet.h"
#endif #endif
#include <stdint.h> #include <stdint.h>

View file

@ -13,7 +13,7 @@
#include "util.h" #include "util.h"
#include "utilstrencodings.h" #include "utilstrencodings.h"
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#include "wallet.h" #include "wallet/wallet.h"
#endif #endif
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>

View file

@ -14,6 +14,7 @@
#include <string.h> #include <string.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include "crypto/common.h"
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
@ -417,14 +418,16 @@ public:
else if (b.size() <= 0xffff) else if (b.size() <= 0xffff)
{ {
insert(end(), OP_PUSHDATA2); insert(end(), OP_PUSHDATA2);
unsigned short nSize = b.size(); uint8_t data[2];
insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize)); WriteLE16(data, b.size());
insert(end(), data, data + sizeof(data));
} }
else else
{ {
insert(end(), OP_PUSHDATA4); insert(end(), OP_PUSHDATA4);
unsigned int nSize = b.size(); uint8_t data[4];
insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize)); WriteLE32(data, b.size());
insert(end(), data, data + sizeof(data));
} }
insert(end(), b.begin(), b.end()); insert(end(), b.begin(), b.end());
return *this; return *this;
@ -497,15 +500,14 @@ public:
{ {
if (end() - pc < 2) if (end() - pc < 2)
return false; return false;
nSize = 0; nSize = ReadLE16(&pc[0]);
memcpy(&nSize, &pc[0], 2);
pc += 2; pc += 2;
} }
else if (opcode == OP_PUSHDATA4) else if (opcode == OP_PUSHDATA4)
{ {
if (end() - pc < 4) if (end() - pc < 4)
return false; return false;
memcpy(&nSize, &pc[0], 4); nSize = ReadLE32(&pc[0]);
pc += 4; pc += 4;
} }
if (end() - pc < 0 || (unsigned int)(end() - pc) < nSize) if (end() - pc < 0 || (unsigned int)(end() - pc) < nSize)

View file

@ -17,22 +17,31 @@ using namespace std;
typedef vector<unsigned char> valtype; typedef vector<unsigned char> valtype;
bool Sign1(const CKeyID& address, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet) TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), checker(txTo, nIn) {}
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode) const
{ {
CKey key; CKey key;
if (!keystore.GetKey(address, key)) if (!keystore->GetKey(address, key))
return false; return false;
vector<unsigned char> vchSig; uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
if (!key.Sign(hash, vchSig)) if (!key.Sign(hash, vchSig))
return false; return false;
vchSig.push_back((unsigned char)nHashType); vchSig.push_back((unsigned char)nHashType);
scriptSigRet << vchSig;
return true; return true;
} }
bool SignN(const vector<valtype>& multisigdata, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet) static bool Sign1(const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, CScript& scriptSigRet)
{
vector<unsigned char> vchSig;
if (!creator.CreateSig(vchSig, address, scriptCode))
return false;
scriptSigRet << vchSig;
return true;
}
static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, CScript& scriptSigRet)
{ {
int nSigned = 0; int nSigned = 0;
int nRequired = multisigdata.front()[0]; int nRequired = multisigdata.front()[0];
@ -40,20 +49,20 @@ bool SignN(const vector<valtype>& multisigdata, const CKeyStore& keystore, uint2
{ {
const valtype& pubkey = multisigdata[i]; const valtype& pubkey = multisigdata[i];
CKeyID keyID = CPubKey(pubkey).GetID(); CKeyID keyID = CPubKey(pubkey).GetID();
if (Sign1(keyID, keystore, hash, nHashType, scriptSigRet)) if (Sign1(keyID, creator, scriptCode, scriptSigRet))
++nSigned; ++nSigned;
} }
return nSigned==nRequired; return nSigned==nRequired;
} }
/** /**
* Sign scriptPubKey with private keys stored in keystore, given transaction hash and hash type. * Sign scriptPubKey using signature made with creator.
* Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed), * Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),
* unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script. * unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script.
* Returns false if scriptPubKey could not be completely satisfied. * Returns false if scriptPubKey could not be completely satisfied.
*/ */
bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash, int nHashType, static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptPubKey,
CScript& scriptSigRet, txnouttype& whichTypeRet) CScript& scriptSigRet, txnouttype& whichTypeRet)
{ {
scriptSigRet.clear(); scriptSigRet.clear();
@ -71,39 +80,32 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash
return false; return false;
case TX_PUBKEY: case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID(); keyID = CPubKey(vSolutions[0]).GetID();
return Sign1(keyID, keystore, hash, nHashType, scriptSigRet); return Sign1(keyID, creator, scriptPubKey, scriptSigRet);
case TX_PUBKEYHASH: case TX_PUBKEYHASH:
keyID = CKeyID(uint160(vSolutions[0])); keyID = CKeyID(uint160(vSolutions[0]));
if (!Sign1(keyID, keystore, hash, nHashType, scriptSigRet)) if (!Sign1(keyID, creator, scriptPubKey, scriptSigRet))
return false; return false;
else else
{ {
CPubKey vch; CPubKey vch;
keystore.GetPubKey(keyID, vch); creator.KeyStore().GetPubKey(keyID, vch);
scriptSigRet << ToByteVector(vch); scriptSigRet << ToByteVector(vch);
} }
return true; return true;
case TX_SCRIPTHASH: case TX_SCRIPTHASH:
return keystore.GetCScript(uint160(vSolutions[0]), scriptSigRet); return creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptSigRet);
case TX_MULTISIG: case TX_MULTISIG:
scriptSigRet << OP_0; // workaround CHECKMULTISIG bug scriptSigRet << OP_0; // workaround CHECKMULTISIG bug
return (SignN(vSolutions, keystore, hash, nHashType, scriptSigRet)); return (SignN(vSolutions, creator, scriptPubKey, scriptSigRet));
} }
return false; return false;
} }
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType) bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, CScript& scriptSig)
{ {
assert(nIn < txTo.vin.size());
CTxIn& txin = txTo.vin[nIn];
// Leave out the signature from the hash, since a signature can't sign itself.
// The checksig op will also drop the signatures from its hash.
uint256 hash = SignatureHash(fromPubKey, txTo, nIn, nHashType);
txnouttype whichType; txnouttype whichType;
if (!Solver(keystore, fromPubKey, hash, nHashType, txin.scriptSig, whichType)) if (!SignStep(creator, fromPubKey, scriptSig, whichType))
return false; return false;
if (whichType == TX_SCRIPTHASH) if (whichType == TX_SCRIPTHASH)
@ -111,21 +113,29 @@ bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutabl
// Solver returns the subscript that need to be evaluated; // Solver returns the subscript that need to be evaluated;
// the final scriptSig is the signatures from that // the final scriptSig is the signatures from that
// and then the serialized subscript: // and then the serialized subscript:
CScript subscript = txin.scriptSig; CScript subscript = scriptSig;
// Recompute txn hash using subscript in place of scriptPubKey:
uint256 hash2 = SignatureHash(subscript, txTo, nIn, nHashType);
txnouttype subType; txnouttype subType;
bool fSolved = bool fSolved =
Solver(keystore, subscript, hash2, nHashType, txin.scriptSig, subType) && subType != TX_SCRIPTHASH; SignStep(creator, subscript, scriptSig, subType) && subType != TX_SCRIPTHASH;
// Append serialized subscript whether or not it is completely signed: // Append serialized subscript whether or not it is completely signed:
txin.scriptSig << static_cast<valtype>(subscript); scriptSig << static_cast<valtype>(subscript);
if (!fSolved) return false; if (!fSolved) return false;
} }
// Test solution // Test solution
return VerifyScript(txin.scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&txTo, nIn)); return VerifyScript(scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker());
}
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
{
assert(nIn < txTo.vin.size());
CTxIn& txin = txTo.vin[nIn];
CTransaction txToConst(txTo);
TransactionSignatureCreator creator(&keystore, &txToConst, nIn, nHashType);
return ProduceSignature(creator, fromPubKey, txin.scriptSig);
} }
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType) bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
@ -146,7 +156,7 @@ static CScript PushAll(const vector<valtype>& values)
return result; return result;
} }
static CScript CombineMultisig(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
const vector<valtype>& vSolutions, const vector<valtype>& vSolutions,
const vector<valtype>& sigs1, const vector<valtype>& sigs2) const vector<valtype>& sigs1, const vector<valtype>& sigs2)
{ {
@ -176,7 +186,7 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const CTransaction&
if (sigs.count(pubkey)) if (sigs.count(pubkey))
continue; // Already got a sig for this pubkey continue; // Already got a sig for this pubkey
if (TransactionSignatureChecker(&txTo, nIn).CheckSig(sig, pubkey, scriptPubKey)) if (checker.CheckSig(sig, pubkey, scriptPubKey))
{ {
sigs[pubkey] = sig; sigs[pubkey] = sig;
break; break;
@ -201,7 +211,7 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const CTransaction&
return result; return result;
} }
static CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, static CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
const txnouttype txType, const vector<valtype>& vSolutions, const txnouttype txType, const vector<valtype>& vSolutions,
vector<valtype>& sigs1, vector<valtype>& sigs2) vector<valtype>& sigs1, vector<valtype>& sigs2)
{ {
@ -235,12 +245,12 @@ static CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction
Solver(pubKey2, txType2, vSolutions2); Solver(pubKey2, txType2, vSolutions2);
sigs1.pop_back(); sigs1.pop_back();
sigs2.pop_back(); sigs2.pop_back();
CScript result = CombineSignatures(pubKey2, txTo, nIn, txType2, vSolutions2, sigs1, sigs2); CScript result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2);
result << spk; result << spk;
return result; return result;
} }
case TX_MULTISIG: case TX_MULTISIG:
return CombineMultisig(scriptPubKey, txTo, nIn, vSolutions, sigs1, sigs2); return CombineMultisig(scriptPubKey, checker, vSolutions, sigs1, sigs2);
} }
return CScript(); return CScript();
@ -248,6 +258,13 @@ static CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction
CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
const CScript& scriptSig1, const CScript& scriptSig2) const CScript& scriptSig1, const CScript& scriptSig2)
{
TransactionSignatureChecker checker(&txTo, nIn);
return CombineSignatures(scriptPubKey, checker, scriptSig1, scriptSig2);
}
CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
const CScript& scriptSig1, const CScript& scriptSig2)
{ {
txnouttype txType; txnouttype txType;
vector<vector<unsigned char> > vSolutions; vector<vector<unsigned char> > vSolutions;
@ -258,5 +275,5 @@ CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo,
vector<valtype> stack2; vector<valtype> stack2;
EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker()); EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker());
return CombineSignatures(scriptPubKey, txTo, nIn, txType, vSolutions, stack1, stack2); return CombineSignatures(scriptPubKey, checker, txType, vSolutions, stack1, stack2);
} }

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