Implement a hard fork for extended/infinite claim expiration times #112
74
configure.ac
|
@ -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,8 +605,12 @@ 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"
|
||||||
|
|
||||||
dnl Boost >= 1.50 uses sleep_for rather than the now-deprecated sleep, however
|
dnl Boost >= 1.50 uses sleep_for rather than the now-deprecated sleep, however
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
73
contrib/devtools/optimize-pngs.py
Executable 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"
|
BIN
contrib/gitian-downloader/jonasschnelli.pgp
Normal 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).
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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 ()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
@ -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 ()
|
|
@ -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
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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 = \
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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");
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,7 +32,6 @@ protected:
|
||||||
|
|
||||||
int nRPCPort;
|
int nRPCPort;
|
||||||
std::string strDataDir;
|
std::string strDataDir;
|
||||||
Network networkID;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
2
src/db.h
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
54
src/init.cpp
|
@ -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);
|
||||||
|
|
83
src/main.cpp
|
@ -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)
|
||||||
|
|
|
@ -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) */
|
||||||
|
|
|
@ -49,7 +49,6 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace boost;
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -162,7 +162,7 @@ struct CBlockLocator
|
||||||
vHave.clear();
|
vHave.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsNull()
|
bool IsNull() const
|
||||||
{
|
{
|
||||||
return vHave.empty();
|
return vHave.empty();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 784 B After Width: | Height: | Size: 712 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 306 KiB After Width: | Height: | Size: 306 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 883 B After Width: | Height: | Size: 883 B |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 762 B |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |