diff options
112 files changed, 765 insertions, 605 deletions
diff --git a/Makefile.am b/Makefile.am index 2f478e4b4..ab68d8fa6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -202,6 +202,8 @@ check-local: @qa/pull-tester/run-bitcoind-for-test.sh $(JAVA) -jar $(JAVA_COMPARISON_TOOL) qa/tmp/compTool $(COMPARISON_TOOL_REORG_TESTS) 2>&1 endif +dist_noinst_SCRIPTS = autogen.sh + EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.sh qa/pull-tester/run-bitcoin-cli qa/rpc-tests $(DIST_DOCS) $(WINDOWS_PACKAGING) $(OSX_PACKAGING) CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER) diff --git a/configure.ac b/configure.ac index 8a54c2f76..7f90b5f39 100644 --- a/configure.ac +++ b/configure.ac @@ -147,12 +147,13 @@ AC_ARG_ENABLE([debug], [enable_debug=no]) if test "x$enable_debug" = xyes; then + CPPFLAGS="$CPPFLAGS -DDEBUG -DDEBUG_LOCKORDER" if test "x$GCC" = xyes; then - CFLAGS="-g3 -O0 -DDEBUG" + CFLAGS="$CFLAGS -g3 -O0" fi if test "x$GXX" = xyes; then - CXXFLAGS="-g3 -O0 -DDEBUG" + CXXFLAGS="$CXXFLAGS -g3 -O0" fi fi diff --git a/contrib/gitian-downloader/centaur1-key.pgp b/contrib/gitian-downloader/centaur1-key.pgp new file mode 100644 index 000000000..71a42e514 --- /dev/null +++ b/contrib/gitian-downloader/centaur1-key.pgp @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.12 (GNU/Linux) + +mQENBFTjy20BCAC7q/tpPQ9tdEALpDqe8kpVAT5ysOJDLDeFEE1J5O8NuDFuibiN +XYkb2nAt4Vdr23in9z0LAiTSgr7znndnab/rOSn6pXbXQfLTHrSnAeClTHVQVPSq +m5kNg1vWvNxFtIpZ/fGsc6LLmIHxdgeLn+NOpvNx7RzF/N5ctX51vMxMUeDq3daZ +tLneJVRj5tXHRJcjW62cyiNFasYAZ3JC8wjwzr0SOndc7kygbEVCTWNkTAGd1Lax +KSJW6TjhBPK7j+RljS5nfx/Tf+OG4AoA7/53593YL7Shfx8rwWVIeF4nS6efFnuf +eIj+aS5haGyFvNgw8DE7QUCrPiUxeA8wuXu7ABEBAAG0H2NlbnRhdXIgPGNlbnRh +dXJAcGhvbmVib29rLmNvbT6JATgEEwECACIFAlTjy20CGwMGCwkIBwMCBhUIAgkK +CwQWAgMBAh4BAheAAAoJEP+V+qlxaXQF8r4IAKnE8D9AOTdM/YvYxpCeI6ndEUUs +8NcotpbIBJ67vr1Dsot7Ee0PrmIYOiInA+T81lPUDecJYrnemVefhquiyJ5VJ4/d +z2zUKBfxjeOsj/PHgcowVxMco8fNEWQa2fZX6X8RVADIsUnIIwpRFVUcbssK/3xJ +k46vjWwYNQywht/ZgFBesOgywyz5GozmwrK6TixJxKk8M69GFz2fHhJjp1bxDZuk +Rs3YmWeOcCasoJ6GbvIboKQSPHGyEOCqIuiBL63YMa0n1FU0ooDteNZ04eRinIhc +fo9JC66fQrUFn8CmmRTtdZOrZ/efYjQtfLAunCkzSM3p6DE9u4Y7d8E5Ar65AQ0E +VOPLbQEIANhxtouZuQmw+k89toBWXw75s+csxKHKZuhw8QntaFyFYq3IOnIeV1sK +PRENkWsqDInjEM8k9eZ6pnS11EQ1rrFffss+mprTbL3I4S489tJETYZKHrmmox7h +ustRi5eXBEmGeKW0mqpb/9r4okpTaIfs+EJ4C9jj0ghWkqU0acyzanJiUY/0R46F +vPfGfHnhZ5TAl3eiL0H2JkF6taG8K1XOLemahdZHE9wJh0ZFWnDDkA1l6j2rtYga +jEi/ucOp5GkmumxbFiVgponDBqBpsscRrCV6SbZs9gz3dQNgqe5A3CKGZRuVCY6s +djRJelgqCF5+dV0fAT0oF3C/3E5KAgcAEQEAAYkBHwQYAQIACQUCVOPLbQIbDAAK +CRD/lfqpcWl0BUSxCACjEFwQSHcfZINWD+KdNMayxyHQlBwsEDX+xQkgnn+/Q3hW +9VI3SSSfFV3ustlUa3IaNHwuWzsrSqG6mLG47LAQ6vPAWVh723gVCpyJf42Oms/e +qeyn0f/PT/6RuNMXQeHbfddmRp4PFjyKOms5Bmf3oi4t4JSvOS4yABBBKzhDQYC9 +e+qv6Y1sDYpSiCxstQLzIHKiB5bfZ8Szfk09EyyLdqLGkiB0MFhHoXWwQxKiLVc+ +xNFj2a/jw0rQVgN5DZgHBWU5WqvS5CWIczi+2S9MFI26iBhCn3urZToaaQ/DObqC +qmekFrJ/GOj5vB1Mm014lWjG2X3EovLZ1XkgWI7W +=vtNZ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/contrib/linearize/README.md b/contrib/linearize/README.md index 157586e4d..06f278f3b 100644 --- a/contrib/linearize/README.md +++ b/contrib/linearize/README.md @@ -3,7 +3,7 @@ Construct a linear, no-fork, best version of the blockchain. ## Step 1: Download hash list - $ ./linearize-hashes.py linearize.cfg > hashlist.txt + $ ./linearize-hashes.py linearize.cfg > hashlist.txt Required configuration file settings for linearize-hashes: * RPC: rpcuser, rpcpassword @@ -14,7 +14,7 @@ Optional config file setting for linearize-hashes: ## Step 2: Copy local block data - $ ./linearize-data.py linearize.cfg + $ ./linearize-data.py linearize.cfg Required configuration file settings: * "input": bitcoind blocks/ directory containing blkNNNNN.dat @@ -26,7 +26,7 @@ output. Optional config file setting for linearize-data: * "netmagic": network magic number -* "max_out_sz": maximum output file size (default 1000*1000*1000) +* "max_out_sz": maximum output file size (default `1000*1000*1000`) * "split_timestamp": Split files when a new month is first seen, in addition to reaching a maximum file size. * "file_timestamp": Set each file's last-modified time to that of the diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py index 7947c6bf7..0f6fde2a6 100755 --- a/contrib/linearize/linearize-data.py +++ b/contrib/linearize/linearize-data.py @@ -12,6 +12,7 @@ import json import struct import re import os +import os.path import base64 import httplib import sys @@ -115,19 +116,20 @@ class BlockDataCopier: self.setFileTime = True if settings['split_timestamp'] != 0: self.timestampSplit = True - # Extents and cache for out-of-order blocks + # Extents and cache for out-of-order blocks self.blockExtents = {} self.outOfOrderData = {} self.outOfOrderSize = 0 # running total size for items in outOfOrderData def writeBlock(self, inhdr, blk_hdr, rawblock): - if not self.fileOutput and ((self.outsz + self.inLen) > self.maxOutSz): + blockSizeOnDisk = len(inhdr) + len(blk_hdr) + len(rawblock) + if not self.fileOutput and ((self.outsz + blockSizeOnDisk) > self.maxOutSz): self.outF.close() if self.setFileTime: os.utime(outFname, (int(time.time()), highTS)) self.outF = None self.outFname = None - self.outFn = outFn + 1 + self.outFn = self.outFn + 1 self.outsz = 0 (blkDate, blkTS) = get_blk_dt(blk_hdr) @@ -147,7 +149,7 @@ class BlockDataCopier: if self.fileOutput: outFname = self.settings['output_file'] else: - outFname = "%s/blk%05d.dat" % (self.settings['output'], outFn) + outFname = os.path.join(self.settings['output'], "blk%05d.dat" % self.outFn) print("Output file " + outFname) self.outF = open(outFname, "wb") @@ -165,7 +167,7 @@ class BlockDataCopier: (self.blkCountIn, self.blkCountOut, len(self.blkindex), 100.0 * self.blkCountOut / len(self.blkindex))) def inFileName(self, fn): - return "%s/blk%05d.dat" % (self.settings['input'], fn) + return os.path.join(self.settings['input'], "blk%05d.dat" % fn) def fetchBlock(self, extent): '''Fetch block contents from disk given extents''' diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index e7aa48ddf..d27a70134 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -1,9 +1,8 @@ package=boost -$(package)_version=1_55_0 -$(package)_download_path=http://sourceforge.net/projects/boost/files/boost/1.55.0 +$(package)_version=1_58_0 +$(package)_download_path=http://sourceforge.net/projects/boost/files/boost/1.58.0 $(package)_file_name=$(package)_$($(package)_version).tar.bz2 -$(package)_sha256_hash=fff00023dd79486d444c8e29922f4072e1d451fc5a4d2b6075852ead7f2b7b52 -$(package)_patches=darwin_boost_atomic-1.patch darwin_boost_atomic-2.patch gcc_5_no_cxx11.patch +$(package)_sha256_hash=fdfc204fc33ec79c99b9a74944c3e54bd78be4f7f15e260c0e2700a36dc7d3e5 define $(package)_set_vars $(package)_config_opts_release=variant=release @@ -26,9 +25,6 @@ $(package)_cxxflags_linux=-fPIC endef define $(package)_preprocess_cmds - patch -p2 < $($(package)_patch_dir)/darwin_boost_atomic-1.patch && \ - patch -p2 < $($(package)_patch_dir)/darwin_boost_atomic-2.patch && \ - patch -p2 < $($(package)_patch_dir)/gcc_5_no_cxx11.patch && \ echo "using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : <cxxflags>\"$($(package)_cxxflags) $($(package)_cppflags)\" <linkflags>\"$($(package)_ldflags)\" <archiver>\"$(boost_archiver_$(host_os))\" <striper>\"$(host_STRIP)\" <ranlib>\"$(host_RANLIB)\" <rc>\"$(host_WINDRES)\" : ;" > user-config.jam endef diff --git a/depends/packages/miniupnpc.mk b/depends/packages/miniupnpc.mk index 00101f1b9..e6573986f 100644 --- a/depends/packages/miniupnpc.mk +++ b/depends/packages/miniupnpc.mk @@ -1,8 +1,8 @@ package=miniupnpc -$(package)_version=1.9.20140701 +$(package)_version=1.9.20150609 $(package)_download_path=http://miniupnp.free.fr/files $(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=26f3985bad7768b8483b793448ae49414cdc4451d0ec83e7c1944367e15f9f07 +$(package)_sha256_hash=86e6ccec5b660ba6889893d1f3fca21db087c6466b1a90f495a1f87ab1cd1c36 define $(package)_set_vars $(package)_build_opts=CC="$($(package)_cc)" diff --git a/depends/packages/native_ccache.mk b/depends/packages/native_ccache.mk index 3226e89a6..745d7a398 100644 --- a/depends/packages/native_ccache.mk +++ b/depends/packages/native_ccache.mk @@ -1,8 +1,8 @@ package=native_ccache -$(package)_version=3.1.9 +$(package)_version=3.2.2 $(package)_download_path=http://samba.org/ftp/ccache $(package)_file_name=ccache-$($(package)_version).tar.bz2 -$(package)_sha256_hash=04d3e2e438ac8d4cc4b110b68cdd61bd59226c6588739a4a386869467f5ced7c +$(package)_sha256_hash=440f5e15141cc72d2bfff467c977020979810eb800882e3437ad1a7153cce7b2 define $(package)_set_vars $(package)_config_opts= diff --git a/depends/packages/native_protobuf.mk b/depends/packages/native_protobuf.mk index ed1a771f0..ce50b366f 100644 --- a/depends/packages/native_protobuf.mk +++ b/depends/packages/native_protobuf.mk @@ -1,8 +1,8 @@ package=native_protobuf -$(package)_version=2.5.0 -$(package)_download_path=https://protobuf.googlecode.com/files +$(package)_version=2.6.1 +$(package)_download_path=https://github.com/google/protobuf/releases/download/v$($(package)_version) $(package)_file_name=protobuf-$($(package)_version).tar.bz2 -$(package)_sha256_hash=13bfc5ae543cf3aa180ac2485c0bc89495e3ae711fc6fab4f8ffe90dfb4bb677 +$(package)_sha256_hash=ee445612d544d885ae240ffbcbf9267faa9f593b7b101f21d58beceb92661910 define $(package)_set_vars $(package)_config_opts=--disable-shared diff --git a/depends/packages/qrencode.mk b/depends/packages/qrencode.mk index 1ad329e94..7b2124713 100644 --- a/depends/packages/qrencode.mk +++ b/depends/packages/qrencode.mk @@ -1,8 +1,8 @@ package=qrencode -$(package)_version=3.4.3 +$(package)_version=3.4.4 $(package)_download_path=https://fukuchi.org/works/qrencode/ $(package)_file_name=qrencode-$(qrencode_version).tar.bz2 -$(package)_sha256_hash=dfd71487513c871bad485806bfd1fdb304dedc84d2b01a8fb8e0940b50597a98 +$(package)_sha256_hash=efe5188b1ddbcbf98763b819b146be6a90481aac30cfc8d858ab78a19cde1fa5 define $(package)_set_vars $(package)_config_opts=--disable-shared -without-tools --disable-sdltest diff --git a/doc/README.md b/doc/README.md index ecddf50d4..7b0c39d38 100644 --- a/doc/README.md +++ b/doc/README.md @@ -58,6 +58,7 @@ The Bitcoin repo's [root README](https://github.com/bitcoin/bitcoin/blob/master/ - [Translation Strings Policy](translation_strings_policy.md) - [Unit Tests](unit-tests.md) - [Unauthenticated REST Interface](REST-interface.md) +- [Shared Libraries](shared-libraries.md) - [BIPS](bips.md) - [Dnsseed Policy](dnsseed-policy.md) diff --git a/doc/REST-interface.md b/doc/REST-interface.md index 1ba01362d..ac7cd45f7 100644 --- a/doc/REST-interface.md +++ b/doc/REST-interface.md @@ -9,8 +9,7 @@ Supported API ####Transactions `GET /rest/tx/<TX-HASH>.<bin|hex|json>` -Given a transaction hash, -Returns a transaction, in binary, hex-encoded binary or JSON formats. +Given a transaction hash: returns a transaction in binary, hex-encoded binary, or JSON formats. For full TX query capability, one must enable the transaction index via "txindex=1" command line / configuration option. @@ -18,8 +17,7 @@ For full TX query capability, one must enable the transaction index via "txindex `GET /rest/block/<BLOCK-HASH>.<bin|hex|json>` `GET /rest/block/notxdetails/<BLOCK-HASH>.<bin|hex|json>` -Given a block hash, -Returns a block, in binary, hex-encoded binary or JSON formats. +Given a block hash: returns a block, in binary, hex-encoded binary or JSON formats. The HTTP request and response are both handled entirely in-memory, thus making maximum memory usage at least 2.66MB (1 MB max block, plus hex encoding) per request. @@ -28,8 +26,7 @@ With the /notxdetails/ option JSON response will only contain the transaction ha ####Blockheaders `GET /rest/headers/<COUNT>/<BLOCK-HASH>.<bin|hex|json>` -Given a block hash, -Returns <COUNT> amount of blockheaders in upward direction. +Given a block hash: returns <COUNT> amount of blockheaders in upward direction. ####Chaininfos `GET /rest/chaininfo.json` @@ -43,6 +40,9 @@ Only supports JSON as output format. * difficulty : (numeric) the current difficulty * verificationprogress : (numeric) estimate of verification progress [0..1] * chainwork : (string) total amount of work in active chain, in hexadecimal +* pruned : (boolean) if the blocks are subject to pruning +* pruneheight : (numeric) heighest block available +* softforks : (array) status of softforks in progress ####Query UTXO set `GET /rest/getutxos/<checkmempool>/<txid>-<n>/<txid>-<n>/.../<txid>-<n>.<bin|hex|json>` @@ -79,4 +79,4 @@ $ curl localhost:18332/rest/getutxos/checkmempool/b2cdfd7b89def827ff8af7cd9bff76 Risks ------------- -Running a webbrowser on the same node with a REST enabled bitcoind can be a risk. Accessing prepared XSS websites could read out tx/block data of your node by placing links like `<script src="http://127.0.0.1:8332/rest/tx/1234567890.json">` which might break the nodes privacy. +Running a web browser on the same node with a REST enabled bitcoind can be a risk. Accessing prepared XSS websites could read out tx/block data of your node by placing links like `<script src="http://127.0.0.1:8332/rest/tx/1234567890.json">` which might break the nodes privacy. diff --git a/doc/build-unix.md b/doc/build-unix.md index f70bf7f1f..92aed7725 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -59,7 +59,7 @@ Build requirements: sudo apt-get install build-essential libtool autotools-dev autoconf pkg-config libssl-dev -for Ubuntu 12.04 and later or Debian 7 and later libboost-all-dev has to be installed: +For Ubuntu 12.04 and later or Debian 7 and later libboost-all-dev has to be installed: sudo apt-get install libboost-all-dev @@ -72,18 +72,7 @@ for Ubuntu 12.04 and later or Debian 7 and later libboost-all-dev has to be inst Ubuntu 12.04 and later have packages for libdb5.1-dev and libdb5.1++-dev, but using these will break binary wallet compatibility, and is not recommended. -for Debian 7 (Wheezy) and later: - The oldstable repository contains db4.8 packages. - Add the following line to /etc/apt/sources.list, - replacing [mirror] with any official debian mirror. - - deb http://[mirror]/debian/ oldstable main - -To enable the change run - - sudo apt-get update - -for other Debian & Ubuntu (with ppa): +For other Debian & Ubuntu (with ppa): sudo apt-get install libdb4.8-dev libdb4.8++-dev diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 1fa5b5f98..630b3c04a 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -74,7 +74,7 @@ In the VirtualBox GUI click "Create" and choose the following parameters in the - Disk size: at least 40GB; as low as 20GB *may* be possible, but better to err on the safe side - Push the `Create` button -Get the [Debian 7.8 net installer](http://cdimage.debian.org/debian-cd/7.8.0/amd64/iso-cd/debian-7.8.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)). +Get the [Debian 7.8 net installer](http://cdimage.debian.org/cdimage/archive/7.8.0/amd64/iso-cd/debian-7.8.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)). This DVD image can be validated using a SHA256 hashing tool, for example on Unixy OSes by entering the following in a terminal: diff --git a/doc/release-notes.md b/doc/release-notes.md index 6bb8587d7..d5ac70380 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,6 +4,21 @@ release-notes at release time) Notable changes =============== +Random-cookie RPC authentication +--------------------------------- + +When no `-rpcpassword` is specified, the daemon now uses a special 'cookie' +file for authentication. This file is generated with random content when the +daemon starts, and deleted when it exits. Its contents are used as +authentication token. Read access to this file controls who can access through +RPC. By default it is stored in the data directory but its location can be +overridden with the option `-rpccookiefile`. + +This is similar to Tor's CookieAuthentication: see +https://www.torproject.org/docs/tor-manual.html.en + +This allows running bitcoind without having to do any manual configuration. + Example header ---------------------- diff --git a/doc/shared-libraries.md b/doc/shared-libraries.md new file mode 100644 index 000000000..1fc32112c --- /dev/null +++ b/doc/shared-libraries.md @@ -0,0 +1,42 @@ +Shared Libraries +================ + +## bitcoinconsensus + +The purpose of this library is to make the verification functionality that is critical to Bitcoin's consensus available to other applications, e.g. to language bindings. + +### API + +The interface is defined in the C header `bitcoinconsensus.h` located in `src/script/bitcoinconsensus.h`. + +#### Version + +`bitcoinconsensus_version` returns an `unsigned int` with the the API version *(currently at an experimental `0`)*. + +#### Script Validation + +`bitcoinconsensus_verify_script` returns an `int` with the status of the verification. It will be `1` if the input script correctly spends the previous output `scriptPubKey`. + +##### Parameters +- `const unsigned char *scriptPubKey` - The previous output script that encumbers spending. +- `unsigned int scriptPubKeyLen` - The number of bytes for the `scriptPubKey`. +- `const unsigned char *txTo` - The transaction with the input that is spending the previous output. +- `unsigned int txToLen` - The number of bytes for the `txTo`. +- `unsigned int nIn` - The index of the input in `txTo` that spends the `scriptPubKey`. +- `unsigned int flags` - The script validation flags *(see below)*. +- `bitcoinconsensus_error* err` - Will have the error/success code for the operation *(see below)*. + +##### Script Flags +- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NONE` +- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH` - Evaluate P2SH ([BIP16](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki)) subscripts +- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG` - Enforce strict DER ([BIP66](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki)) compliance + +##### Errors +- `bitcoinconsensus_ERR_OK` - No errors with input parameters *(see the return value of `bitcoinconsensus_verify_script` for the verification status)* +- `bitcoinconsensus_ERR_TX_INDEX` - An invalid index for `txTo` +- `bitcoinconsensus_ERR_TX_SIZE_MISMATCH` - `txToLen` did not match with the size of `txTo` +- `bitcoinconsensus_ERR_DESERIALIZE` - An error deserializing `txTo` + +### Example Implementations +- [NBitcoin](https://github.com/NicolasDorier/NBitcoin/blob/master/NBitcoin/Script.cs#L814) (.NET Bindings) +- [node-libbitcoinconsensus](https://github.com/bitpay/node-libbitcoinconsensus) (Node.js Bindings) diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index b28208239..72a282bc0 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -19,10 +19,8 @@ testScripts=( 'wallet.py' 'listtransactions.py' 'mempool_resurrect_test.py' - 'txn_doublespend.py' 'txn_doublespend.py --mineblock' 'txn_clone.py' - 'txn_clone.py --mineblock' 'getchaintips.py' 'rawtransactions.py' 'rest.py' @@ -44,6 +42,8 @@ testScriptsExt=( 'bipdersig.py' 'getblocktemplate_longpoll.py' 'getblocktemplate_proposals.py' + 'txn_doublespend.py' + 'txn_clone.py --mineblock' 'pruning.py' 'forknotify.py' 'invalidateblock.py' @@ -54,7 +54,6 @@ testScriptsExt=( 'smartfees.py' 'maxblocksinflight.py' 'invalidblockrequest.py' - 'rawtransactions.py' # 'forknotify.py' 'p2p-acceptblock.py' ); diff --git a/qa/rpc-tests/README.md b/qa/rpc-tests/README.md index efc81e7a9..cfda8fe91 100644 --- a/qa/rpc-tests/README.md +++ b/qa/rpc-tests/README.md @@ -12,10 +12,6 @@ Base class for new regression tests. ### [test_framework/util.py](test_framework/util.py) Generally useful functions. -Bash-based tests, to be ported to Python: ------------------------------------------ -- conflictedbalance.sh : More testing of malleable transaction handling - Notes ===== diff --git a/qa/rpc-tests/conflictedbalance.sh b/qa/rpc-tests/conflictedbalance.sh deleted file mode 100755 index 7e4409737..000000000 --- a/qa/rpc-tests/conflictedbalance.sh +++ /dev/null @@ -1,147 +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 marking of spent outputs - -# Create a transaction graph with four transactions, -# A/B/C/D -# C spends A -# D spends B and C - -# Then simulate C being mutated, to create C' -# that is mined. -# A is still (correctly) considered spent. -# B should be treated as unspent - -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) - -# Two nodes; one will play the part of merchant, the -# other an evil transaction-mutating miner. - -D1=${D}/node1 -CreateDataDir $D1 port=11000 rpcport=11001 -B1ARGS="-datadir=$D1 -debug=mempool" -$BITCOIND $B1ARGS & -B1PID=$! - -D2=${D}/node2 -CreateDataDir $D2 port=11010 rpcport=11011 -B2ARGS="-datadir=$D2 -debug=mempool" -$BITCOIND $B2ARGS & -B2PID=$! - -# Wait until both nodes are at the same block number -function WaitBlocks { - while : - do - sleep 1 - declare -i BLOCKS1=$( GetBlocks $B1ARGS ) - declare -i BLOCKS2=$( GetBlocks $B2ARGS ) - if (( BLOCKS1 == BLOCKS2 )) - then - break - fi - done -} - -# Wait until node has $N peers -function WaitPeers { - while : - do - declare -i PEERS=$( $CLI $1 getconnectioncount ) - if (( PEERS == "$2" )) - then - break - fi - sleep 1 - done -} - -echo "Generating test blockchain..." - -# Start with B2 connected to B1: -$CLI $B2ARGS addnode 127.0.0.1:11000 onetry -WaitPeers "$B1ARGS" 1 - -# 2 block, 50 XBT each == 100 XBT -# These will be transactions "A" and "B" -$CLI $B1ARGS generate 2 - -WaitBlocks -# 100 blocks, 0 mature == 0 XBT -$CLI $B2ARGS generate 100 -WaitBlocks - -CheckBalance "$B1ARGS" 100 -CheckBalance "$B2ARGS" 0 - -# restart B2 with no connection -$CLI $B2ARGS stop > /dev/null 2>&1 -wait $B2PID -$BITCOIND $B2ARGS & -B2PID=$! - -B1ADDRESS=$( $CLI $B1ARGS getnewaddress ) -B2ADDRESS=$( $CLI $B2ARGS getnewaddress ) - -# Transaction C: send-to-self, spend A -TXID_C=$( $CLI $B1ARGS sendtoaddress $B1ADDRESS 50.0) - -# Transaction D: spends B and C -TXID_D=$( $CLI $B1ARGS sendtoaddress $B2ADDRESS 100.0) - -CheckBalance "$B1ARGS" 0 - -# Mutate TXID_C and add it to B2's memory pool: -RAWTX_C=$( $CLI $B1ARGS getrawtransaction $TXID_C ) - -# ... mutate C to create C' -L=${RAWTX_C:82:2} -NEWLEN=$( printf "%x" $(( 16#$L + 1 )) ) -MUTATEDTX_C=${RAWTX_C:0:82}${NEWLEN}4c${RAWTX_C:84} -# ... give mutated tx1 to B2: -MUTATEDTXID=$( $CLI $B2ARGS sendrawtransaction $MUTATEDTX_C ) - -echo "TXID_C: " $TXID_C -echo "Mutated: " $MUTATEDTXID - -# Re-connect nodes, and have both nodes mine some blocks: -$CLI $B2ARGS addnode 127.0.0.1:11000 onetry -WaitPeers "$B1ARGS" 1 - -# Having B2 mine the next block puts the mutated -# transaction C in the chain: -$CLI $B2ARGS generate 1 -WaitBlocks - -# B1 should still be able to spend 100, because D is conflicted -# so does not count as a spend of B -CheckBalance "$B1ARGS" 100 - -$CLI $B2ARGS stop > /dev/null 2>&1 -wait $B2PID -$CLI $B1ARGS stop > /dev/null 2>&1 -wait $B1PID - -echo "Tests successful, cleaning up" -rm -rf $D -exit 0 diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index e859b2643..80f1d1e12 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -30,6 +30,7 @@ class RawTransactionsTest(BitcoinTestFramework): feeTolerance = Decimal(0.00000002) #if the fee's positive delta is higher than this value tests will fail, neg. delta always fail the tests self.nodes[2].generate(1) + self.sync_all() self.nodes[0].generate(101) self.sync_all() self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5); @@ -46,17 +47,10 @@ class RawTransactionsTest(BitcoinTestFramework): outputs = { self.nodes[0].getnewaddress() : 1.0 } rawtx = self.nodes[2].createrawtransaction(inputs, outputs) dec_tx = self.nodes[2].decoderawtransaction(rawtx) - rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - totalOut = 0 - for out in dec_tx['vout']: - totalOut += out['value'] - - assert_equal(len(dec_tx['vin']), 1) #one vin coin - assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') - assert_equal(fee + totalOut, 1.5) #the 1.5BTC coin must be taken + assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enought inputs ############################## # simple test with two coins # @@ -69,14 +63,7 @@ class RawTransactionsTest(BitcoinTestFramework): rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - totalOut = 0 - for out in dec_tx['vout']: - totalOut += out['value'] - - assert_equal(len(dec_tx['vin']), 2) #one vin coin - assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') - assert_equal(dec_tx['vin'][1]['scriptSig']['hex'], '') - assert_equal(fee + totalOut, 2.5) #the 1.5BTC+1.0BTC coins must have be taken + assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enough inputs ############################## # simple test with two coins # @@ -89,13 +76,8 @@ class RawTransactionsTest(BitcoinTestFramework): rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - totalOut = 0 - for out in dec_tx['vout']: - totalOut += out['value'] - - assert_equal(len(dec_tx['vin']), 1) #one vin coin + assert_equal(len(dec_tx['vin']) > 0, True) assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') - assert_equal(fee + totalOut, 5.0) #the 5.0BTC coin must have be taken ################################ @@ -113,11 +95,8 @@ class RawTransactionsTest(BitcoinTestFramework): for out in dec_tx['vout']: totalOut += out['value'] - assert_equal(len(dec_tx['vin']), 2) #one vin coin + assert_equal(len(dec_tx['vin']) > 0, True) assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') - assert_equal(dec_tx['vin'][1]['scriptSig']['hex'], '') - assert_equal(fee + totalOut, 6.0) #the 5.0BTC + 1.0BTC coins must have be taken - ######################################################################### @@ -220,8 +199,6 @@ class RawTransactionsTest(BitcoinTestFramework): assert_equal(matchingOuts, 1) assert_equal(len(dec_tx['vout']), 2) - assert_equal(fee + totalOut, 2.5) #this tx must use the 1.0BTC and the 1.5BTC coin - ########################################### # test a fundrawtransaction with two VINs # @@ -264,8 +241,6 @@ class RawTransactionsTest(BitcoinTestFramework): matchingIns+=1 assert_equal(matchingIns, 2) #we now must see two vins identical to vins given as params - assert_equal(fee + totalOut, 7.5) #this tx must use the 1.0BTC and the 1.5BTC coin - ######################################################### # test a fundrawtransaction with two VINs and two vOUTs # @@ -300,8 +275,6 @@ class RawTransactionsTest(BitcoinTestFramework): assert_equal(matchingOuts, 2) assert_equal(len(dec_tx['vout']), 3) - assert_equal(fee + totalOut, 7.5) #this tx must use the 1.0BTC and the 1.5BTC coin - ############################################## # test a fundrawtransaction with invalid vin # diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py index 1378514c8..173faf736 100755 --- a/qa/rpc-tests/rawtransactions.py +++ b/qa/rpc-tests/rawtransactions.py @@ -40,6 +40,7 @@ class RawTransactionsTest(BitcoinTestFramework): #prepare some coins for multiple *rawtransaction commands self.nodes[2].generate(1) + self.sync_all() self.nodes[0].generate(101) self.sync_all() self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5); diff --git a/qa/rpc-tests/send.sh b/qa/rpc-tests/send.sh deleted file mode 100755 index 2d54cc6de..000000000 --- a/qa/rpc-tests/send.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/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. -TIMEOUT=10 -SIGNAL=HUP -PIDFILE=.send.pid -if [ $# -eq 0 ]; then - echo -e "Usage:\t$0 <cmd>" - echo -e "\tRuns <cmd> and wait ${TIMEOUT} seconds or until SIG${SIGNAL} is received." - echo -e "\tReturns: 0 if SIG${SIGNAL} is received, 1 otherwise." - echo -e "Or:\t$0 -STOP" - echo -e "\tsends SIG${SIGNAL} to running send.sh" - exit 0 -fi - -if [ $1 = "-STOP" ]; then - if [ -s ${PIDFILE} ]; then - kill -s ${SIGNAL} $(<$PIDFILE 2>/dev/null) 2>/dev/null - fi - exit 0 -fi - -trap '[[ ${PID} ]] && kill ${PID}' ${SIGNAL} -trap 'rm -f ${PIDFILE}' EXIT -echo $$ > ${PIDFILE} -"$@" -sleep ${TIMEOUT} & PID=$! -wait ${PID} && exit 1 - -exit 0 diff --git a/qa/rpc-tests/txn_clone.py b/qa/rpc-tests/txn_clone.py index 0d276ecc9..e8ced0e5b 100755 --- a/qa/rpc-tests/txn_clone.py +++ b/qa/rpc-tests/txn_clone.py @@ -125,6 +125,8 @@ class TxnMallTest(BitcoinTestFramework): # Reconnect the split network, and sync chain: connect_nodes(self.nodes[1], 2) + self.nodes[2].sendrawtransaction(fund_bar_tx["hex"]) + self.nodes[2].sendrawtransaction(tx2["hex"]) self.nodes[2].generate(1) # Mine another block to make sure we sync sync_blocks(self.nodes) @@ -136,7 +138,7 @@ class TxnMallTest(BitcoinTestFramework): # Verify expected confirmations assert_equal(tx1["confirmations"], -1) assert_equal(tx1_clone["confirmations"], 2) - assert_equal(tx2["confirmations"], 0) + assert_equal(tx2["confirmations"], 1) # Check node0's total balance; should be same as before the clone, + 100 BTC for 2 matured, # less possible orphaned matured subsidy diff --git a/qa/rpc-tests/util.sh b/qa/rpc-tests/util.sh deleted file mode 100644 index c2b700430..000000000 --- a/qa/rpc-tests/util.sh +++ /dev/null @@ -1,103 +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. - -# Functions used by more than one test - -function echoerr { - echo "$@" 1>&2; -} - -# Usage: ExtractKey <key> "<json_object_string>" -# Warning: this will only work for the very-well-behaved -# JSON produced by bitcoind, do NOT use it to try to -# parse arbitrary/nested/etc JSON. -function ExtractKey { - echo $2 | tr -d ' "{}\n' | awk -v RS=',' -F: "\$1 ~ /$1/ { print \$2}" -} - -function CreateDataDir { - DIR=$1 - mkdir -p $DIR - CONF=$DIR/bitcoin.conf - echo "regtest=1" >> $CONF - echo "keypool=2" >> $CONF - echo "rpcuser=rt" >> $CONF - echo "rpcpassword=rt" >> $CONF - echo "rpcwait=1" >> $CONF - echo "walletnotify=${SENDANDWAIT} -STOP" >> $CONF - shift - while (( "$#" )); do - echo $1 >> $CONF - shift - done -} - -function AssertEqual { - if (( $( echo "$1 == $2" | bc ) == 0 )) - then - echoerr "AssertEqual: $1 != $2" - declare -f CleanUp > /dev/null 2>&1 - if [[ $? -eq 0 ]] ; then - CleanUp - fi - exit 1 - fi -} - -# CheckBalance -datadir=... amount account minconf -function CheckBalance { - declare -i EXPECT="$2" - B=$( $CLI $1 getbalance $3 $4 ) - if (( $( echo "$B == $EXPECT" | bc ) == 0 )) - then - echoerr "bad balance: $B (expected $2)" - declare -f CleanUp > /dev/null 2>&1 - if [[ $? -eq 0 ]] ; then - CleanUp - fi - exit 1 - fi -} - -# Use: Address <datadir> [account] -function Address { - $CLI $1 getnewaddress $2 -} - -# Send from to amount -function Send { - from=$1 - to=$2 - amount=$3 - address=$(Address $to) - txid=$( ${SENDANDWAIT} $CLI $from sendtoaddress $address $amount ) -} - -# Use: Unspent <datadir> <n'th-last-unspent> <var> -function Unspent { - local r=$( $CLI $1 listunspent | awk -F'[ |:,"]+' "\$2 ~ /$3/ { print \$3 }" | tail -n $2 | head -n 1) - echo $r -} - -# Use: CreateTxn1 <datadir> <n'th-last-unspent> <destaddress> -# produces hex from signrawtransaction -function CreateTxn1 { - TXID=$(Unspent $1 $2 txid) - AMOUNT=$(Unspent $1 $2 amount) - VOUT=$(Unspent $1 $2 vout) - RAWTXN=$( $CLI $1 createrawtransaction "[{\"txid\":\"$TXID\",\"vout\":$VOUT}]" "{\"$3\":$AMOUNT}") - ExtractKey hex "$( $CLI $1 signrawtransaction $RAWTXN )" -} - -# Use: SendRawTxn <datadir> <hex_txn_data> -function SendRawTxn { - ${SENDANDWAIT} $CLI $1 sendrawtransaction $2 -} - -# Use: GetBlocks <datadir> -# returns number of blocks from getinfo -function GetBlocks { - $CLI $1 getblockcount -} diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 6b7c42285..2ec3468e0 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -322,7 +322,7 @@ RES_MOVIES = $(wildcard qt/res/movies/spinner-*.png) BITCOIN_RC = qt/res/bitcoin-qt-res.rc BITCOIN_QT_INCLUDES = -I$(builddir)/qt -I$(srcdir)/qt -I$(srcdir)/qt/forms \ - -I$(builddir)/qt/forms + -I$(builddir)/qt/forms -DQT_NO_KEYWORDS qt_libbitcoinqt_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ $(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 903777ba5..1c5a31287 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -97,12 +97,6 @@ static bool AppInitRPC(int argc, char* argv[]) UniValue CallRPC(const string& strMethod, const UniValue& params) { - if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "") - throw runtime_error(strprintf( - _("You must set rpcpassword=<password> in the configuration file:\n%s\n" - "If the file does not exist, create it with owner-readable-only file permissions."), - GetConfigFile().string().c_str())); - // Connect to localhost bool fUseSSL = GetBoolArg("-rpcssl", false); boost::asio::io_service io_service; @@ -116,10 +110,24 @@ UniValue CallRPC(const string& strMethod, const UniValue& params) if (!fConnected) throw CConnectionFailed("couldn't connect to server"); + // Find credentials to use + std::string strRPCUserColonPass; + if (mapArgs["-rpcpassword"] == "") { + // Try fall back to cookie-based authentication if no password is provided + if (!GetAuthCookie(&strRPCUserColonPass)) { + throw runtime_error(strprintf( + _("You must set rpcpassword=<password> in the configuration file:\n%s\n" + "If the file does not exist, create it with owner-readable-only file permissions."), + GetConfigFile().string().c_str())); + + } + } else { + strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; + } + // HTTP basic authentication - string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]); map<string, string> mapRequestHeaders; - mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64; + mapRequestHeaders["Authorization"] = string("Basic ") + EncodeBase64(strRPCUserColonPass); // Send request string strRequest = JSONRPCRequest(strMethod, params, 1); diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 778541751..d693fba05 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -50,7 +50,6 @@ public: pchMessageStart[3] = 0xd9; vAlertPubKey = ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284"); nDefaultPort = 8333; - nMinerThreads = 0; nPruneAfterHeight = 100000; /** @@ -99,7 +98,6 @@ public: vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main)); - fRequireRPCPassword = true; fMiningRequiresPeers = true; fDefaultConsistencyChecks = false; fRequireStandard = true; @@ -147,7 +145,6 @@ public: pchMessageStart[3] = 0x07; vAlertPubKey = ParseHex("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a"); nDefaultPort = 18333; - nMinerThreads = 0; nPruneAfterHeight = 1000; //! Modify the testnet genesis block so the timestamp is valid for a later start. @@ -171,7 +168,6 @@ public: vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test)); - fRequireRPCPassword = true; fMiningRequiresPeers = true; fDefaultConsistencyChecks = false; fRequireStandard = false; @@ -206,7 +202,6 @@ public: pchMessageStart[1] = 0xbf; pchMessageStart[2] = 0xb5; pchMessageStart[3] = 0xda; - nMinerThreads = 1; genesis.nTime = 1296688602; genesis.nBits = 0x207fffff; genesis.nNonce = 2; @@ -218,7 +213,6 @@ public: vFixedSeeds.clear(); //! Regtest mode doesn't have any fixed seeds. vSeeds.clear(); //! Regtest mode doesn't have any DNS seeds. - fRequireRPCPassword = false; fMiningRequiresPeers = false; fDefaultConsistencyChecks = true; fRequireStandard = false; diff --git a/src/chainparams.h b/src/chainparams.h index 8044b553e..66d865b62 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -50,10 +50,7 @@ public: const std::vector<unsigned char>& AlertKey() const { return vAlertPubKey; } int GetDefaultPort() const { return nDefaultPort; } - /** Used if GenerateBitcoins is called with a negative number of threads */ - int DefaultMinerThreads() const { return nMinerThreads; } const CBlock& GenesisBlock() const { return genesis; } - bool RequireRPCPassword() const { return fRequireRPCPassword; } /** Make miner wait to have peers to avoid wasting work */ bool MiningRequiresPeers() const { return fMiningRequiresPeers; } /** Default value for -checkmempool and -checkblockindex argument */ @@ -79,14 +76,12 @@ protected: //! Raw pub key bytes for the broadcast alert signing key. std::vector<unsigned char> vAlertPubKey; int nDefaultPort; - int nMinerThreads; uint64_t nPruneAfterHeight; std::vector<CDNSSeedData> vSeeds; std::vector<unsigned char> base58Prefixes[MAX_BASE58_TYPES]; std::string strNetworkID; CBlock genesis; std::vector<SeedSpec6> vFixedSeeds; - bool fRequireRPCPassword; bool fMiningRequiresPeers; bool fDefaultConsistencyChecks; bool fRequireStandard; diff --git a/src/main.cpp b/src/main.cpp index 03c09f0a2..fb90d7578 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2059,7 +2059,6 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001); { CCoinsViewCache view(pcoinsTip); - CInv inv(MSG_BLOCK, pindexNew->GetBlockHash()); bool rv = ConnectBlock(*pblock, state, pindexNew, view); GetMainSignals().BlockChecked(*pblock, state); if (!rv) { @@ -2067,7 +2066,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * InvalidBlockFound(pindexNew, state); return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString()); } - mapBlockSource.erase(inv.hash); + mapBlockSource.erase(pindexNew->GetBlockHash()); nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2; LogPrint("bench", " - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001); assert(view.Flush()); diff --git a/src/memusage.h b/src/memusage.h index 9f7de9e2e..7a831e6d3 100644 --- a/src/memusage.h +++ b/src/memusage.h @@ -11,6 +11,7 @@ #include <set> #include <vector> +#include <boost/foreach.hpp> #include <boost/unordered_set.hpp> #include <boost/unordered_map.hpp> @@ -20,12 +21,28 @@ namespace memusage /** Compute the total memory used by allocating alloc bytes. */ static size_t MallocUsage(size_t alloc); +/** Dynamic memory usage for built-in types is zero. */ +static inline size_t DynamicUsage(const int8_t& v) { return 0; } +static inline size_t DynamicUsage(const uint8_t& v) { return 0; } +static inline size_t DynamicUsage(const int16_t& v) { return 0; } +static inline size_t DynamicUsage(const uint16_t& v) { return 0; } +static inline size_t DynamicUsage(const int32_t& v) { return 0; } +static inline size_t DynamicUsage(const uint32_t& v) { return 0; } +static inline size_t DynamicUsage(const int64_t& v) { return 0; } +static inline size_t DynamicUsage(const uint64_t& v) { return 0; } +static inline size_t DynamicUsage(const float& v) { return 0; } +static inline size_t DynamicUsage(const double& v) { return 0; } +template<typename X> static inline size_t DynamicUsage(X * const &v) { return 0; } +template<typename X> static inline size_t DynamicUsage(const X * const &v) { return 0; } +template<typename X, typename Y> static inline size_t DynamicUsage(std::pair<X, Y> &p) { return 0; } + /** Compute the memory used for dynamically allocated but owned data structures. * For generic data types, this is *not* recursive. DynamicUsage(vector<vector<int> >) * will compute the memory used for the vector<int>'s, but not for the ints inside. * This is for efficiency reasons, as these functions are intended to be fast. If * application data structures require more accurate inner accounting, they should - * do the recursion themselves, or use more efficient caching + updating on modification. + * use RecursiveDynamicUsage, iterate themselves, or use more efficient caching + + * updating on modification. */ template<typename X> static size_t DynamicUsage(const std::vector<X>& v); template<typename X> static size_t DynamicUsage(const std::set<X>& s); @@ -34,6 +51,12 @@ template<typename X, typename Y> static size_t DynamicUsage(const boost::unorder template<typename X, typename Y, typename Z> static size_t DynamicUsage(const boost::unordered_map<X, Y, Z>& s); template<typename X> static size_t DynamicUsage(const X& x); +template<typename X> static size_t RecursiveDynamicUsage(const std::vector<X>& v); +template<typename X> static size_t RecursiveDynamicUsage(const std::set<X>& v); +template<typename X, typename Y> static size_t RecursiveDynamicUsage(const std::map<X, Y>& v); +template<typename X, typename Y> static size_t RecursiveDynamicUsage(const std::pair<X, Y>& v); +template<typename X> static size_t RecursiveDynamicUsage(const X& v); + static inline size_t MallocUsage(size_t alloc) { // Measured on libc6 2.19 on Linux. @@ -66,17 +89,53 @@ static inline size_t DynamicUsage(const std::vector<X>& v) } template<typename X> +static inline size_t RecursiveDynamicUsage(const std::vector<X>& v) +{ + size_t usage = DynamicUsage(v); + BOOST_FOREACH(const X& x, v) { + usage += RecursiveDynamicUsage(x); + } + return usage; +} + +template<typename X> static inline size_t DynamicUsage(const std::set<X>& s) { return MallocUsage(sizeof(stl_tree_node<X>)) * s.size(); } +template<typename X> +static inline size_t RecursiveDynamicUsage(const std::set<X>& v) +{ + size_t usage = DynamicUsage(v); + BOOST_FOREACH(const X& x, v) { + usage += RecursiveDynamicUsage(x); + } + return usage; +} + template<typename X, typename Y> static inline size_t DynamicUsage(const std::map<X, Y>& m) { return MallocUsage(sizeof(stl_tree_node<std::pair<const X, Y> >)) * m.size(); } +template<typename X, typename Y> +static inline size_t RecursiveDynamicUsage(const std::map<X, Y>& v) +{ + size_t usage = DynamicUsage(v); + for (typename std::map<X, Y>::const_iterator it = v.begin(); it != v.end(); it++) { + usage += RecursiveDynamicUsage(*it); + } + return usage; +} + +template<typename X, typename Y> +static inline size_t RecursiveDynamicUsage(const std::pair<X, Y>& v) +{ + return RecursiveDynamicUsage(v.first) + RecursiveDynamicUsage(v.second); +} + // Boost data structures template<typename X> @@ -106,6 +165,12 @@ static inline size_t DynamicUsage(const X& x) return x.DynamicMemoryUsage(); } +template<typename X> +static inline size_t RecursiveDynamicUsage(const X& x) +{ + return DynamicUsage(x); +} + } #endif diff --git a/src/miner.cpp b/src/miner.cpp index bdb85c8c7..5e575f45f 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -542,13 +542,8 @@ void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainpar { static boost::thread_group* minerThreads = NULL; - if (nThreads < 0) { - // In regtest threads defaults to 1 - if (Params().DefaultMinerThreads()) - nThreads = Params().DefaultMinerThreads(); - else - nThreads = GetNumCores(); - } + if (nThreads < 0) + nThreads = GetNumCores(); if (minerThreads != NULL) { diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 606dbea79..7ed2d4597 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -72,6 +72,11 @@ void CTransaction::UpdateHash() const *const_cast<uint256*>(&hash) = SerializeHash(*this); } +size_t CTransaction::DynamicMemoryUsage() const +{ + return memusage::RecursiveDynamicUsage(vin) + memusage::RecursiveDynamicUsage(vout); +} + CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { } CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) { diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 6cfd93a9a..77326c64b 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -7,6 +7,7 @@ #define BITCOIN_PRIMITIVES_TRANSACTION_H #include "amount.h" +#include "memusage.h" #include "script/script.h" #include "serialize.h" #include "uint256.h" @@ -48,6 +49,8 @@ public: } std::string ToString() const; + + size_t DynamicMemoryUsage() const { return 0; } }; /** An input of a transaction. It contains the location of the previous @@ -96,6 +99,8 @@ public: } std::string ToString() const; + + size_t DynamicMemoryUsage() const { return scriptSig.DynamicMemoryUsage(); } }; /** An output of a transaction. It contains the public key that the next input @@ -166,6 +171,8 @@ public: } std::string ToString() const; + + size_t DynamicMemoryUsage() const { return scriptPubKey.DynamicMemoryUsage(); } }; struct CMutableTransaction; @@ -249,6 +256,8 @@ public: } std::string ToString() const; + + size_t DynamicMemoryUsage() const; }; /** A mutable version of CTransaction. */ diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index 54635f1d5..af6801919 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -254,7 +254,7 @@ void AddressBookPage::done(int retval) // Figure out which address was selected, and return it QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); - foreach (const QModelIndex& index, indexes) { + Q_FOREACH (const QModelIndex& index, indexes) { QVariant address = table->model()->data(index); returnValue = address.toString(); } diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h index 5105f09ce..09634ce33 100644 --- a/src/qt/addressbookpage.h +++ b/src/qt/addressbookpage.h @@ -45,7 +45,7 @@ public: void setModel(AddressTableModel *model); const QString &getReturnValue() const { return returnValue; } -public slots: +public Q_SLOTS: void done(int retval); private: @@ -59,7 +59,7 @@ private: QAction *deleteAction; // to be able to explicitly disable it QString newAddressToSelect; -private slots: +private Q_SLOTS: /** Delete currently selected address entry */ void on_deleteAddress_clicked(); /** Create a new address for receiving coins and / or add a new address book entry */ @@ -80,7 +80,7 @@ private slots: /** New entry/entries were added to address table */ void selectNewAddress(const QModelIndex &parent, int begin, int /*end*/); -signals: +Q_SIGNALS: void sendCoins(QString addr); }; diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index 8e20836c6..c5ac07cfc 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -450,5 +450,5 @@ int AddressTableModel::lookupAddress(const QString &address) const void AddressTableModel::emitDataChanged(int idx) { - emit dataChanged(index(idx, 0, QModelIndex()), index(idx, columns.length()-1, QModelIndex())); + Q_EMIT dataChanged(index(idx, 0, QModelIndex()), index(idx, columns.length()-1, QModelIndex())); } diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h index 6b34b2eac..2b7475c4e 100644 --- a/src/qt/addresstablemodel.h +++ b/src/qt/addresstablemodel.h @@ -84,7 +84,7 @@ private: /** Notify listeners that data changed. */ void emitDataChanged(int index); -public slots: +public Q_SLOTS: /* Update address list from core. */ void updateEntry(const QString &address, const QString &label, bool isMine, const QString &purpose, int status); diff --git a/src/qt/askpassphrasedialog.h b/src/qt/askpassphrasedialog.h index 74d54d18f..d4d832825 100644 --- a/src/qt/askpassphrasedialog.h +++ b/src/qt/askpassphrasedialog.h @@ -40,7 +40,7 @@ private: WalletModel *model; bool fCapsLock; -private slots: +private Q_SLOTS: void textChanged(); protected: diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 07250e72c..ec02c4be9 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -169,11 +169,11 @@ class BitcoinCore: public QObject public: explicit BitcoinCore(); -public slots: +public Q_SLOTS: void initialize(); void shutdown(); -signals: +Q_SIGNALS: void initializeResult(int retval); void shutdownResult(int retval); void runawayException(const QString &message); @@ -216,13 +216,13 @@ public: /// Get window identifier of QMainWindow (BitcoinGUI) WId getMainWinId() const; -public slots: +public Q_SLOTS: void initializeResult(int retval); void shutdownResult(int retval); /// Handle runaway exceptions. Shows a message box with the problem and quits the program. void handleRunawayException(const QString &message); -signals: +Q_SIGNALS: void requestedInitialize(); void requestedShutdown(); void stopThread(); @@ -253,7 +253,7 @@ BitcoinCore::BitcoinCore(): void BitcoinCore::handleRunawayException(const std::exception *e) { PrintExceptionContinue(e, "Runaway exception"); - emit runawayException(QString::fromStdString(strMiscWarning)); + Q_EMIT runawayException(QString::fromStdString(strMiscWarning)); } void BitcoinCore::initialize() @@ -269,7 +269,7 @@ void BitcoinCore::initialize() */ StartDummyRPCThread(); } - emit initializeResult(rv); + Q_EMIT initializeResult(rv); } catch (const std::exception& e) { handleRunawayException(&e); } catch (...) { @@ -286,7 +286,7 @@ void BitcoinCore::shutdown() threadGroup.join_all(); Shutdown(); qDebug() << __func__ << ": Shutdown finished"; - emit shutdownResult(1); + Q_EMIT shutdownResult(1); } catch (const std::exception& e) { handleRunawayException(&e); } catch (...) { @@ -315,7 +315,7 @@ BitcoinApplication::~BitcoinApplication() if(coreThread) { qDebug() << __func__ << ": Stopping thread"; - emit stopThread(); + Q_EMIT stopThread(); coreThread->wait(); qDebug() << __func__ << ": Stopped thread"; } @@ -386,7 +386,7 @@ void BitcoinApplication::requestInitialize() { qDebug() << __func__ << ": Requesting initialize"; startThread(); - emit requestedInitialize(); + Q_EMIT requestedInitialize(); } void BitcoinApplication::requestShutdown() @@ -409,7 +409,7 @@ void BitcoinApplication::requestShutdown() ShutdownWindow::showShutdownWindow(window); // Request shutdown from core thread - emit requestedShutdown(); + Q_EMIT requestedShutdown(); } void BitcoinApplication::initializeResult(int retval) @@ -449,7 +449,7 @@ void BitcoinApplication::initializeResult(int retval) { window->show(); } - emit splashFinished(window); + Q_EMIT splashFinished(window); #ifdef ENABLE_WALLET // Now that initialization/startup is done, process any command-line diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp index d31a1e018..d19b9fd4a 100644 --- a/src/qt/bitcoinamountfield.cpp +++ b/src/qt/bitcoinamountfield.cpp @@ -61,7 +61,7 @@ public: void setValue(const CAmount& value) { lineEdit()->setText(BitcoinUnits::format(currentUnit, value, false, BitcoinUnits::separatorAlways)); - emit valueChanged(); + Q_EMIT valueChanged(); } void stepBy(int steps) @@ -184,7 +184,7 @@ protected: return rv; } -signals: +Q_SIGNALS: void valueChanged(); }; diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h index b047e6c51..3703b1f8d 100644 --- a/src/qt/bitcoinamountfield.h +++ b/src/qt/bitcoinamountfield.h @@ -56,7 +56,7 @@ public: */ QWidget *setupTabChain(QWidget *prev); -signals: +Q_SIGNALS: void valueChanged(); protected: @@ -67,7 +67,7 @@ private: AmountSpinBox *amount; QValueComboBox *unit; -private slots: +private Q_SLOTS: void unitChanged(int idx); }; diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index efba0f5e1..396435f12 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -600,7 +600,7 @@ void BitcoinGUI::openClicked() OpenURIDialog dlg(this); if(dlg.exec()) { - emit receivedURI(dlg.getURI()); + Q_EMIT receivedURI(dlg.getURI()); } } @@ -886,9 +886,9 @@ void BitcoinGUI::dropEvent(QDropEvent *event) { if(event->mimeData()->hasUrls()) { - foreach(const QUrl &uri, event->mimeData()->urls()) + Q_FOREACH(const QUrl &uri, event->mimeData()->urls()) { - emit receivedURI(uri.toString()); + Q_EMIT receivedURI(uri.toString()); } } event->acceptProposedAction(); @@ -1050,7 +1050,7 @@ UnitDisplayStatusBarControl::UnitDisplayStatusBarControl() : QList<BitcoinUnits::Unit> units = BitcoinUnits::availableUnits(); int max_width = 0; const QFontMetrics fm(font()); - foreach (const BitcoinUnits::Unit unit, units) + Q_FOREACH (const BitcoinUnits::Unit unit, units) { max_width = qMax(max_width, fm.width(BitcoinUnits::name(unit))); } @@ -1069,7 +1069,7 @@ void UnitDisplayStatusBarControl::mousePressEvent(QMouseEvent *event) void UnitDisplayStatusBarControl::createContextMenu() { menu = new QMenu(); - foreach(BitcoinUnits::Unit u, BitcoinUnits::availableUnits()) + Q_FOREACH(BitcoinUnits::Unit u, BitcoinUnits::availableUnits()) { QAction *menuAction = new QAction(QString(BitcoinUnits::name(u)), this); menuAction->setData(QVariant(u)); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 494541f00..4e50b1712 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -136,11 +136,11 @@ private: /** Disconnect core signals from GUI client */ void unsubscribeFromCoreSignals(); -signals: +Q_SIGNALS: /** Signal raised when a URI was entered or dragged to the GUI */ void receivedURI(const QString &uri); -public slots: +public Q_SLOTS: /** Set number of connections shown in the UI */ void setNumConnections(int count); /** Set number of blocks and last block date shown in the UI */ @@ -168,7 +168,7 @@ public slots: void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label); #endif // ENABLE_WALLET -private slots: +private Q_SLOTS: #ifdef ENABLE_WALLET /** Switch to overview (home) page */ void gotoOverviewPage(); @@ -232,7 +232,7 @@ private: /** Creates context menu, its actions, and wires up all the relevant signals for mouse events. */ void createContextMenu(); -private slots: +private Q_SLOTS: /** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */ void updateDisplayUnit(int newUnits); /** Tells underlying optionsModel to update its current display unit. */ diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 5ac11324d..92a9ef279 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -117,15 +117,15 @@ void ClientModel::updateTimer() cachedReindexing = fReindex; cachedImporting = fImporting; - emit numBlocksChanged(newNumBlocks, newBlockDate); + Q_EMIT numBlocksChanged(newNumBlocks, newBlockDate); } - emit bytesChanged(getTotalBytesRecv(), getTotalBytesSent()); + Q_EMIT bytesChanged(getTotalBytesRecv(), getTotalBytesSent()); } void ClientModel::updateNumConnections(int numConnections) { - emit numConnectionsChanged(numConnections); + Q_EMIT numConnectionsChanged(numConnections); } void ClientModel::updateAlert(const QString &hash, int status) @@ -138,11 +138,11 @@ void ClientModel::updateAlert(const QString &hash, int status) CAlert alert = CAlert::getAlertByHash(hash_256); if(!alert.IsNull()) { - emit message(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), CClientUIInterface::ICON_ERROR); + Q_EMIT message(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), CClientUIInterface::ICON_ERROR); } } - emit alertsChanged(getStatusBarWarnings()); + Q_EMIT alertsChanged(getStatusBarWarnings()); } bool ClientModel::inInitialBlockDownload() const diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 214701810..68434f404 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -82,7 +82,7 @@ private: void subscribeToCoreSignals(); void unsubscribeFromCoreSignals(); -signals: +Q_SIGNALS: void numConnectionsChanged(int count); void numBlocksChanged(int count, const QDateTime& blockDate); void alertsChanged(const QString &warnings); @@ -94,7 +94,7 @@ signals: // Show progress dialog e.g. for verifychain void showProgress(const QString &title, int nProgress); -public slots: +public Q_SLOTS: void updateTimer(); void updateNumConnections(int numConnections); void updateAlert(const QString &hash, int status); diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index eea450353..cb888a07c 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -461,7 +461,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) CAmount nPayAmount = 0; bool fDust = false; CMutableTransaction txDummy; - foreach(const CAmount &amount, CoinControlDialog::payAmounts) + Q_FOREACH(const CAmount &amount, CoinControlDialog::payAmounts) { nPayAmount += amount; diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h index 5ec382838..0566b02c9 100644 --- a/src/qt/coincontroldialog.h +++ b/src/qt/coincontroldialog.h @@ -102,7 +102,7 @@ private: return column; } -private slots: +private Q_SLOTS: void showMenu(const QPoint &); void copyAmount(); void copyLabel(); diff --git a/src/qt/editaddressdialog.h b/src/qt/editaddressdialog.h index 13c6da8ed..d59fce2d4 100644 --- a/src/qt/editaddressdialog.h +++ b/src/qt/editaddressdialog.h @@ -40,7 +40,7 @@ public: QString getAddress() const; void setAddress(const QString &address); -public slots: +public Q_SLOTS: void accept(); private: diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 55df64a25..0ac3db632 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -169,7 +169,7 @@ namespace GUIUtil void setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode); void resizeColumn(int nColumnIndex, int width); - private slots: + private Q_SLOTS: void on_sectionResized(int logicalIndex, int oldSize, int newSize); void on_geometriesChanged(); }; diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 9f72602b4..117969758 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -42,10 +42,10 @@ public: ST_ERROR }; -public slots: +public Q_SLOTS: void check(); -signals: +Q_SIGNALS: void reply(int status, const QString &message, quint64 available); private: @@ -102,7 +102,7 @@ void FreespaceChecker::check() replyStatus = ST_ERROR; replyMessage = tr("Cannot create data directory here."); } - emit reply(replyStatus, replyMessage, freeBytesAvailable); + Q_EMIT reply(replyStatus, replyMessage, freeBytesAvailable); } @@ -121,7 +121,7 @@ Intro::~Intro() { delete ui; /* Ensure thread is finished before it is deleted */ - emit stopThread(); + Q_EMIT stopThread(); thread->wait(); } @@ -277,7 +277,7 @@ void Intro::checkPath(const QString &dataDir) if(!signalled) { signalled = true; - emit requestCheck(); + Q_EMIT requestCheck(); } mutex.unlock(); } diff --git a/src/qt/intro.h b/src/qt/intro.h index c9735615b..50783f722 100644 --- a/src/qt/intro.h +++ b/src/qt/intro.h @@ -43,14 +43,14 @@ public: */ static QString getDefaultDataDirectory(); -signals: +Q_SIGNALS: void requestCheck(); void stopThread(); -public slots: +public Q_SLOTS: void setStatus(int status, const QString &message, quint64 bytesAvailable); -private slots: +private Q_SLOTS: void on_dataDirectory_textChanged(const QString &arg1); void on_ellipsisButton_clicked(); void on_dataDirDefault_clicked(); diff --git a/src/qt/macdockiconhandler.h b/src/qt/macdockiconhandler.h index 15a6583ca..8bd867c10 100644 --- a/src/qt/macdockiconhandler.h +++ b/src/qt/macdockiconhandler.h @@ -30,7 +30,7 @@ public: static void cleanup(); void handleDockIconClickEvent(); -signals: +Q_SIGNALS: void dockIconClicked(); private: diff --git a/src/qt/macdockiconhandler.mm b/src/qt/macdockiconhandler.mm index 58a0365d3..a41d39d51 100644 --- a/src/qt/macdockiconhandler.mm +++ b/src/qt/macdockiconhandler.mm @@ -130,5 +130,5 @@ void MacDockIconHandler::handleDockIconClickEvent() this->mainWindow->show(); } - emit this->dockIconClicked(); + Q_EMIT this->dockIconClicked(); } diff --git a/src/qt/notificator.h b/src/qt/notificator.h index 182e948c7..f2a15e9c3 100644 --- a/src/qt/notificator.h +++ b/src/qt/notificator.h @@ -40,7 +40,7 @@ public: Critical /**< An error occurred */ }; -public slots: +public Q_SLOTS: /** Show notification message. @param[in] cls general message class @param[in] title title shown with message diff --git a/src/qt/openuridialog.h b/src/qt/openuridialog.h index d5c434ba9..28b8f56ca 100644 --- a/src/qt/openuridialog.h +++ b/src/qt/openuridialog.h @@ -21,10 +21,10 @@ public: QString getURI(); -protected slots: +protected Q_SLOTS: void accept(); -private slots: +private Q_SLOTS: void on_selectFileButton_clicked(); private: diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 87c727335..173bed3b6 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -73,7 +73,7 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : /* Display elements init */ QDir translations(":translations"); ui->lang->addItem(QString("(") + tr("default") + QString(")"), QVariant("")); - foreach(const QString &langStr, translations.entryList()) + Q_FOREACH(const QString &langStr, translations.entryList()) { QLocale locale(langStr); @@ -281,7 +281,7 @@ bool OptionsDialog::eventFilter(QObject *object, QEvent *event) { if(object == ui->proxyIp) { - emit proxyIpChecks(ui->proxyIp, ui->proxyPort->text().toInt()); + Q_EMIT proxyIpChecks(ui->proxyIp, ui->proxyPort->text().toInt()); } } return QDialog::eventFilter(object, event); diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h index f4e515759..fa983e798 100644 --- a/src/qt/optionsdialog.h +++ b/src/qt/optionsdialog.h @@ -33,7 +33,7 @@ public: protected: bool eventFilter(QObject *object, QEvent *event); -private slots: +private Q_SLOTS: /* enable OK button */ void enableOkButton(); /* disable OK button */ @@ -48,7 +48,7 @@ private slots: void clearStatusLabel(); void doProxyIpChecks(QValidatedLineEdit *pUiProxyIp, int nProxyPort); -signals: +Q_SIGNALS: void proxyIpChecks(QValidatedLineEdit *pUiProxyIp, int nProxyPort); private: diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 41d6acf35..b4ce8191d 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -286,7 +286,7 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in case CoinControlFeatures: fCoinControlFeatures = value.toBool(); settings.setValue("fCoinControlFeatures", fCoinControlFeatures); - emit coinControlFeaturesChanged(fCoinControlFeatures); + Q_EMIT coinControlFeaturesChanged(fCoinControlFeatures); break; case DatabaseCache: if (settings.value("nDatabaseCache") != value) { @@ -311,7 +311,7 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in } } - emit dataChanged(index, index); + Q_EMIT dataChanged(index, index); return successful; } @@ -324,7 +324,7 @@ void OptionsModel::setDisplayUnit(const QVariant &value) QSettings settings; nDisplayUnit = value.toInt(); settings.setValue("nDisplayUnit", nDisplayUnit); - emit displayUnitChanged(nDisplayUnit); + Q_EMIT displayUnitChanged(nDisplayUnit); } } diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index bf892768e..fc26d65b0 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -81,7 +81,7 @@ private: /// Add option to list of GUI options overridden through command line/config file void addOverriddenOption(const std::string &option); -signals: +Q_SIGNALS: void displayUnitChanged(int unit); void coinControlFeaturesChanged(bool); }; diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 2e33b9adf..bbd95ef47 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -142,7 +142,7 @@ OverviewPage::OverviewPage(QWidget *parent) : void OverviewPage::handleTransactionClicked(const QModelIndex &index) { if(filter) - emit transactionClicked(filter->mapToSource(index)); + Q_EMIT transactionClicked(filter->mapToSource(index)); } OverviewPage::~OverviewPage() diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index 64cb1dc4e..de5ac345d 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -35,11 +35,11 @@ public: void setWalletModel(WalletModel *walletModel); void showOutOfSyncWarning(bool fShow); -public slots: +public Q_SLOTS: void setBalance(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance); -signals: +Q_SIGNALS: void transactionClicked(const QModelIndex &index); private: @@ -56,7 +56,7 @@ private: TxViewDelegate *txdelegate; TransactionFilterProxy *filter; -private slots: +private Q_SLOTS: void updateDisplayUnit(); void handleTransactionClicked(const QModelIndex &index); void updateAlerts(const QString &warnings); diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 09e9949b1..654292903 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -148,7 +148,7 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store) int nRootCerts = 0; const QDateTime currentTime = QDateTime::currentDateTime(); - foreach (const QSslCertificate& cert, certList) { + Q_FOREACH (const QSslCertificate& cert, certList) { // Don't log NULL certificates if (cert.isNull()) continue; @@ -201,7 +201,7 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store) // when uiReady() is called. // // Warning: ipcSendCommandLine() is called early in init, -// so don't use "emit message()", but "QMessageBox::"! +// so don't use "Q_EMIT message()", but "QMessageBox::"! // void PaymentServer::ipcParseCommandLine(int argc, char* argv[]) { @@ -269,7 +269,7 @@ void PaymentServer::ipcParseCommandLine(int argc, char* argv[]) bool PaymentServer::ipcSendCommandLine() { bool fResult = false; - foreach (const QString& r, savedPaymentRequests) + Q_FOREACH (const QString& r, savedPaymentRequests) { QLocalSocket* socket = new QLocalSocket(); socket->connectToServer(ipcServerName(), QIODevice::WriteOnly); @@ -326,7 +326,7 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) : uriServer = new QLocalServer(this); if (!uriServer->listen(name)) { - // constructor is called early in init, so don't use "emit message()" here + // constructor is called early in init, so don't use "Q_EMIT message()" here QMessageBox::critical(0, tr("Payment request error"), tr("Cannot start bitcoin: click-to-pay handler")); } @@ -394,7 +394,7 @@ void PaymentServer::uiReady() initNetManager(); saveURIs = false; - foreach (const QString& s, savedPaymentRequests) + Q_FOREACH (const QString& s, savedPaymentRequests) { handleURIOrFile(s); } @@ -431,7 +431,7 @@ void PaymentServer::handleURIOrFile(const QString& s) else { qWarning() << "PaymentServer::handleURIOrFile: Invalid URL: " << fetchUrl; - emit message(tr("URI handling"), + Q_EMIT message(tr("URI handling"), tr("Payment request fetch URL is invalid: %1").arg(fetchUrl.toString()), CClientUIInterface::ICON_WARNING); } @@ -445,14 +445,14 @@ void PaymentServer::handleURIOrFile(const QString& s) { CBitcoinAddress address(recipient.address.toStdString()); if (!address.IsValid()) { - emit message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address), + Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address), CClientUIInterface::MSG_ERROR); } else - emit receivedPaymentRequest(recipient); + Q_EMIT receivedPaymentRequest(recipient); } else - emit message(tr("URI handling"), + Q_EMIT message(tr("URI handling"), tr("URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters."), CClientUIInterface::ICON_WARNING); @@ -466,12 +466,12 @@ void PaymentServer::handleURIOrFile(const QString& s) SendCoinsRecipient recipient; if (!readPaymentRequestFromFile(s, request)) { - emit message(tr("Payment request file handling"), + Q_EMIT message(tr("Payment request file handling"), tr("Payment request file cannot be read! This can be caused by an invalid payment request file."), CClientUIInterface::ICON_WARNING); } else if (processPaymentRequest(request, recipient)) - emit receivedPaymentRequest(recipient); + Q_EMIT receivedPaymentRequest(recipient); return; } @@ -500,7 +500,7 @@ void PaymentServer::handleURIConnection() // // Warning: readPaymentRequestFromFile() is used in ipcSendCommandLine() -// so don't use "emit message()", but "QMessageBox::"! +// so don't use "Q_EMIT message()", but "QMessageBox::"! // bool PaymentServer::readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request) { @@ -533,7 +533,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen if (request.IsInitialized()) { // Payment request network matches client network? if (!verifyNetwork(request.getDetails())) { - emit message(tr("Payment request rejected"), tr("Payment request network doesn't match client network."), + Q_EMIT message(tr("Payment request rejected"), tr("Payment request network doesn't match client network."), CClientUIInterface::MSG_ERROR); return false; @@ -542,13 +542,13 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen // Make sure any payment requests involved are still valid. // This is re-checked just before sending coins in WalletModel::sendCoins(). if (verifyExpired(request.getDetails())) { - emit message(tr("Payment request rejected"), tr("Payment request expired."), + Q_EMIT message(tr("Payment request rejected"), tr("Payment request expired."), CClientUIInterface::MSG_ERROR); return false; } } else { - emit message(tr("Payment request error"), tr("Payment request is not initialized."), + Q_EMIT message(tr("Payment request error"), tr("Payment request is not initialized."), CClientUIInterface::MSG_ERROR); return false; @@ -562,7 +562,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen QList<std::pair<CScript, CAmount> > sendingTos = request.getPayTo(); QStringList addresses; - foreach(const PAIRTYPE(CScript, CAmount)& sendingTo, sendingTos) { + Q_FOREACH(const PAIRTYPE(CScript, CAmount)& sendingTo, sendingTos) { // Extract and check destination addresses CTxDestination dest; if (ExtractDestination(sendingTo.first, dest)) { @@ -573,7 +573,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen // Unauthenticated payment requests to custom bitcoin addresses are not supported // (there is no good way to tell the user where they are paying in a way they'd // have a chance of understanding). - emit message(tr("Payment request rejected"), + Q_EMIT message(tr("Payment request rejected"), tr("Unverified payment requests to custom payment scripts are unsupported."), CClientUIInterface::MSG_ERROR); return false; @@ -583,14 +583,14 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen // but CAmount is defined as int64_t. Because of that we need to verify that amounts are in a valid range // and no overflow has happened. if (!verifyAmount(sendingTo.second)) { - emit message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR); + Q_EMIT message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR); return false; } // Extract and check amounts CTxOut txOut(sendingTo.second, sendingTo.first); if (txOut.IsDust(::minRelayTxFee)) { - emit message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).") + Q_EMIT message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).") .arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)), CClientUIInterface::MSG_ERROR); @@ -600,7 +600,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen recipient.amount += sendingTo.second; // Also verify that the final amount is still in a valid range after adding additional amounts. if (!verifyAmount(recipient.amount)) { - emit message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR); + Q_EMIT message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR); return false; } } @@ -694,7 +694,7 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply) .arg(BIP70_MAX_PAYMENTREQUEST_SIZE); qWarning() << QString("PaymentServer::%1:").arg(__func__) << msg; - emit message(tr("Payment request DoS protection"), msg, CClientUIInterface::MSG_ERROR); + Q_EMIT message(tr("Payment request DoS protection"), msg, CClientUIInterface::MSG_ERROR); return; } @@ -704,7 +704,7 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply) .arg(reply->errorString()); qWarning() << "PaymentServer::netRequestFinished: " << msg; - emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); + Q_EMIT message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); return; } @@ -718,12 +718,12 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply) if (!request.parse(data)) { qWarning() << "PaymentServer::netRequestFinished: Error parsing payment request"; - emit message(tr("Payment request error"), + Q_EMIT message(tr("Payment request error"), tr("Payment request cannot be parsed!"), CClientUIInterface::MSG_ERROR); } else if (processPaymentRequest(request, recipient)) - emit receivedPaymentRequest(recipient); + Q_EMIT receivedPaymentRequest(recipient); return; } @@ -736,11 +736,11 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply) .arg(reply->request().url().toString()); qWarning() << "PaymentServer::netRequestFinished: " << msg; - emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); + Q_EMIT message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); } else { - emit receivedPaymentACK(GUIUtil::HtmlEscape(paymentACK.memo())); + Q_EMIT receivedPaymentACK(GUIUtil::HtmlEscape(paymentACK.memo())); } } } @@ -750,11 +750,11 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError> Q_UNUSED(reply); QString errString; - foreach (const QSslError& err, errs) { + Q_FOREACH (const QSslError& err, errs) { qWarning() << "PaymentServer::reportSslErrors: " << err; errString += err.errorString() + "\n"; } - emit message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR); + Q_EMIT message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR); } void PaymentServer::setOptionsModel(OptionsModel *optionsModel) @@ -765,7 +765,7 @@ void PaymentServer::setOptionsModel(OptionsModel *optionsModel) void PaymentServer::handlePaymentACK(const QString& paymentACKMsg) { // currently we don't futher process or store the paymentACK message - emit message(tr("Payment acknowledged"), paymentACKMsg, CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MODAL); + Q_EMIT message(tr("Payment acknowledged"), paymentACKMsg, CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MODAL); } bool PaymentServer::verifyNetwork(const payments::PaymentDetails& requestDetails) diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h index 32ed27983..5df0a14cf 100644 --- a/src/qt/paymentserver.h +++ b/src/qt/paymentserver.h @@ -98,7 +98,7 @@ public: // Verify the payment request amount is valid static bool verifyAmount(const CAmount& requestAmount); -signals: +Q_SIGNALS: // Fired when a valid payment request is received void receivedPaymentRequest(SendCoinsRecipient); @@ -108,7 +108,7 @@ signals: // Fired when a message should be reported to the user void message(const QString &title, const QString &message, unsigned int style); -public slots: +public Q_SLOTS: // Signal this when the main window's UI is ready // to display payment requests to the user void uiReady(); @@ -119,7 +119,7 @@ public slots: // Handle an incoming URI, URI with local file scheme or file void handleURIOrFile(const QString& s); -private slots: +private Q_SLOTS: void handleURIConnection(); void netRequestFinished(QNetworkReply*); void reportSslErrors(QNetworkReply*, const QList<QSslError> &); diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index f5904a4d8..85339166b 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -63,7 +63,7 @@ public: #if QT_VERSION >= 0x040700 cachedNodeStats.reserve(vNodes.size()); #endif - foreach (CNode* pnode, vNodes) + Q_FOREACH (CNode* pnode, vNodes) { CNodeCombinedStats stats; stats.nodeStateStats.nMisbehavior = 0; @@ -92,7 +92,7 @@ public: // build index map mapNodeRows.clear(); int row = 0; - foreach (const CNodeCombinedStats& stats, cachedNodeStats) + Q_FOREACH (const CNodeCombinedStats& stats, cachedNodeStats) mapNodeRows.insert(std::pair<NodeId, int>(stats.nodeStats.nodeid, row++)); } @@ -220,9 +220,9 @@ const CNodeCombinedStats *PeerTableModel::getNodeStats(int idx) void PeerTableModel::refresh() { - emit layoutAboutToBeChanged(); + Q_EMIT layoutAboutToBeChanged(); priv->refreshPeers(); - emit layoutChanged(); + Q_EMIT layoutChanged(); } int PeerTableModel::getRowByNodeId(NodeId nodeid) diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h index bff7bb824..fcb89b761 100644 --- a/src/qt/peertablemodel.h +++ b/src/qt/peertablemodel.h @@ -68,7 +68,7 @@ public: void sort(int column, Qt::SortOrder order); /*@}*/ -public slots: +public Q_SLOTS: void refresh(); private: diff --git a/src/qt/qvalidatedlineedit.h b/src/qt/qvalidatedlineedit.h index f63568d27..8665acda5 100644 --- a/src/qt/qvalidatedlineedit.h +++ b/src/qt/qvalidatedlineedit.h @@ -27,11 +27,11 @@ private: bool valid; const QValidator *checkValidator; -public slots: +public Q_SLOTS: void setValid(bool valid); void setEnabled(bool enabled); -private slots: +private Q_SLOTS: void markValid(); void checkValidity(); }; diff --git a/src/qt/qvaluecombobox.cpp b/src/qt/qvaluecombobox.cpp index f73268c95..800436661 100644 --- a/src/qt/qvaluecombobox.cpp +++ b/src/qt/qvaluecombobox.cpp @@ -27,5 +27,5 @@ void QValueComboBox::setRole(int role) void QValueComboBox::handleSelectionChanged(int idx) { - emit valueChanged(); + Q_EMIT valueChanged(); } diff --git a/src/qt/qvaluecombobox.h b/src/qt/qvaluecombobox.h index dc85d64cb..5b20e6a5a 100644 --- a/src/qt/qvaluecombobox.h +++ b/src/qt/qvaluecombobox.h @@ -24,13 +24,13 @@ public: /** Specify model role to use as ordinal value (defaults to Qt::UserRole) */ void setRole(int role); -signals: +Q_SIGNALS: void valueChanged(); private: int role; -private slots: +private Q_SLOTS: void handleSelectionChanged(int idx); }; diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index fd225f51a..43b46c63b 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -185,7 +185,7 @@ void ReceiveCoinsDialog::on_showRequestButton_clicked() return; QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows(); - foreach (const QModelIndex& index, selection) { + Q_FOREACH (const QModelIndex& index, selection) { on_recentRequestsView_doubleClicked(index); } } diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h index 70a1842fa..6bb159482 100644 --- a/src/qt/receivecoinsdialog.h +++ b/src/qt/receivecoinsdialog.h @@ -44,7 +44,7 @@ public: void setModel(WalletModel *model); -public slots: +public Q_SLOTS: void clear(); void reject(); void accept(); @@ -60,7 +60,7 @@ private: void copyColumnToClipboard(int column); virtual void resizeEvent(QResizeEvent *event); -private slots: +private Q_SLOTS: void on_receiveButton_clicked(); void on_showRequestButton_clicked(); void on_removeRequestButton_clicked(); diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h index 3e5f897be..69f84ebbd 100644 --- a/src/qt/receiverequestdialog.h +++ b/src/qt/receiverequestdialog.h @@ -32,7 +32,7 @@ public: explicit QRImageWidget(QWidget *parent = 0); QImage exportImage(); -public slots: +public Q_SLOTS: void saveImage(); void copyImage(); @@ -55,7 +55,7 @@ public: void setModel(OptionsModel *model); void setInfo(const SendCoinsRecipient &info); -private slots: +private Q_SLOTS: void on_btnCopyURI_clicked(); void on_btnCopyAddress_clicked(); diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp index 543b977d8..5692a7aae 100644 --- a/src/qt/recentrequeststablemodel.cpp +++ b/src/qt/recentrequeststablemodel.cpp @@ -119,7 +119,7 @@ QVariant RecentRequestsTableModel::headerData(int section, Qt::Orientation orien void RecentRequestsTableModel::updateAmountColumnTitle() { columns[Amount] = getAmountTitle(); - emit headerDataChanged(Qt::Horizontal,Amount,Amount); + Q_EMIT headerDataChanged(Qt::Horizontal,Amount,Amount); } /** Gets title for amount column including current display unit if optionsModel reference available. */ @@ -214,7 +214,7 @@ void RecentRequestsTableModel::addNewRequest(RecentRequestEntry &recipient) void RecentRequestsTableModel::sort(int column, Qt::SortOrder order) { qSort(list.begin(), list.end(), RecentRequestEntryLessThan(column, order)); - emit dataChanged(index(0, 0, QModelIndex()), index(list.size() - 1, NUMBER_OF_COLUMNS - 1, QModelIndex())); + Q_EMIT dataChanged(index(0, 0, QModelIndex()), index(list.size() - 1, NUMBER_OF_COLUMNS - 1, QModelIndex())); } void RecentRequestsTableModel::updateDisplayUnit() diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h index 85bad126d..64faa72d4 100644 --- a/src/qt/recentrequeststablemodel.h +++ b/src/qt/recentrequeststablemodel.h @@ -89,7 +89,7 @@ public: void addNewRequest(const std::string &recipient); void addNewRequest(RecentRequestEntry &recipient); -public slots: +public Q_SLOTS: void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); void updateDisplayUnit(); diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index f828ce253..2fafb83d4 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -60,10 +60,10 @@ class RPCExecutor : public QObject { Q_OBJECT -public slots: +public Q_SLOTS: void request(const QString &command); -signals: +Q_SIGNALS: void reply(int category, const QString &command); }; @@ -95,7 +95,7 @@ bool parseCommandLine(std::vector<std::string> &args, const std::string &strComm STATE_ESCAPE_DOUBLEQUOTED } state = STATE_EATING_SPACES; std::string curarg; - foreach(char ch, strCommand) + Q_FOREACH(char ch, strCommand) { switch(state) { @@ -158,7 +158,7 @@ void RPCExecutor::request(const QString &command) std::vector<std::string> args; if(!parseCommandLine(args, command.toStdString())) { - emit reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \"")); + Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \"")); return; } if(args.empty()) @@ -180,7 +180,7 @@ void RPCExecutor::request(const QString &command) else strPrint = result.write(2); - emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint)); + Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint)); } catch (UniValue& objError) { @@ -188,16 +188,16 @@ void RPCExecutor::request(const QString &command) { int code = find_value(objError, "code").get_int(); std::string message = find_value(objError, "message").get_str(); - emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")"); + Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")"); } catch (const std::runtime_error&) // raised when converting to invalid type, i.e. missing code or message { // Show raw JSON object - emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(objError.write())); + Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(objError.write())); } } catch (const std::exception& e) { - emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what())); + Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what())); } } @@ -245,7 +245,7 @@ RPCConsole::RPCConsole(QWidget *parent) : RPCConsole::~RPCConsole() { GUIUtil::saveWindowGeometry("nRPCConsoleWindow", this); - emit stopExecutor(); + Q_EMIT stopExecutor(); delete ui; } @@ -431,7 +431,7 @@ void RPCConsole::on_lineEdit_returnPressed() if(!cmd.isEmpty()) { message(CMD_REQUEST, cmd); - emit cmdRequest(cmd); + Q_EMIT cmdRequest(cmd); // Remove command, if already in history history.removeOne(cmd); // Append command to history diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index a309df7ba..6f42aa08b 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -46,7 +46,7 @@ protected: virtual bool eventFilter(QObject* obj, QEvent *event); void keyPressEvent(QKeyEvent *); -private slots: +private Q_SLOTS: void on_lineEdit_returnPressed(); void on_tabWidget_currentChanged(int index); /** open the debug.log from the current datadir */ @@ -61,7 +61,7 @@ private slots: /** Show custom context menu on Peers tab */ void showMenu(const QPoint& point); -public slots: +public Q_SLOTS: void clear(); void message(int category, const QString &message, bool html = false); /** Set number of connections shown in the UI */ @@ -79,7 +79,7 @@ public slots: /** Disconnect a selected node on the Peers tab */ void disconnectSelectedNode(); -signals: +Q_SIGNALS: // For RPC command executor void stopExecutor(); void cmdRequest(const QString &command); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 3d5771156..e13cd714a 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -251,7 +251,7 @@ void SendCoinsDialog::on_sendButton_clicked() // Format confirmation message QStringList formatted; - foreach(const SendCoinsRecipient &rcp, currentTransaction.getRecipients()) + Q_FOREACH(const SendCoinsRecipient &rcp, currentTransaction.getRecipients()) { // generate bold amount string QString amount = "<b>" + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount); @@ -305,7 +305,7 @@ void SendCoinsDialog::on_sendButton_clicked() questionString.append("<hr />"); CAmount totalAmount = currentTransaction.getTotalTransactionAmount() + txFee; QStringList alternativeUnits; - foreach(BitcoinUnits::Unit u, BitcoinUnits::availableUnits()) + Q_FOREACH(BitcoinUnits::Unit u, BitcoinUnits::availableUnits()) { if(u != model->getOptionsModel()->getDisplayUnit()) alternativeUnits.append(BitcoinUnits::formatHtmlWithUnit(u, totalAmount)); @@ -540,7 +540,7 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn return; } - emit message(tr("Send Coins"), msgParams.first, msgParams.second); + Q_EMIT message(tr("Send Coins"), msgParams.first, msgParams.second); } void SendCoinsDialog::minimizeFeeSection(bool fMinimize) diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index fc513bf2b..c833da84b 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -45,7 +45,7 @@ public: void pasteEntry(const SendCoinsRecipient &rv); bool handlePaymentRequest(const SendCoinsRecipient &recipient); -public slots: +public Q_SLOTS: void clear(); void reject(); void accept(); @@ -62,13 +62,13 @@ private: bool fFeeMinimized; // Process WalletModel::SendCoinsReturn and generate a pair consisting - // of a message and message flags for use in emit message(). + // of a message and message flags for use in Q_EMIT message(). // Additional parameter msgArg can be used via .arg(msgArg). void processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg = QString()); void minimizeFeeSection(bool fMinimize); void updateFeeMinimizedLabel(); -private slots: +private Q_SLOTS: void on_sendButton_clicked(); void on_buttonChooseFee_clicked(); void on_buttonMinimizeFee_clicked(); @@ -93,7 +93,7 @@ private slots: void updateSmartFeeLabel(); void updateGlobalFeeVariables(); -signals: +Q_SIGNALS: // Fired when a message should be reported to the user void message(const QString &title, const QString &message, unsigned int style); }; diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index 6eec33ffd..90a8cbdc4 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -114,7 +114,7 @@ void SendCoinsEntry::clear() void SendCoinsEntry::deleteClicked() { - emit removeEntry(this); + Q_EMIT removeEntry(this); } bool SendCoinsEntry::validate() diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h index c2d1185bd..d7e655fdc 100644 --- a/src/qt/sendcoinsentry.h +++ b/src/qt/sendcoinsentry.h @@ -45,15 +45,15 @@ public: void setFocus(); -public slots: +public Q_SLOTS: void clear(); -signals: +Q_SIGNALS: void removeEntry(SendCoinsEntry *entry); void payAmountChanged(); void subtractFeeFromAmountChanged(); -private slots: +private Q_SLOTS: void deleteClicked(); void on_payTo_textChanged(const QString &address); void on_addressBookButton_clicked(); diff --git a/src/qt/signverifymessagedialog.h b/src/qt/signverifymessagedialog.h index 27807adc8..bf841e4f8 100644 --- a/src/qt/signverifymessagedialog.h +++ b/src/qt/signverifymessagedialog.h @@ -35,7 +35,7 @@ private: Ui::SignVerifyMessageDialog *ui; WalletModel *model; -private slots: +private Q_SLOTS: /* sign message */ void on_addressBookButton_SM_clicked(); void on_pasteButton_SM_clicked(); diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h index 84e4556dd..29d16d4ea 100644 --- a/src/qt/splashscreen.h +++ b/src/qt/splashscreen.h @@ -27,7 +27,7 @@ protected: void paintEvent(QPaintEvent *event); void closeEvent(QCloseEvent *event); -public slots: +public Q_SLOTS: /** Slot to call finish() method as it's not defined as slot */ void slotFinish(QWidget *mainWin); diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp index e2ec439b2..b28934cd3 100644 --- a/src/qt/test/paymentservertests.cpp +++ b/src/qt/test/paymentservertests.cpp @@ -195,7 +195,7 @@ void PaymentServerTests::paymentServerTests() QVERIFY(r.paymentRequest.IsInitialized()); // Extract address and amount from the request QList<std::pair<CScript, CAmount> > sendingTos = r.paymentRequest.getPayTo(); - foreach (const PAIRTYPE(CScript, CAmount)& sendingTo, sendingTos) { + Q_FOREACH (const PAIRTYPE(CScript, CAmount)& sendingTo, sendingTos) { CTxDestination dest; if (ExtractDestination(sendingTo.first, dest)) QCOMPARE(PaymentServer::verifyAmount(sendingTo.second), false); diff --git a/src/qt/test/paymentservertests.h b/src/qt/test/paymentservertests.h index c98bbf083..71d61fcbe 100644 --- a/src/qt/test/paymentservertests.h +++ b/src/qt/test/paymentservertests.h @@ -14,7 +14,7 @@ class PaymentServerTests : public QObject { Q_OBJECT -private slots: +private Q_SLOTS: void paymentServerTests(); }; @@ -25,7 +25,7 @@ class RecipientCatcher : public QObject { Q_OBJECT -public slots: +public Q_SLOTS: void getRecipient(SendCoinsRecipient r); public: diff --git a/src/qt/test/uritests.h b/src/qt/test/uritests.h index a0b7dc6c7..434169dcd 100644 --- a/src/qt/test/uritests.h +++ b/src/qt/test/uritests.h @@ -12,7 +12,7 @@ class URITests : public QObject { Q_OBJECT -private slots: +private Q_SLOTS: void uriTests(); }; diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp index 0b2eb9eaf..9b67445bc 100644 --- a/src/qt/trafficgraphwidget.cpp +++ b/src/qt/trafficgraphwidget.cpp @@ -139,10 +139,10 @@ void TrafficGraphWidget::updateRates() } float tmax = 0.0f; - foreach(float f, vSamplesIn) { + Q_FOREACH(float f, vSamplesIn) { if(f > tmax) tmax = f; } - foreach(float f, vSamplesOut) { + Q_FOREACH(float f, vSamplesOut) { if(f > tmax) tmax = f; } fMax = tmax; diff --git a/src/qt/trafficgraphwidget.h b/src/qt/trafficgraphwidget.h index 4c6b17fe7..6336a8d14 100644 --- a/src/qt/trafficgraphwidget.h +++ b/src/qt/trafficgraphwidget.h @@ -27,7 +27,7 @@ public: protected: void paintEvent(QPaintEvent *); -public slots: +public Q_SLOTS: void updateRates(); void setGraphRangeMins(int mins); void clear(); diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 5662b1665..d7ee3d4c7 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -243,14 +243,14 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "<b>" + tr("Transaction ID") + ":</b> " + TransactionRecord::formatSubTxId(wtx.GetHash(), rec->idx) + "<br>"; // Message from normal bitcoin:URI (bitcoin:123...?message=example) - foreach (const PAIRTYPE(string, string)& r, wtx.vOrderForm) + Q_FOREACH (const PAIRTYPE(string, string)& r, wtx.vOrderForm) if (r.first == "Message") strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(r.second, true) + "<br>"; // // PaymentRequest info: // - foreach (const PAIRTYPE(string, string)& r, wtx.vOrderForm) + Q_FOREACH (const PAIRTYPE(string, string)& r, wtx.vOrderForm) { if (r.first == "PaymentRequest") { diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 34464b407..e3d64387f 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -142,7 +142,7 @@ public: { parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1); int insert_idx = lowerIndex; - foreach(const TransactionRecord &rec, toInsert) + Q_FOREACH(const TransactionRecord &rec, toInsert) { cachedWallet.insert(insert_idx, rec); insert_idx += 1; @@ -245,7 +245,7 @@ TransactionTableModel::~TransactionTableModel() void TransactionTableModel::updateAmountColumnTitle() { columns[Amount] = BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit()); - emit headerDataChanged(Qt::Horizontal,Amount,Amount); + Q_EMIT headerDataChanged(Qt::Horizontal,Amount,Amount); } void TransactionTableModel::updateTransaction(const QString &hash, int status, bool showTransaction) @@ -262,8 +262,8 @@ void TransactionTableModel::updateConfirmations() // Invalidate status (number of confirmations) and (possibly) description // for all rows. Qt is smart enough to only actually request the data for the // visible rows. - emit dataChanged(index(0, Status), index(priv->size()-1, Status)); - emit dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress)); + Q_EMIT dataChanged(index(0, Status), index(priv->size()-1, Status)); + Q_EMIT dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress)); } int TransactionTableModel::rowCount(const QModelIndex &parent) const @@ -650,7 +650,7 @@ void TransactionTableModel::updateDisplayUnit() { // emit dataChanged to update Amount column with the current unit updateAmountColumnTitle(); - emit dataChanged(index(0, Amount), index(priv->size()-1, Amount)); + Q_EMIT dataChanged(index(0, Amount), index(priv->size()-1, Amount)); } // queue notifications to show a non freezing progress dialog e.g. for rescan diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h index 30a15df9e..25c82c764 100644 --- a/src/qt/transactiontablemodel.h +++ b/src/qt/transactiontablemodel.h @@ -98,7 +98,7 @@ private: QVariant txWatchonlyDecoration(const TransactionRecord *wtx) const; QVariant txAddressDecoration(const TransactionRecord *wtx) const; -public slots: +public Q_SLOTS: /* New transaction, or transaction changed status */ void updateTransaction(const QString &hash, int status, bool showTransaction); void updateConfirmations(); diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 526940632..998789b3a 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -341,11 +341,11 @@ void TransactionView::exportClicked() writer.addColumn(tr("ID"), 0, TransactionTableModel::TxIDRole); if(!writer.write()) { - emit message(tr("Exporting Failed"), tr("There was an error trying to save the transaction history to %1.").arg(filename), + Q_EMIT message(tr("Exporting Failed"), tr("There was an error trying to save the transaction history to %1.").arg(filename), CClientUIInterface::MSG_ERROR); } else { - emit message(tr("Exporting Successful"), tr("The transaction history was successfully saved to %1.").arg(filename), + Q_EMIT message(tr("Exporting Successful"), tr("The transaction history was successfully saved to %1.").arg(filename), CClientUIInterface::MSG_INFORMATION); } } diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h index 092d91904..6c35362be 100644 --- a/src/qt/transactionview.h +++ b/src/qt/transactionview.h @@ -83,7 +83,7 @@ private: bool eventFilter(QObject *obj, QEvent *event); -private slots: +private Q_SLOTS: void contextualMenu(const QPoint &); void dateRangeChanged(); void showDetails(); @@ -95,13 +95,13 @@ private slots: void openThirdPartyTxUrl(QString url); void updateWatchOnlyColumn(bool fHaveWatchOnly); -signals: +Q_SIGNALS: void doubleClicked(const QModelIndex&); /** Fired when a message should be reported to the user */ void message(const QString &title, const QString &message, unsigned int style); -public slots: +public Q_SLOTS: void chooseDate(int idx); void chooseType(int idx); void chooseWatchonly(int idx); diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 386cf31d7..5e26f3e01 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -84,7 +84,7 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) : QTextCharFormat bold; bold.setFontWeight(QFont::Bold); - foreach (const QString &line, coreOptions.split("\n")) { + Q_FOREACH (const QString &line, coreOptions.split("\n")) { if (line.startsWith(" -")) { cursor.currentTable()->appendRows(1); diff --git a/src/qt/utilitydialog.h b/src/qt/utilitydialog.h index 288b985f1..47282ae2d 100644 --- a/src/qt/utilitydialog.h +++ b/src/qt/utilitydialog.h @@ -31,7 +31,7 @@ private: Ui::HelpMessageDialog *ui; QString text; -private slots: +private Q_SLOTS: void on_okButton_accepted(); }; diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index eea97defc..5a5e2ab94 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -47,7 +47,7 @@ private: WalletView *currentWalletView(); -public slots: +public Q_SLOTS: /** Switch to overview (home) page */ void gotoOverviewPage(); /** Switch to history (transactions) page */ diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 9b8be76be..2691fa930 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -107,7 +107,7 @@ void WalletModel::updateStatus() EncryptionStatus newEncryptionStatus = getEncryptionStatus(); if(cachedEncryptionStatus != newEncryptionStatus) - emit encryptionStatusChanged(newEncryptionStatus); + Q_EMIT encryptionStatusChanged(newEncryptionStatus); } void WalletModel::pollBalanceChanged() @@ -159,7 +159,7 @@ void WalletModel::checkBalanceChanged() cachedWatchOnlyBalance = newWatchOnlyBalance; cachedWatchUnconfBalance = newWatchUnconfBalance; cachedWatchImmatureBalance = newWatchImmatureBalance; - emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance, + Q_EMIT balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance, newWatchOnlyBalance, newWatchUnconfBalance, newWatchImmatureBalance); } } @@ -180,7 +180,7 @@ void WalletModel::updateAddressBook(const QString &address, const QString &label void WalletModel::updateWatchOnlyFlag(bool fHaveWatchonly) { fHaveWatchOnly = fHaveWatchonly; - emit notifyWatchonlyChanged(fHaveWatchonly); + Q_EMIT notifyWatchonlyChanged(fHaveWatchonly); } bool WalletModel::validateAddress(const QString &address) @@ -205,7 +205,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact int nAddresses = 0; // Pre-check input data for validity - foreach(const SendCoinsRecipient &rcp, recipients) + Q_FOREACH(const SendCoinsRecipient &rcp, recipients) { if (rcp.fSubtractFeeFromAmount) fSubtractFeeFromAmount = true; @@ -285,7 +285,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact { return SendCoinsReturn(AmountWithFeeExceedsBalance); } - emit message(tr("Send Coins"), QString::fromStdString(strFailReason), + Q_EMIT message(tr("Send Coins"), QString::fromStdString(strFailReason), CClientUIInterface::MSG_ERROR); return TransactionCreationFailed; } @@ -306,7 +306,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran LOCK2(cs_main, wallet->cs_wallet); CWalletTx *newTx = transaction.getTransaction(); - foreach(const SendCoinsRecipient &rcp, transaction.getRecipients()) + Q_FOREACH(const SendCoinsRecipient &rcp, transaction.getRecipients()) { if (rcp.paymentRequest.IsInitialized()) { @@ -337,7 +337,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran // Add addresses / update labels that we've sent to to the address book, // and emit coinsSent signal for each recipient - foreach(const SendCoinsRecipient &rcp, transaction.getRecipients()) + Q_FOREACH(const SendCoinsRecipient &rcp, transaction.getRecipients()) { // Don't touch the address book when we have a payment request if (!rcp.paymentRequest.IsInitialized()) @@ -361,7 +361,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran } } } - emit coinsSent(wallet, rcp, transaction_array); + Q_EMIT coinsSent(wallet, rcp, transaction_array); } checkBalanceChanged(); // update balance immediately, otherwise there could be a short noticeable delay until pollBalanceChanged hits @@ -521,7 +521,7 @@ WalletModel::UnlockContext WalletModel::requestUnlock() if(was_locked) { // Request UI to unlock wallet - emit requireUnlock(); + Q_EMIT requireUnlock(); } // If wallet is still locked, unlock was failed or cancelled, mark context as invalid bool valid = getEncryptionStatus() != Locked; diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index e26343888..40bc62354 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -227,7 +227,7 @@ private: void unsubscribeFromCoreSignals(); void checkBalanceChanged(); -signals: +Q_SIGNALS: // Signal that balance in wallet changed void balanceChanged(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance); @@ -252,7 +252,7 @@ signals: // Watch-only address added void notifyWatchonlyChanged(bool fHaveWatchonly); -public slots: +public Q_SLOTS: /* Wallet status might have changed */ void updateStatus(); /* New transaction, or transaction changed status */ diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index 206bb7c77..6a9b2d5bd 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -81,7 +81,7 @@ void WalletModelTransaction::reassignAmounts(int nChangePosRet) CAmount WalletModelTransaction::getTotalTransactionAmount() { CAmount totalTransactionAmount = 0; - foreach(const SendCoinsRecipient &rcp, recipients) + Q_FOREACH(const SendCoinsRecipient &rcp, recipients) { totalTransactionAmount += rcp.amount; } diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 956c8b891..c5f556b44 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -153,7 +153,7 @@ void WalletView::processNewTransaction(const QModelIndex& parent, int start, int QString address = ttm->data(index, TransactionTableModel::AddressRole).toString(); QString label = ttm->data(index, TransactionTableModel::LabelRole).toString(); - emit incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label); + Q_EMIT incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label); } void WalletView::gotoOverviewPage() @@ -215,7 +215,7 @@ void WalletView::showOutOfSyncWarning(bool fShow) void WalletView::updateEncryptionStatus() { - emit encryptionStatusChanged(walletModel->getEncryptionStatus()); + Q_EMIT encryptionStatusChanged(walletModel->getEncryptionStatus()); } void WalletView::encryptWallet(bool status) @@ -239,11 +239,11 @@ void WalletView::backupWallet() return; if (!walletModel->backupWallet(filename)) { - emit message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to %1.").arg(filename), + Q_EMIT message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to %1.").arg(filename), CClientUIInterface::MSG_ERROR); } else { - emit message(tr("Backup Successful"), tr("The wallet data was successfully saved to %1.").arg(filename), + Q_EMIT message(tr("Backup Successful"), tr("The wallet data was successfully saved to %1.").arg(filename), CClientUIInterface::MSG_INFORMATION); } } diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 1840e21e9..87c5d7bfb 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -65,7 +65,7 @@ private: QProgressDialog *progressDialog; -public slots: +public Q_SLOTS: /** Switch to overview (home) page */ void gotoOverviewPage(); /** Switch to history (transactions) page */ @@ -105,7 +105,7 @@ public slots: /** Show progress dialog e.g. for rescan */ void showProgress(const QString &title, int nProgress); -signals: +Q_SIGNALS: /** Signal that we want to show the main window */ void showNormalIfMinimized(); /** Fired when a message should be reported to the user */ diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 9cdd0770e..f1c5ffe05 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -594,6 +594,8 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" + " \"pruned\": xx, (boolean) if the blocks are subject to pruning\n" + " \"pruneheight\": xxxxxx, (numeric) heighest block available\n" " \"softforks\": [ (array) status of softforks in progress\n" " {\n" " \"id\": \"xxxx\", (string) name of softfork\n" @@ -758,6 +760,7 @@ UniValue getmempoolinfo(const UniValue& params, bool fHelp) "{\n" " \"size\": xxxxx (numeric) Current tx count\n" " \"bytes\": xxxxx (numeric) Sum of all tx sizes\n" + " \"usage\": xxxxx (numeric) Total memory usage for the mempool\n" "}\n" "\nExamples:\n" + HelpExampleCli("getmempoolinfo", "") @@ -767,6 +770,7 @@ UniValue getmempoolinfo(const UniValue& params, bool fHelp) UniValue ret(UniValue::VOBJ); ret.push_back(Pair("size", (int64_t) mempool.size())); ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize())); + ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage())); return ret; } diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp index 89dec2977..2e5c91373 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -6,6 +6,7 @@ #include "rpcprotocol.h" #include "clientversion.h" +#include "random.h" #include "tinyformat.h" #include "util.h" #include "utilstrencodings.h" @@ -13,6 +14,7 @@ #include "version.h" #include <stdint.h> +#include <fstream> #include <boost/algorithm/string.hpp> #include <boost/asio.hpp> @@ -287,3 +289,68 @@ UniValue JSONRPCError(int code, const string& message) error.push_back(Pair("message", message)); return error; } + +/** Username used when cookie authentication is in use (arbitrary, only for + * recognizability in debugging/logging purposes) + */ +static const std::string COOKIEAUTH_USER = "__cookie__"; +/** Default name for auth cookie file */ +static const std::string COOKIEAUTH_FILE = ".cookie"; + +boost::filesystem::path GetAuthCookieFile() +{ + boost::filesystem::path path(GetArg("-rpccookiefile", COOKIEAUTH_FILE)); + if (!path.is_complete()) path = GetDataDir() / path; + return path; +} + +bool GenerateAuthCookie(std::string *cookie_out) +{ + unsigned char rand_pwd[32]; + GetRandBytes(rand_pwd, 32); + std::string cookie = COOKIEAUTH_USER + ":" + EncodeBase64(&rand_pwd[0],32); + + /** the umask determines what permissions are used to create this file - + * these are set to 077 in init.cpp unless overridden with -sysperms. + */ + std::ofstream file; + boost::filesystem::path filepath = GetAuthCookieFile(); + file.open(filepath.string().c_str()); + if (!file.is_open()) { + LogPrintf("Unable to open cookie authentication file %s for writing\n", filepath.string()); + return false; + } + file << cookie; + file.close(); + LogPrintf("Generated RPC authentication cookie %s\n", filepath.string()); + + if (cookie_out) + *cookie_out = cookie; + return true; +} + +bool GetAuthCookie(std::string *cookie_out) +{ + std::ifstream file; + std::string cookie; + boost::filesystem::path filepath = GetAuthCookieFile(); + file.open(filepath.string().c_str()); + if (!file.is_open()) + return false; + std::getline(file, cookie); + file.close(); + + if (cookie_out) + *cookie_out = cookie; + return true; +} + +void DeleteAuthCookie() +{ + try { + boost::filesystem::remove(GetAuthCookieFile()); + } catch (const boost::filesystem::filesystem_error& e) { + LogPrintf("%s: Unable to remove random auth cookie file: %s\n", __func__, e.what()); + } +} + diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h index ccd2439c9..2360ec2c6 100644 --- a/src/rpcprotocol.h +++ b/src/rpcprotocol.h @@ -14,6 +14,7 @@ #include <boost/iostreams/stream.hpp> #include <boost/asio.hpp> #include <boost/asio/ssl.hpp> +#include <boost/filesystem.hpp> #include "univalue/univalue.h" @@ -165,4 +166,13 @@ UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const Un std::string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id); UniValue JSONRPCError(int code, const std::string& message); +/** Get name of RPC authentication cookie file */ +boost::filesystem::path GetAuthCookieFile(); +/** Generate a new RPC authentication cookie and write it to disk */ +bool GenerateAuthCookie(std::string *cookie_out); +/** Read the RPC authentication cookie from disk */ +bool GetAuthCookie(std::string *cookie_out); +/** Delete RPC authentication cookie from disk */ +void DeleteAuthCookie(); + #endif // BITCOIN_RPCPROTOCOL_H diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 287cfb2f1..bcad06a0c 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -124,7 +124,7 @@ CAmount AmountFromValue(const UniValue& value) if (!value.isReal() && !value.isNum()) throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number"); CAmount amount; - if (!ParseMoney(value.getValStr(), amount)) + if (!ParseFixedPoint(value.getValStr(), 8, &amount)) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount"); if (!MoneyRange(amount)) throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range"); @@ -597,28 +597,18 @@ void StartRPCThreads() strAllowed += subnet.ToString() + " "; LogPrint("rpc", "Allowing RPC connections from: %s\n", strAllowed); - strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; - if (((mapArgs["-rpcpassword"] == "") || - (mapArgs["-rpcuser"] == mapArgs["-rpcpassword"])) && Params().RequireRPCPassword()) + if (mapArgs["-rpcpassword"] == "") { - unsigned char rand_pwd[32]; - GetRandBytes(rand_pwd, 32); - uiInterface.ThreadSafeMessageBox(strprintf( - _("To use bitcoind, or the -server option to bitcoin-qt, you must set an rpcpassword in the configuration file:\n" - "%s\n" - "It is recommended you use the following random password:\n" - "rpcuser=bitcoinrpc\n" - "rpcpassword=%s\n" - "(you do not need to remember this password)\n" - "The username and password MUST NOT be the same.\n" - "If the file does not exist, create it with owner-readable-only file permissions.\n" - "It is also recommended to set alertnotify so you are notified of problems;\n" - "for example: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" [email protected]\n"), - GetConfigFile().string(), - EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32)), - "", CClientUIInterface::MSG_ERROR | CClientUIInterface::SECURE); - StartShutdown(); - return; + LogPrintf("No rpcpassword set - using random cookie authentication\n"); + if (!GenerateAuthCookie(&strRPCUserColonPass)) { + uiInterface.ThreadSafeMessageBox( + _("Error: A fatal internal error occured, see debug.log for details"), // Same message as AbortNode + "", CClientUIInterface::MSG_ERROR); + StartShutdown(); + return; + } + } else { + strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; } assert(rpc_io_service == NULL); @@ -769,6 +759,8 @@ void StopRPCThreads() } deadlineTimers.clear(); + DeleteAuthCookie(); + rpc_io_service->stop(); g_rpcSignals.Stopped(); if (rpc_worker_group != NULL) diff --git a/src/script/script.cpp b/src/script/script.cpp index fd3392473..b1d2ceeb9 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -260,3 +260,8 @@ std::string CScript::ToString() const } return str; } + +size_t CScript::DynamicMemoryUsage() const +{ + return memusage::DynamicUsage(*(static_cast<const std::vector<unsigned char>*>(this))); +} diff --git a/src/script/script.h b/src/script/script.h index e39ca57f4..aea34d05f 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_SCRIPT_SCRIPT_H #define BITCOIN_SCRIPT_SCRIPT_H +#include "memusage.h" #include "crypto/common.h" #include <assert.h> @@ -607,6 +608,8 @@ public: // The default std::vector::clear() does not release memory. std::vector<unsigned char>().swap(*this); } + + size_t DynamicMemoryUsage() const; }; class CReserveScript diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 9e99ff628..25599beaf 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -142,6 +142,24 @@ BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values) BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("1.00000000")), 100000000LL); BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999.9999999")), 2099999999999990LL); BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999.99999999")), 2099999999999999LL); + + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("1e-8")), COIN/100000000); + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.1e-7")), COIN/100000000); + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.01e-6")), COIN/100000000); + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.0000000000000000000000000000000000000000000000000000000000000000000000000001e+68")), COIN/100000000); + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("10000000000000000000000000000000000000000000000000000000000000000e-64")), COIN); + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000e64")), COIN); + + BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e-9")), UniValue); //should fail + BOOST_CHECK_THROW(AmountFromValue(ValueFromString("0.000000019")), UniValue); //should fail + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000001000000")), 1LL); //should pass, cut trailing 0 + BOOST_CHECK_THROW(AmountFromValue(ValueFromString("19e-9")), UniValue); //should fail + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.19e-6")), 19); //should pass, leading 0 is present + + BOOST_CHECK_THROW(AmountFromValue(ValueFromString("92233720368.54775808")), UniValue); //overflow error + BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e+11")), UniValue); //overflow error + BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e11")), UniValue); //overflow error signless + BOOST_CHECK_THROW(AmountFromValue(ValueFromString("93e+9")), UniValue); //overflow error } BOOST_AUTO_TEST_CASE(json_parse_errors) @@ -151,6 +169,9 @@ BOOST_AUTO_TEST_CASE(json_parse_errors) // Valid, with leading or trailing whitespace BOOST_CHECK_EQUAL(ParseNonRFCJSONValue(" 1.0").get_real(), 1.0); BOOST_CHECK_EQUAL(ParseNonRFCJSONValue("1.0 ").get_real(), 1.0); + + BOOST_CHECK_THROW(AmountFromValue(ParseNonRFCJSONValue(".19e-6")), std::runtime_error); //should fail, missing leading 0, therefore invalid JSON + BOOST_CHECK_EQUAL(AmountFromValue(ParseNonRFCJSONValue("0.00000000000000000000000000000000000001e+30 ")), 1); // Invalid, initial garbage BOOST_CHECK_THROW(ParseNonRFCJSONValue("[1.0"), std::runtime_error); BOOST_CHECK_THROW(ParseNonRFCJSONValue("a1.0"), std::runtime_error); diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 5cb589425..e956cc5b9 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -418,4 +418,70 @@ BOOST_AUTO_TEST_CASE(test_FormatSubVersion) BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:0.9.99(comment1)/")); BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:0.9.99(comment1; comment2)/")); } + +BOOST_AUTO_TEST_CASE(test_ParseFixedPoint) +{ + int64_t amount = 0; + BOOST_CHECK(ParseFixedPoint("0", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 0LL); + BOOST_CHECK(ParseFixedPoint("1", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 100000000LL); + BOOST_CHECK(ParseFixedPoint("0.0", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 0LL); + BOOST_CHECK(ParseFixedPoint("-0.1", 8, &amount)); + BOOST_CHECK_EQUAL(amount, -10000000LL); + BOOST_CHECK(ParseFixedPoint("1.1", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 110000000LL); + BOOST_CHECK(ParseFixedPoint("1.10000000000000000", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 110000000LL); + BOOST_CHECK(ParseFixedPoint("1.1e1", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 1100000000LL); + BOOST_CHECK(ParseFixedPoint("1.1e-1", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 11000000LL); + BOOST_CHECK(ParseFixedPoint("1000", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 100000000000LL); + BOOST_CHECK(ParseFixedPoint("-1000", 8, &amount)); + BOOST_CHECK_EQUAL(amount, -100000000000LL); + BOOST_CHECK(ParseFixedPoint("0.00000001", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 1LL); + BOOST_CHECK(ParseFixedPoint("0.0000000100000000", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 1LL); + BOOST_CHECK(ParseFixedPoint("-0.00000001", 8, &amount)); + BOOST_CHECK_EQUAL(amount, -1LL); + BOOST_CHECK(ParseFixedPoint("1000000000.00000001", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 100000000000000001LL); + BOOST_CHECK(ParseFixedPoint("9999999999.99999999", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 999999999999999999LL); + BOOST_CHECK(ParseFixedPoint("-9999999999.99999999", 8, &amount)); + BOOST_CHECK_EQUAL(amount, -999999999999999999LL); + + BOOST_CHECK(!ParseFixedPoint("", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("a-1000", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-a1000", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-1000a", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-01000", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("00.1", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint(".1", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("--0.1", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("0.000000001", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-0.000000001", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("0.00000001000000001", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-10000000000.00000000", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("10000000000.00000000", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-10000000000.00000001", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("10000000000.00000001", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-10000000000.00000009", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("10000000000.00000009", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-99999999999.99999999", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("99999909999.09999999", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("92233720368.54775807", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("92233720368.54775808", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-92233720368.54775808", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-92233720368.54775809", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("1.1e", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("1.1e-", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("1.", 8, &amount)); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 2292191be..4caa5fc82 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -18,7 +18,7 @@ using namespace std; CTxMemPoolEntry::CTxMemPoolEntry(): - nFee(0), nTxSize(0), nModSize(0), nTime(0), dPriority(0.0), hadNoDependencies(false) + nFee(0), nTxSize(0), nModSize(0), nUsageSize(0), nTime(0), dPriority(0.0), hadNoDependencies(false) { nHeight = MEMPOOL_HEIGHT; } @@ -31,6 +31,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, { nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); nModSize = tx.CalculateModifiedSize(nTxSize); + nUsageSize = tx.DynamicMemoryUsage(); } CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other) @@ -101,6 +102,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i); nTransactionsUpdated++; totalTxSize += entry.GetTxSize(); + cachedInnerUsage += entry.DynamicMemoryUsage(); minerPolicyEstimator->processTransaction(entry, fCurrentEstimate); return true; @@ -146,6 +148,7 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list<CTransaction>& rem removed.push_back(tx); totalTxSize -= mapTx[hash].GetTxSize(); + cachedInnerUsage -= mapTx[hash].DynamicMemoryUsage(); mapTx.erase(hash); nTransactionsUpdated++; minerPolicyEstimator->removeTx(hash); @@ -226,6 +229,7 @@ void CTxMemPool::clear() mapTx.clear(); mapNextTx.clear(); totalTxSize = 0; + cachedInnerUsage = 0; ++nTransactionsUpdated; } @@ -237,6 +241,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const LogPrint("mempool", "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size()); uint64_t checkTotal = 0; + uint64_t innerUsage = 0; CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins)); @@ -245,6 +250,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) { unsigned int i = 0; checkTotal += it->second.GetTxSize(); + innerUsage += it->second.DynamicMemoryUsage(); const CTransaction& tx = it->second.GetTx(); bool fDependsWait = false; BOOST_FOREACH(const CTxIn &txin, tx.vin) { @@ -299,6 +305,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const } assert(totalTxSize == checkTotal); + assert(innerUsage == cachedInnerUsage); } void CTxMemPool::queryHashes(vector<uint256>& vtxid) @@ -419,3 +426,8 @@ bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) const { bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) const { return mempool.exists(txid) || base->HaveCoins(txid); } + +size_t CTxMemPool::DynamicMemoryUsage() const { + LOCK(cs); + return memusage::DynamicUsage(mapTx) + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + cachedInnerUsage; +} diff --git a/src/txmempool.h b/src/txmempool.h index 7271a5f60..ea36ce1ad 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -40,6 +40,7 @@ private: CAmount nFee; //! Cached to avoid expensive parent-transaction lookups size_t nTxSize; //! ... and avoid recomputing tx size size_t nModSize; //! ... and modified size for priority + size_t nUsageSize; //! ... and total memory usage int64_t nTime; //! Local time when entering the mempool double dPriority; //! Priority when entering the mempool unsigned int nHeight; //! Chain height when entering the mempool @@ -58,6 +59,7 @@ public: int64_t GetTime() const { return nTime; } unsigned int GetHeight() const { return nHeight; } bool WasClearAtEntry() const { return hadNoDependencies; } + size_t DynamicMemoryUsage() const { return nUsageSize; } }; class CBlockPolicyEstimator; @@ -73,6 +75,7 @@ public: CInPoint(const CTransaction* ptxIn, uint32_t nIn) { ptx = ptxIn; n = nIn; } void SetNull() { ptx = NULL; n = (uint32_t) -1; } bool IsNull() const { return (ptx == NULL && n == (uint32_t) -1); } + size_t DynamicMemoryUsage() const { return 0; } }; /** @@ -93,6 +96,7 @@ private: CBlockPolicyEstimator* minerPolicyEstimator; uint64_t totalTxSize; //! sum of all mempool tx' byte sizes + uint64_t cachedInnerUsage; //! sum of dynamic memory usage of all the map elements (NOT the maps themselves) public: mutable CCriticalSection cs; @@ -139,6 +143,7 @@ public: LOCK(cs); return mapTx.size(); } + uint64_t GetTotalTxSize() { LOCK(cs); @@ -162,6 +167,8 @@ public: /** Write/Read estimates to disk */ bool WriteFeeEstimates(CAutoFile& fileout) const; bool ReadFeeEstimates(CAutoFile& filein); + + size_t DynamicMemoryUsage() const; }; /** diff --git a/src/util.cpp b/src/util.cpp index bb7df2320..00d0f3a00 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -83,6 +83,7 @@ #include <boost/thread.hpp> #include <openssl/crypto.h> #include <openssl/rand.h> +#include <openssl/conf.h> // Work around clang compilation problem in Boost 1.46: // /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup @@ -134,6 +135,13 @@ public: ppmutexOpenSSL[i] = new CCriticalSection(); CRYPTO_set_locking_callback(locking_callback); + // OpenSSL can optionally load a config file which lists optional loadable modules and engines. + // We don't use them so we don't require the config. However some of our libs may call functions + // which attempt to load the config file, possibly resulting in an exit() or crash if it is missing + // or corrupt. Explicitly tell OpenSSL not to try to load the file. The result for our libs will be + // that the config appears to have been loaded and there are no modules/engines available. + OPENSSL_no_config(); + #ifdef WIN32 // Seed OpenSSL PRNG with current contents of the screen RAND_screen(); diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index 7d1de7d6a..7208ca947 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -538,3 +538,123 @@ int atoi(const std::string& str) { return atoi(str.c_str()); } + +/** Upper bound for mantissa. + * 10^18-1 is the largest arbitrary decimal that will fit in a signed 64-bit integer. + * Larger integers cannot consist of arbitrary combinations of 0-9: + * + * 999999999999999999 1^18-1 + * 9223372036854775807 (1<<63)-1 (max int64_t) + * 9999999999999999999 1^19-1 (would overflow) + */ +static const int64_t UPPER_BOUND = 1000000000000000000LL - 1LL; + +/** Helper function for ParseFixedPoint */ +static inline bool ProcessMantissaDigit(char ch, int64_t &mantissa, int &mantissa_tzeros) +{ + if(ch == '0') + ++mantissa_tzeros; + else { + for (int i=0; i<=mantissa_tzeros; ++i) { + if (mantissa > (UPPER_BOUND / 10LL)) + return false; /* overflow */ + mantissa *= 10; + } + mantissa += ch - '0'; + mantissa_tzeros = 0; + } + return true; +} + +bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out) +{ + int64_t mantissa = 0; + int64_t exponent = 0; + int mantissa_tzeros = 0; + bool mantissa_sign = false; + bool exponent_sign = false; + int ptr = 0; + int end = val.size(); + int point_ofs = 0; + + if (ptr < end && val[ptr] == '-') { + mantissa_sign = true; + ++ptr; + } + if (ptr < end) + { + if (val[ptr] == '0') { + /* pass single 0 */ + ++ptr; + } else if (val[ptr] >= '1' && val[ptr] <= '9') { + while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { + if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros)) + return false; /* overflow */ + ++ptr; + } + } else return false; /* missing expected digit */ + } else return false; /* empty string or loose '-' */ + if (ptr < end && val[ptr] == '.') + { + ++ptr; + if (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') + { + while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { + if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros)) + return false; /* overflow */ + ++ptr; + ++point_ofs; + } + } else return false; /* missing expected digit */ + } + if (ptr < end && (val[ptr] == 'e' || val[ptr] == 'E')) + { + ++ptr; + if (ptr < end && val[ptr] == '+') + ++ptr; + else if (ptr < end && val[ptr] == '-') { + exponent_sign = true; + ++ptr; + } + if (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { + while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { + if (exponent > (UPPER_BOUND / 10LL)) + return false; /* overflow */ + exponent = exponent * 10 + val[ptr] - '0'; + ++ptr; + } + } else return false; /* missing expected digit */ + } + if (ptr != end) + return false; /* trailing garbage */ + + /* finalize exponent */ + if (exponent_sign) + exponent = -exponent; + exponent = exponent - point_ofs + mantissa_tzeros; + + /* finalize mantissa */ + if (mantissa_sign) + mantissa = -mantissa; + + /* convert to one 64-bit fixed-point value */ + exponent += decimals; + if (exponent < 0) + return false; /* cannot represent values smaller than 10^-decimals */ + if (exponent >= 18) + return false; /* cannot represent values larger than or equal to 10^(18-decimals) */ + + for (int i=0; i < exponent; ++i) { + if (mantissa > (UPPER_BOUND / 10LL) || mantissa < -(UPPER_BOUND / 10LL)) + return false; /* overflow */ + mantissa *= 10; + } + if (mantissa > UPPER_BOUND || mantissa < -UPPER_BOUND) + return false; /* overflow */ + + if (amount_out) + *amount_out = mantissa; + + return true; +} + diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h index 58329b51b..dcd56751f 100644 --- a/src/utilstrencodings.h +++ b/src/utilstrencodings.h @@ -109,4 +109,11 @@ bool TimingResistantEqual(const T& a, const T& b) return accumulator == 0; } +/** Parse number as fixed point according to JSON number syntax. + * See http://json.org/number.gif + * @returns true on success, false on error. + * @note The result must be in the range (-10^18,10^18), otherwise an overflow error will trigger. + */ +bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out); + #endif // BITCOIN_UTILSTRENCODINGS_H |