diff options
43 files changed, 469 insertions, 250 deletions
diff --git a/contrib/gitian-downloader/aschildbach-key.pgp b/contrib/gitian-downloader/aschildbach-key.pgp Binary files differnew file mode 100644 index 0000000000..df06e19fa4 --- /dev/null +++ b/contrib/gitian-downloader/aschildbach-key.pgp diff --git a/contrib/gitian-downloader/linux-download-config b/contrib/gitian-downloader/linux-download-config index ae0377a704..b5e0561aa3 100644 --- a/contrib/gitian-downloader/linux-download-config +++ b/contrib/gitian-downloader/linux-download-config @@ -8,39 +8,32 @@ rss: pattern: bitcoin-\d+.\d+.\d+-linux-gitian.zip signers: 0A82509767C7D4A5D14DA2301AE1D35043E08E54: - weight: 40 name: BlueMatt key: bluematt BF6273FAEF7CC0BA1F562E50989F6B3048A116B5: - weight: 40 name: Devrandom key: devrandom E463A93F5F3117EEDE6C7316BD02942421F4889F: - weight: 40 name: Luke-Jr key: luke-jr D762373D24904A3E42F33B08B9A408E71DAAC974: - weight: 40 name: "Pieter Wuille" key: sipa 77E72E69DA7EE0A148C06B21B34821D4944DE5F7: - weight: 40 name: tcatm key: tcatm 01CDF4627A3B88AAE4A571C87588242FBE38D3A8: - weight: 40 name: "Gavin Andresen" key: gavinandresen 71A3B16735405025D447E8F274810B012346C9A6: - weight: 40 name: "Wladimir J. van der Laan" key: laanwj AEC1884398647C47413C1C3FB1179EB7347DC10D: - weight: 40 name: "Warren Togami" key: wtogami 9692B91BBF0E8D34DFD33B1882C5C009628ECF0C: - weight: 1 name: michagogo key: michagogo -minimum_weight: 120 + E944AE667CF960B1004BC32FCA662BE18B877A60: + name: "Andreas Schildbach" + key: aschildbach diff --git a/contrib/gitian-downloader/win32-download-config b/contrib/gitian-downloader/win32-download-config index 1ead2fddcb..5d56db863e 100644 --- a/contrib/gitian-downloader/win32-download-config +++ b/contrib/gitian-downloader/win32-download-config @@ -8,39 +8,32 @@ rss: pattern: bitcoin-\d+.\d+.\d+-win32-gitian.zip signers: 0A82509767C7D4A5D14DA2301AE1D35043E08E54: - weight: 40 name: BlueMatt key: bluematt BF6273FAEF7CC0BA1F562E50989F6B3048A116B5: - weight: 40 name: Devrandom key: devrandom E463A93F5F3117EEDE6C7316BD02942421F4889F: - weight: 40 name: Luke-Jr key: luke-jr D762373D24904A3E42F33B08B9A408E71DAAC974: - weight: 40 name: "Pieter Wuille" key: sipa 77E72E69DA7EE0A148C06B21B34821D4944DE5F7: - weight: 40 name: tcatm key: tcatm 01CDF4627A3B88AAE4A571C87588242FBE38D3A8: - weight: 40 name: "Gavin Andresen" key: gavinandresen 71A3B16735405025D447E8F274810B012346C9A6: - weight: 40 name: "Wladimir J. van der Laan" key: laanwj AEC1884398647C47413C1C3FB1179EB7347DC10D: - weight: 40 name: "Warren Togami" key: wtogami 9692B91BBF0E8D34DFD33B1882C5C009628ECF0C: - weight: 1 name: michagogo key: michagogo -minimum_weight: 120 + E944AE667CF960B1004BC32FCA662BE18B877A60: + name: "Andreas Schildbach" + key: aschildbach diff --git a/doc/assets-attribution.md b/doc/assets-attribution.md index d42be8fb24..61b457a282 100644 --- a/doc/assets-attribution.md +++ b/doc/assets-attribution.md @@ -78,13 +78,13 @@ Everaldo (Everaldo Coelho) ### Assets Used scripts/img/reload.xcf (modified), src/qt/res/movies/*.png -[Vignoni David](http://www.oxygen-icons.org) +[Vignoni David](http://techbase.kde.org/Projects/Oxygen) ----------------------- ### Info * Designer: Vignoni David * License: Oxygen icon theme is dual licensed. You may copy it under the Creative Common Attribution-ShareAlike 3.0 License or the GNU Library General Public License. -* Site: [http://www.oxygen-icons.org](http://www.oxygen-icons.org) +* Site: [http://techbase.kde.org/Projects/Oxygen](http://techbase.kde.org/Projects/Oxygen) ### Assets Used src/qt/res/icons/debugwindow.png diff --git a/doc/translation_process.md b/doc/translation_process.md index 9fb7622868..4b7b19f82f 100644 --- a/doc/translation_process.md +++ b/doc/translation_process.md @@ -70,7 +70,7 @@ We are using https://transifex.com as a frontend for translating the client. https://www.transifex.com/projects/p/bitcoin/resource/tx/ -The "Transifex client" (see: http://help.transifex.com/features/client/) +The "Transifex client" (see: http://support.transifex.com/customer/portal/topics/440187-transifex-client/articles) will help with fetching new translations from Transifex. Use the following config to be able to connect with the client: diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py index 6ffee6bbe8..f16095c125 100755 --- a/qa/rpc-tests/listtransactions.py +++ b/qa/rpc-tests/listtransactions.py @@ -118,6 +118,7 @@ def main(): check_json_precision() success = False + nodes = [] try: print("Initializing test directory "+options.tmpdir) if not os.path.isdir(options.tmpdir): @@ -127,6 +128,7 @@ def main(): nodes = start_nodes(2, options.tmpdir) connect_nodes(nodes[1], 0) sync_blocks(nodes) + run_test(nodes) success = True @@ -135,12 +137,12 @@ def main(): print("Assertion failed: "+e.message) except Exception as e: print("Unexpected exception caught during testing: "+str(e)) - stack = traceback.extract_tb(sys.exc_info()[2]) - print(stack[-1]) + traceback.print_tb(sys.exc_info()[2]) if not options.nocleanup: print("Cleaning up") - stop_nodes() + stop_nodes(nodes) + wait_bitcoinds() shutil.rmtree(options.tmpdir) if success: diff --git a/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/.gitignore b/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/.gitignore new file mode 100644 index 0000000000..0d20b6487c --- /dev/null +++ b/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/__init__.py b/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/__init__.py diff --git a/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/authproxy.py b/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/authproxy.py new file mode 100644 index 0000000000..c2e5406c2f --- /dev/null +++ b/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/authproxy.py @@ -0,0 +1,140 @@ + +""" + Copyright 2011 Jeff Garzik + + AuthServiceProxy has the following improvements over python-jsonrpc's + ServiceProxy class: + + - HTTP connections persist for the life of the AuthServiceProxy object + (if server supports HTTP/1.1) + - sends protocol 'version', per JSON-RPC 1.1 + - sends proper, incrementing 'id' + - sends Basic HTTP authentication headers + - parses all JSON numbers that look like floats as Decimal + - uses standard Python json lib + + Previous copyright, from python-jsonrpc/jsonrpc/proxy.py: + + Copyright (c) 2007 Jan-Klaas Kollhof + + This file is part of jsonrpc. + + jsonrpc is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This software is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this software; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +""" + +try: + import http.client as httplib +except ImportError: + import httplib +import base64 +import json +import decimal +try: + import urllib.parse as urlparse +except ImportError: + import urlparse + +USER_AGENT = "AuthServiceProxy/0.1" + +HTTP_TIMEOUT = 30 + + +class JSONRPCException(Exception): + def __init__(self, rpc_error): + Exception.__init__(self) + self.error = rpc_error + + +class AuthServiceProxy(object): + def __init__(self, service_url, service_name=None, timeout=HTTP_TIMEOUT, connection=None): + self.__service_url = service_url + self.__service_name = service_name + self.__url = urlparse.urlparse(service_url) + if self.__url.port is None: + port = 80 + else: + port = self.__url.port + self.__id_count = 0 + (user, passwd) = (self.__url.username, self.__url.password) + try: + user = user.encode('utf8') + except AttributeError: + pass + try: + passwd = passwd.encode('utf8') + except AttributeError: + pass + authpair = user + b':' + passwd + self.__auth_header = b'Basic ' + base64.b64encode(authpair) + + if connection: + # Callables re-use the connection of the original proxy + self.__conn = connection + elif self.__url.scheme == 'https': + self.__conn = httplib.HTTPSConnection(self.__url.hostname, port, + None, None, False, + timeout) + else: + self.__conn = httplib.HTTPConnection(self.__url.hostname, port, + False, timeout) + + def __getattr__(self, name): + if name.startswith('__') and name.endswith('__'): + # Python internal stuff + raise AttributeError + if self.__service_name is not None: + name = "%s.%s" % (self.__service_name, name) + return AuthServiceProxy(self.__service_url, name, connection=self.__conn) + + def __call__(self, *args): + self.__id_count += 1 + + postdata = json.dumps({'version': '1.1', + 'method': self.__service_name, + 'params': args, + 'id': self.__id_count}) + self.__conn.request('POST', self.__url.path, postdata, + {'Host': self.__url.hostname, + 'User-Agent': USER_AGENT, + 'Authorization': self.__auth_header, + 'Content-type': 'application/json'}) + + response = self._get_response() + if response['error'] is not None: + raise JSONRPCException(response['error']) + elif 'result' not in response: + raise JSONRPCException({ + 'code': -343, 'message': 'missing JSON-RPC result'}) + else: + return response['result'] + + def _batch(self, rpc_call_list): + postdata = json.dumps(list(rpc_call_list)) + self.__conn.request('POST', self.__url.path, postdata, + {'Host': self.__url.hostname, + 'User-Agent': USER_AGENT, + 'Authorization': self.__auth_header, + 'Content-type': 'application/json'}) + + return self._get_response() + + def _get_response(self): + http_response = self.__conn.getresponse() + if http_response is None: + raise JSONRPCException({ + 'code': -342, 'message': 'missing HTTP response from server'}) + + return json.loads(http_response.read().decode('utf8'), + parse_float=decimal.Decimal) diff --git a/qa/rpc-tests/python-bitcoinrpc/setup.py b/qa/rpc-tests/python-bitcoinrpc/setup.py new file mode 100644 index 0000000000..b5a217bf93 --- /dev/null +++ b/qa/rpc-tests/python-bitcoinrpc/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +from distutils.core import setup + +setup(name='python-bitcoinrpc', + version='0.1', + description='Enhanced version of python-jsonrpc for use with Bitcoin', + long_description=open('README').read(), + author='Jeff Garzik', + author_email='<jgarzik@exmulti.com>', + maintainer='Jeff Garzik', + maintainer_email='<jgarzik@exmulti.com>', + url='http://www.github.com/jgarzik/python-bitcoinrpc', + packages=['bitcoinrpc'], + classifiers=['License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)', 'Operating System :: OS Independent']) diff --git a/qa/rpc-tests/skeleton.py b/qa/rpc-tests/skeleton.py index 5d4b62e55f..126b6bfaf4 100755 --- a/qa/rpc-tests/skeleton.py +++ b/qa/rpc-tests/skeleton.py @@ -45,6 +45,7 @@ def main(): check_json_precision() success = False + nodes = [] try: print("Initializing test directory "+options.tmpdir) if not os.path.isdir(options.tmpdir): @@ -63,12 +64,12 @@ def main(): print("Assertion failed: "+e.message) except Exception as e: print("Unexpected exception caught during testing: "+str(e)) - stack = traceback.extract_tb(sys.exc_info()[2]) - print(stack[-1]) + traceback.print_tb(sys.exc_info()[2]) if not options.nocleanup: print("Cleaning up") - stop_nodes() + stop_nodes(nodes) + wait_bitcoinds() shutil.rmtree(options.tmpdir) if success: diff --git a/qa/rpc-tests/util.py b/qa/rpc-tests/util.py index 6184c1fbad..fa0700f1c8 100644 --- a/qa/rpc-tests/util.py +++ b/qa/rpc-tests/util.py @@ -55,6 +55,8 @@ def sync_mempools(rpc_connections): time.sleep(1) +bitcoind_processes = [] + def initialize_chain(test_dir): """ Create (or copy from cache) a 200-block-long chain and @@ -64,7 +66,6 @@ def initialize_chain(test_dir): if not os.path.isdir(os.path.join("cache", "node0")): # Create cache directories, run bitcoinds: - bitcoinds = [] for i in range(4): datadir = os.path.join("cache", "node"+str(i)) os.makedirs(datadir) @@ -77,7 +78,7 @@ def initialize_chain(test_dir): args = [ "bitcoind", "-keypool=1", "-datadir="+datadir ] if i > 0: args.append("-connect=127.0.0.1:"+str(START_P2P_PORT)) - bitcoinds.append(subprocess.Popen(args)) + bitcoind_processes.append(subprocess.Popen(args)) subprocess.check_output([ "bitcoin-cli", "-datadir="+datadir, "-rpcwait", "getblockcount"]) @@ -90,8 +91,6 @@ def initialize_chain(test_dir): sys.stderr.write("Error connecting to "+url+"\n") sys.exit(1) - import pdb; pdb.set_trace() - # Create a 200-block-long chain; each of the 4 nodes # gets 25 mature blocks and 25 immature. for i in range(4): @@ -100,17 +99,18 @@ def initialize_chain(test_dir): for i in range(4): rpcs[i].setgenerate(True, 25) sync_blocks(rpcs) - # Shut them down + + # Shut them down, and remove debug.logs: + stop_nodes(rpcs) + wait_bitcoinds() for i in range(4): - rpcs[i].stop() + os.remove(debug_log("cache", i)) for i in range(4): from_dir = os.path.join("cache", "node"+str(i)) to_dir = os.path.join(test_dir, "node"+str(i)) shutil.copytree(from_dir, to_dir) -bitcoind_processes = [] - def start_nodes(num_nodes, dir): # Start bitcoinds, and wait for RPC interface to be up and running: for i in range(num_nodes): @@ -126,9 +126,19 @@ def start_nodes(num_nodes, dir): rpc_connections.append(AuthServiceProxy(url)) return rpc_connections -def stop_nodes(): - for process in bitcoind_processes: - process.kill() +def debug_log(dir, n_node): + return os.path.join(dir, "node"+str(n_node), "regtest", "debug.log") + +def stop_nodes(nodes): + for i in range(len(nodes)): + nodes[i].stop() + del nodes[:] # Emptying array closes connections as a side effect + +def wait_bitcoinds(): + # Wait for all bitcoinds to cleanly exit + for bitcoind in bitcoind_processes: + bitcoind.wait() + del bitcoind_processes[:] def connect_nodes(from_connection, node_num): ip_port = "127.0.0.1:"+str(START_P2P_PORT+node_num) diff --git a/src/Makefile.am b/src/Makefile.am index da842a9e6f..c725c4f1c2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -90,9 +90,7 @@ version.o: obj/build.h libbitcoin_server_a_SOURCES = \ addrman.cpp \ alert.cpp \ - rpcserver.cpp \ bloom.cpp \ - chainparams.cpp \ checkpoints.cpp \ coins.cpp \ init.cpp \ @@ -107,6 +105,7 @@ libbitcoin_server_a_SOURCES = \ rpcmisc.cpp \ rpcnet.cpp \ rpcrawtransaction.cpp \ + rpcserver.cpp \ txdb.cpp \ txmempool.cpp \ $(JSON_H) \ diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 5e6566a7ac..b52774ee20 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -144,6 +144,7 @@ public: vSeeds.push_back(CDNSSeedData("bluematt.me", "dnsseed.bluematt.me")); vSeeds.push_back(CDNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org")); vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com")); + vSeeds.push_back(CDNSSeedData("bitnodes.io", "seed.bitnodes.io")); vSeeds.push_back(CDNSSeedData("xf2.org", "bitseed.xf2.org")); base58Prefixes[PUBKEY_ADDRESS] = list_of(0); diff --git a/src/init.cpp b/src/init.cpp index 1a325ca691..cd06e0c204 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -190,33 +190,47 @@ std::string HelpMessage(HelpMessageMode hmm) { string strUsage = _("Options:") + "\n"; strUsage += " -? " + _("This help message") + "\n"; + strUsage += " -alertnotify=<cmd> " + _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)") + "\n"; + strUsage += " -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n"; + strUsage += " -checkblocks=<n> " + _("How many blocks to check at startup (default: 288, 0 = all)") + "\n"; + strUsage += " -checklevel=<n> " + _("How thorough the block verification of -checkblocks is (0-4, default: 3)") + "\n"; strUsage += " -conf=<file> " + _("Specify configuration file (default: bitcoin.conf)") + "\n"; + if (hmm == HMM_BITCOIND) + { +#if !defined(WIN32) + strUsage += " -daemon " + _("Run in the background as a daemon and accept commands") + "\n"; +#endif + } strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n"; - strUsage += " -testnet " + _("Use the test network") + "\n"; - strUsage += " -pid=<file> " + _("Specify pid file (default: bitcoind.pid)") + "\n"; - strUsage += " -gen " + _("Generate coins (default: 0)") + "\n"; strUsage += " -dbcache=<n> " + strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache) + "\n"; - strUsage += " -timeout=<n> " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n"; - strUsage += " -proxy=<ip:port> " + _("Connect through SOCKS proxy") + "\n"; - strUsage += " -socks=<n> " + _("Select SOCKS version for -proxy (4 or 5, default: 5)") + "\n"; - strUsage += " -onion=<ip:port> " + _("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy)") + "\n"; - strUsage += " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n"; - strUsage += " -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n"; - strUsage += " -maxconnections=<n> " + _("Maintain at most <n> connections to peers (default: 125)") + "\n"; + strUsage += " -keypool=<n> " + _("Set key pool size to <n> (default: 100)") + "\n"; + strUsage += " -loadblock=<file> " + _("Imports blocks from external blk000??.dat file") + " " + _("on startup") + "\n"; + strUsage += " -par=<n> " + strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), -(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS) + "\n"; + strUsage += " -pid=<file> " + _("Specify pid file (default: bitcoind.pid)") + "\n"; + strUsage += " -reindex " + _("Rebuild block chain index from current blk000??.dat files") + " " + _("on startup") + "\n"; + strUsage += " -txindex " + _("Maintain a full transaction index (default: 0)") + "\n"; + + strUsage += "\n" + _("Connection options:") + "\n"; strUsage += " -addnode=<ip> " + _("Add a node to connect to and attempt to keep the connection open") + "\n"; + strUsage += " -banscore=<n> " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n"; + strUsage += " -bantime=<n> " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n"; + strUsage += " -bind=<addr> " + _("Bind to given address and always listen on it. Use [host]:port notation for IPv6") + "\n"; strUsage += " -connect=<ip> " + _("Connect only to the specified node(s)") + "\n"; - strUsage += " -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n"; - strUsage += " -externalip=<ip> " + _("Specify your own public address") + "\n"; - strUsage += " -onlynet=<net> " + _("Only connect to nodes in network <net> (IPv4, IPv6 or Tor)") + "\n"; strUsage += " -discover " + _("Discover own IP address (default: 1 when listening and no -externalip)") + "\n"; - strUsage += " -checkpoints " + _("Only accept block chain matching built-in checkpoints (default: 1)") + "\n"; - strUsage += " -listen " + _("Accept connections from outside (default: 1 if no -proxy or -connect)") + "\n"; - strUsage += " -bind=<addr> " + _("Bind to given address and always listen on it. Use [host]:port notation for IPv6") + "\n"; + strUsage += " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + " " + _("(default: 1)") + "\n"; strUsage += " -dnsseed " + _("Find peers using DNS lookup (default: 1 unless -connect)") + "\n"; - strUsage += " -banscore=<n> " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n"; - strUsage += " -bantime=<n> " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n"; + strUsage += " -externalip=<ip> " + _("Specify your own public address") + "\n"; + strUsage += " -listen " + _("Accept connections from outside (default: 1 if no -proxy or -connect)") + "\n"; + strUsage += " -maxconnections=<n> " + _("Maintain at most <n> connections to peers (default: 125)") + "\n"; strUsage += " -maxreceivebuffer=<n> " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000)") + "\n"; strUsage += " -maxsendbuffer=<n> " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 1000)") + "\n"; + strUsage += " -onion=<ip:port> " + _("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy)") + "\n"; + strUsage += " -onlynet=<net> " + _("Only connect to nodes in network <net> (IPv4, IPv6 or Tor)") + "\n"; + strUsage += " -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n"; + strUsage += " -proxy=<ip:port> " + _("Connect through SOCKS proxy") + "\n"; + strUsage += " -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n"; + strUsage += " -socks=<n> " + _("Select SOCKS version for -proxy (4 or 5, default: 5)") + "\n"; + strUsage += " -timeout=<n> " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n"; #ifdef USE_UPNP #if USE_UPNP strUsage += " -upnp " + _("Use UPnP to map the listening port (default: 1 when listening)") + "\n"; @@ -224,64 +238,78 @@ std::string HelpMessage(HelpMessageMode hmm) strUsage += " -upnp " + _("Use UPnP to map the listening port (default: 0)") + "\n"; #endif #endif + +#ifdef ENABLE_WALLET + strUsage += "\n" + _("Wallet options:") + "\n"; + strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n"; + strUsage += " -paytxfee=<amt> " + _("Fee per kB to add to transactions you send") + "\n"; + strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + " " + _("on startup") + "\n"; + strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup") + "\n"; + strUsage += " -spendzeroconfchange " + _("Spend unconfirmed change when sending transactions (default: 1)") + "\n"; + strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n"; + strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + " " + _("(default: wallet.dat)") + "\n"; + strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n"; + strUsage += " -zapwallettxes " + _("Clear list of wallet transactions (diagnostic tool; implies -rescan)") + "\n"; +#endif + + strUsage += "\n" + _("Debugging/Testing options:") + "\n"; + if (GetBoolArg("-help-debug", false)) + { + strUsage += " -benchmark " + _("Show benchmark information (default: 0)") + "\n"; + strUsage += " -checkpoints " + _("Only accept block chain matching built-in checkpoints (default: 1)") + "\n"; + strUsage += " -dblogsize=<n> " + _("Flush database activity from memory pool to disk log every <n> megabytes (default: 100)") + "\n"; + strUsage += " -disablesafemode " + _("Disable safemode, override a real safe mode event (default: 0)") + "\n"; + strUsage += " -testsafemode " + _("Force safe mode (default: 0)") + "\n"; + strUsage += " -dropmessagestest=<n> " + _("Randomly drop 1 of every <n> network messages") + "\n"; + strUsage += " -fuzzmessagestest=<n> " + _("Randomly fuzz 1 of every <n> network messages") + "\n"; + strUsage += " -flushwallet " + _("Run a thread to flush wallet periodically (default: 1)") + "\n"; + } strUsage += " -debug=<category> " + _("Output debugging information (default: 0, supplying <category> is optional)") + "\n"; strUsage += " " + _("If <category> is not supplied, output all debugging information.") + "\n"; strUsage += " " + _("<category> can be:"); strUsage += " addrman, alert, coindb, db, lock, rand, rpc, selectcoins, mempool, net"; // Don't translate these and qt below if (hmm == HMM_BITCOIN_QT) + strUsage += ", qt"; + strUsage += ".\n"; + strUsage += " -gen " + _("Generate coins (default: 0)") + "\n"; + strUsage += " -genproclimit=<n> " + _("Set the processor limit for when generation is on (-1 = unlimited, default: -1)") + "\n"; + strUsage += " -help-debug " + _("Show all debugging options (usage: --help -help-debug)") + "\n"; + strUsage += " -logtimestamps " + _("Prepend debug output with timestamp (default: 1)") + "\n"; + if (GetBoolArg("-help-debug", false)) { - strUsage += ", qt.\n"; + strUsage += " -limitfreerelay=<n> " + _("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:15)") + "\n"; + strUsage += " -maxsigcachesize=<n> " + _("Limit size of signature cache to <n> entries (default: 50000)") + "\n"; } - else + strUsage += " -mintxfee=<amt> " + _("Fees smaller than this are considered zero fee (for transaction creation) (default:") + " " + FormatMoney(CTransaction::nMinTxFee) + ")" + "\n"; + strUsage += " -minrelaytxfee=<amt> " + _("Fees smaller than this are considered zero fee (for relaying) (default:") + " " + FormatMoney(CTransaction::nMinRelayTxFee) + ")" + "\n"; + strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n"; + if (GetBoolArg("-help-debug", false)) { - strUsage += ".\n"; + strUsage += " -printblock=<hash> " + _("Print block on startup, if found in block index") + "\n"; + strUsage += " -printblocktree " + _("Print block tree on startup (default: 0)") + "\n"; + strUsage += " -printpriority " + _("Log transaction priority and fee per kB when mining blocks (default: 0)") + "\n"; + strUsage += " -privdb " + _("Sets the DB_PRIVATE flag in the wallet db environment (default: 1)") + "\n"; + strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n"; + strUsage += " " + _("This is intended for regression testing tools and app development.") + "\n"; + strUsage += " " + _("In this mode -genproclimit controls how many blocks are generated immediately.") + "\n"; } - strUsage += " -logtimestamps " + _("Prepend debug output with timestamp (default: 1)") + "\n"; strUsage += " -shrinkdebugfile " + _("Shrink debug.log file on client startup (default: 1 when no -debug)") + "\n"; - strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n"; - strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n"; - strUsage += " " + _("This is intended for regression testing tools and app development.") + "\n"; - strUsage += " -server " + _("Accept command line and JSON-RPC commands") + "\n"; + strUsage += " -testnet " + _("Use the test network") + "\n"; - if (hmm == HMM_BITCOIND) - { -#if !defined(WIN32) - strUsage += " -daemon " + _("Run in the background as a daemon and accept commands") + "\n"; -#endif - } + strUsage += "\n" + _("Block creation options:") + "\n"; + strUsage += " -blockminsize=<n> " + _("Set minimum block size in bytes (default: 0)") + "\n"; + strUsage += " -blockmaxsize=<n> " + strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE) + "\n"; + strUsage += " -blockprioritysize=<n> " + strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE) + "\n"; + strUsage += "\n" + _("RPC server options:") + "\n"; + strUsage += " -server " + _("Accept command line and JSON-RPC commands") + "\n"; strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n"; strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n"; strUsage += " -rpcport=<port> " + _("Listen for JSON-RPC connections on <port> (default: 8332 or testnet: 18332)") + "\n"; strUsage += " -rpcallowip=<ip> " + _("Allow JSON-RPC connections from specified IP address") + "\n"; strUsage += " -rpcthreads=<n> " + _("Set the number of threads to service RPC calls (default: 4)") + "\n"; - strUsage += " -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n"; - strUsage += " -alertnotify=<cmd> " + _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)") + "\n"; - strUsage += " -keypool=<n> " + _("Set key pool size to <n> (default: 100)") + "\n"; - strUsage += " -checkblocks=<n> " + _("How many blocks to check at startup (default: 288, 0 = all)") + "\n"; - strUsage += " -checklevel=<n> " + _("How thorough the block verification is (0-4, default: 3)") + "\n"; - strUsage += " -txindex " + _("Maintain a full transaction index (default: 0)") + "\n"; - strUsage += " -loadblock=<file> " + _("Imports blocks from external blk000??.dat file") + "\n"; - strUsage += " -reindex " + _("Rebuild block chain index from current blk000??.dat files") + "\n"; - strUsage += " -par=<n> " + _("Set the number of script verification threads (up to 16, 0 = auto, <0 = leave that many cores free, default: 0)") + "\n"; -#ifdef ENABLE_WALLET - strUsage += "\n" + _("Wallet options:") + "\n"; - strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n"; - strUsage += " -paytxfee=<amt> " + _("Fee per kB to add to transactions you send") + "\n"; - strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + "\n"; - strUsage += " -zapwallettxes " + _("Clear list of wallet transactions (diagnostic tool; implies -rescan)") + "\n"; - strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + "\n"; - strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + "\n"; - strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + "\n"; - strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n"; - strUsage += " -spendzeroconfchange " + _("Spend unconfirmed change when sending transactions (default: 1)") + "\n"; -#endif - strUsage += "\n" + _("Block creation options:") + "\n"; - strUsage += " -blockminsize=<n> " + _("Set minimum block size in bytes (default: 0)") + "\n"; - strUsage += " -blockmaxsize=<n> " + strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE) + "\n"; - strUsage += " -blockprioritysize=<n> " + strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE) + "\n"; - strUsage += "\n" + _("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 += " -rpcsslcertificatechainfile=<file.cert> " + _("Server certificate file (default: server.cert)") + "\n"; strUsage += " -rpcsslprivatekeyfile=<file.pem> " + _("Server private key (default: server.pem)") + "\n"; @@ -491,7 +519,7 @@ bool AppInit2(boost::thread_group& threadGroup) Checkpoints::fEnabled = GetBoolArg("-checkpoints", true); // -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency - nScriptCheckThreads = GetArg("-par", 0); + nScriptCheckThreads = GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS); if (nScriptCheckThreads <= 0) nScriptCheckThreads += boost::thread::hardware_concurrency(); if (nScriptCheckThreads <= 1) diff --git a/src/keystore.h b/src/keystore.h index 0d55e6c81e..79d8661aca 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -32,7 +32,7 @@ public: virtual void GetKeys(std::set<CKeyID> &setAddress) const =0; virtual bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const; - // Support for BIP 0013 : see https://en.bitcoin.it/wiki/BIP_0013 + // Support for BIP 0013 : see https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki virtual bool AddCScript(const CScript& redeemScript) =0; virtual bool HaveCScript(const CScriptID &hash) const =0; virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0; diff --git a/src/main.cpp b/src/main.cpp index 836c86483a..12f76cc9ea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3021,7 +3021,7 @@ void PrintBlockTree() // print item CBlock block; ReadBlockFromDisk(block, pindex); - LogPrintf("%d (blk%05u.dat:0x%x) %s tx %"PRIszu"", + LogPrintf("%d (blk%05u.dat:0x%x) %s tx %"PRIszu"\n", pindex->nHeight, pindex->GetBlockPos().nFile, pindex->GetBlockPos().nPos, DateTimeStrFormat("%Y-%m-%d %H:%M:%S", block.GetBlockTime()), diff --git a/src/main.h b/src/main.h index 5ecf9d8365..aff20d0379 100644 --- a/src/main.h +++ b/src/main.h @@ -60,6 +60,8 @@ static const int COINBASE_MATURITY = 100; static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC /** Maximum number of script-checking threads allowed */ static const int MAX_SCRIPTCHECK_THREADS = 16; +/** -par default (number of script-checking threads, 0 = auto) */ +static const int DEFAULT_SCRIPTCHECK_THREADS = 0; /** Number of blocks that can be requested at any given time from a single peer. */ static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 128; /** Timeout in seconds before considering a block download peer unresponsive. */ diff --git a/src/net.cpp b/src/net.cpp index 653f24ec37..657a39bcff 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -27,6 +27,8 @@ #include <miniupnpc/upnperrors.h> #endif +#include <boost/filesystem.hpp> + // Dump addresses to peers.dat every 15 minutes (900s) #define DUMP_ADDRESSES_INTERVAL 900 @@ -1986,9 +1988,9 @@ bool CAddrDB::Read(CAddrMan& addr) return error("CAddrman::Read() : open failed"); // use file size to size memory buffer - int fileSize = GetFilesize(filein); + int fileSize = boost::filesystem::file_size(pathAddr); int dataSize = fileSize - sizeof(uint256); - //Don't try to resize to a negative number if file is small + // Don't try to resize to a negative number if file is small if ( dataSize < 0 ) dataSize = 0; vector<unsigned char> vchData; vchData.resize(dataSize); diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 36b070f1c8..9fbc865185 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -98,13 +98,7 @@ <item> <widget class="QSpinBox" name="threadsScriptVerif"> <property name="toolTip"> - <string>Set the number of script verification threads (up to 16, 0 = auto, <0 = leave that many cores free, default: 0)</string> - </property> - <property name="minimum"> - <number>-16</number> - </property> - <property name="maximum"> - <number>16</number> + <string>(0 = auto, <0 = leave that many cores free)</string> </property> </widget> </item> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 4a4fece3e1..7b264d27c7 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -33,6 +33,9 @@ #include <boost/filesystem.hpp> #include <boost/filesystem/fstream.hpp> +#if BOOST_FILESYSTEM_VERSION >= 3 +#include <boost/filesystem/detail/utf8_codecvt_facet.hpp> +#endif #include <QAbstractItemView> #include <QApplication> @@ -54,6 +57,10 @@ #include <QUrlQuery> #endif +#if BOOST_FILESYSTEM_VERSION >= 3 +static boost::filesystem::detail::utf8_codecvt_facet utf8; +#endif + namespace GUIUtil { QString dateTimeStr(const QDateTime &date) @@ -352,7 +359,7 @@ void openDebugLogfile() /* Open debug.log with the associated application */ if (boost::filesystem::exists(pathDebug)) - QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(pathDebug.string()))); + QDesktopServices::openUrl(QUrl::fromLocalFile(boostPathToQString(pathDebug))); } ToolTipToRichTextFilter::ToolTipToRichTextFilter(int size_threshold, QObject *parent) : @@ -385,14 +392,15 @@ void TableViewLastColumnResizingFixer::connectViewHeadersSignals() connect(tableView->horizontalHeader(), SIGNAL(geometriesChanged()), this, SLOT(on_geometriesChanged())); } -//we need to disconnect these while handling the resize events, otherwise we can enter infinite loops +// We need to disconnect these while handling the resize events, otherwise we can enter infinite loops. void TableViewLastColumnResizingFixer::disconnectViewHeadersSignals() { disconnect(tableView->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(on_sectionResized(int,int,int))); disconnect(tableView->horizontalHeader(), SIGNAL(geometriesChanged()), this, SLOT(on_geometriesChanged())); } -//setup the resize mode, handles compatibility for QT5 and below as the method signatures changed. (refactored here for readability) +// Setup the resize mode, handles compatibility for Qt5 and below as the method signatures changed. +// Refactored here for readability. void TableViewLastColumnResizingFixer::setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode) { #if QT_VERSION < 0x050000 @@ -402,7 +410,8 @@ void TableViewLastColumnResizingFixer::setViewHeaderResizeMode(int logicalIndex, #endif } -void TableViewLastColumnResizingFixer::resizeColumn(int nColumnIndex, int width) { +void TableViewLastColumnResizingFixer::resizeColumn(int nColumnIndex, int width) +{ tableView->setColumnWidth(nColumnIndex, width); tableView->horizontalHeader()->resizeSection(nColumnIndex, width); } @@ -431,7 +440,7 @@ int TableViewLastColumnResizingFixer::getAvailableWidthForColumn(int column) return nResult; } -//make sure we don't make the columns wider than the table's viewport's width. +// Make sure we don't make the columns wider than the tables viewport width. void TableViewLastColumnResizingFixer::adjustTableColumnsWidth() { disconnectViewHeadersSignals(); @@ -446,14 +455,15 @@ void TableViewLastColumnResizingFixer::adjustTableColumnsWidth() } } -//make column use all the space available, useful during window resizing. -void TableViewLastColumnResizingFixer::stretchColumnWidth(int column) { +// Make column use all the space available, useful during window resizing. +void TableViewLastColumnResizingFixer::stretchColumnWidth(int column) +{ disconnectViewHeadersSignals(); resizeColumn(column, getAvailableWidthForColumn(column)); connectViewHeadersSignals(); } -//when a section is resized this is a slot-proxy for ajustAmountColumnWidth() +// When a section is resized this is a slot-proxy for ajustAmountColumnWidth(). void TableViewLastColumnResizingFixer::on_sectionResized(int logicalIndex, int oldSize, int newSize) { adjustTableColumnsWidth(); @@ -464,8 +474,8 @@ void TableViewLastColumnResizingFixer::on_sectionResized(int logicalIndex, int o } } -//when the table's geometry is ready, we manually perform the Stretch of the "Message" column -//as the "Stretch" resize mode does not allow for interactive resizing. +// When the tabless geometry is ready, we manually perform the stretch of the "Message" column, +// as the "Stretch" resize mode does not allow for interactive resizing. void TableViewLastColumnResizingFixer::on_geometriesChanged() { if ((getColumnsWidth() - this->tableView->horizontalHeader()->width()) != 0) @@ -481,9 +491,9 @@ void TableViewLastColumnResizingFixer::on_geometriesChanged() * the resize modes of the last 2 columns of the table and */ TableViewLastColumnResizingFixer::TableViewLastColumnResizingFixer(QTableView* table, int lastColMinimumWidth, int allColsMinimumWidth) : - tableView(table), - lastColumnMinimumWidth(lastColMinimumWidth), - allColumnsMinimumWidth(allColsMinimumWidth) + tableView(table), + lastColumnMinimumWidth(lastColMinimumWidth), + allColumnsMinimumWidth(allColsMinimumWidth) { columnCount = tableView->horizontalHeader()->count(); lastColumnIndex = columnCount - 1; @@ -493,7 +503,6 @@ TableViewLastColumnResizingFixer::TableViewLastColumnResizingFixer(QTableView* t setViewHeaderResizeMode(lastColumnIndex, QHeaderView::Interactive); } - #ifdef WIN32 boost::filesystem::path static StartupShortcutPath() { @@ -718,4 +727,27 @@ void setClipboard(const QString& str) QApplication::clipboard()->setText(str, QClipboard::Selection); } +#if BOOST_FILESYSTEM_VERSION >= 3 +boost::filesystem::path qstringToBoostPath(const QString &path) +{ + return boost::filesystem::path(path.toStdString(), utf8); +} + +QString boostPathToQString(const boost::filesystem::path &path) +{ + return QString::fromStdString(path.string(utf8)); +} +#else +#warning Conversion between boost path and QString can use invalid character encoding with boost_filesystem v2 and older +boost::filesystem::path qstringToBoostPath(const QString &path) +{ + return boost::filesystem::path(path.toStdString()); +} + +QString boostPathToQString(const boost::filesystem::path &path) +{ + return QString::fromStdString(path.string()); +} +#endif + } // namespace GUIUtil diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 26202e8d41..4f9416d1af 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -5,11 +5,13 @@ #ifndef GUIUTIL_H #define GUIUTIL_H +#include <QHeaderView> #include <QMessageBox> #include <QObject> #include <QString> #include <QTableView> -#include <QHeaderView> + +#include <boost/filesystem.hpp> class QValidatedLineEdit; class SendCoinsRecipient; @@ -130,30 +132,31 @@ namespace GUIUtil */ class TableViewLastColumnResizingFixer: public QObject { - Q_OBJECT - public: - TableViewLastColumnResizingFixer(QTableView* table, int lastColMinimumWidth, int allColsMinimumWidth); - void stretchColumnWidth(int column); + Q_OBJECT - private: - QTableView* tableView; - int lastColumnMinimumWidth; - int allColumnsMinimumWidth; - int lastColumnIndex; - int columnCount; - int secondToLastColumnIndex; - - void adjustTableColumnsWidth(); - int getAvailableWidthForColumn(int column); - int getColumnsWidth(); - void connectViewHeadersSignals(); - void disconnectViewHeadersSignals(); - void setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode); - void resizeColumn(int nColumnIndex, int width); - - private slots: - void on_sectionResized(int logicalIndex, int oldSize, int newSize); - void on_geometriesChanged(); + public: + TableViewLastColumnResizingFixer(QTableView* table, int lastColMinimumWidth, int allColsMinimumWidth); + void stretchColumnWidth(int column); + + private: + QTableView* tableView; + int lastColumnMinimumWidth; + int allColumnsMinimumWidth; + int lastColumnIndex; + int columnCount; + int secondToLastColumnIndex; + + void adjustTableColumnsWidth(); + int getAvailableWidthForColumn(int column); + int getColumnsWidth(); + void connectViewHeadersSignals(); + void disconnectViewHeadersSignals(); + void setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode); + void resizeColumn(int nColumnIndex, int width); + + private slots: + void on_sectionResized(int logicalIndex, int oldSize, int newSize); + void on_geometriesChanged(); }; bool GetStartOnSystemStartup(); @@ -164,6 +167,12 @@ namespace GUIUtil /** Restore window size and position */ void restoreWindowGeometry(const QString& strSetting, const QSize &defaultSizeIn, QWidget *parent); + /* Convert QString to OS specific boost path through UTF-8 */ + boost::filesystem::path qstringToBoostPath(const QString &path); + + /* Convert OS specific boost path to QString through UTF-8 */ + QString boostPathToQString(const boost::filesystem::path &path); + } // namespace GUIUtil #endif // GUIUTIL_H diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 3bc19f8645..f342606495 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -5,9 +5,12 @@ #include "intro.h" #include "ui_intro.h" +#include "guiutil.h" + #include "util.h" #include <boost/filesystem.hpp> + #include <QFileDialog> #include <QSettings> #include <QMessageBox> @@ -59,7 +62,7 @@ void FreespaceChecker::check() { namespace fs = boost::filesystem; QString dataDirStr = intro->getPathToCheck(); - fs::path dataDir = fs::path(dataDirStr.toStdString()); + fs::path dataDir = GUIUtil::qstringToBoostPath(dataDirStr); uint64_t freeBytesAvailable = 0; int replyStatus = ST_OK; QString replyMessage = tr("A new data directory will be created."); @@ -143,7 +146,7 @@ void Intro::setDataDirectory(const QString &dataDir) QString Intro::getDefaultDataDirectory() { - return QString::fromStdString(GetDefaultDataDir().string()); + return GUIUtil::boostPathToQString(GetDefaultDataDir()); } void Intro::pickDataDirectory() @@ -159,7 +162,7 @@ void Intro::pickDataDirectory() /* 2) Allow QSettings to override default dir */ dataDir = settings.value("strDataDir", dataDir).toString(); - if(!fs::exists(dataDir.toStdString()) || GetBoolArg("-choosedatadir", false)) + if(!fs::exists(GUIUtil::qstringToBoostPath(dataDir)) || GetBoolArg("-choosedatadir", false)) { /* If current default data directory does not exist, let the user choose one */ Intro intro; @@ -175,7 +178,7 @@ void Intro::pickDataDirectory() } dataDir = intro.getDataDirectory(); try { - fs::create_directory(dataDir.toStdString()); + fs::create_directory(GUIUtil::qstringToBoostPath(dataDir)); break; } catch(fs::filesystem_error &e) { QMessageBox::critical(0, tr("Bitcoin"), @@ -186,7 +189,12 @@ void Intro::pickDataDirectory() settings.setValue("strDataDir", dataDir); } - SoftSetArg("-datadir", dataDir.toStdString()); + /* Only override -datadir if different from the default, to make it possible to + * override -datadir in the bitcoin.conf file in the default data directory + * (to be consistent with bitcoind behavior) + */ + if(dataDir != getDefaultDataDirectory()) + SoftSetArg("-datadir", GUIUtil::qstringToBoostPath(dataDir).string()); // use OS locale for path setting } void Intro::setStatus(int status, const QString &message, quint64 bytesAvailable) diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 9f7c484946..977f7f4da7 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -14,7 +14,7 @@ #include "monitoreddatamapper.h" #include "optionsmodel.h" -#include "main.h" // for CTransaction::nMinTxFee +#include "main.h" // for CTransaction::nMinTxFee and MAX_SCRIPTCHECK_THREADS #include "netbase.h" #include "txdb.h" // for -dbcache defaults @@ -37,6 +37,8 @@ OptionsDialog::OptionsDialog(QWidget *parent) : /* Main elements init */ ui->databaseCache->setMinimum(nMinDbCache); ui->databaseCache->setMaximum(nMaxDbCache); + ui->threadsScriptVerif->setMinimum(-(int)boost::thread::hardware_concurrency()); + ui->threadsScriptVerif->setMaximum(MAX_SCRIPTCHECK_THREADS); /* Network elements init */ #ifndef USE_UPNP diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index b61fdd2301..9abe9351bb 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -76,6 +76,17 @@ void OptionsModel::Init() // by command-line and show this in the UI. // Main + if (!settings.contains("nDatabaseCache")) + settings.setValue("nDatabaseCache", (qint64)nDefaultDbCache); + if (!SoftSetArg("-dbcache", settings.value("nDatabaseCache").toString().toStdString())) + addOverriddenOption("-dbcache"); + + if (!settings.contains("nThreadsScriptVerif")) + settings.setValue("nThreadsScriptVerif", DEFAULT_SCRIPTCHECK_THREADS); + if (!SoftSetArg("-par", settings.value("nThreadsScriptVerif").toString().toStdString())) + addOverriddenOption("-par"); + + // Wallet #ifdef ENABLE_WALLET if (!settings.contains("nTransactionFee")) settings.setValue("nTransactionFee", 0); @@ -89,16 +100,6 @@ void OptionsModel::Init() addOverriddenOption("-spendzeroconfchange"); #endif - if (!settings.contains("nDatabaseCache")) - settings.setValue("nDatabaseCache", (qint64)nDefaultDbCache); - if (!SoftSetArg("-dbcache", settings.value("nDatabaseCache").toString().toStdString())) - addOverriddenOption("-dbcache"); - - if (!settings.contains("nThreadsScriptVerif")) - settings.setValue("nThreadsScriptVerif", 0); - if (!SoftSetArg("-par", settings.value("nThreadsScriptVerif").toString().toStdString())) - addOverriddenOption("-par"); - // Network if (!settings.contains("fUseUPnP")) #ifdef USE_UPNP diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 007b13d648..3ccfb429a6 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -55,8 +55,6 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(QWidget *parent) : connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear())); } - - void ReceiveCoinsDialog::setModel(WalletModel *model) { this->model = model; @@ -79,11 +77,9 @@ void ReceiveCoinsDialog::setModel(WalletModel *model) tableView->setColumnWidth(RecentRequestsTableModel::Label, LABEL_COLUMN_WIDTH); connect(tableView->selectionModel(), - SIGNAL(selectionChanged(QItemSelection, QItemSelection)), - this, + SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(on_recentRequestsView_selectionChanged(QItemSelection, QItemSelection))); - - //(last 2 columns are set when the table geometry is ready) by the columnResizingFixer. + // Last 2 columns are set by the columnResizingFixer, when the table geometry is ready. columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH); } } @@ -202,10 +198,12 @@ void ReceiveCoinsDialog::on_removeRequestButton_clicked() model->getRecentRequestsTableModel()->removeRows(firstIndex.row(), selection.length(), firstIndex.parent()); } -//We override the virtual resizeEvent of the QWidget to adjust tablet's column sizes as the table's width is proportional to the dialog's. -void ReceiveCoinsDialog::resizeEvent(QResizeEvent* event) { - QWidget::resizeEvent(event); - columnResizingFixer->stretchColumnWidth(RecentRequestsTableModel::Message); +// We override the virtual resizeEvent of the QWidget to adjust tables column +// sizes as the tables width is proportional to the dialogs width. +void ReceiveCoinsDialog::resizeEvent(QResizeEvent* event) +{ + QWidget::resizeEvent(event); + columnResizingFixer->stretchColumnWidth(RecentRequestsTableModel::Message); } void ReceiveCoinsDialog::keyPressEvent(QKeyEvent *event) diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h index 1d051d9324..ab63331597 100644 --- a/src/qt/receivecoinsdialog.h +++ b/src/qt/receivecoinsdialog.h @@ -6,12 +6,13 @@ #define RECEIVECOINSDIALOG_H #include <QDialog> +#include <QHeaderView> +#include <QItemSelection> #include <QKeyEvent> #include <QMenu> #include <QPoint> #include <QVariant> -#include <QHeaderView> -#include <QItemSelection> + #include "guiutil.h" namespace Ui { @@ -31,16 +32,16 @@ class ReceiveCoinsDialog : public QDialog public: enum ColumnWidths { - DATE_COLUMN_WIDTH = 130, - LABEL_COLUMN_WIDTH = 120, - AMOUNT_MINIMUM_COLUMN_WIDTH = 160, - MINIMUM_COLUMN_WIDTH = 130 + DATE_COLUMN_WIDTH = 130, + LABEL_COLUMN_WIDTH = 120, + AMOUNT_MINIMUM_COLUMN_WIDTH = 160, + MINIMUM_COLUMN_WIDTH = 130 }; explicit ReceiveCoinsDialog(QWidget *parent = 0); ~ReceiveCoinsDialog(); - void setModel(WalletModel *model); + void setModel(WalletModel *model); public slots: void clear(); diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index d178efe8d5..a363150919 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -438,8 +438,10 @@ void TransactionView::focusTransaction(const QModelIndex &idx) transactionView->setFocus(); } -//We override the virtual resizeEvent of the QWidget to adjust tablet's column sizes as the table's width is proportional to the dialog's. -void TransactionView::resizeEvent(QResizeEvent* event) { - QWidget::resizeEvent(event); - columnResizingFixer->stretchColumnWidth(TransactionTableModel::ToAddress); +// We override the virtual resizeEvent of the QWidget to adjust tables column +// sizes as the tables width is proportional to the dialogs width. +void TransactionView::resizeEvent(QResizeEvent* event) +{ + QWidget::resizeEvent(event); + columnResizingFixer->stretchColumnWidth(TransactionTableModel::ToAddress); } diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h index fe8e205d6c..ef4f9d6f34 100644 --- a/src/qt/transactionview.h +++ b/src/qt/transactionview.h @@ -5,9 +5,10 @@ #ifndef TRANSACTIONVIEW_H #define TRANSACTIONVIEW_H -#include <QWidget> #include "guiutil.h" +#include <QWidget> + class TransactionFilterProxy; class WalletModel; @@ -46,11 +47,11 @@ public: }; enum ColumnWidths { - STATUS_COLUMN_WIDTH = 23, - DATE_COLUMN_WIDTH = 120, - TYPE_COLUMN_WIDTH = 120, - AMOUNT_MINIMUM_COLUMN_WIDTH = 120, - MINIMUM_COLUMN_WIDTH = 23 + STATUS_COLUMN_WIDTH = 23, + DATE_COLUMN_WIDTH = 120, + TYPE_COLUMN_WIDTH = 120, + AMOUNT_MINIMUM_COLUMN_WIDTH = 120, + MINIMUM_COLUMN_WIDTH = 23 }; private: diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 24992db465..01b710e876 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -38,9 +38,9 @@ void AboutDialog::setModel(ClientModel *model) * 32 and 64 bit builds. On other architectures, 32/64 bit may be more ambigious. */ #if defined(__x86_64__) - version += tr(" (%1-bit)").arg(64); + version += " " + tr("(%1-bit)").arg(64); #elif defined(__i386__ ) - version += tr(" (%1-bit)").arg(32); + version += " " + tr("(%1-bit)").arg(32); #endif ui->versionLabel->setText(version); } @@ -72,10 +72,11 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent) : coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT)); uiOptions = tr("UI options") + ":\n" + - " -lang=<lang> " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" + - " -min " + tr("Start minimized") + "\n" + - " -splash " + tr("Show splash screen on startup (default: 1)") + "\n" + - " -choosedatadir " + tr("Choose data directory on startup (default: 0)"); + " -choosedatadir " + tr("Choose data directory on startup (default: 0)") + "\n" + + " -lang=<lang> " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" + + " -min " + tr("Start minimized") + "\n" + + " -rootcertificates=<file> " + tr("Set SSL root certificates for payment request (default: -system-)") + "\n" + + " -splash " + tr("Show splash screen on startup (default: 1)"); ui->helpMessageLabel->setFont(GUIUtil::bitcoinAddressFont()); diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index efb1fa1183..8620a87297 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -265,11 +265,12 @@ std::string HelpMessageCli(bool mainProgram) strUsage += " -rpcconnect=<ip> " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n"; strUsage += " -rpcport=<port> " + _("Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332)") + "\n"; strUsage += " -rpcwait " + _("Wait for RPC server to start") + "\n"; - strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n"; - strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n"; if(mainProgram) { + strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n"; + strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n"; + strUsage += "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n"; strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n"; } diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index efe4f54b0e..3fe328772a 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -138,8 +138,7 @@ Value getpeerinfo(const Array& params, bool fHelp) if (fStateStats) { obj.push_back(Pair("banscore", statestats.nMisbehavior)); } - if (stats.fSyncNode) - obj.push_back(Pair("syncnode", true)); + obj.push_back(Pair("syncnode", stats.fSyncNode)); ret.push_back(obj); } diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp index 13028fdc77..652b14d187 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -221,7 +221,7 @@ int ReadHTTPMessage(std::basic_istream<char>& stream, map<string, // unspecified (HTTP errors and contents of 'error'). // // 1.0 spec: http://json-rpc.org/wiki/specification -// 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http +// 1.2 spec: http://jsonrpc.org/historical/json-rpc-over-http.html // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx // diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h index 80cdb34f15..8b3df19621 100644 --- a/src/rpcprotocol.h +++ b/src/rpcprotocol.h @@ -49,6 +49,9 @@ enum RPCErrorCode RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter RPC_DATABASE_ERROR = -20, // Database error RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format + RPC_TRANSACTION_ERROR = -25, // General error during transaction submission + RPC_TRANSACTION_REJECTED = -26, // Transaction was rejected by network rules + RPC_TRANSACTION_ALREADY_IN_CHAIN= -27, // Transaction already in chain // P2P client errors RPC_CLIENT_NOT_CONNECTED = -9, // Bitcoin is not connected diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 837aee7eaa..f0267cf8ab 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -777,25 +777,23 @@ Value sendrawtransaction(const Array& params, bool fHelp) } uint256 hashTx = tx.GetHash(); - bool fHave = false; CCoinsViewCache &view = *pcoinsTip; CCoins existingCoins; - { - fHave = view.GetCoins(hashTx, existingCoins); - if (!fHave) { - // push to local node - CValidationState state; - if (!AcceptToMemoryPool(mempool, state, tx, false, NULL, !fOverrideFees)) - throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected"); // TODO: report validation state + bool fHaveMempool = mempool.exists(hashTx); + bool fHaveChain = view.GetCoins(hashTx, existingCoins) && existingCoins.nHeight < 1000000000; + if (!fHaveMempool && !fHaveChain) { + // push to local node and sync with wallets + CValidationState state; + if (AcceptToMemoryPool(mempool, state, tx, false, NULL, !fOverrideFees)) + SyncWithWallets(hashTx, tx, NULL); + else { + if(state.IsInvalid()) + throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason())); + else + throw JSONRPCError(RPC_TRANSACTION_ERROR, state.GetRejectReason()); } - } - if (fHave) { - if (existingCoins.nHeight < 1000000000) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "transaction already in block chain"); - // Not in block, but already in the memory pool; will drop - // through to re-relay it. - } else { - SyncWithWallets(hashTx, tx, NULL); + } else if (fHaveChain) { + throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain"); } RelayTransaction(tx, hashTx); diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 2c0cdd345f..7ad73836a7 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -732,7 +732,7 @@ static string JSONRPCExecBatch(const Array& vReq) void ServiceConnection(AcceptedConnection *conn) { bool fRun = true; - while (fRun) + while (fRun && !ShutdownRequested()) { int nProto = 0; map<string, string> mapHeaders; diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index c8b2127264..a5a7df0867 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -1918,6 +1918,3 @@ Value getwalletinfo(const Array& params, bool fHelp) obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime)); return obj; } - - - diff --git a/src/test/bignum_tests.cpp b/src/test/bignum_tests.cpp index 6587389a07..d5ee8c9778 100644 --- a/src/test/bignum_tests.cpp +++ b/src/test/bignum_tests.cpp @@ -39,11 +39,8 @@ BOOST_AUTO_TEST_SUITE(bignum_tests) // stack buffer overruns. // // For more accurate diagnostics, you can use an undefined arithmetic operation -// detector such as the clang-based tool: -// -// "IOC: An Integer Overflow Checker for C/C++" -// -// Available at: http://embed.cs.utah.edu/ioc/ +// detector such as the clang's undefined behaviour checker. +// See also: http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation // // It might also be useful to use Google's AddressSanitizer to detect // stack buffer overruns, which valgrind can't currently detect. diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 7d38700736..4321852d11 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -93,7 +93,7 @@ BOOST_AUTO_TEST_CASE(netbase_lookupnumeric) BOOST_AUTO_TEST_CASE(onioncat_test) { - // values from http://www.cypherpunk.at/onioncat/wiki/OnionCat + // values from https://web.archive.org/web/20121122003543/http://www.cypherpunk.at/onioncat/wiki/OnionCat CNetAddr addr1("5wyqrzbvrdsumnok.onion"); CNetAddr addr2("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca"); BOOST_CHECK(addr1 == addr2); diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 3b75aad14b..2d993e24db 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -84,3 +84,8 @@ void StartShutdown() exit(0); } +bool ShutdownRequested() +{ + return false; +} + diff --git a/src/util.cpp b/src/util.cpp index 36dfd8ab79..b90921ab83 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1107,16 +1107,6 @@ void FileCommit(FILE *fileout) #endif } -int GetFilesize(FILE* file) -{ - int nSavePos = ftell(file); - int nFilesize = -1; - if (fseek(file, 0, SEEK_END) == 0) - nFilesize = ftell(file); - fseek(file, nSavePos, SEEK_SET); - return nFilesize; -} - bool TruncateFile(FILE *file, unsigned int length) { #if defined(WIN32) return _chsize(_fileno(file), length) == 0; @@ -1195,7 +1185,7 @@ void ShrinkDebugFile() // Scroll debug.log if it's getting too big boost::filesystem::path pathLog = GetDataDir() / "debug.log"; FILE* file = fopen(pathLog.string().c_str(), "r"); - if (file && GetFilesize(file) > 10 * 1000000) + if (file && boost::filesystem::file_size(pathLog) > 10 * 1000000) { // Restart the file with some of the end char pch[200000]; @@ -1214,13 +1204,6 @@ void ShrinkDebugFile() fclose(file); } - - - - - - - // // "Never go to sea with two chronometers; take one or three." // Our three time sources are: diff --git a/src/util.h b/src/util.h index 32bc050369..b0dabd2f67 100644 --- a/src/util.h +++ b/src/util.h @@ -185,7 +185,6 @@ void ParseParameters(int argc, const char*const argv[]); bool WildcardMatch(const char* psz, const char* mask); bool WildcardMatch(const std::string& str, const std::string& mask); void FileCommit(FILE *fileout); -int GetFilesize(FILE* file); bool TruncateFile(FILE *file, unsigned int length); int RaiseFileDescriptorLimit(int nMinFD); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); diff --git a/src/wallet.h b/src/wallet.h index e2e89fffe7..487c258a20 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -620,9 +620,10 @@ public: return nAvailableCreditCached; int64_t nCredit = 0; + uint256 hashTx = GetHash(); for (unsigned int i = 0; i < vout.size(); i++) { - if (!pwallet->IsSpent(GetHash(), i)) + if (!pwallet->IsSpent(hashTx, i)) { const CTxOut &txout = vout[i]; nCredit += pwallet->GetCredit(txout); |