merge in bitcoin changes

This commit is contained in:
Jimmy Kiselak 2015-01-15 12:52:38 -05:00
commit a50a5ad369
143 changed files with 1435 additions and 1095 deletions

View file

@ -171,6 +171,24 @@ if test "x$CXXFLAGS_overridden" = "xno"; then
fi fi
CPPFLAGS="$CPPFLAGS -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS" CPPFLAGS="$CPPFLAGS -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS"
AC_ARG_WITH([utils],
[AS_HELP_STRING([--with-utils],
[build bitcoin-cli bitcoin-tx (default=yes)])],
[build_bitcoin_utils=$withval],
[build_bitcoin_utils=yes])
AC_ARG_WITH([libs],
[AS_HELP_STRING([--with-libs],
[build libraries (default=yes)])],
[build_bitcoin_libs=$withval],
[build_bitcoin_libs=yes])
AC_ARG_WITH([daemon],
[AS_HELP_STRING([--with-daemon],
[build bitcoind daemon (default=yes)])],
[build_bitcoind=$withval],
[build_bitcoind=yes])
AC_LANG_PUSH([C++]) AC_LANG_PUSH([C++])
use_pkgconfig=yes use_pkgconfig=yes
@ -500,6 +518,19 @@ if test x$use_upnp != xno; then
) )
fi fi
BITCOIN_QT_INIT
dnl sets $bitcoin_enable_qt, $bitcoin_enable_qt_test, $bitcoin_enable_qt_dbus
BITCOIN_QT_CONFIGURE([$use_pkgconfig], [qt4])
if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests = xnononono; then
use_boost=no
else
use_boost=yes
fi
if test x$use_boost = xyes; then
dnl Check for boost libs dnl Check for boost libs
AX_BOOST_BASE AX_BOOST_BASE
AX_BOOST_SYSTEM AX_BOOST_SYSTEM
@ -537,6 +568,10 @@ if test x$use_reduce_exports != xno; then
CPPFLAGS="$TEMP_CPPFLAGS" CPPFLAGS="$TEMP_CPPFLAGS"
fi fi
elif test x$use_reduce_exports = xauto; then
use_reduce_exports=yes
fi
if test x$use_reduce_exports != xno; then if test x$use_reduce_exports != xno; 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"])
@ -549,6 +584,8 @@ if test x$use_tests = xyes; then
fi fi
if test x$use_boost = xyes; then
AX_BOOST_UNIT_TEST_FRAMEWORK AX_BOOST_UNIT_TEST_FRAMEWORK
dnl Determine if -DBOOST_TEST_DYN_LINK is needed dnl Determine if -DBOOST_TEST_DYN_LINK is needed
@ -568,7 +605,11 @@ if test x$use_tests = xyes; then
[AC_MSG_RESULT(no)]) [AC_MSG_RESULT(no)])
LIBS="$TEMP_LIBS" LIBS="$TEMP_LIBS"
CPPFLAGS="$TEMP_CPPFLAGS" CPPFLAGS="$TEMP_CPPFLAGS"
fi fi
fi
if test x$use_boost = xyes; then
BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_PROGRAM_OPTIONS_LIB $BOOST_THREAD_LIB" BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_PROGRAM_OPTIONS_LIB $BOOST_THREAD_LIB"
@ -626,25 +667,7 @@ if test x$boost_sleep != xyes; then
AC_MSG_ERROR(No working boost sleep implementation found.) AC_MSG_ERROR(No working boost sleep implementation found.)
fi fi
AC_ARG_WITH([utils], fi
[AS_HELP_STRING([--with-utils],
[build bitcoin-cli bitcoin-tx (default=yes)])],
[build_bitcoin_utils=$withval],
[build_bitcoin_utils=yes])
AC_ARG_WITH([libs],
[AS_HELP_STRING([--with-libs],
[build libraries (default=yes)])],
[build_bitcoin_libs=$withval],
[build_bitcoin_libs=yes])
AC_ARG_WITH([daemon],
[AS_HELP_STRING([--with-daemon],
[build bitcoind daemon (default=yes)])],
[build_bitcoind=$withval],
[build_bitcoind=yes])
BITCOIN_QT_INIT
if test x$use_pkgconfig = xyes; then if test x$use_pkgconfig = xyes; then
@ -678,6 +701,14 @@ else
fi fi
fi fi
CFLAGS_TEMP="$CFLAGS"
LIBS_TEMP="$LIBS"
CFLAGS="$CFLAGS $SSL_CFLAGS $CRYPTO_CFLAGS"
LIBS="$LIBS $SSL_LIBS $CRYPTO_LIBS"
AC_CHECK_HEADER([openssl/ec.h],, AC_MSG_ERROR(OpenSSL ec header missing),)
CFLAGS="$CFLAGS_TEMP"
LIBS="$LIBS_TEMP"
BITCOIN_QT_PATH_PROGS([PROTOC], [protoc],$protoc_bin_path) BITCOIN_QT_PATH_PROGS([PROTOC], [protoc],$protoc_bin_path)
AC_MSG_CHECKING([whether to build bitcoind]) AC_MSG_CHECKING([whether to build bitcoind])
@ -696,9 +727,6 @@ if test x$build_bitcoin_libs = xyes; then
fi fi
AC_MSG_RESULT($build_bitcoin_libs) AC_MSG_RESULT($build_bitcoin_libs)
dnl sets $bitcoin_enable_qt, $bitcoin_enable_qt_test, $bitcoin_enable_qt_dbus
BITCOIN_QT_CONFIGURE([$use_pkgconfig], [qt4])
AC_LANG_POP AC_LANG_POP
if test "x$use_ccache" != "xno"; then if test "x$use_ccache" != "xno"; then
@ -812,7 +840,7 @@ else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
fi fi
if test x$build_bitcoin_utils$build_bitcoin_libs$build_bitcoind$bitcoin_enable_qt$use_tests = xnononono; then if test x$build_bitcoin_utils$build_bitcoin_libs$build_bitcoind$bitcoin_enable_qt$use_tests = xnonononono; then
AC_MSG_ERROR([No targets! Please specify at least one of: --with-utils --with-libs --with-daemon --with-gui or --enable-tests]) AC_MSG_ERROR([No targets! Please specify at least one of: --with-utils --with-libs --with-daemon --with-gui or --enable-tests])
fi fi

View file

@ -0,0 +1,73 @@
#!/usr/bin/env python
import os
import sys
import subprocess
import hashlib
from PIL import Image
def file_hash(filename):
'''Return hash of raw file contents'''
with open(filename, 'rb') as f:
return hashlib.sha256(f.read()).hexdigest()
def content_hash(filename):
'''Return hash of RGBA contents of image'''
i = Image.open(filename)
i = i.convert('RGBA')
data = i.tostring()
return hashlib.sha256(data).hexdigest()
#optimize png, remove various color profiles, remove ancillary chunks (alla) and text chunks (text)
#pngcrush -brute -ow -rem gAMA -rem cHRM -rem iCCP -rem sRGB -rem alla -rem text
pngcrush = 'pngcrush'
git = 'git'
folders = ["src/qt/res/movies", "src/qt/res/icons", "src/qt/res/images"]
basePath = subprocess.check_output([git, 'rev-parse', '--show-toplevel']).rstrip('\n')
totalSaveBytes = 0
outputArray = []
for folder in folders:
absFolder=os.path.join(basePath, folder)
for file in os.listdir(absFolder):
extension = os.path.splitext(file)[1]
if extension.lower() == '.png':
print("optimizing "+file+"..."),
file_path = os.path.join(absFolder, file)
fileMetaMap = {'file' : file, 'osize': os.path.getsize(file_path), 'sha256Old' : file_hash(file_path)};
fileMetaMap['contentHashPre'] = content_hash(file_path)
pngCrushOutput = ""
try:
pngCrushOutput = subprocess.check_output(
[pngcrush, "-brute", "-ow", "-rem", "gAMA", "-rem", "cHRM", "-rem", "iCCP", "-rem", "sRGB", "-rem", "alla", "-rem", "text", file_path],
stderr=subprocess.STDOUT).rstrip('\n')
except:
print "pngcrush is not installed, aborting..."
sys.exit(0)
#verify
if "Not a PNG file" in subprocess.check_output([pngcrush, "-n", "-v", file_path], stderr=subprocess.STDOUT):
print "PNG file "+file+" is corrupted after crushing, check out pngcursh version"
sys.exit(1)
fileMetaMap['sha256New'] = file_hash(file_path)
fileMetaMap['contentHashPost'] = content_hash(file_path)
if fileMetaMap['contentHashPre'] != fileMetaMap['contentHashPost']:
print "Image contents of PNG file "+file+" before and after crushing don't match"
sys.exit(1)
fileMetaMap['psize'] = os.path.getsize(file_path)
outputArray.append(fileMetaMap)
print("done\n"),
print "summary:\n+++++++++++++++++"
for fileDict in outputArray:
oldHash = fileDict['sha256Old']
newHash = fileDict['sha256New']
totalSaveBytes += fileDict['osize'] - fileDict['psize']
print fileDict['file']+"\n size diff from: "+str(fileDict['osize'])+" to: "+str(fileDict['psize'])+"\n old sha256: "+oldHash+"\n new sha256: "+newHash+"\n"
print "completed. Total reduction: "+str(totalSaveBytes)+" bytes"

Binary file not shown.

View file

@ -1,11 +1,8 @@
### Seeds ### ### Seeds ###
Utility to generate the pnSeed[] array that is compiled into the client Utility to generate the seeds.txt list that is compiled into the client
(see [src/net.cpp](/src/net.cpp)). (see [src/chainparamsseeds.h](/src/chainparamsseeds.h) and [share/seeds](/share/seeds)).
The 600 seeds compiled into the 0.8 release were created from sipa's DNS seed data, like this: The 512 seeds compiled into the 0.10 release were created from sipa's DNS seed data, like this:
curl -s http://bitcoin.sipa.be/seeds.txt | head -1000 | makeseeds.py curl -s http://bitcoin.sipa.be/seeds.txt | makeseeds.py
The input to makeseeds.py is assumed to be approximately sorted from most-reliable to least-reliable,
with IP:port first on each line (lines that don't match IPv4:port are ignored).

View file

@ -1,32 +1,118 @@
#!/usr/bin/env python #!/usr/bin/env python
# #
# Generate pnSeed[] from Pieter's DNS seeder # Generate seeds.txt from Pieter's DNS seeder
# #
NSEEDS=600 NSEEDS=512
MAX_SEEDS_PER_ASN=2
MIN_BLOCKS = 337600
# These are hosts that have been observed to be behaving strangely (e.g.
# aggressively connecting to every node).
SUSPICIOUS_HOSTS = set([
"130.211.129.106", "178.63.107.226",
"83.81.130.26", "88.198.17.7", "148.251.238.178", "176.9.46.6",
"54.173.72.127", "54.174.10.182", "54.183.64.54", "54.194.231.211",
"54.66.214.167", "54.66.220.137", "54.67.33.14", "54.77.251.214",
"54.94.195.96", "54.94.200.247"
])
import re import re
import sys import sys
from subprocess import check_output import dns.resolver
PATTERN_IPV4 = re.compile(r"^((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})):8333$")
PATTERN_AGENT = re.compile(r"^(\/Satoshi:0.8.6\/|\/Satoshi:0.9.(2|3)\/|\/Satoshi:0.10.\d{1,2}\/)$")
def parseline(line):
sline = line.split()
if len(sline) < 11:
return None
# Match only IPv4
m = PATTERN_IPV4.match(sline[0])
if m is None:
return None
# Do IPv4 sanity check
ip = 0
for i in range(0,4):
if int(m.group(i+2)) < 0 or int(m.group(i+2)) > 255:
return None
ip = ip + (int(m.group(i+2)) << (8*(3-i)))
if ip == 0:
return None
# Skip bad results.
if sline[1] == 0:
return None
# Extract uptime %.
uptime30 = float(sline[7][:-1])
# Extract Unix timestamp of last success.
lastsuccess = int(sline[2])
# Extract protocol version.
version = int(sline[10])
# Extract user agent.
agent = sline[11][1:-1]
# Extract service flags.
service = int(sline[9], 16)
# Extract blocks.
blocks = int(sline[8])
# Construct result.
return {
'ip': m.group(1),
'ipnum': ip,
'uptime': uptime30,
'lastsuccess': lastsuccess,
'version': version,
'agent': agent,
'service': service,
'blocks': blocks,
}
# Based on Greg Maxwell's seed_filter.py
def filterbyasn(ips, max_per_asn, max_total):
result = []
asn_count = {}
for ip in ips:
if len(result) == max_total:
break
try:
asn = int([x.to_text() for x in dns.resolver.query('.'.join(reversed(ip['ip'].split('.'))) + '.origin.asn.cymru.com', 'TXT').response.answer][0].split('\"')[1].split(' ')[0])
if asn not in asn_count:
asn_count[asn] = 0
if asn_count[asn] == max_per_asn:
continue
asn_count[asn] += 1
result.append(ip)
except:
sys.stderr.write('ERR: Could not resolve ASN for "' + ip['ip'] + '"\n')
return result
def main(): def main():
lines = sys.stdin.readlines() lines = sys.stdin.readlines()
ips = [parseline(line) for line in lines]
ips = [] # Skip entries with valid IPv4 address.
pattern = re.compile(r"^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}):8333") ips = [ip for ip in ips if ip is not None]
for line in lines: # Skip entries from suspicious hosts.
m = pattern.match(line) ips = [ip for ip in ips if ip['ip'] not in SUSPICIOUS_HOSTS]
if m is None: # Enforce minimal number of blocks.
continue ips = [ip for ip in ips if ip['blocks'] >= MIN_BLOCKS]
ip = 0 # Require service bit 1.
for i in range(0,4): ips = [ip for ip in ips if (ip['service'] & 1) == 1]
ip = ip + (int(m.group(i+1)) << (8*(i))) # Require at least 50% 30-day uptime.
if ip == 0: ips = [ip for ip in ips if ip['uptime'] > 50]
continue # Require a known and recent user agent.
ips.append(ip) ips = [ip for ip in ips if PATTERN_AGENT.match(ip['agent'])]
# Sort by availability (and use last success as tie breaker)
ips.sort(key=lambda x: (x['uptime'], x['lastsuccess'], x['ip']), reverse=True)
# Look up ASNs and limit results, both per ASN and globally.
ips = filterbyasn(ips, MAX_SEEDS_PER_ASN, NSEEDS)
# Sort the results by IP address (for deterministic output).
ips.sort(key=lambda x: (x['ipnum']))
for row in range(0, min(NSEEDS,len(ips)), 8): for ip in ips:
print " " + ", ".join([ "0x%08x"%i for i in ips[row:row+8] ]) + "," print ip['ip']
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View file

@ -1,8 +1,8 @@
package=openssl package=openssl
$(package)_version=1.0.1j $(package)_version=1.0.1k
$(package)_download_path=https://www.openssl.org/source $(package)_download_path=https://www.openssl.org/source
$(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=1b60ca8789ba6f03e8ef20da2293b8dc131c39d83814e775069f02d26354edf3 $(package)_sha256_hash=8f9faeaebad088e772f4ef5e38252d472be4d878c6b3a2718c10a4fcebe7a41c
define $(package)_set_vars define $(package)_set_vars
$(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)" $(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)"
@ -23,7 +23,7 @@ $(package)_config_opts_i686_mingw32=mingw
endef endef
define $(package)_preprocess_cmds define $(package)_preprocess_cmds
sed -i.old "/define DATE/d" crypto/Makefile && \ sed -i.old "/define DATE/d" util/mkbuildinf.pl && \
sed -i.old "s|engines apps test|engines|" Makefile.org sed -i.old "s|engines apps test|engines|" Makefile.org
endef endef

View file

@ -21,12 +21,6 @@ Xcode 4.3 or later, you'll need to install its command line tools. This can
be done in `Xcode > Preferences > Downloads > Components` and generally must be done in `Xcode > Preferences > Downloads > Components` and generally must
be re-done or updated every time Xcode is updated. be re-done or updated every time Xcode is updated.
There's also an assumption that you already have `git` installed. If
not, it's the path of least resistance to install [Github for Mac](https://mac.github.com/)
(OS X 10.7+) or
[Git for OS X](https://code.google.com/p/git-osx-installer/). It is also
available via Homebrew.
You will also need to install [Homebrew](http://brew.sh) in order to install library You will also need to install [Homebrew](http://brew.sh) in order to install library
dependencies. dependencies.
@ -38,7 +32,9 @@ Instructions: Homebrew
#### Install dependencies using Homebrew #### Install dependencies using Homebrew
brew install autoconf automake libtool boost miniupnpc openssl pkg-config protobuf qt brew install autoconf automake libtool boost miniupnpc openssl pkg-config protobuf qt5
NOTE: Building with Qt4 is still supported, however, could result in a broken UI. As such, building with Qt5 is recommended.
#### Installing berkeley-db4 using Homebrew #### Installing berkeley-db4 using Homebrew
@ -46,7 +42,7 @@ The homebrew package for berkeley-db4 has been broken for some time. It will in
Running this command takes you into brew's interactive mode, which allows you to configure, make, and install by hand: Running this command takes you into brew's interactive mode, which allows you to configure, make, and install by hand:
``` ```
$ brew install https://raw.github.com/mxcl/homebrew/master/Library/Formula/berkeley-db4.rb -without-java $ brew install https://raw.github.com/homebrew/homebrew/master/Library/Formula/berkeley-db4.rb -without-java
``` ```
The rest of these commands are run inside brew interactive mode: The rest of these commands are run inside brew interactive mode:
@ -73,7 +69,7 @@ After exiting, you'll get a warning that the install is keg-only, which means it
2. Build bitcoind: 2. Build bitcoind:
./autogen.sh ./autogen.sh
./configure ./configure --with-gui=qt5
make make
3. It is also a good idea to build and run the unit tests: 3. It is also a good idea to build and run the unit tests:
@ -115,7 +111,7 @@ All dependencies should be compiled with these flags:
-arch x86_64 -arch x86_64
-isysroot $(xcode-select --print-path)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk -isysroot $(xcode-select --print-path)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk
Once dependencies are compiled, see release-process.md for how the Bitcoin-Qt.app Once dependencies are compiled, see [doc/release-process.md](release-process.md) for how the Bitcoin-Qt.app
bundle is packaged and signed to create the .dmg disk image that is distributed. bundle is packaged and signed to create the .dmg disk image that is distributed.
Running Running

View file

@ -26,6 +26,7 @@ testScripts=(
'mempool_spendcoinbase.py' 'mempool_spendcoinbase.py'
'mempool_coinbase_spends.py' 'mempool_coinbase_spends.py'
'httpbasics.py' 'httpbasics.py'
'zapwallettxes.py'
# 'forknotify.py' # 'forknotify.py'
); );
if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then
@ -33,7 +34,7 @@ if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then
do do
if [ -z "$1" ] || [ "$1" == "${testScripts[$i]}" ] || [ "$1.py" == "${testScripts[$i]}" ] if [ -z "$1" ] || [ "$1" == "${testScripts[$i]}" ] || [ "$1.py" == "${testScripts[$i]}" ]
then then
echo -e "running testscript \033[1m${testScripts[$i]}...\033[0m" echo -e "Running testscript \033[1m${testScripts[$i]}...\033[0m"
${BUILDDIR}/qa/rpc-tests/${testScripts[$i]} --srcdir "${BUILDDIR}/src" ${BUILDDIR}/qa/rpc-tests/${testScripts[$i]} --srcdir "${BUILDDIR}/src"
fi fi
done done

View file

@ -10,7 +10,7 @@ touch "$DATADIR/regtest/debug.log"
tail -q -n 1 -F "$DATADIR/regtest/debug.log" | grep -m 1 -q "Done loading" & tail -q -n 1 -F "$DATADIR/regtest/debug.log" | grep -m 1 -q "Done loading" &
WAITER=$! WAITER=$!
PORT=`expr 10000 + $$ % 55536` PORT=`expr 10000 + $$ % 55536`
"@abs_top_builddir@/src/bitcoind@EXEEXT@" -connect=0.0.0.0 -datadir="$DATADIR" -rpcuser=user -rpcpassword=pass -listen -keypool=3 -debug -debug=net -logtimestamps -checkmempool=0 -port=$PORT -whitelist=127.0.0.1 -regtest -rpcport=`expr $PORT + 1` & "@abs_top_builddir@/src/bitcoind@EXEEXT@" -connect=0.0.0.0 -datadir="$DATADIR" -rpcuser=user -rpcpassword=pass -listen -keypool=3 -debug -debug=net -logtimestamps -checkmempool=0 -relaypriority=0 -port=$PORT -whitelist=127.0.0.1 -regtest -rpcport=`expr $PORT + 1` &
BITCOIND=$! BITCOIND=$!
#Install a watchdog. #Install a watchdog.

View file

@ -21,6 +21,9 @@ except ImportError:
import urlparse import urlparse
class HTTPBasicsTest (BitcoinTestFramework): class HTTPBasicsTest (BitcoinTestFramework):
def setup_nodes(self):
return start_nodes(4, self.options.tmpdir, extra_args=[['-rpckeepalive=1'], ['-rpckeepalive=0'], [], []])
def run_test(self): def run_test(self):
################################################# #################################################
@ -71,6 +74,29 @@ class HTTPBasicsTest (BitcoinTestFramework):
assert_equal('"error":null' in out1, True) assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, False) #now the connection must be closed after the response assert_equal(conn.sock!=None, False) #now the connection must be closed after the response
#node1 (2nd node) is running with disabled keep-alive option
urlNode1 = urlparse.urlparse(self.nodes[1].url)
authpair = urlNode1.username + ':' + urlNode1.password
headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
conn = httplib.HTTPConnection(urlNode1.hostname, urlNode1.port)
conn.connect()
conn.request('GET', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read();
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, False) #connection must be closed because keep-alive was set to false
#node2 (third node) is running with standard keep-alive parameters which means keep-alive is off
urlNode2 = urlparse.urlparse(self.nodes[2].url)
authpair = urlNode2.username + ':' + urlNode2.password
headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port)
conn.connect()
conn.request('GET', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read();
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, False) #connection must be closed because bitcoind should use keep-alive by default
if __name__ == '__main__': if __name__ == '__main__':
HTTPBasicsTest ().main () HTTPBasicsTest ().main ()

View file

@ -16,20 +16,20 @@ class EstimateFeeTest(BitcoinTestFramework):
def setup_network(self): def setup_network(self):
self.nodes = [] self.nodes = []
self.nodes.append(start_node(0, self.options.tmpdir, self.nodes.append(start_node(0, self.options.tmpdir,
["-debug=mempool", "-debug=estimatefee"])) ["-debug=mempool", "-debug=estimatefee", "-relaypriority=0"]))
# Node1 mines small-but-not-tiny blocks, and allows free transactions. # Node1 mines small-but-not-tiny blocks, and allows free transactions.
# NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes, # NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes,
# so blockmaxsize of 2,000 is really just 1,000 bytes (room enough for # so blockmaxsize of 2,000 is really just 1,000 bytes (room enough for
# 6 or 7 transactions) # 6 or 7 transactions)
self.nodes.append(start_node(1, self.options.tmpdir, self.nodes.append(start_node(1, self.options.tmpdir,
["-blockprioritysize=1500", "-blockmaxsize=2000", ["-blockprioritysize=1500", "-blockmaxsize=2000",
"-debug=mempool", "-debug=estimatefee"])) "-debug=mempool", "-debug=estimatefee", "-relaypriority=0"]))
connect_nodes(self.nodes[1], 0) connect_nodes(self.nodes[1], 0)
# Node2 is a stingy miner, that # Node2 is a stingy miner, that
# produces very small blocks (room for only 3 or so transactions) # produces very small blocks (room for only 3 or so transactions)
node2args = [ "-blockprioritysize=0", "-blockmaxsize=1500", node2args = [ "-blockprioritysize=0", "-blockmaxsize=1500",
"-debug=mempool", "-debug=estimatefee"] "-debug=mempool", "-debug=estimatefee", "-relaypriority=0"]
self.nodes.append(start_node(2, self.options.tmpdir, node2args)) self.nodes.append(start_node(2, self.options.tmpdir, node2args))
connect_nodes(self.nodes[2], 0) connect_nodes(self.nodes[2], 0)

View file

@ -33,8 +33,11 @@ class BitcoinTestFramework(object):
print("Initializing test directory "+self.options.tmpdir) print("Initializing test directory "+self.options.tmpdir)
initialize_chain(self.options.tmpdir) initialize_chain(self.options.tmpdir)
def setup_nodes(self):
return start_nodes(4, self.options.tmpdir)
def setup_network(self, split = False): def setup_network(self, split = False):
self.nodes = start_nodes(4, self.options.tmpdir) self.nodes = self.setup_nodes()
# Connect the nodes as a "chain". This allows us # Connect the nodes as a "chain". This allows us
# to split the network between nodes 1 and 2 to get # to split the network between nodes 1 and 2 to get

82
qa/rpc-tests/zapwallettxes.py Executable file
View file

@ -0,0 +1,82 @@
#!/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.
from test_framework import BitcoinTestFramework
from util import *
class ZapWalletTXesTest (BitcoinTestFramework):
def setup_chain(self):
print("Initializing test directory "+self.options.tmpdir)
initialize_chain_clean(self.options.tmpdir, 3)
def setup_network(self, split=False):
self.nodes = start_nodes(3, self.options.tmpdir)
connect_nodes_bi(self.nodes,0,1)
connect_nodes_bi(self.nodes,1,2)
connect_nodes_bi(self.nodes,0,2)
self.is_network_split=False
self.sync_all()
def run_test (self):
print "Mining blocks..."
self.nodes[0].setgenerate(True, 1)
self.sync_all()
self.nodes[1].setgenerate(True, 101)
self.sync_all()
assert_equal(self.nodes[0].getbalance(), 50)
txid0 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
txid1 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
self.sync_all()
self.nodes[0].setgenerate(True, 1)
self.sync_all()
txid2 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
txid3 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
tx0 = self.nodes[0].gettransaction(txid0)
assert_equal(tx0['txid'], txid0) #tx0 must be available (confirmed)
tx1 = self.nodes[0].gettransaction(txid1)
assert_equal(tx1['txid'], txid1) #tx1 must be available (confirmed)
tx2 = self.nodes[0].gettransaction(txid2)
assert_equal(tx2['txid'], txid2) #tx2 must be available (unconfirmed)
tx3 = self.nodes[0].gettransaction(txid3)
assert_equal(tx3['txid'], txid3) #tx3 must be available (unconfirmed)
#restart bitcoind
self.nodes[0].stop()
bitcoind_processes[0].wait()
self.nodes[0] = start_node(0,self.options.tmpdir)
tx3 = self.nodes[0].gettransaction(txid3)
assert_equal(tx3['txid'], txid3) #tx must be available (unconfirmed)
self.nodes[0].stop()
bitcoind_processes[0].wait()
#restart bitcoind with zapwallettxes
self.nodes[0] = start_node(0,self.options.tmpdir, ["-zapwallettxes=1"])
aException = False
try:
tx3 = self.nodes[0].gettransaction(txid3)
except JSONRPCException,e:
print e
aException = True
assert_equal(aException, True) #there must be a expection because the unconfirmed wallettx0 must be gone by now
tx0 = self.nodes[0].gettransaction(txid0)
assert_equal(tx0['txid'], txid0) #tx0 (confirmed) must still be available because it was confirmed
if __name__ == '__main__':
ZapWalletTXesTest ().main ()

View file

@ -1,165 +0,0 @@
#!/usr/bin/env bash
# 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 -zapwallettxes=<mode>
if [ $# -lt 1 ]; then
echo "Usage: $0 path_to_binaries"
echo "e.g. $0 ../../src"
echo "Env vars BITCOIND and BITCOINCLI may be used to specify the exact binaries used"
exit 1
fi
set -f
BITCOIND=${BITCOIND:-${1}/bitcoind}
CLI=${BITCOINCLI:-${1}/bitcoin-cli}
DIR="${BASH_SOURCE%/*}"
SENDANDWAIT="${DIR}/send.sh"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
. "$DIR/util.sh"
D=$(mktemp -d test.XXXXX)
D1=${D}/node1
CreateDataDir "$D1" port=11000 rpcport=11001
B1ARGS="-datadir=$D1"
$BITCOIND $B1ARGS &
B1PID=$!
D2=${D}/node2
CreateDataDir "$D2" port=11010 rpcport=11011
B2ARGS="-datadir=$D2"
$BITCOIND $B2ARGS &
B2PID=$!
function CleanUp {
$CLI $B2ARGS stop > /dev/null 2>&1
wait $B2PID
$CLI $B1ARGS stop > /dev/null 2>&1
wait $B1PID
rm -rf $D
}
# 110 blocks, 10 mature == 500 XBT
$CLI $B1ARGS setgenerate true 110
$CLI $B2ARGS setgenerate true 110
CheckBalance "$B1ARGS" 500
CheckBalance "$B2ARGS" 500
# Send 10 XBT
TXID1_DEFAULT=$($CLI $B1ARGS sendtoaddress "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 10)
TXID2_DEFAULT=$($CLI $B2ARGS sendtoaddress "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 10)
CheckBalance $B1ARGS 490
CheckBalance $B2ARGS 490
# Move 10 XBT to testaccount
TMP=$($CLI $B1ARGS move "" "testaccount" 10)
TMP=$($CLI $B2ARGS move "" "testaccount" 10)
CheckBalance $B1ARGS 10 "testaccount"
CheckBalance $B2ARGS 10 "testaccount"
# Send 1 XBT from testaccount
TXID1_TESTACCOUNT=$($CLI $B1ARGS sendfrom "testaccount" "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 1)
TXID2_TESTACCOUNT=$($CLI $B2ARGS sendfrom "testaccount" "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 1)
CheckBalance $B1ARGS 9 "testaccount"
CheckBalance $B2ARGS 9 "testaccount"
CheckBalance $B1ARGS 489
CheckBalance $B2ARGS 489
# Confirm transactions
$CLI $B1ARGS setgenerate true 1
$CLI $B2ARGS setgenerate true 1
# Create unconfirmed transaction
TXID1_UNCONFIRMED=$($CLI $B1ARGS sendtoaddress "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 1)
TXID2_UNCONFIRMED=$($CLI $B2ARGS sendtoaddress "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 1)
# check balance (we created another 50 and spent 1 in the meantime)
CheckBalance $B1ARGS 538
CheckBalance $B2ARGS 538
# Safety check, if unconfirmed transactions are there
$CLI $B1ARGS gettransaction $TXID1_UNCONFIRMED > /dev/null 2>&1
if [[ $? -ne 0 ]] ; then
echoerr "gettransaction1_1: $TXID1_UNCONFIRMED failed"
CleanUp
exit 1
fi
$CLI $B2ARGS gettransaction $TXID2_UNCONFIRMED > /dev/null 2>&1
if [[ $? -ne 0 ]] ; then
echoerr "gettransaction2_1: $TXID2_UNCONFIRMED failed"
CleanUp
exit 1
fi
# stop nodes
$CLI $B2ARGS stop > /dev/null 2>&1
wait $B2PID
$CLI $B1ARGS stop > /dev/null 2>&1
wait $B1PID
# restart nodes with -zapwallettxes
$BITCOIND -zapwallettxes=1 $B1ARGS &
B1PID=$!
$BITCOIND -zapwallettxes=2 $B2ARGS &
B2PID=$!
# check if confirmed transactions are there
$CLI $B1ARGS gettransaction $TXID1_DEFAULT > /dev/null 2>&1
if [[ $? -ne 0 ]] ; then
echoerr "check confirmed transaction 1: $TXID1_DEFAULT failed"
CleanUp
exit 1
fi
$CLI $B2ARGS gettransaction $TXID2_DEFAULT > /dev/null 2>&1
if [[ $? -ne 0 ]] ; then
echoerr "check confirmed transaction 2: $TXID2_DEFAULT failed"
CleanUp
exit 1
fi
$CLI $B1ARGS gettransaction $TXID1_TESTACCOUNT > /dev/null 2>&1
if [[ $? -ne 0 ]] ; then
echoerr "check confirmed transaction 3: $TXID1_TESTACCOUNT failed"
CleanUp
exit 1
fi
$CLI $B2ARGS gettransaction $TXID2_TESTACCOUNT > /dev/null 2>&1
if [[ $? -ne 0 ]] ; then
echoerr "check confirmed transaction 4: $TXID2_TESTACCOUNT failed"
CleanUp
exit 1
fi
# check if unconfirmed transaction is gone
$CLI $B1ARGS gettransaction $TXID1_UNCONFIRMED > /dev/null 2>&1
if [[ $? -eq 0 ]] ; then
echoerr "check unconfirmed transaction 1: $TXID1_UNCONFIRMED failed"
CleanUp
exit 1
fi
$CLI $B2ARGS gettransaction $TXID2_UNCONFIRMED > /dev/null 2>&1
if [[ $? -eq 0 ]] ; then
echoerr "check unconfirmed transaction 2: $TXID2_UNCONFIRMED failed"
CleanUp
exit 1
fi
# check zapwallet mode 1, testaccount balance must be 9 (keeping transaction metadata)
CheckBalance $B1ARGS 9 "testaccount"
# check zapwallet mode 2, testaccount balance must be 10 (dropping transaction metadata)
CheckBalance $B2ARGS 10 "testaccount"
echo "Tests successful, cleaning up"
CleanUp
exit 0

View file

@ -37,7 +37,7 @@ $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
# Make is not made aware of per-object dependencies to avoid limiting building parallelization # Make is not made aware of per-object dependencies to avoid limiting building parallelization
# But to build the less dependent modules first, we manually select their order here: # But to build the less dependent modules first, we manually select their order here:
noinst_LIBRARIES = \ EXTRA_LIBRARIES = \
crypto/libbitcoin_crypto.a \ crypto/libbitcoin_crypto.a \
libbitcoin_util.a \ libbitcoin_util.a \
libbitcoin_common.a \ libbitcoin_common.a \
@ -46,7 +46,7 @@ noinst_LIBRARIES = \
libbitcoin_cli.a libbitcoin_cli.a
if ENABLE_WALLET if ENABLE_WALLET
BITCOIN_INCLUDES += $(BDB_CPPFLAGS) BITCOIN_INCLUDES += $(BDB_CPPFLAGS)
noinst_LIBRARIES += libbitcoin_wallet.a EXTRA_LIBRARIES += libbitcoin_wallet.a
endif endif
if BUILD_BITCOIN_LIBS if BUILD_BITCOIN_LIBS
@ -234,6 +234,7 @@ univalue_libbitcoin_univalue_a_SOURCES = \
libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES)
libbitcoin_common_a_SOURCES = \ libbitcoin_common_a_SOURCES = \
allocators.cpp \ allocators.cpp \
arith_uint256.cpp \
amount.cpp \ amount.cpp \
base58.cpp \ base58.cpp \
chainparams.cpp \ chainparams.cpp \
@ -264,7 +265,6 @@ 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 = \
arith_uint256.cpp \
chainparamsbase.cpp \ chainparamsbase.cpp \
clientversion.cpp \ clientversion.cpp \
compat/glibc_sanity.cpp \ compat/glibc_sanity.cpp \
@ -356,7 +356,6 @@ bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
if BUILD_BITCOIN_LIBS if BUILD_BITCOIN_LIBS
include_HEADERS = script/bitcoinconsensus.h include_HEADERS = script/bitcoinconsensus.h
libbitcoinconsensus_la_SOURCES = \ libbitcoinconsensus_la_SOURCES = \
arith_uint256.cpp \
crypto/hmac_sha512.cpp \ crypto/hmac_sha512.cpp \
crypto/ripemd160.cpp \ crypto/ripemd160.cpp \
crypto/sha1.cpp \ crypto/sha1.cpp \

View file

@ -1,5 +1,5 @@
bin_PROGRAMS += qt/bitcoin-qt bin_PROGRAMS += qt/bitcoin-qt
noinst_LIBRARIES += qt/libbitcoinqt.a EXTRA_LIBRARIES += qt/libbitcoinqt.a
# bitcoin qt core # # bitcoin qt core #
QT_TS = \ QT_TS = \

View file

@ -58,6 +58,7 @@ BITCOIN_TESTS =\
test/netbase_tests.cpp \ test/netbase_tests.cpp \
test/pmt_tests.cpp \ test/pmt_tests.cpp \
test/rpc_tests.cpp \ test/rpc_tests.cpp \
test/sanity_tests.cpp \
test/script_P2SH_tests.cpp \ test/script_P2SH_tests.cpp \
test/script_tests.cpp \ test/script_tests.cpp \
test/scriptnum_tests.cpp \ test/scriptnum_tests.cpp \

View file

@ -15,8 +15,6 @@
#define _(x) std::string(x) /* Keep the _() around in case gettext or such will be used later to translate non-UI */ #define _(x) std::string(x) /* Keep the _() around in case gettext or such will be used later to translate non-UI */
using namespace std; using namespace std;
using namespace boost;
using namespace boost::asio;
using namespace json_spirit; using namespace json_spirit;
std::string HelpMessageCli() std::string HelpMessageCli()
@ -108,12 +106,12 @@ Object CallRPC(const string& strMethod, const Array& params)
// Connect to localhost // Connect to localhost
bool fUseSSL = GetBoolArg("-rpcssl", false); bool fUseSSL = GetBoolArg("-rpcssl", false);
asio::io_service io_service; boost::asio::io_service io_service;
ssl::context context(io_service, ssl::context::sslv23); boost::asio::ssl::context context(io_service, boost::asio::ssl::context::sslv23);
context.set_options(ssl::context::no_sslv2 | ssl::context::no_sslv3); context.set_options(boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::no_sslv3);
asio::ssl::stream<asio::ip::tcp::socket> sslStream(io_service, context); boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sslStream(io_service, context);
SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL); SSLIOStreamDevice<boost::asio::ip::tcp> d(sslStream, fUseSSL);
iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d); boost::iostreams::stream< SSLIOStreamDevice<boost::asio::ip::tcp> > stream(d);
const bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(BaseParams().RPCPort()))); const bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(BaseParams().RPCPort())));
if (!fConnected) if (!fConnected)

View file

@ -22,7 +22,6 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/assign/list_of.hpp> #include <boost/assign/list_of.hpp>
using namespace boost::assign;
using namespace std; using namespace std;
static bool fCreateBlank; static bool fCreateBlank;
@ -375,7 +374,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
if (!prevOut.isObject()) if (!prevOut.isObject())
throw runtime_error("expected prevtxs internal object"); throw runtime_error("expected prevtxs internal object");
map<string,UniValue::VType> types = map_list_of("txid", UniValue::VSTR)("vout",UniValue::VNUM)("scriptPubKey",UniValue::VSTR); map<string,UniValue::VType> types = boost::assign::map_list_of("txid", UniValue::VSTR)("vout",UniValue::VNUM)("scriptPubKey",UniValue::VSTR);
if (!prevOut.checkObject(types)) if (!prevOut.checkObject(types))
throw runtime_error("prevtxs internal object typecheck fail"); throw runtime_error("prevtxs internal object typecheck fail");

View file

@ -15,7 +15,6 @@
#include <stdio.h> #include <stdio.h>
using namespace std; using namespace std;
using namespace boost::assign;
struct SeedSpec6 { struct SeedSpec6 {
uint8_t addr[16]; uint8_t addr[16];
@ -106,7 +105,6 @@ static const Checkpoints::CCheckpointData dataRegtest = {
class CMainParams : public CChainParams { class CMainParams : public CChainParams {
public: public:
CMainParams() { CMainParams() {
networkID = CBaseChainParams::MAIN;
strNetworkID = "newcc"; strNetworkID = "newcc";
/** /**
* The message start string is designed to be unlikely to occur in normal data. * The message start string is designed to be unlikely to occur in normal data.
@ -187,11 +185,11 @@ public:
vSeeds.clear(); vSeeds.clear();
//vFixedSeeds.clear(); //vFixedSeeds.clear();
base58Prefixes[PUBKEY_ADDRESS] = list_of(0); base58Prefixes[PUBKEY_ADDRESS] = boost::assign::list_of(0);
base58Prefixes[SCRIPT_ADDRESS] = list_of(5); base58Prefixes[SCRIPT_ADDRESS] = boost::assign::list_of(5);
base58Prefixes[SECRET_KEY] = list_of(128); base58Prefixes[SECRET_KEY] = boost::assign::list_of(128);
base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x88)(0xB2)(0x1E); base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E);
base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x88)(0xAD)(0xE4); base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4);
convertSeed6(vFixedSeeds, pnSeed6_main, ARRAYLEN(pnSeed6_main)); convertSeed6(vFixedSeeds, pnSeed6_main, ARRAYLEN(pnSeed6_main));
@ -218,7 +216,6 @@ static CMainParams mainParams;
class CTestNetParams : public CMainParams { class CTestNetParams : public CMainParams {
public: public:
CTestNetParams() { CTestNetParams() {
networkID = CBaseChainParams::TESTNET;
strNetworkID = "test"; strNetworkID = "test";
pchMessageStart[0] = 0x0b; pchMessageStart[0] = 0x0b;
pchMessageStart[1] = 0x11; pchMessageStart[1] = 0x11;
@ -246,11 +243,11 @@ public:
//vSeeds.push_back(CDNSSeedData("bluematt.me", "testnet-seed.bluematt.me")); //vSeeds.push_back(CDNSSeedData("bluematt.me", "testnet-seed.bluematt.me"));
//vSeeds.push_back(CDNSSeedData("bitcoin.schildbach.de", "testnet-seed.bitcoin.schildbach.de")); //vSeeds.push_back(CDNSSeedData("bitcoin.schildbach.de", "testnet-seed.bitcoin.schildbach.de"));
base58Prefixes[PUBKEY_ADDRESS] = list_of(111); base58Prefixes[PUBKEY_ADDRESS] = boost::assign::list_of(111);
base58Prefixes[SCRIPT_ADDRESS] = list_of(196); base58Prefixes[SCRIPT_ADDRESS] = boost::assign::list_of(196);
base58Prefixes[SECRET_KEY] = list_of(239); base58Prefixes[SECRET_KEY] = boost::assign::list_of(239);
base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x35)(0x87)(0xCF); base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF);
base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x35)(0x83)(0x94); base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94);
convertSeed6(vFixedSeeds, pnSeed6_test, ARRAYLEN(pnSeed6_test)); convertSeed6(vFixedSeeds, pnSeed6_test, ARRAYLEN(pnSeed6_test));
@ -275,7 +272,6 @@ static CTestNetParams testNetParams;
class CRegTestParams : public CTestNetParams { class CRegTestParams : public CTestNetParams {
public: public:
CRegTestParams() { CRegTestParams() {
networkID = CBaseChainParams::REGTEST;
strNetworkID = "regtest"; strNetworkID = "regtest";
pchMessageStart[0] = 0xfa; pchMessageStart[0] = 0xfa;
pchMessageStart[1] = 0xbf; pchMessageStart[1] = 0xbf;
@ -320,7 +316,6 @@ static CRegTestParams regTestParams;
class CUnitTestParams : public CMainParams, public CModifiableParams { class CUnitTestParams : public CMainParams, public CModifiableParams {
public: public:
CUnitTestParams() { CUnitTestParams() {
networkID = CBaseChainParams::UNITTEST;
strNetworkID = "unittest"; strNetworkID = "unittest";
nDefaultPort = 18445; nDefaultPort = 18445;
vFixedSeeds.clear(); //! Unit test mode doesn't have any fixed seeds. vFixedSeeds.clear(); //! Unit test mode doesn't have any fixed seeds.

View file

@ -97,7 +97,6 @@ protected:
int nMinerThreads; int nMinerThreads;
std::vector<CDNSSeedData> vSeeds; std::vector<CDNSSeedData> vSeeds;
std::vector<unsigned char> base58Prefixes[MAX_BASE58_TYPES]; std::vector<unsigned char> base58Prefixes[MAX_BASE58_TYPES];
CBaseChainParams::Network networkID;
std::string strNetworkID; std::string strNetworkID;
CBlock genesis; CBlock genesis;
std::vector<CAddress> vFixedSeeds; std::vector<CAddress> vFixedSeeds;

View file

@ -9,10 +9,6 @@
#include <assert.h> #include <assert.h>
#include <boost/assign/list_of.hpp>
using namespace boost::assign;
/** /**
* Main network * Main network
*/ */
@ -21,7 +17,6 @@ class CBaseMainParams : public CBaseChainParams
public: public:
CBaseMainParams() CBaseMainParams()
{ {
networkID = CBaseChainParams::MAIN;
nRPCPort = 8332; nRPCPort = 8332;
} }
}; };
@ -35,7 +30,6 @@ class CBaseTestNetParams : public CBaseMainParams
public: public:
CBaseTestNetParams() CBaseTestNetParams()
{ {
networkID = CBaseChainParams::TESTNET;
nRPCPort = 18332; nRPCPort = 18332;
strDataDir = "testnet3"; strDataDir = "testnet3";
} }
@ -50,7 +44,6 @@ class CBaseRegTestParams : public CBaseTestNetParams
public: public:
CBaseRegTestParams() CBaseRegTestParams()
{ {
networkID = CBaseChainParams::REGTEST;
strDataDir = "regtest"; strDataDir = "regtest";
} }
}; };
@ -64,7 +57,6 @@ class CBaseUnitTestParams : public CBaseMainParams
public: public:
CBaseUnitTestParams() CBaseUnitTestParams()
{ {
networkID = CBaseChainParams::UNITTEST;
strDataDir = "unittest"; strDataDir = "unittest";
} }
}; };

View file

@ -32,7 +32,6 @@ protected:
int nRPCPort; int nRPCPort;
std::string strDataDir; std::string strDataDir;
Network networkID;
}; };
/** /**

File diff suppressed because it is too large Load diff

View file

@ -92,7 +92,6 @@ bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) const {
CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) { CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) {
assert(!hasModifier); assert(!hasModifier);
hasModifier = true;
std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry())); std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry()));
if (ret.second) { if (ret.second) {
if (!base->GetCoins(txid, ret.first->second.coins)) { if (!base->GetCoins(txid, ret.first->second.coins)) {
@ -233,7 +232,10 @@ double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const
return tx.ComputePriority(dResult); return tx.ComputePriority(dResult);
} }
CCoinsModifier::CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_) : cache(cache_), it(it_) {} CCoinsModifier::CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_) : cache(cache_), it(it_) {
assert(!cache.hasModifier);
cache.hasModifier = true;
}
CCoinsModifier::~CCoinsModifier() CCoinsModifier::~CCoinsModifier()
{ {

View file

@ -20,8 +20,6 @@
#include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/split.hpp>
#include <boost/assign/list_of.hpp> #include <boost/assign/list_of.hpp>
using namespace boost;
using namespace boost::algorithm;
using namespace std; using namespace std;
CScript ParseScript(std::string s) CScript ParseScript(std::string s)
@ -44,13 +42,13 @@ CScript ParseScript(std::string s)
string strName(name); string strName(name);
mapOpNames[strName] = (opcodetype)op; mapOpNames[strName] = (opcodetype)op;
// Convenience: OP_ADD and just ADD are both recognized: // Convenience: OP_ADD and just ADD are both recognized:
replace_first(strName, "OP_", ""); boost::algorithm::replace_first(strName, "OP_", "");
mapOpNames[strName] = (opcodetype)op; mapOpNames[strName] = (opcodetype)op;
} }
} }
vector<string> words; vector<string> words;
split(words, s, is_any_of(" \t\n"), token_compress_on); boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), boost::algorithm::token_compress_on);
for (std::vector<std::string>::const_iterator w = words.begin(); w != words.end(); ++w) for (std::vector<std::string>::const_iterator w = words.begin(); w != words.end(); ++w)
{ {
@ -58,20 +56,20 @@ CScript ParseScript(std::string s)
{ {
// Empty string, ignore. (boost::split given '' will return one word) // Empty string, ignore. (boost::split given '' will return one word)
} }
else if (all(*w, is_digit()) || else if (all(*w, boost::algorithm::is_digit()) ||
(starts_with(*w, "-") && all(string(w->begin()+1, w->end()), is_digit()))) (boost::algorithm::starts_with(*w, "-") && all(string(w->begin()+1, w->end()), boost::algorithm::is_digit())))
{ {
// Number // Number
int64_t n = atoi64(*w); int64_t n = atoi64(*w);
result << n; result << n;
} }
else if (starts_with(*w, "0x") && (w->begin()+2 != w->end()) && IsHex(string(w->begin()+2, w->end()))) else if (boost::algorithm::starts_with(*w, "0x") && (w->begin()+2 != w->end()) && IsHex(string(w->begin()+2, w->end())))
{ {
// Raw hex data, inserted NOT pushed onto stack: // Raw hex data, inserted NOT pushed onto stack:
std::vector<unsigned char> raw = ParseHex(string(w->begin()+2, w->end())); std::vector<unsigned char> raw = ParseHex(string(w->begin()+2, w->end()));
result.insert(result.end(), raw.begin(), raw.end()); result.insert(result.end(), raw.begin(), raw.end());
} }
else if (w->size() >= 2 && starts_with(*w, "'") && ends_with(*w, "'")) else if (w->size() >= 2 && boost::algorithm::starts_with(*w, "'") && boost::algorithm::ends_with(*w, "'"))
{ {
// Single-quoted string, pushed as data. NOTE: this is poor-man's // Single-quoted string, pushed as data. NOTE: this is poor-man's
// parsing, spaces/tabs/newlines in single-quoted strings won't work. // parsing, spaces/tabs/newlines in single-quoted strings won't work.

View file

@ -24,7 +24,6 @@
#include <openssl/rand.h> #include <openssl/rand.h>
using namespace std; using namespace std;
using namespace boost;
unsigned int nWalletDBUpdated; unsigned int nWalletDBUpdated;
@ -73,9 +72,9 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn)
boost::this_thread::interruption_point(); boost::this_thread::interruption_point();
path = pathIn; path = pathIn;
filesystem::path pathLogDir = path / "database"; boost::filesystem::path pathLogDir = path / "database";
TryCreateDirectory(pathLogDir); TryCreateDirectory(pathLogDir);
filesystem::path pathErrorFile = path / "db.log"; boost::filesystem::path pathErrorFile = path / "db.log";
LogPrintf("CDBEnv::Open : LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string()); LogPrintf("CDBEnv::Open : LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string());
unsigned int nEnvFlags = 0; unsigned int nEnvFlags = 0;

View file

@ -23,8 +23,6 @@
class CDiskBlockIndex; class CDiskBlockIndex;
class COutPoint; class COutPoint;
struct CBlockLocator;
extern unsigned int nWalletDBUpdated; extern unsigned int nWalletDBUpdated;
void ThreadFlushWalletDB(const std::string& strWalletFile); void ThreadFlushWalletDB(const std::string& strWalletFile);

View file

@ -117,10 +117,34 @@ bool CECKey::SetPubKey(const unsigned char* pubkey, size_t size) {
} }
bool CECKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) { bool CECKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
// -1 = error, 0 = bad sig, 1 = good if (vchSig.empty())
if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
return false; return false;
return true;
// New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first.
unsigned char *norm_der = NULL;
ECDSA_SIG *norm_sig = ECDSA_SIG_new();
const unsigned char* sigptr = &vchSig[0];
assert(norm_sig);
if (d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()) == NULL)
{
/* As of OpenSSL 1.0.0p d2i_ECDSA_SIG frees and nulls the pointer on
* error. But OpenSSL's own use of this function redundantly frees the
* result. As ECDSA_SIG_free(NULL) is a no-op, and in the absence of a
* clear contract for the function behaving the same way is more
* conservative.
*/
ECDSA_SIG_free(norm_sig);
return false;
}
int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der);
ECDSA_SIG_free(norm_sig);
if (derlen <= 0)
return false;
// -1 = error, 0 = bad sig, 1 = good
bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1;
OPENSSL_free(norm_der);
return ret;
} }
bool CECKey::Recover(const uint256 &hash, const unsigned char *p64, int rec) bool CECKey::Recover(const uint256 &hash, const unsigned char *p64, int rec)

View file

@ -43,7 +43,6 @@
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include <openssl/crypto.h> #include <openssl/crypto.h>
using namespace boost;
using namespace std; using namespace std;
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
@ -112,7 +111,28 @@ bool ShutdownRequested()
return fRequestShutdown; return fRequestShutdown;
} }
class CCoinsViewErrorCatcher : public CCoinsViewBacked
{
public:
CCoinsViewErrorCatcher(CCoinsView* view) : CCoinsViewBacked(view) {}
bool GetCoins(const uint256 &txid, CCoins &coins) const {
try {
return CCoinsViewBacked::GetCoins(txid, coins);
} catch(const std::runtime_error& e) {
uiInterface.ThreadSafeMessageBox(_("Error reading from database, shutting down."), "", CClientUIInterface::MSG_ERROR);
LogPrintf("Error reading from database: %s\n", e.what());
// Starting the shutdown sequence and returning false to the caller would be
// interpreted as 'entry not found' (as opposed to unable to read data), and
// could lead to invalid interpration. Just exit immediately, as we can't
// continue anyway, and all writes should be atomic.
abort();
}
}
// Writes do not need similar protection, as failure to write is handled by the caller.
};
static CCoinsViewDB *pcoinsdbview = NULL; static CCoinsViewDB *pcoinsdbview = NULL;
static CCoinsViewErrorCatcher *pcoinscatcher = NULL;
void Shutdown() void Shutdown()
{ {
@ -155,6 +175,8 @@ void Shutdown()
} }
delete pcoinsTip; delete pcoinsTip;
pcoinsTip = NULL; pcoinsTip = NULL;
delete pcoinscatcher;
pcoinscatcher = NULL;
delete pcoinsdbview; delete pcoinsdbview;
pcoinsdbview = NULL; pcoinsdbview = NULL;
delete pblocktree; delete pblocktree;
@ -324,6 +346,7 @@ std::string HelpMessage(HelpMessageMode mode)
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 += " -limitfreerelay=<n> " + strprintf(_("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:%u)"), 15) + "\n";
strUsage += " -relaypriority " + strprintf(_("Require high priority for relaying free or low-fee transactions (default:%u)"), 1) + "\n";
strUsage += " -maxsigcachesize=<n> " + strprintf(_("Limit size of signature cache to <n> entries (default: %u)"), 50000) + "\n"; strUsage += " -maxsigcachesize=<n> " + strprintf(_("Limit size of signature cache to <n> entries (default: %u)"), 50000) + "\n";
} }
strUsage += " -minrelaytxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK())) + "\n"; strUsage += " -minrelaytxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK())) + "\n";
@ -357,6 +380,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += " -rpcport=<port> " + strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), 8332, 18332) + "\n"; strUsage += " -rpcport=<port> " + strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), 8332, 18332) + "\n";
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 += " -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 += " -rpcthreads=<n> " + strprintf(_("Set the number of threads to service RPC calls (default: %d)"), 4) + "\n"; strUsage += " -rpcthreads=<n> " + strprintf(_("Set the number of threads to service RPC calls (default: %d)"), 4) + "\n";
strUsage += " -rpckeepalive " + strprintf(_("RPC support for HTTP persistent connections (default: %d)"), 0) + "\n";
strUsage += "\n" + _("RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n"; strUsage += "\n" + _("RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n";
strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n"; strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n";
@ -427,12 +451,12 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles)
} }
// hardcoded $DATADIR/bootstrap.dat // hardcoded $DATADIR/bootstrap.dat
filesystem::path pathBootstrap = GetDataDir() / "bootstrap.dat"; boost::filesystem::path pathBootstrap = GetDataDir() / "bootstrap.dat";
if (filesystem::exists(pathBootstrap)) { if (boost::filesystem::exists(pathBootstrap)) {
FILE *file = fopen(pathBootstrap.string().c_str(), "rb"); FILE *file = fopen(pathBootstrap.string().c_str(), "rb");
if (file) { if (file) {
CImportingNow imp; CImportingNow imp;
filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; boost::filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old";
LogPrintf("Importing bootstrap.dat...\n"); LogPrintf("Importing bootstrap.dat...\n");
LoadExternalBlockFile(file); LoadExternalBlockFile(file);
RenameOver(pathBootstrap, pathBootstrapOld); RenameOver(pathBootstrap, pathBootstrapOld);
@ -816,7 +840,7 @@ bool AppInit2(boost::thread_group& threadGroup)
return false; return false;
} }
if (filesystem::exists(GetDataDir() / strWalletFile)) if (boost::filesystem::exists(GetDataDir() / strWalletFile))
{ {
CDBEnv::VerifyResult r = bitdb.Verify(strWalletFile, CWalletDB::Recover); CDBEnv::VerifyResult r = bitdb.Verify(strWalletFile, CWalletDB::Recover);
if (r == CDBEnv::RECOVER_OK) if (r == CDBEnv::RECOVER_OK)
@ -937,20 +961,20 @@ bool AppInit2(boost::thread_group& threadGroup)
fReindex = GetBoolArg("-reindex", false); fReindex = GetBoolArg("-reindex", false);
// Upgrading to 0.8; hard-link the old blknnnn.dat files into /blocks/ // Upgrading to 0.8; hard-link the old blknnnn.dat files into /blocks/
filesystem::path blocksDir = GetDataDir() / "blocks"; boost::filesystem::path blocksDir = GetDataDir() / "blocks";
if (!filesystem::exists(blocksDir)) if (!boost::filesystem::exists(blocksDir))
{ {
filesystem::create_directories(blocksDir); boost::filesystem::create_directories(blocksDir);
bool linked = false; bool linked = false;
for (unsigned int i = 1; i < 10000; i++) { for (unsigned int i = 1; i < 10000; i++) {
filesystem::path source = GetDataDir() / strprintf("blk%04u.dat", i); boost::filesystem::path source = GetDataDir() / strprintf("blk%04u.dat", i);
if (!filesystem::exists(source)) break; if (!boost::filesystem::exists(source)) break;
filesystem::path dest = blocksDir / strprintf("blk%05u.dat", i-1); boost::filesystem::path dest = blocksDir / strprintf("blk%05u.dat", i-1);
try { try {
filesystem::create_hard_link(source, dest); boost::filesystem::create_hard_link(source, dest);
LogPrintf("Hardlinked %s -> %s\n", source.string(), dest.string()); LogPrintf("Hardlinked %s -> %s\n", source.string(), dest.string());
linked = true; linked = true;
} catch (const filesystem::filesystem_error& e) { } catch (const boost::filesystem::filesystem_error& e) {
// Note: hardlink creation failing is not a disaster, it just means // Note: hardlink creation failing is not a disaster, it just means
// blocks will get re-downloaded from peers. // blocks will get re-downloaded from peers.
LogPrintf("Error hardlinking blk%04u.dat : %s\n", i, e.what()); LogPrintf("Error hardlinking blk%04u.dat : %s\n", i, e.what());
@ -990,11 +1014,13 @@ bool AppInit2(boost::thread_group& threadGroup)
UnloadBlockIndex(); UnloadBlockIndex();
delete pcoinsTip; delete pcoinsTip;
delete pcoinsdbview; delete pcoinsdbview;
delete pcoinscatcher;
delete pblocktree; delete pblocktree;
pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex); pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex);
pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex); pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex);
pcoinsTip = new CCoinsViewCache(pcoinsdbview); pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview);
pcoinsTip = new CCoinsViewCache(pcoinscatcher);
if (fReindex) if (fReindex)
pblocktree->WriteReindexing(true); pblocktree->WriteReindexing(true);

View file

@ -30,7 +30,6 @@
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
#include <boost/thread.hpp> #include <boost/thread.hpp>
using namespace boost;
using namespace std; using namespace std;
#if defined(NDEBUG) #if defined(NDEBUG)
@ -141,9 +140,14 @@ namespace {
uint256 hash; uint256 hash;
CBlockIndex *pindex; //! Optional. CBlockIndex *pindex; //! Optional.
int64_t nTime; //! Time of "getdata" request in microseconds. int64_t nTime; //! Time of "getdata" request in microseconds.
int nValidatedQueuedBefore; //! Number of blocks queued with validated headers (globally) at the time this one is requested.
bool fValidatedHeaders; //! Whether this block has validated headers at the time of request.
}; };
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight; map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight;
/** Number of blocks in flight with validated headers. */
int nQueuedValidatedHeaders = 0;
/** Number of preferable block download peers. */ /** Number of preferable block download peers. */
int nPreferredDownload = 0; int nPreferredDownload = 0;
@ -325,6 +329,7 @@ void MarkBlockAsReceived(const uint256& hash) {
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash); map<uint256, pair<NodeId, list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash);
if (itInFlight != mapBlocksInFlight.end()) { if (itInFlight != mapBlocksInFlight.end()) {
CNodeState *state = State(itInFlight->second.first); CNodeState *state = State(itInFlight->second.first);
nQueuedValidatedHeaders -= itInFlight->second.second->fValidatedHeaders;
state->vBlocksInFlight.erase(itInFlight->second.second); state->vBlocksInFlight.erase(itInFlight->second.second);
state->nBlocksInFlight--; state->nBlocksInFlight--;
state->nStallingSince = 0; state->nStallingSince = 0;
@ -340,7 +345,8 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, CBlockIndex *pindex
// Make sure it's not listed somewhere already. // Make sure it's not listed somewhere already.
MarkBlockAsReceived(hash); MarkBlockAsReceived(hash);
QueuedBlock newentry = {hash, pindex, GetTimeMicros()}; QueuedBlock newentry = {hash, pindex, GetTimeMicros(), nQueuedValidatedHeaders, pindex != NULL};
nQueuedValidatedHeaders += newentry.fValidatedHeaders;
list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry); list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry);
state->nBlocksInFlight++; state->nBlocksInFlight++;
mapBlocksInFlight[hash] = std::make_pair(nodeid, it); mapBlocksInFlight[hash] = std::make_pair(nodeid, it);
@ -622,35 +628,12 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
bool IsStandardTx(const CTransaction& tx, string& reason) bool IsStandardTx(const CTransaction& tx, string& reason)
{ {
AssertLockHeld(cs_main);
// TODO: We may have a different version here // TODO: We may have a different version here
if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) { if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) {
reason = "version"; reason = "version";
return false; return false;
} }
// Treat non-final transactions as non-standard to prevent a specific type
// of double-spend attack, as well as DoS attacks. (if the transaction
// can't be mined, the attacker isn't expending resources broadcasting it)
// Basically we don't want to propagate transactions that can't be included in
// the next block.
//
// However, IsFinalTx() is confusing... Without arguments, it uses
// chainActive.Height() to evaluate nLockTime; when a block is accepted, chainActive.Height()
// is set to the value of nHeight in the block. However, when IsFinalTx()
// is called within CBlock::AcceptBlock(), the height of the block *being*
// evaluated is what is used. Thus if we want to know if a transaction can
// be part of the *next* block, we need to call IsFinalTx() with one more
// than chainActive.Height().
//
// Timestamps on the other hand don't get any special treatment, because we
// can't know what timestamp the next block will have, and there aren't
// timestamp applications where it matters.
if (!IsFinalTx(tx, chainActive.Height() + 1)) {
reason = "non-final";
return false;
}
// Extremely large transactions with lots of inputs can cost the network // Extremely large transactions with lots of inputs can cost the network
// almost as much to process as they cost the sender in fees, because // almost as much to process as they cost the sender in fees, because
// computing signature hashes is O(ninputs*txsize). Limiting transactions // computing signature hashes is O(ninputs*txsize). Limiting transactions
@ -765,7 +748,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
// IsStandard() will have already returned false // IsStandard() will have already returned false
// and this method isn't called. // and this method isn't called.
vector<vector<unsigned char> > stack; vector<vector<unsigned char> > stack;
if (!EvalScript(stack, tx.vin[i].scriptSig, false, BaseSignatureChecker())) if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker()))
return false; return false;
if (whichType == TX_SCRIPTHASH) if (whichType == TX_SCRIPTHASH)
@ -944,6 +927,26 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
error("AcceptToMemoryPool : nonstandard transaction: %s", reason), error("AcceptToMemoryPool : nonstandard transaction: %s", reason),
REJECT_NONSTANDARD, reason); REJECT_NONSTANDARD, reason);
// Only accept nLockTime-using transactions that can be mined in the next
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
//
// However, IsFinalTx() is confusing... Without arguments, it uses
// chainActive.Height() to evaluate nLockTime; when a block is accepted,
// chainActive.Height() is set to the value of nHeight in the block.
// However, when IsFinalTx() is called within CBlock::AcceptBlock(), the
// height of the block *being* evaluated is what is used. Thus if we want
// to know if a transaction can be part of the *next* block, we need to
// call IsFinalTx() with one more than chainActive.Height().
//
// Timestamps on the other hand don't get any special treatment, because we
// can't know what timestamp the next block will have, and there aren't
// timestamp applications where it matters.
if (!IsFinalTx(tx, chainActive.Height() + 1))
return state.DoS(0,
error("AcceptToMemoryPool : non-final"),
REJECT_NONSTANDARD, "non-final");
// is it already in the memory pool? // is it already in the memory pool?
uint256 hash = tx.GetHash(); uint256 hash = tx.GetHash();
if (pool.exists(hash)) if (pool.exists(hash))
@ -1008,15 +1011,15 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Check that the transaction doesn't have an excessive number of // Check that the transaction doesn't have an excessive number of
// sigops, making it impossible to mine. Since the coinbase transaction // sigops, making it impossible to mine. Since the coinbase transaction
// itself can contain sigops MAX_TX_SIGOPS is less than // itself can contain sigops MAX_STANDARD_TX_SIGOPS is less than
// MAX_BLOCK_SIGOPS; we still consider this an invalid rather than // MAX_BLOCK_SIGOPS; we still consider this an invalid rather than
// merely non-standard transaction. // merely non-standard transaction.
unsigned int nSigOps = GetLegacySigOpCount(tx); unsigned int nSigOps = GetLegacySigOpCount(tx);
nSigOps += GetP2SHSigOpCount(tx, view); nSigOps += GetP2SHSigOpCount(tx, view);
if (nSigOps > MAX_TX_SIGOPS) if (nSigOps > MAX_STANDARD_TX_SIGOPS)
return state.DoS(0, return state.DoS(0,
error("AcceptToMemoryPool : too many sigops %s, %d > %d", error("AcceptToMemoryPool : too many sigops %s, %d > %d",
hash.ToString(), nSigOps, MAX_TX_SIGOPS), hash.ToString(), nSigOps, MAX_STANDARD_TX_SIGOPS),
REJECT_NONSTANDARD, "bad-txns-too-many-sigops"); REJECT_NONSTANDARD, "bad-txns-too-many-sigops");
CAmount nValueOut = tx.GetValueOut(); CAmount nValueOut = tx.GetValueOut();
@ -1033,6 +1036,11 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
hash.ToString(), nFees, txMinFee), hash.ToString(), nFees, txMinFee),
REJECT_INSUFFICIENTFEE, "insufficient fee"); REJECT_INSUFFICIENTFEE, "insufficient fee");
// Require that free transactions have sufficient priority to be mined in the next block.
if (GetBoolArg("-relaypriority", true) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(view.GetPriority(tx, chainActive.Height() + 1))) {
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient priority");
}
// Continuously rate-limit free (really, very-low-fee) transactions // Continuously rate-limit free (really, very-low-fee) transactions
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to // This mitigates 'penny-flooding' -- sending thousands of free transactions just to
// be annoying or make others' transactions take longer to confirm. // be annoying or make others' transactions take longer to confirm.
@ -1052,7 +1060,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// At default rate it would take over a month to fill 1GB // At default rate it would take over a month to fill 1GB
if (dFreeCount >= GetArg("-limitfreerelay", 15)*10*1000) if (dFreeCount >= GetArg("-limitfreerelay", 15)*10*1000)
return state.DoS(0, error("AcceptToMemoryPool : free transaction rejected by rate limiter"), return state.DoS(0, error("AcceptToMemoryPool : free transaction rejected by rate limiter"),
REJECT_INSUFFICIENTFEE, "insufficient priority"); REJECT_INSUFFICIENTFEE, "rate limited free transaction");
LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize); LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
dFreeCount += nSize; dFreeCount += nSize;
} }
@ -1888,6 +1896,7 @@ enum FlushStateMode {
bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) {
LOCK(cs_main); LOCK(cs_main);
static int64_t nLastWrite = 0; static int64_t nLastWrite = 0;
try {
if ((mode == FLUSH_STATE_ALWAYS) || if ((mode == FLUSH_STATE_ALWAYS) ||
((mode == FLUSH_STATE_PERIODIC || mode == FLUSH_STATE_IF_NEEDED) && pcoinsTip->GetCacheSize() > nCoinCacheSize) || ((mode == FLUSH_STATE_PERIODIC || mode == FLUSH_STATE_IF_NEEDED) && pcoinsTip->GetCacheSize() > nCoinCacheSize) ||
(mode == FLUSH_STATE_PERIODIC && GetTimeMicros() > nLastWrite + DATABASE_WRITE_INTERVAL * 1000000)) { (mode == FLUSH_STATE_PERIODIC && GetTimeMicros() > nLastWrite + DATABASE_WRITE_INTERVAL * 1000000)) {
@ -1927,6 +1936,9 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) {
} }
nLastWrite = GetTimeMicros(); nLastWrite = GetTimeMicros();
} }
} catch (const std::runtime_error& e) {
return state.Abort(std::string("System error while flushing: ") + e.what());
}
return true; return true;
} }
@ -2797,7 +2809,7 @@ bool AbortNode(const std::string &strMessage, const std::string &userMessage) {
bool CheckDiskSpace(uint64_t nAdditionalBytes) bool CheckDiskSpace(uint64_t nAdditionalBytes)
{ {
uint64_t nFreeBytesAvailable = filesystem::space(GetDataDir()).available; uint64_t nFreeBytesAvailable = boost::filesystem::space(GetDataDir()).available;
// Check for nMinDiskSpace bytes (currently 50MB) // Check for nMinDiskSpace bytes (currently 50MB)
if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes) if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes)
@ -4530,6 +4542,15 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->id); LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->id);
pto->fDisconnect = true; pto->fDisconnect = true;
} }
// In case there is a block that has been in flight from this peer for (1 + 0.5 * N) times the block interval
// (with N the number of validated blocks that were in flight at the time it was requested), disconnect due to
// timeout. We compensate for in-flight blocks to prevent killing off peers due to our own downstream link
// being saturated. We only count validated in-flight blocks so peers can't advertize nonexisting block hashes
// to unreasonably increase our timeout.
if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0 && state.vBlocksInFlight.front().nTime < nNow - 500000 * Params().TargetSpacing() * (2 + state.vBlocksInFlight.front().nValidatedQueuedBefore)) {
LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", state.vBlocksInFlight.front().hash.ToString(), pto->id);
pto->fDisconnect = true;
}
// //
// Message: getdata (blocks) // Message: getdata (blocks)

View file

@ -60,7 +60,7 @@ static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
/** Maximum number of signature check operations in an IsStandard() P2SH script */ /** Maximum number of signature check operations in an IsStandard() P2SH script */
static const unsigned int MAX_P2SH_SIGOPS = 15; static const unsigned int MAX_P2SH_SIGOPS = 15;
/** The maximum number of sigops we're willing to relay/mine in a single tx */ /** The maximum number of sigops we're willing to relay/mine in a single tx */
static const unsigned int MAX_TX_SIGOPS = MAX_BLOCK_SIGOPS/5; static const unsigned int MAX_STANDARD_TX_SIGOPS = MAX_BLOCK_SIGOPS/5;
/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */ /** Default for -maxorphantx, maximum number of orphan transactions kept in memory */
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100; static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100;
/** The maximum size of a blk?????.dat file (since 0.8) */ /** The maximum size of a blk?????.dat file (since 0.8) */

View file

@ -49,7 +49,6 @@
#endif #endif
#endif #endif
using namespace boost;
using namespace std; using namespace std;
namespace { namespace {

View file

@ -162,7 +162,7 @@ struct CBlockLocator
vHave.clear(); vHave.clear();
} }
bool IsNull() bool IsNull() const
{ {
return vHave.empty(); return vHave.empty();
} }

View file

@ -20,6 +20,7 @@
class AmountSpinBox: public QAbstractSpinBox class AmountSpinBox: public QAbstractSpinBox
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AmountSpinBox(QWidget *parent): explicit AmountSpinBox(QWidget *parent):
QAbstractSpinBox(parent), QAbstractSpinBox(parent),
@ -72,23 +73,6 @@ public:
setValue(val); setValue(val);
} }
StepEnabled stepEnabled() const
{
StepEnabled rv = 0;
if(text().isEmpty()) // Allow step-up with empty field
return StepUpEnabled;
bool valid = false;
CAmount val = value(&valid);
if(valid)
{
if(val > 0)
rv |= StepDownEnabled;
if(val < BitcoinUnits::maxMoney())
rv |= StepUpEnabled;
}
return rv;
}
void setDisplayUnit(int unit) void setDisplayUnit(int unit)
{ {
bool valid = false; bool valid = false;
@ -139,6 +123,7 @@ public:
} }
return cachedMinimumSizeHint; return cachedMinimumSizeHint;
} }
private: private:
int currentUnit; int currentUnit;
CAmount singleStep; CAmount singleStep;
@ -179,6 +164,26 @@ protected:
return QAbstractSpinBox::event(event); return QAbstractSpinBox::event(event);
} }
StepEnabled stepEnabled() const
{
if (isReadOnly()) // Disable steps when AmountSpinBox is read-only
return StepNone;
if (text().isEmpty()) // Allow step-up with empty field
return StepUpEnabled;
StepEnabled rv = 0;
bool valid = false;
CAmount val = value(&valid);
if(valid)
{
if(val > 0)
rv |= StepDownEnabled;
if(val < BitcoinUnits::maxMoney())
rv |= StepUpEnabled;
}
return rv;
}
signals: signals:
void valueChanged(); void valueChanged();
}; };

View file

@ -76,12 +76,14 @@ BitcoinGUI::BitcoinGUI(const NetworkStyle *networkStyle, QWidget *parent) :
historyAction(0), historyAction(0),
quitAction(0), quitAction(0),
sendCoinsAction(0), sendCoinsAction(0),
sendCoinsMenuAction(0),
usedSendingAddressesAction(0), usedSendingAddressesAction(0),
usedReceivingAddressesAction(0), usedReceivingAddressesAction(0),
signMessageAction(0), signMessageAction(0),
verifyMessageAction(0), verifyMessageAction(0),
aboutAction(0), aboutAction(0),
receiveCoinsAction(0), receiveCoinsAction(0),
receiveCoinsMenuAction(0),
optionsAction(0), optionsAction(0),
toggleHideAction(0), toggleHideAction(0),
encryptWalletAction(0), encryptWalletAction(0),
@ -256,6 +258,10 @@ void BitcoinGUI::createActions(const NetworkStyle *networkStyle)
sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2)); sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
tabGroup->addAction(sendCoinsAction); tabGroup->addAction(sendCoinsAction);
sendCoinsMenuAction = new QAction(TextColorIcon(":/icons/send"), sendCoinsAction->text(), this);
sendCoinsMenuAction->setStatusTip(sendCoinsAction->statusTip());
sendCoinsMenuAction->setToolTip(sendCoinsMenuAction->statusTip());
receiveCoinsAction = new QAction(SingleColorIcon(":/icons/receiving_addresses"), tr("&Receive"), this); receiveCoinsAction = new QAction(SingleColorIcon(":/icons/receiving_addresses"), tr("&Receive"), this);
receiveCoinsAction->setStatusTip(tr("Request payments (generates QR codes and bitcoin: URIs)")); receiveCoinsAction->setStatusTip(tr("Request payments (generates QR codes and bitcoin: URIs)"));
receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip()); receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip());
@ -263,6 +269,10 @@ void BitcoinGUI::createActions(const NetworkStyle *networkStyle)
receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3)); receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
tabGroup->addAction(receiveCoinsAction); tabGroup->addAction(receiveCoinsAction);
receiveCoinsMenuAction = new QAction(TextColorIcon(":/icons/receiving_addresses"), receiveCoinsAction->text(), this);
receiveCoinsMenuAction->setStatusTip(receiveCoinsAction->statusTip());
receiveCoinsMenuAction->setToolTip(receiveCoinsMenuAction->statusTip());
historyAction = new QAction(SingleColorIcon(":/icons/history"), tr("&Transactions"), this); historyAction = new QAction(SingleColorIcon(":/icons/history"), tr("&Transactions"), this);
historyAction->setStatusTip(tr("Browse transaction history")); historyAction->setStatusTip(tr("Browse transaction history"));
historyAction->setToolTip(historyAction->statusTip()); historyAction->setToolTip(historyAction->statusTip());
@ -277,8 +287,12 @@ void BitcoinGUI::createActions(const NetworkStyle *networkStyle)
connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage())); connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage())); connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
connect(sendCoinsMenuAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(sendCoinsMenuAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage())); connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
connect(receiveCoinsMenuAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(receiveCoinsMenuAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage())); connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
#endif // ENABLE_WALLET #endif // ENABLE_WALLET
@ -475,7 +489,9 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
{ {
overviewAction->setEnabled(enabled); overviewAction->setEnabled(enabled);
sendCoinsAction->setEnabled(enabled); sendCoinsAction->setEnabled(enabled);
sendCoinsMenuAction->setEnabled(enabled);
receiveCoinsAction->setEnabled(enabled); receiveCoinsAction->setEnabled(enabled);
receiveCoinsMenuAction->setEnabled(enabled);
historyAction->setEnabled(enabled); historyAction->setEnabled(enabled);
encryptWalletAction->setEnabled(enabled); encryptWalletAction->setEnabled(enabled);
backupWalletAction->setEnabled(enabled); backupWalletAction->setEnabled(enabled);
@ -522,8 +538,8 @@ void BitcoinGUI::createTrayIconMenu()
// Configuration of the tray icon (or dock icon) icon menu // Configuration of the tray icon (or dock icon) icon menu
trayIconMenu->addAction(toggleHideAction); trayIconMenu->addAction(toggleHideAction);
trayIconMenu->addSeparator(); trayIconMenu->addSeparator();
trayIconMenu->addAction(sendCoinsAction); trayIconMenu->addAction(sendCoinsMenuAction);
trayIconMenu->addAction(receiveCoinsAction); trayIconMenu->addAction(receiveCoinsMenuAction);
trayIconMenu->addSeparator(); trayIconMenu->addSeparator();
trayIconMenu->addAction(signMessageAction); trayIconMenu->addAction(signMessageAction);
trayIconMenu->addAction(verifyMessageAction); trayIconMenu->addAction(verifyMessageAction);

View file

@ -90,12 +90,14 @@ private:
QAction *historyAction; QAction *historyAction;
QAction *quitAction; QAction *quitAction;
QAction *sendCoinsAction; QAction *sendCoinsAction;
QAction *sendCoinsMenuAction;
QAction *usedSendingAddressesAction; QAction *usedSendingAddressesAction;
QAction *usedReceivingAddressesAction; QAction *usedReceivingAddressesAction;
QAction *signMessageAction; QAction *signMessageAction;
QAction *verifyMessageAction; QAction *verifyMessageAction;
QAction *aboutAction; QAction *aboutAction;
QAction *receiveCoinsAction; QAction *receiveCoinsAction;
QAction *receiveCoinsMenuAction;
QAction *optionsAction; QAction *optionsAction;
QAction *toggleHideAction; QAction *toggleHideAction;
QAction *encryptWalletAction; QAction *encryptWalletAction;

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>800</width> <width>585</width>
<height>400</height> <height>225</height>
</rect> </rect>
</property> </property>
<property name="font"> <property name="font">
@ -34,6 +34,13 @@
</item> </item>
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextEdit" name="helpMessage">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item> <item>
<widget class="QScrollArea" name="scrollArea"> <widget class="QScrollArea" name="scrollArea">
<property name="verticalScrollBarPolicy"> <property name="verticalScrollBarPolicy">
@ -47,19 +54,22 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>659</width> <width>447</width>
<height>348</height> <height>68</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<widget class="QLabel" name="helpMessageLabel"> <widget class="QLabel" name="aboutMessage">
<property name="cursor"> <property name="cursor">
<cursorShape>IBeamCursor</cursorShape> <cursorShape>IBeamCursor</cursorShape>
</property> </property>
<property name="textFormat"> <property name="textFormat">
<enum>Qt::PlainText</enum> <enum>Qt::PlainText</enum>
</property> </property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="openExternalLinks"> <property name="openExternalLinks">
<bool>true</bool> <bool>true</bool>
</property> </property>

View file

@ -30,7 +30,7 @@
<item> <item>
<widget class="QLabel" name="infoLabel_SM"> <widget class="QLabel" name="infoLabel_SM">
<property name="text"> <property name="text">
<string>You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</string> <string>You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</string>
</property> </property>
<property name="textFormat"> <property name="textFormat">
<enum>Qt::PlainText</enum> <enum>Qt::PlainText</enum>
@ -237,7 +237,7 @@
<item> <item>
<widget class="QLabel" name="infoLabel_VM"> <widget class="QLabel" name="infoLabel_VM">
<property name="text"> <property name="text">
<string>Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack.</string> <string>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</string>
</property> </property>
<property name="textFormat"> <property name="textFormat">
<enum>Qt::PlainText</enum> <enum>Qt::PlainText</enum>

View file

@ -46,7 +46,6 @@
#include <QUrlQuery> #include <QUrlQuery>
#endif #endif
using namespace boost;
using namespace std; using namespace std;
const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds
@ -522,8 +521,7 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins
const payments::PaymentDetails& details = request.getDetails(); const payments::PaymentDetails& details = request.getDetails();
// Payment request network matches client network? // Payment request network matches client network?
if (details.network() != Params().NetworkIDString()) if (!verifyNetwork(request.getDetails())) {
{
emit message(tr("Payment request rejected"), tr("Payment request network doesn't match client network."), emit message(tr("Payment request rejected"), tr("Payment request network doesn't match client network."),
CClientUIInterface::MSG_ERROR); CClientUIInterface::MSG_ERROR);
@ -746,3 +744,15 @@ void PaymentServer::handlePaymentACK(const QString& paymentACKMsg)
// currently we don't futher process or store the paymentACK message // currently we don't futher process or store the paymentACK message
emit message(tr("Payment acknowledged"), paymentACKMsg, CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MODAL); emit message(tr("Payment acknowledged"), paymentACKMsg, CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MODAL);
} }
bool PaymentServer::verifyNetwork(const payments::PaymentDetails& requestDetails)
{
bool fVerified = requestDetails.network() == Params().NetworkIDString();
if (!fVerified) {
qWarning() << QString("PaymentServer::%1: Payment request network \"%2\" doesn't match client network \"%3\".")
.arg(__func__)
.arg(QString::fromStdString(requestDetails.network()))
.arg(QString::fromStdString(Params().NetworkIDString()));
}
return fVerified;
}

View file

@ -91,6 +91,9 @@ public:
// This is now public, because we use it in paymentservertests.cpp // This is now public, because we use it in paymentservertests.cpp
static bool readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request); static bool readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request);
// Verify that the payment request network matches the client network
static bool verifyNetwork(const payments::PaymentDetails& requestDetails);
signals: signals:
// Fired when a valid payment request is received // Fired when a valid payment request is received
void receivedPaymentRequest(SendCoinsRecipient); void receivedPaymentRequest(SendCoinsRecipient);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 712 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 KiB

After

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 883 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

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