diff options
34 files changed, 851 insertions, 558 deletions
diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index 100b8653a8..121e10bd37 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -110,13 +110,8 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ if test x$bitcoin_qt_got_major_vers = x5; then _BITCOIN_QT_IS_STATIC if test x$bitcoin_cv_static_qt = xyes; then + _BITCOIN_QT_FIND_STATIC_PLUGINS AC_DEFINE(QT_STATICPLUGIN, 1, [Define this symbol if qt plugins are static]) - if test x$qt_plugin_path != x; then - QT_LIBS="$QT_LIBS -L$qt_plugin_path/platforms" - fi - if test x$use_pkgconfig = xyes; then - PKG_CHECK_MODULES([QTPLATFORM], [Qt5PlatformSupport], [QT_LIBS="$QTPLATFORM_LIBS $QT_LIBS"]) - fi AC_CACHE_CHECK(for Qt < 5.4, bitcoin_cv_need_acc_widget,[AC_COMPILE_IFELSE([AC_LANG_PROGRAM( [[#include <QtCore>]],[[ #if QT_VERSION >= 0x050400 @@ -127,25 +122,15 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ [bitcoin_cv_need_acc_widget=no]) ]) if test "x$bitcoin_cv_need_acc_widget" = "xyes"; then - if test x$qt_plugin_path != x; then - QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible" - fi _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(AccessibleFactory)], [-lqtaccessiblewidgets]) fi if test x$TARGET_OS = xwindows; then _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)],[-lqwindows]) AC_DEFINE(QT_QPA_PLATFORM_WINDOWS, 1, [Define this symbol if the qt platform is windows]) elif test x$TARGET_OS = xlinux; then - PKG_CHECK_MODULES([X11XCB], [x11-xcb], [QT_LIBS="$X11XCB_LIBS $QT_LIBS"]) - if ${PKG_CONFIG} --exists "Qt5Core >= 5.5" 2>/dev/null; then - PKG_CHECK_MODULES([QTXCBQPA], [Qt5XcbQpa], [QT_LIBS="$QTXCBQPA_LIBS $QT_LIBS"]) - fi _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)],[-lqxcb -lxcb-static]) AC_DEFINE(QT_QPA_PLATFORM_XCB, 1, [Define this symbol if the qt platform is xcb]) elif test x$TARGET_OS = xdarwin; then - if test x$use_pkgconfig = xyes; then - PKG_CHECK_MODULES([QTPRINT], [Qt5PrintSupport], [QT_LIBS="$QTPRINT_LIBS $QT_LIBS"]) - fi AX_CHECK_LINK_FLAG([[-framework IOKit]],[QT_LIBS="$QT_LIBS -framework IOKit"],[AC_MSG_ERROR(could not iokit framework)]) _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin)],[-lqcocoa]) AC_DEFINE(QT_QPA_PLATFORM_COCOA, 1, [Define this symbol if the qt platform is cocoa]) @@ -154,10 +139,6 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ else if test x$TARGET_OS = xwindows; then AC_DEFINE(QT_STATICPLUGIN, 1, [Define this symbol if qt plugins are static]) - if test x$qt_plugin_path != x; then - QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible" - QT_LIBS="$QT_LIBS -L$qt_plugin_path/codecs" - fi _BITCOIN_QT_CHECK_STATIC_PLUGINS([ Q_IMPORT_PLUGIN(qcncodecs) Q_IMPORT_PLUGIN(qjpcodecs) @@ -297,6 +278,39 @@ AC_DEFUN([_BITCOIN_QT_CHECK_STATIC_PLUGINS],[ LIBS="$CHECK_STATIC_PLUGINS_TEMP_LIBS" ]) +dnl Internal. Find paths necessary for linking qt static plugins +dnl Inputs: bitcoin_qt_got_major_vers. 4 or 5. +dnl Inputs: qt_plugin_path. optional. +dnl Outputs: QT_LIBS is appended +AC_DEFUN([_BITCOIN_QT_FIND_STATIC_PLUGINS],[ + if test x$bitcoin_qt_got_major_vers = x5; then + if test x$qt_plugin_path != x; then + QT_LIBS="$QT_LIBS -L$qt_plugin_path/platforms" + if test -d "$qt_plugin_path/accessible"; then + QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible" + fi + fi + m4_ifdef([PKG_CHECK_MODULES],[ + if test x$use_pkgconfig = xyes; then + PKG_CHECK_MODULES([QTPLATFORM], [Qt5PlatformSupport], [QT_LIBS="$QTPLATFORM_LIBS $QT_LIBS"]) + if test x$TARGET_OS = xlinux; then + PKG_CHECK_MODULES([X11XCB], [x11-xcb], [QT_LIBS="$X11XCB_LIBS $QT_LIBS"]) + if ${PKG_CONFIG} --exists "Qt5Core >= 5.5" 2>/dev/null; then + PKG_CHECK_MODULES([QTXCBQPA], [Qt5XcbQpa], [QT_LIBS="$QTXCBQPA_LIBS $QT_LIBS"]) + fi + elif test x$TARGET_OS = xdarwin; then + PKG_CHECK_MODULES([QTPRINT], [Qt5PrintSupport], [QT_LIBS="$QTPRINT_LIBS $QT_LIBS"]) + fi + fi + ]) + else + if test x$qt_plugin_path != x; then + QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible" + QT_LIBS="$QT_LIBS -L$qt_plugin_path/codecs" + fi + fi +]) + dnl Internal. Find Qt libraries using pkg-config. dnl Inputs: bitcoin_qt_want_version (from --with-gui=). The version to check dnl first. diff --git a/configure.ac b/configure.ac index 7f90b5f395..a524bded6f 100644 --- a/configure.ac +++ b/configure.ac @@ -680,19 +680,26 @@ else fi fi -AC_CHECK_LIB([crypto],[RAND_egd],[],[ - AC_ARG_WITH([libressl], - [AS_HELP_STRING([--with-libressl],[Build with system LibreSSL (default is no; DANGEROUS; NOT SUPPORTED)])], - [AC_MSG_WARN([Detected LibreSSL: This is NOT supported, and may break consensus compatibility!])], - [AC_MSG_ERROR([Detected LibreSSL: This is NOT supported, and may break consensus compatibility!])] - ) -]) - CFLAGS_TEMP="$CFLAGS" LIBS_TEMP="$LIBS" CFLAGS="$CFLAGS $SSL_CFLAGS $CRYPTO_CFLAGS" LIBS="$LIBS $SSL_LIBS $CRYPTO_LIBS" AC_CHECK_HEADER([openssl/ec.h],, AC_MSG_ERROR(OpenSSL ec header missing),) + +AC_MSG_CHECKING(for a supported OpenSSL version) +AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + #include <openssl/rand.h> + ]], + [[RAND_egd(NULL);]])], + [AC_MSG_RESULT(yes)], + [ + AC_ARG_WITH([libressl], + [AS_HELP_STRING([--with-libressl],[Build with system LibreSSL (default is no; DANGEROUS; NOT SUPPORTED)])], + [AC_MSG_WARN([Detected LibreSSL: This is NOT supported, and may break consensus compatibility!])], + [AC_MSG_ERROR([Detected LibreSSL: This is NOT supported, and may break consensus compatibility!])] + )] +) + CFLAGS="$CFLAGS_TEMP" LIBS="$LIBS_TEMP" diff --git a/contrib/README.md b/contrib/README.md index 7d4b91e887..125594312b 100644 --- a/contrib/README.md +++ b/contrib/README.md @@ -1,9 +1,6 @@ Wallet Tools --------------------- -### [BitRPC](/contrib/bitrpc) ### -Allows for sending of all standard Bitcoin commands via RPC rather than as command line args. - ### [SpendFrom](/contrib/spendfrom) ### Use the raw transactions API to send coins received on a particular diff --git a/contrib/bitrpc/README.md b/contrib/bitrpc/README.md deleted file mode 100644 index f5ef2f0405..0000000000 --- a/contrib/bitrpc/README.md +++ /dev/null @@ -1,8 +0,0 @@ -### BitRPC -Allows for sending of all standard Bitcoin commands via RPC rather than as command line args. - -### Looking for Wallet Tools? -BitRPC.py is able to do the exact same thing as `walletchangepass.py` and `walletunlock.py`. Their respective commands in BitRPC.py are: - - bitrpc.py walletpassphrasechange - bitrpc.py walletpassphrase
\ No newline at end of file diff --git a/contrib/bitrpc/bitrpc.py b/contrib/bitrpc/bitrpc.py deleted file mode 100644 index c3ce9d7936..0000000000 --- a/contrib/bitrpc/bitrpc.py +++ /dev/null @@ -1,335 +0,0 @@ -from jsonrpc import ServiceProxy -import sys -import string -import getpass - -# ===== BEGIN USER SETTINGS ===== -# if you do not set these you will be prompted for a password for every command -rpcuser = "" -rpcpass = "" -# ====== END USER SETTINGS ====== - - -if rpcpass == "": - access = ServiceProxy("http://127.0.0.1:8332") -else: - access = ServiceProxy("http://"+rpcuser+":"+rpcpass+"@127.0.0.1:8332") -cmd = sys.argv[1].lower() - -if cmd == "backupwallet": - try: - path = raw_input("Enter destination path/filename: ") - print access.backupwallet(path) - except Exception as inst: - print inst - -elif cmd == "encryptwallet": - try: - pwd = getpass.getpass(prompt="Enter passphrase: ") - pwd2 = getpass.getpass(prompt="Repeat passphrase: ") - if pwd == pwd2: - access.encryptwallet(pwd) - print "\n---Wallet encrypted. Server stopping, restart to run with encrypted wallet---\n" - else: - print "\n---Passphrases do not match---\n" - except Exception as inst: - print inst - -elif cmd == "getaccount": - try: - addr = raw_input("Enter a Bitcoin address: ") - print access.getaccount(addr) - except Exception as inst: - print inst - -elif cmd == "getaccountaddress": - try: - acct = raw_input("Enter an account name: ") - print access.getaccountaddress(acct) - except Exception as inst: - print inst - -elif cmd == "getaddressesbyaccount": - try: - acct = raw_input("Enter an account name: ") - print access.getaddressesbyaccount(acct) - except Exception as inst: - print inst - -elif cmd == "getbalance": - try: - acct = raw_input("Enter an account (optional): ") - mc = raw_input("Minimum confirmations (optional): ") - try: - print access.getbalance(acct, mc) - except: - print access.getbalance() - except Exception as inst: - print inst - -elif cmd == "getblockbycount": - try: - height = raw_input("Height: ") - print access.getblockbycount(height) - except Exception as inst: - print inst - -elif cmd == "getblockcount": - try: - print access.getblockcount() - except Exception as inst: - print inst - -elif cmd == "getblocknumber": - try: - print access.getblocknumber() - except Exception as inst: - print inst - -elif cmd == "getconnectioncount": - try: - print access.getconnectioncount() - except Exception as inst: - print inst - -elif cmd == "getdifficulty": - try: - print access.getdifficulty() - except Exception as inst: - print inst - -elif cmd == "getgenerate": - try: - print access.getgenerate() - except Exception as inst: - print inst - -elif cmd == "gethashespersec": - try: - print access.gethashespersec() - except Exception as inst: - print inst - -elif cmd == "getinfo": - try: - print access.getinfo() - except Exception as inst: - print inst - -elif cmd == "getnewaddress": - try: - acct = raw_input("Enter an account name: ") - try: - print access.getnewaddress(acct) - except: - print access.getnewaddress() - except Exception as inst: - print inst - -elif cmd == "getreceivedbyaccount": - try: - acct = raw_input("Enter an account (optional): ") - mc = raw_input("Minimum confirmations (optional): ") - try: - print access.getreceivedbyaccount(acct, mc) - except: - print access.getreceivedbyaccount() - except Exception as inst: - print inst - -elif cmd == "getreceivedbyaddress": - try: - addr = raw_input("Enter a Bitcoin address (optional): ") - mc = raw_input("Minimum confirmations (optional): ") - try: - print access.getreceivedbyaddress(addr, mc) - except: - print access.getreceivedbyaddress() - except Exception as inst: - print inst - -elif cmd == "gettransaction": - try: - txid = raw_input("Enter a transaction ID: ") - print access.gettransaction(txid) - except Exception as inst: - print inst - -elif cmd == "getwork": - try: - data = raw_input("Data (optional): ") - try: - print access.gettransaction(data) - except: - print access.gettransaction() - except Exception as inst: - print inst - -elif cmd == "help": - try: - cmd = raw_input("Command (optional): ") - try: - print access.help(cmd) - except: - print access.help() - except Exception as inst: - print inst - -elif cmd == "listaccounts": - try: - mc = raw_input("Minimum confirmations (optional): ") - try: - print access.listaccounts(mc) - except: - print access.listaccounts() - except Exception as inst: - print inst - -elif cmd == "listreceivedbyaccount": - try: - mc = raw_input("Minimum confirmations (optional): ") - incemp = raw_input("Include empty? (true/false, optional): ") - try: - print access.listreceivedbyaccount(mc, incemp) - except: - print access.listreceivedbyaccount() - except Exception as inst: - print inst - -elif cmd == "listreceivedbyaddress": - try: - mc = raw_input("Minimum confirmations (optional): ") - incemp = raw_input("Include empty? (true/false, optional): ") - try: - print access.listreceivedbyaddress(mc, incemp) - except: - print access.listreceivedbyaddress() - except Exception as inst: - print inst - -elif cmd == "listtransactions": - try: - acct = raw_input("Account (optional): ") - count = raw_input("Number of transactions (optional): ") - frm = raw_input("Skip (optional):") - try: - print access.listtransactions(acct, count, frm) - except: - print access.listtransactions() - except Exception as inst: - print inst - -elif cmd == "move": - try: - frm = raw_input("From: ") - to = raw_input("To: ") - amt = raw_input("Amount:") - mc = raw_input("Minimum confirmations (optional): ") - comment = raw_input("Comment (optional): ") - try: - print access.move(frm, to, amt, mc, comment) - except: - print access.move(frm, to, amt) - except Exception as inst: - print inst - -elif cmd == "sendfrom": - try: - frm = raw_input("From: ") - to = raw_input("To: ") - amt = raw_input("Amount:") - mc = raw_input("Minimum confirmations (optional): ") - comment = raw_input("Comment (optional): ") - commentto = raw_input("Comment-to (optional): ") - try: - print access.sendfrom(frm, to, amt, mc, comment, commentto) - except: - print access.sendfrom(frm, to, amt) - except Exception as inst: - print inst - -elif cmd == "sendmany": - try: - frm = raw_input("From: ") - to = raw_input("To (in format address1:amount1,address2:amount2,...): ") - mc = raw_input("Minimum confirmations (optional): ") - comment = raw_input("Comment (optional): ") - try: - print access.sendmany(frm,to,mc,comment) - except: - print access.sendmany(frm,to) - except Exception as inst: - print inst - -elif cmd == "sendtoaddress": - try: - to = raw_input("To (in format address1:amount1,address2:amount2,...): ") - amt = raw_input("Amount:") - comment = raw_input("Comment (optional): ") - commentto = raw_input("Comment-to (optional): ") - try: - print access.sendtoaddress(to,amt,comment,commentto) - except: - print access.sendtoaddress(to,amt) - except Exception as inst: - print inst - -elif cmd == "setaccount": - try: - addr = raw_input("Address: ") - acct = raw_input("Account:") - print access.setaccount(addr,acct) - except Exception as inst: - print inst - -elif cmd == "setgenerate": - try: - gen= raw_input("Generate? (true/false): ") - cpus = raw_input("Max processors/cores (-1 for unlimited, optional):") - try: - print access.setgenerate(gen, cpus) - except: - print access.setgenerate(gen) - except Exception as inst: - print inst - -elif cmd == "settxfee": - try: - amt = raw_input("Amount:") - print access.settxfee(amt) - except Exception as inst: - print inst - -elif cmd == "stop": - try: - print access.stop() - except Exception as inst: - print inst - -elif cmd == "validateaddress": - try: - addr = raw_input("Address: ") - print access.validateaddress(addr) - except Exception as inst: - print inst - -elif cmd == "walletpassphrase": - try: - pwd = getpass.getpass(prompt="Enter wallet passphrase: ") - access.walletpassphrase(pwd, 60) - print "\n---Wallet unlocked---\n" - except Exception as inst: - print inst - -elif cmd == "walletpassphrasechange": - try: - pwd = getpass.getpass(prompt="Enter old wallet passphrase: ") - pwd2 = getpass.getpass(prompt="Enter new wallet passphrase: ") - access.walletpassphrasechange(pwd, pwd2) - print - print "\n---Passphrase changed---\n" - except Exception as inst: - print inst - -else: - print "Command not found or not supported" diff --git a/doc/release-notes.md b/doc/release-notes.md index 7480a7cd21..9caac4f7ae 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -27,6 +27,14 @@ Low-level RPC API changes advantage if a JSON library insists on using a lossy floating point type for numbers, which would be dangerous for monetary amounts. +Option parsing behavior +----------------------- + +Command line options are now parsed strictly in the order in which they are +specified. It used to be the case that `-X -noX` ends up, unintuitively, with X +set, as `-X` had precedence over `-noX`. This is no longer the case. Like for +other software, the last specified value for an option will hold. + 0.12.0 Change log ================= @@ -55,3 +63,5 @@ git merge commit are mentioned. ### Miscellaneous +- Removed bitrpc.py from contrib + diff --git a/doc/release-notes/release-notes-0.11.0.md b/doc/release-notes/release-notes-0.11.0.md new file mode 100644 index 0000000000..28e49fb7ea --- /dev/null +++ b/doc/release-notes/release-notes-0.11.0.md @@ -0,0 +1,505 @@ +Bitcoin Core version 0.11.0 is now available from: + + <https://bitcoin.org/bin/bitcoin-core-0.11.0/> + +This is a new major version release, bringing both new features and +bug fixes. + +Please report bugs using the issue tracker at github: + + <https://github.com/bitcoin/bitcoin/issues> + +Upgrading and downgrading +========================= + +How to Upgrade +-------------- + +If you are running an older version, shut it down. Wait until it has completely +shut down (which might take a few minutes for older versions), then run the +installer (on Windows) or just copy over /Applications/Bitcoin-Qt (on Mac) or +bitcoind/bitcoin-qt (on Linux). + +Downgrade warning +------------------ + +Because release 0.10.0 and later makes use of headers-first synchronization and +parallel block download (see further), the block files and databases are not +backwards-compatible with pre-0.10 versions of Bitcoin Core or other software: + +* Blocks will be stored on disk out of order (in the order they are +received, really), which makes it incompatible with some tools or +other programs. Reindexing using earlier versions will also not work +anymore as a result of this. + +* The block index database will now hold headers for which no block is +stored on disk, which earlier versions won't support. + +If you want to be able to downgrade smoothly, make a backup of your entire data +directory. Without this your node will need start syncing (or importing from +bootstrap.dat) anew afterwards. It is possible that the data from a completely +synchronised 0.10 node may be usable in older versions as-is, but this is not +supported and may break as soon as the older version attempts to reindex. + +This does not affect wallet forward or backward compatibility. There are no +known problems when downgrading from 0.11.x to 0.10.x. + +Important information +====================== + +Transaction flooding +--------------------- + +At the time of this release, the P2P network is being flooded with low-fee +transactions. This causes a ballooning of the mempool size. + +If this growth of the mempool causes problematic memory use on your node, it is +possible to change a few configuration options to work around this. The growth +of the mempool can be monitored with the RPC command `getmempoolinfo`. + +One is to increase the minimum transaction relay fee `minrelaytxfee`, which +defaults to 0.00001. This will cause transactions with fewer BTC/kB fee to be +rejected, and thus fewer transactions entering the mempool. + +The other is to restrict the relaying of free transactions with +`limitfreerelay`. This option sets the number of kB/minute at which +free transactions (with enough priority) will be accepted. It defaults to 15. +Reducing this number reduces the speed at which the mempool can grow due +to free transactions. + +For example, add the following to `bitcoin.conf`: + + minrelaytxfee=0.00005 + limitfreerelay=5 + +More robust solutions are being worked on for a follow-up release. + +Notable changes +=============== + +Block file pruning +---------------------- + +This release supports running a fully validating node without maintaining a copy +of the raw block and undo data on disk. To recap, there are four types of data +related to the blockchain in the bitcoin system: the raw blocks as received over +the network (blk???.dat), the undo data (rev???.dat), the block index and the +UTXO set (both LevelDB databases). The databases are built from the raw data. + +Block pruning allows Bitcoin Core to delete the raw block and undo data once +it's been validated and used to build the databases. At that point, the raw data +is used only to relay blocks to other nodes, to handle reorganizations, to look +up old transactions (if -txindex is enabled or via the RPC/REST interfaces), or +for rescanning the wallet. The block index continues to hold the metadata about +all blocks in the blockchain. + +The user specifies how much space to allot for block & undo files. The minimum +allowed is 550MB. Note that this is in addition to whatever is required for the +block index and UTXO databases. The minimum was chosen so that Bitcoin Core will +be able to maintain at least 288 blocks on disk (two days worth of blocks at 10 +minutes per block). In rare instances it is possible that the amount of space +used will exceed the pruning target in order to keep the required last 288 +blocks on disk. + +Block pruning works during initial sync in the same way as during steady state, +by deleting block files "as you go" whenever disk space is allocated. Thus, if +the user specifies 550MB, once that level is reached the program will begin +deleting the oldest block and undo files, while continuing to download the +blockchain. + +For now, block pruning disables block relay. In the future, nodes with block +pruning will at a minimum relay "new" blocks, meaning blocks that extend their +active chain. + +Block pruning is currently incompatible with running a wallet due to the fact +that block data is used for rescanning the wallet and importing keys or +addresses (which require a rescan.) However, running the wallet with block +pruning will be supported in the near future, subject to those limitations. + +Block pruning is also incompatible with -txindex and will automatically disable +it. + +Once you have pruned blocks, going back to unpruned state requires +re-downloading the entire blockchain. To do this, re-start the node with +-reindex. Note also that any problem that would cause a user to reindex (e.g., +disk corruption) will cause a pruned node to redownload the entire blockchain. +Finally, note that when a pruned node reindexes, it will delete any blk???.dat +and rev???.dat files in the data directory prior to restarting the download. + +To enable block pruning on the command line: + +- `-prune=N`: where N is the number of MB to allot for raw block & undo data. + +Modified RPC calls: + +- `getblockchaininfo` now includes whether we are in pruned mode or not. +- `getblock` will check if the block's data has been pruned and if so, return an +error. +- `getrawtransaction` will no longer be able to locate a transaction that has a +UTXO but where its block file has been pruned. + +Pruning is disabled by default. + +Big endian support +-------------------- + +Experimental support for big-endian CPU architectures was added in this +release. All little-endian specific code was replaced with endian-neutral +constructs. This has been tested on at least MIPS and PPC hosts. The build +system will automatically detect the endianness of the target. + +Memory usage optimization +-------------------------- + +There have been many changes in this release to reduce the default memory usage +of a node, among which: + +- Accurate UTXO cache size accounting (#6102); this makes the option `-dbcache` + precise where this grossly underestimated memory usage before +- Reduce size of per-peer data structure (#6064 and others); this increases the + number of connections that can be supported with the same amount of memory +- Reduce the number of threads (#5964, #5679); lowers the amount of (esp. + virtual) memory needed + +Fee estimation changes +---------------------- + +This release improves the algorithm used for fee estimation. Previously, -1 +was returned when there was insufficient data to give an estimate. Now, -1 +will also be returned when there is no fee or priority high enough for the +desired confirmation target. In those cases, it can help to ask for an estimate +for a higher target number of blocks. It is not uncommon for there to be no +fee or priority high enough to be reliably (85%) included in the next block and +for this reason, the default for `-txconfirmtarget=n` has changed from 1 to 2. + +Privacy: Disable wallet transaction broadcast +---------------------------------------------- + +This release adds an option `-walletbroadcast=0` to prevent automatic +transaction broadcast and rebroadcast (#5951). This option allows separating +transaction submission from the node functionality. + +Making use of this, third-party scripts can be written to take care of +transaction (re)broadcast: + +- Send the transaction as normal, either through RPC or the GUI +- Retrieve the transaction data through RPC using `gettransaction` (NOT + `getrawtransaction`). The `hex` field of the result will contain the raw + hexadecimal representation of the transaction +- The transaction can then be broadcasted through arbitrary mechanisms + supported by the script + +One such application is selective Tor usage, where the node runs on the normal +internet but transactions are broadcasted over Tor. + +For an example script see [bitcoin-submittx](https://github.com/laanwj/bitcoin-submittx). + +Privacy: Stream isolation for Tor +---------------------------------- + +This release adds functionality to create a new circuit for every peer +connection, when the software is used with Tor. The new option, +`-proxyrandomize`, is on by default. + +When enabled, every outgoing connection will (potentially) go through a +different exit node. That significantly reduces the chance to get unlucky and +pick a single exit node that is either malicious, or widely banned from the P2P +network. This improves connection reliability as well as privacy, especially +for the initial connections. + +**Important note:** If a non-Tor SOCKS5 proxy is configured that supports +authentication, but doesn't require it, this change may cause that proxy to reject +connections. A user and password is sent where they weren't before. This setup +is exceedingly rare, but in this case `-proxyrandomize=0` can be passed to +disable the behavior. + +0.11.0 Change log +================= + +Detailed release notes follow. This overview includes changes that affect +behavior, not code moves, refactors and string updates. For convenience in locating +the code changes and accompanying discussion, both the pull request and +git merge commit are mentioned. + +### RPC and REST +- #5461 `5f7279a` signrawtransaction: validate private key +- #5444 `103f66b` Add /rest/headers/<count>/<hash>.<ext> +- #4964 `95ecc0a` Add scriptPubKey field to validateaddress RPC call +- #5476 `c986972` Add time offset into getpeerinfo output +- #5540 `84eba47` Add unconfirmed and immature balances to getwalletinfo +- #5599 `40e96a3` Get rid of the internal miner's hashmeter +- #5711 `87ecfb0` Push down RPC locks +- #5754 `1c4e3f9` fix getblocktemplate lock issue +- #5756 `5d901d8` Fix getblocktemplate_proposals test by mining one block +- #5548 `d48ce48` Add /rest/chaininfos +- #5992 `4c4f1b4` Push down RPC reqWallet flag +- #6036 `585b5db` Show zero value txouts in listunspent +- #5199 `6364408` Add RPC call `gettxoutproof` to generate and verify merkle blocks +- #5418 `16341cc` Report missing inputs in sendrawtransaction +- #5937 `40f5e8d` show script verification errors in signrawtransaction result +- #5420 `1fd2d39` getutxos REST command (based on Bip64) +- #6193 `42746b0` [REST] remove json input for getutxos, limit to query max. 15 outpoints +- #6226 `5901596` json: fail read_string if string contains trailing garbage + +### Configuration and command-line options +- #5636 `a353ad4` Add option `-allowselfsignedrootcertificate` to allow self signed root certs (for testing payment requests) +- #5900 `3e8a1f2` Add a consistency check `-checkblockindex` for the block chain data structures +- #5951 `7efc9cf` Make it possible to disable wallet transaction broadcast (using `-walletbroadcast=0`) +- #5911 `b6ea3bc` privacy: Stream isolation for Tor (on by default, use `-proxyrandomize=0` to disable) +- #5863 `c271304` Add autoprune functionality (`-prune=<size>`) +- #6153 `0bcf04f` Parameter interaction: disable upnp if -proxy set +- #6274 `4d9c7fe` Add option `-alerts` to opt out of alert system + +### Block and transaction handling +- #5367 `dcc1304` Do all block index writes in a batch +- #5253 `203632d` Check against MANDATORY flags prior to accepting to mempool +- #5459 `4406c3e` Reject headers that build on an invalid parent +- #5481 `055f3ae` Apply AreSane() checks to the fees from the network +- #5580 `40d65eb` Preemptively catch a few potential bugs +- #5349 `f55c5e9` Implement test for merkle tree malleability in CPartialMerkleTree +- #5564 `a89b837` clarify obscure uses of EvalScript() +- #5521 `8e4578a` Reject non-final txs even in testnet/regtest +- #5707 `6af674e` Change hardcoded character constants to descriptive named constants for db keys +- #5286 `fcf646c` Change the default maximum OP_RETURN size to 80 bytes +- #5710 `175d86e` Add more information to errors in ReadBlockFromDisk +- #5948 `b36f1ce` Use GetAncestor to compute new target +- #5959 `a0bfc69` Add additional block index consistency checks +- #6058 `7e0e7f8` autoprune minor post-merge improvements +- #5159 `2cc1372` New fee estimation code +- #6102 `6fb90d8` Implement accurate UTXO cache size accounting +- #6129 `2a82298` Bug fix for clearing fCheckForPruning +- #5947 `e9af4e6` Alert if it is very likely we are getting a bad chain +- #6203 `c00ae64` Remove P2SH coinbase flag, no longer interesting +- #5985 `37b4e42` Fix removing of orphan transactions +- #6221 `6cb70ca` Prune: Support noncontiguous block files +- #6256 `fce474c` Use best header chain timestamps to detect partitioning +- #6233 `a587606` Advance pindexLastCommonBlock for blocks in chainActive + +### P2P protocol and network code +- #5507 `844ace9` Prevent DOS attacks on in-flight data structures +- #5770 `32a8b6a` Sanitize command strings before logging them +- #5859 `dd4ffce` Add correct bool combiner for net signals +- #5876 `8e4fd0c` Add a NODE_GETUTXO service bit and document NODE_NETWORK +- #6028 `b9311fb` Move nLastTry from CAddress to CAddrInfo +- #5662 `5048465` Change download logic to allow calling getdata on inbound peers +- #5971 `18d2832` replace absolute sleep with conditional wait +- #5918 `7bf5d5e` Use equivalent PoW for non-main-chain requests +- #6059 `f026ab6` chainparams: use SeedSpec6's rather than CAddress's for fixed seeds +- #6080 `31c0bf1` Add jonasschnellis dns seeder +- #5976 `9f7809f` Reduce download timeouts as blocks arrive +- #6172 `b4bbad1` Ignore getheaders requests when not synced +- #5875 `304892f` Be stricter in processing unrequested blocks +- #6333 `41bbc85` Hardcoded seeds update June 2015 + +### Validation +- #5143 `48e1765` Implement BIP62 rule 6 +- #5713 `41e6e4c` Implement BIP66 + +### Build system +- #5501 `c76c9d2` Add mips, mipsel and aarch64 to depends platforms +- #5334 `cf87536` libbitcoinconsensus: Add pkg-config support +- #5514 `ed11d53` Fix 'make distcheck' +- #5505 `a99ef7d` Build winshutdownmonitor.cpp on Windows only +- #5582 `e8a6639` Osx toolchain update +- #5684 `ab64022` osx: bump build sdk to 10.9 +- #5695 `23ef5b7` depends: latest config.guess and config.sub +- #5509 `31dedb4` Fixes when compiling in c++11 mode +- #5819 `f8e68f7` release: use static libstdc++ and disable reduced exports by default +- #5510 `7c3fbc3` Big endian support +- #5149 `c7abfa5` Add script to verify all merge commits are signed +- #6082 `7abbb7e` qt: disable qt tests when one of the checks for the gui fails +- #6244 `0401aa2` configure: Detect (and reject) LibreSSL +- #6269 `95aca44` gitian: Use the new bitcoin-detached-sigs git repo for OSX signatures +- #6285 `ef1d506` Fix scheduler build with some boost versions. +- #6280 `25c2216` depends: fix Boost 1.55 build on GCC 5 +- #6303 `b711599` gitian: add a gitian-win-signer descriptor +- #6246 `8ea6d37` Fix build on FreeBSD +- #6282 `daf956b` fix crash on shutdown when e.g. changing -txindex and abort action +- #6354 `bdf0d94` Gitian windows signing normalization + +### Wallet +- #2340 `811c71d` Discourage fee sniping with nLockTime +- #5485 `d01bcc4` Enforce minRelayTxFee on wallet created tx and add a maxtxfee option +- #5508 `9a5cabf` Add RandAddSeedPerfmon to MakeNewKey +- #4805 `8204e19` Do not flush the wallet in AddToWalletIfInvolvingMe(..) +- #5319 `93b7544` Clean up wallet encryption code +- #5831 `df5c246` Subtract fee from amount +- #6076 `6c97fd1` wallet: fix boost::get usage with boost 1.58 +- #5511 `23c998d` Sort pending wallet transactions before reaccepting +- #6126 `26e08a1` Change default nTxConfirmTarget to 2 +- #6183 `75a4d51` Fix off-by-one error w/ nLockTime in the wallet +- #6276 `c9fd907` Fix getbalance * 0 + +### GUI +- #5219 `f3af0c8` New icons +- #5228 `bb3c75b` HiDPI (retina) support for splash screen +- #5258 `73cbf0a` The RPC Console should be a QWidget to make window more independent +- #5488 `851dfc7` Light blue icon color for regtest +- #5547 `a39aa74` New icon for the debug window +- #5493 `e515309` Adopt style colour for button icons +- #5557 `70477a0` On close of splashscreen interrupt verifyDB +- #5559 `83be8fd` Make the command-line-args dialog better +- #5144 `c5380a9` Elaborate on signverify message dialog warning +- #5489 `d1aa3c6` Optimize PNG files +- #5649 `e0cd2f5` Use text-color icons for system tray Send/Receive menu entries +- #5651 `848f55d` Coin Control: Use U+2248 "ALMOST EQUAL TO" rather than a simple tilde +- #5626 `ab0d798` Fix icon sizes and column width +- #5683 `c7b22aa` add new osx dmg background picture +- #5620 `7823598` Payment request expiration bug fix +- #5729 `9c4a5a5` Allow unit changes for read-only BitcoinAmountField +- #5753 `0f44672` Add bitcoin logo to about screen +- #5629 `a956586` Prevent amount overflow problem with payment requests +- #5830 `215475a` Don't save geometry for options and about/help window +- #5793 `d26f0b2` Honor current network when creating autostart link +- #5847 `f238add` Startup script for centos, with documentation +- #5915 `5bd3a92` Fix a static qt5 crash when using certain versions of libxcb +- #5898 `bb56781` Fix rpc console font size to flexible metrics +- #5467 `bc8535b` Payment request / server work - part 2 +- #6161 `180c164` Remove movable option for toolbar +- #6160 `0d862c2` Overviewpage: make sure warning icons gets colored + +### Tests +- #5453 `2f2d337` Add ability to run single test manually to RPC tests +- #5421 `886eb57` Test unexecuted OP_CODESEPARATOR +- #5530 `565b300` Additional rpc tests +- #5611 `37b185c` Fix spurious windows test failures after 012598880c +- #5613 `2eda47b` Fix smartfees test for change to relay policy +- #5612 `e3f5727` Fix zapwallettxes test +- #5642 `30a5b5f` Prepare paymentservertests for new unit tests +- #5784 `e3a3cd7` Fix usage of NegateSignatureS in script_tests +- #5813 `ee9f2bf` Add unit tests for next difficulty calculations +- #5855 `d7989c0` Travis: run unit tests in different orders +- #5852 `cdae53e` Reinitialize state in between individual unit tests. +- #5883 `164d7b6` tests: add a BasicTestingSetup and apply to all tests +- #5940 `446bb70` Regression test for ResendWalletTransactions +- #6052 `cf7adad` fix and enable bip32 unit test +- #6039 `734f80a` tests: Error when setgenerate is used on regtest +- #6074 `948beaf` Correct the PUSHDATA4 minimal encoding test in script_invalid.json +- #6032 `e08886d` Stop nodes after RPC tests, even with --nocleanup +- #6075 `df1609f` Add additional script edge condition tests +- #5981 `da38dc6` Python P2P testing +- #5958 `9ef00c3` Add multisig rpc tests +- #6112 `fec5c0e` Add more script edge condition tests + +### Miscellaneous +- #5457, #5506, #5952, #6047 Update libsecp256k1 +- #5437 `84857e8` Add missing CAutoFile::IsNull() check in main +- #5490 `ec20fd7` Replace uint256/uint160 with opaque blobs where possible +- #5654, #5764 Adding jonasschnelli's GPG key +- #5477 `5f04d1d` OS X 10.10: LSSharedFileListItemResolve() is deprecated +- #5679 `beff11a` Get rid of DetectShutdownThread +- #5787 `9bd8c9b` Add fanquake PGP key +- #5366 `47a79bb` No longer check osx compatibility in RenameThread +- #5689 `07f4386` openssl: abstract out OPENSSL_cleanse +- #5708 `8b298ca` Add list of implemented BIPs +- #5809 `46bfbe7` Add bitcoin-cli man page +- #5839 `86eb461` keys: remove libsecp256k1 verification until it's actually supported +- #5749 `d734d87` Help messages correctly formatted (79 chars) +- #5884 `7077fe6` BUGFIX: Stack around the variable 'rv' was corrupted +- #5849 `41259ca` contrib/init/bitcoind.openrc: Compatibility with previous OpenRC init script variables +- #5950 `41113e3` Fix locale fallback and guard tests against invalid locale settings +- #5965 `7c6bfb1` Add git-subtree-check.sh script +- #6033 `1623f6e` FreeBSD, OpenBSD thread renaming +- #6064 `b46e7c2` Several changes to mruset +- #6104 `3e2559c` Show an init message while activating best chain +- #6125 `351f73e` Clean up parsing of bool command line args +- #5964 `b4c219b` Lightweight task scheduler +- #6116 `30dc3c1` [OSX] rename Bitcoin-Qt.app to Bitcoin-Core.app +- #6168 `b3024f0` contrib/linearize: Support linearization of testnet blocks +- #6098 `7708fcd` Update Windows resource files (and add one for bitcoin-tx) +- #6159 `e1412d3` Catch errors on datadir lock and pidfile delete +- #6186 `182686c` Fix two problems in CSubnet parsing +- #6174 `df992b9` doc: add translation strings policy +- #6210 `dfdb6dd` build: disable optional use of gmp in internal secp256k1 build +- #6264 `94cd705` Remove translation for -help-debug options +- #6286 `3902c15` Remove berkeley-db4 workaround in MacOSX build docs +- #6319 `3f8fcc9` doc: update mailing list address + +Credits +======= + +Thanks to everyone who directly contributed to this release: + +- 21E14 +- Adam Weiss +- Alex Morcos +- ayeowch +- azeteki +- Ben Holden-Crowther +- bikinibabe +- BitcoinPRReadingGroup +- Blake Jakopovic +- BtcDrak +- charlescharles +- Chris Arnesen +- Ciemon +- CohibAA +- Corinne Dashjr +- Cory Fields +- Cozz Lovan +- Daira Hopwood +- Daniel Kraft +- Dave Collins +- David A. Harding +- dexX7 +- Earlz +- Eric Lombrozo +- Eric R. Schulz +- Everett Forth +- Flavien Charlon +- fsb4000 +- Gavin Andresen +- Gregory Maxwell +- Heath +- Ivan Pustogarov +- Jacob Welsh +- Jameson Lopp +- Jason Lewicki +- Jeff Garzik +- Jonas Schnelli +- Jonathan Brown +- Jorge Timón +- joshr +- jtimon +- Julian Yap +- Luca Venturini +- Luke Dashjr +- Manuel Araoz +- MarcoFalke +- Matt Bogosian +- Matt Corallo +- Micha +- Michael Ford +- Mike Hearn +- mrbandrews +- Nicolas Benoit +- paveljanik +- Pavel JanÃk +- Pavel Vasin +- Peter Todd +- Philip Kaufmann +- Pieter Wuille +- pstratem +- randy-waterhouse +- rion +- Rob Van Mieghem +- Ross Nicoll +- Ruben de Vries +- sandakersmann +- Shaul Kfir +- Shawn Wilkinson +- sinetek +- Suhas Daftuar +- svost +- Thomas Zander +- Tom Harding +- UdjinM6 +- Vitalii Demianets +- Wladimir J. van der Laan + +And all those who contributed additional code review and/or security research: + +- Sergio Demian Lerner + +As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/). + diff --git a/src/amount.cpp b/src/amount.cpp index 0a394c96fc..b469181984 100644 --- a/src/amount.cpp +++ b/src/amount.cpp @@ -7,6 +7,8 @@ #include "tinyformat.h" +const std::string CURRENCY_UNIT = "BTC"; + CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nSize) { if (nSize > 0) @@ -27,5 +29,5 @@ CAmount CFeeRate::GetFee(size_t nSize) const std::string CFeeRate::ToString() const { - return strprintf("%d.%08d BTC/kB", nSatoshisPerK / COIN, nSatoshisPerK % COIN); + return strprintf("%d.%08d %s/kB", nSatoshisPerK / COIN, nSatoshisPerK % COIN, CURRENCY_UNIT); } diff --git a/src/amount.h b/src/amount.h index 7dc62edac4..90e6b5aa8e 100644 --- a/src/amount.h +++ b/src/amount.h @@ -16,6 +16,8 @@ typedef int64_t CAmount; static const CAmount COIN = 100000000; static const CAmount CENT = 1000000; +extern const std::string CURRENCY_UNIT; + /** No amount larger than this (in satoshi) is valid. * * Note that this constant is *not* the total money supply, which in Bitcoin diff --git a/src/bloom.cpp b/src/bloom.cpp index 36cba491c4..de87206592 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -8,6 +8,7 @@ #include "hash.h" #include "script/script.h" #include "script/standard.h" +#include "random.h" #include "streams.h" #include <math.h> @@ -121,6 +122,12 @@ void CBloomFilter::clear() isEmpty = true; } +void CBloomFilter::reset(unsigned int nNewTweak) +{ + clear(); + nTweak = nNewTweak; +} + bool CBloomFilter::IsWithinSizeConstraints() const { return vData.size() <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS; @@ -209,15 +216,17 @@ void CBloomFilter::UpdateEmptyFull() isEmpty = empty; } -CRollingBloomFilter::CRollingBloomFilter(unsigned int nElements, double fpRate, unsigned int nTweak) : - b1(nElements * 2, fpRate, nTweak), b2(nElements * 2, fpRate, nTweak) +CRollingBloomFilter::CRollingBloomFilter(unsigned int nElements, double fpRate) : + b1(nElements * 2, fpRate, 0), b2(nElements * 2, fpRate, 0) { // Implemented using two bloom filters of 2 * nElements each. // We fill them up, and clear them, staggered, every nElements // inserted, so at least one always contains the last nElements // inserted. - nBloomSize = nElements * 2; nInsertions = 0; + nBloomSize = nElements * 2; + + reset(); } void CRollingBloomFilter::insert(const std::vector<unsigned char>& vKey) @@ -234,6 +243,12 @@ void CRollingBloomFilter::insert(const std::vector<unsigned char>& vKey) } } +void CRollingBloomFilter::insert(const uint256& hash) +{ + vector<unsigned char> data(hash.begin(), hash.end()); + insert(data); +} + bool CRollingBloomFilter::contains(const std::vector<unsigned char>& vKey) const { if (nInsertions < nBloomSize / 2) { @@ -242,9 +257,16 @@ bool CRollingBloomFilter::contains(const std::vector<unsigned char>& vKey) const return b1.contains(vKey); } -void CRollingBloomFilter::clear() +bool CRollingBloomFilter::contains(const uint256& hash) const +{ + vector<unsigned char> data(hash.begin(), hash.end()); + return contains(data); +} + +void CRollingBloomFilter::reset() { - b1.clear(); - b2.clear(); + unsigned int nNewTweak = GetRand(std::numeric_limits<unsigned int>::max()); + b1.reset(nNewTweak); + b2.reset(nNewTweak); nInsertions = 0; } diff --git a/src/bloom.h b/src/bloom.h index bb17f59c86..a4dba8cb4f 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -89,6 +89,7 @@ public: bool contains(const uint256& hash) const; void clear(); + void reset(unsigned int nNewTweak); //! True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS //! (catch a filter which was just deserialized which was too big) @@ -103,7 +104,11 @@ public: /** * RollingBloomFilter is a probabilistic "keep track of most recently inserted" set. - * Construct it with the number of items to keep track of, and a false-positive rate. + * Construct it with the number of items to keep track of, and a false-positive + * rate. Unlike CBloomFilter, by default nTweak is set to a cryptographically + * secure random value for you. Similarly rather than clear() the method + * reset() is provided, which also changes nTweak to decrease the impact of + * false-positives. * * contains(item) will always return true if item was one of the last N things * insert()'ed ... but may also return true for items that were not inserted. @@ -111,12 +116,17 @@ public: class CRollingBloomFilter { public: - CRollingBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweak); + // A random bloom filter calls GetRand() at creation time. + // Don't create global CRollingBloomFilter objects, as they may be + // constructed before the randomizer is properly initialized. + CRollingBloomFilter(unsigned int nElements, double nFPRate); void insert(const std::vector<unsigned char>& vKey); + void insert(const uint256& hash); bool contains(const std::vector<unsigned char>& vKey) const; + bool contains(const uint256& hash) const; - void clear(); + void reset(); private: unsigned int nBloomSize; diff --git a/src/consensus/validation.h b/src/consensus/validation.h index a97d983a31..719e090a42 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -28,12 +28,12 @@ private: } mode; int nDoS; std::string strRejectReason; - unsigned char chRejectCode; + unsigned int chRejectCode; bool corruptionPossible; public: CValidationState() : mode(MODE_VALID), nDoS(0), chRejectCode(0), corruptionPossible(false) {} bool DoS(int level, bool ret = false, - unsigned char chRejectCodeIn=0, std::string strRejectReasonIn="", + unsigned int chRejectCodeIn=0, std::string strRejectReasonIn="", bool corruptionIn=false) { chRejectCode = chRejectCodeIn; strRejectReason = strRejectReasonIn; @@ -45,7 +45,7 @@ public: return ret; } bool Invalid(bool ret = false, - unsigned char _chRejectCode=0, std::string _strRejectReason="") { + unsigned int _chRejectCode=0, std::string _strRejectReason="") { return DoS(0, ret, _chRejectCode, _strRejectReason); } bool Error(const std::string& strRejectReasonIn) { @@ -73,7 +73,7 @@ public: bool CorruptionPossible() const { return corruptionPossible; } - unsigned char GetRejectCode() const { return chRejectCode; } + unsigned int GetRejectCode() const { return chRejectCode; } std::string GetRejectReason() const { return strRejectReason; } }; diff --git a/src/init.cpp b/src/init.cpp index a03571c31a..ef1c39db25 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -314,7 +314,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-externalip=<ip>", _("Specify your own public address")); strUsage += HelpMessageOpt("-forcednsseed", strprintf(_("Always query for peer addresses via DNS lookup (default: %u)"), 0)); strUsage += HelpMessageOpt("-listen", _("Accept connections from outside (default: 1 if no -proxy or -connect)")); - strUsage += HelpMessageOpt("-maxconnections=<n>", strprintf(_("Maintain at most <n> connections to peers (default: %u)"), 125)); + strUsage += HelpMessageOpt("-maxconnections=<n>", strprintf(_("Maintain at most <n> connections to peers (default: %u)"), DEFAULT_MAX_PEER_CONNECTIONS)); strUsage += HelpMessageOpt("-maxreceivebuffer=<n>", strprintf(_("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)"), 5000)); strUsage += HelpMessageOpt("-maxsendbuffer=<n>", strprintf(_("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)"), 1000)); strUsage += HelpMessageOpt("-onion=<ip:port>", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy")); @@ -342,16 +342,17 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls")); strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), 100)); if (showDebug) - strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)", - FormatMoney(CWallet::minTxFee.GetFeePerK()))); - strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK()))); + strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)", + CURRENCY_UNIT, FormatMoney(CWallet::minTxFee.GetFeePerK()))); + strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"), + CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK()))); strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions") + " " + _("on startup")); strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup")); strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0)); strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1)); strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET)); - strUsage += HelpMessageOpt("-maxtxfee=<amt>", strprintf(_("Maximum total fees to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)"), - FormatMoney(maxTxFee))); + strUsage += HelpMessageOpt("-maxtxfee=<amt>", strprintf(_("Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)"), + CURRENCY_UNIT, FormatMoney(maxTxFee))); strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format") + " " + _("on startup")); strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), "wallet.dat")); strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), true)); @@ -388,7 +389,8 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-relaypriority", strprintf("Require high priority for relaying free or low-fee transactions (default: %u)", 1)); strUsage += HelpMessageOpt("-maxsigcachesize=<n>", strprintf("Limit size of signature cache to <n> entries (default: %u)", 50000)); } - strUsage += HelpMessageOpt("-minrelaytxfee=<amt>", strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK()))); + strUsage += HelpMessageOpt("-minrelaytxfee=<amt>", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for relaying (default: %s)"), + CURRENCY_UNIT, FormatMoney(::minRelayTxFee.GetFeePerK()))); strUsage += HelpMessageOpt("-printtoconsole", _("Send trace/debug info to console instead of debug.log file")); if (showDebug) { @@ -750,7 +752,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // Make sure enough file descriptors are available int nBind = std::max((int)mapArgs.count("-bind") + (int)mapArgs.count("-whitebind"), 1); - int nUserMaxConnections = GetArg("-maxconnections", 125); + int nUserMaxConnections = GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS); nMaxConnections = std::max(nUserMaxConnections, 0); int nUserWhiteConnections = GetArg("-whiteconnections", 0); nWhiteConnections = std::max(nUserWhiteConnections, 0); @@ -1018,6 +1020,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) RegisterNodeSignals(GetNodeSignals()); + // format user agent, check total size + strSubVersion = FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, mapMultiArgs.count("-uacomment") ? mapMultiArgs["-uacomment"] : std::vector<string>()); + if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) { + return InitError(strprintf("Total length of network version string %i exceeds maximum of %i characters. Reduce the number and/or size of uacomments.", + strSubVersion.size(), MAX_SUBVERSION_LENGTH)); + } + if (mapArgs.count("-onlynet")) { std::set<enum Network> nets; BOOST_FOREACH(const std::string& snet, mapMultiArgs["-onlynet"]) { @@ -1228,6 +1237,18 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("Prune: pruned datadir may not have more than %d blocks; -checkblocks=%d may fail\n", MIN_BLOCKS_TO_KEEP, GetArg("-checkblocks", 288)); } + + { + LOCK(cs_main); + CBlockIndex* tip = chainActive.Tip(); + if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) { + strLoadError = _("The block database contains a block which appears to be from the future. " + "This may be due to your computer's date and time being set incorrectly. " + "Only rebuild the block database if you are sure that your computer's date and time are correct"); + break; + } + } + if (!CVerifyDB().VerifyDB(pcoinsdbview, GetArg("-checklevel", 3), GetArg("-checkblocks", 288))) { strLoadError = _("Corrupted block database detected"); @@ -1278,15 +1299,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) mempool.ReadFeeEstimates(est_filein); fFeeEstimatesInitialized = true; - // if prune mode, unset NODE_NETWORK and prune block files - if (fPruneMode) { - LogPrintf("Unsetting NODE_NETWORK on prune mode\n"); - nLocalServices &= ~NODE_NETWORK; - if (!fReindex) { - PruneAndFlush(); - } - } - // ********************************************************* Step 8: load wallet #ifdef ENABLE_WALLET if (fDisableWallet) { @@ -1440,7 +1452,21 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) #else // ENABLE_WALLET LogPrintf("No wallet support compiled in!\n"); #endif // !ENABLE_WALLET - // ********************************************************* Step 9: import blocks + + // ********************************************************* Step 9: data directory maintenance + + // if pruning, unset the service bit and perform the initial blockstore prune + // after any wallet rescanning has taken place. + if (fPruneMode) { + uiInterface.InitMessage(_("Pruning blockstore...")); + LogPrintf("Unsetting NODE_NETWORK on prune mode\n"); + nLocalServices &= ~NODE_NETWORK; + if (!fReindex) { + PruneAndFlush(); + } + } + + // ********************************************************* Step 10: import blocks if (mapArgs.count("-blocknotify")) uiInterface.NotifyBlockTip.connect(BlockNotifyCallback); @@ -1464,7 +1490,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) MilliSleep(10); } - // ********************************************************* Step 10: start node + // ********************************************************* Step 11: start node if (!CheckDiskSpace()) return false; diff --git a/src/main.cpp b/src/main.cpp index d470ba9003..755bec47b8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -162,6 +162,29 @@ namespace { */ map<uint256, NodeId> mapBlockSource; + /** + * Filter for transactions that were recently rejected by + * AcceptToMemoryPool. These are not rerequested until the chain tip + * changes, at which point the entire filter is reset. Protected by + * cs_main. + * + * Without this filter we'd be re-requesting txs from each of our peers, + * increasing bandwidth consumption considerably. For instance, with 100 + * peers, half of which relay a tx we don't accept, that might be a 50x + * bandwidth increase. A flooding attacker attempting to roll-over the + * filter using minimum-sized, 60byte, transactions might manage to send + * 1000/sec if we have fast peers, so we pick 120,000 to give our peers a + * two minute window to send invs to us. + * + * Decreasing the false positive rate is fairly cheap, so we pick one in a + * million to make it highly unlikely for users to have issues with this + * filter. + * + * Memory used: 1.7MB + */ + boost::scoped_ptr<CRollingBloomFilter> recentRejects; + uint256 hashRecentRejectsChainTip; + /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */ struct QueuedBlock { uint256 hash; @@ -904,9 +927,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } if (fRejectAbsurdFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000) - return error("AcceptToMemoryPool: absurdly high fees %s, %d > %d", - hash.ToString(), - nFees, ::minRelayTxFee.GetFee(nSize) * 10000); + return state.Invalid(error("AcceptToMemoryPool: absurdly high fees %s, %d > %d", + hash.ToString(), + nFees, ::minRelayTxFee.GetFee(nSize) * 10000), + REJECT_HIGHFEE, "absurdly-high-fee"); // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. @@ -1204,9 +1228,11 @@ void static InvalidChainFound(CBlockIndex* pindexNew) pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, log(pindexNew->nChainWork.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexNew->GetBlockTime())); + CBlockIndex *tip = chainActive.Tip(); + assert (tip); LogPrintf("%s: current best=%s height=%d log2_work=%.8g date=%s\n", __func__, - chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), - DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime())); + tip->GetBlockHash().ToString(), chainActive.Height(), log(tip->nChainWork.getdouble())/log(2.0), + DateTimeStrFormat("%Y-%m-%d %H:%M:%S", tip->GetBlockTime())); CheckForkWarningConditions(); } @@ -1215,7 +1241,8 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state if (state.IsInvalid(nDoS)) { std::map<uint256, NodeId>::iterator it = mapBlockSource.find(pindex->GetBlockHash()); if (it != mapBlockSource.end() && State(it->second)) { - CBlockReject reject = {state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), pindex->GetBlockHash()}; + assert(state.GetRejectCode() < 0x100); + CBlockReject reject = {(unsigned char)state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), pindex->GetBlockHash()}; State(it->second)->rejects.push_back(reject); if (nDoS > 0) Misbehaving(it->second, nDoS); @@ -3248,6 +3275,7 @@ void UnloadBlockIndex() setDirtyBlockIndex.clear(); setDirtyFileInfo.clear(); mapNodeState.clear(); + recentRejects.reset(NULL); BOOST_FOREACH(BlockMap::value_type& entry, mapBlockIndex) { delete entry.second; @@ -3268,6 +3296,10 @@ bool LoadBlockIndex() bool InitBlockIndex() { const CChainParams& chainparams = Params(); LOCK(cs_main); + + // Initialize global variables that cannot be constructed at startup. + recentRejects.reset(new CRollingBloomFilter(120000, 0.000001)); + // Check whether we're already initialized if (chainActive.Genesis() != NULL) return true; @@ -3398,7 +3430,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) } } } catch (const std::exception& e) { - LogPrintf("%s: Deserialize or I/O error - %s", __func__, e.what()); + LogPrintf("%s: Deserialize or I/O error - %s\n", __func__, e.what()); } } } catch (const std::runtime_error& e) { @@ -3670,10 +3702,21 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { case MSG_TX: { - bool txInMap = false; - txInMap = mempool.exists(inv.hash); - return txInMap || mapOrphanTransactions.count(inv.hash) || - pcoinsTip->HaveCoins(inv.hash); + assert(recentRejects); + if (chainActive.Tip()->GetBlockHash() != hashRecentRejectsChainTip) + { + // If the chain tip has changed previously rejected transactions + // might be now valid, e.g. due to a nLockTime'd tx becoming valid, + // or a double-spend. Reset the rejects filter and give those + // txs a second chance. + hashRecentRejectsChainTip = chainActive.Tip()->GetBlockHash(); + recentRejects->reset(); + } + + return recentRejects->contains(inv.hash) || + mempool.exists(inv.hash) || + mapOrphanTransactions.count(inv.hash) || + pcoinsTip->HaveCoins(inv.hash); } case MSG_BLOCK: return mapBlockIndex.count(inv.hash); @@ -3859,7 +3902,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (!vRecv.empty()) vRecv >> addrFrom >> nNonce; if (!vRecv.empty()) { - vRecv >> LIMITED_STRING(pfrom->strSubVer, 256); + vRecv >> LIMITED_STRING(pfrom->strSubVer, MAX_SUBVERSION_LENGTH); pfrom->cleanSubVer = SanitizeString(pfrom->strSubVer); } if (!vRecv.empty()) @@ -4273,6 +4316,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Probably non-standard or insufficient fee/priority LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString()); vEraseQueue.push_back(orphanHash); + assert(recentRejects); + recentRejects->insert(orphanHash); } mempool.check(pcoinsTip); } @@ -4290,11 +4335,24 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTx); if (nEvicted > 0) LogPrint("mempool", "mapOrphan overflow, removed %u tx\n", nEvicted); - } else if (pfrom->fWhitelisted) { - // Always relay transactions received from whitelisted peers, even - // if they are already in the mempool (allowing the node to function - // as a gateway for nodes hidden behind it). - RelayTransaction(tx); + } else { + // AcceptToMemoryPool() returned false, possibly because the tx is + // already in the mempool; if the tx isn't in the mempool that + // means it was rejected and we shouldn't ask for it again. + if (!mempool.exists(tx.GetHash())) { + assert(recentRejects); + recentRejects->insert(tx.GetHash()); + } + if (pfrom->fWhitelisted) { + // Always relay transactions received from whitelisted peers, even + // if they were rejected from the mempool, allowing the node to + // function as a gateway for nodes hidden behind it. + // + // FIXME: This includes invalid transactions, which means a + // whitelisted peer could get us banned! We may want to change + // that. + RelayTransaction(tx); + } } int nDoS = 0; if (state.IsInvalid(nDoS)) @@ -4797,7 +4855,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) { // Periodically clear addrKnown to allow refresh broadcasts if (nLastRebroadcast) - pnode->addrKnown.clear(); + pnode->addrKnown.reset(); // Rebroadcast our address AdvertizeLocal(pnode); diff --git a/src/main.h b/src/main.h index 96ad54cda6..eec7e6fa59 100644 --- a/src/main.h +++ b/src/main.h @@ -455,4 +455,7 @@ extern CBlockTreeDB *pblocktree; */ int GetSpendHeight(const CCoinsViewCache& inputs); +/** local "reject" message codes for RPC which can not be triggered by p2p trasactions */ +static const unsigned int REJECT_HIGHFEE = 0x100; + #endif // BITCOIN_MAIN_H diff --git a/src/miner.cpp b/src/miner.cpp index e44f3392c8..864e4bf31f 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -84,13 +84,19 @@ public: } }; -void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) +int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) { - pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + int64_t nOldTime = pblock->nTime; + int64_t nNewTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + + if (nOldTime < nNewTime) + pblock->nTime = nNewTime; // Updating time can change work required on testnet: if (consensusParams.fPowAllowMinDifficultyBlocks) pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); + + return nNewTime - nOldTime; } CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) @@ -521,7 +527,9 @@ void static BitcoinMiner(const CChainParams& chainparams) break; // Update nTime every few seconds - UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); + if (UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev) < 0) + break; // Recreate the block if the clock has run backwards, + // so that we can use the correct time. if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks) { // Changing pblock->nTime can change work required on testnet: diff --git a/src/miner.h b/src/miner.h index 777a091967..d690e9447d 100644 --- a/src/miner.h +++ b/src/miner.h @@ -30,6 +30,6 @@ void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainpar CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn); /** Modify the extranonce in a block */ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); -void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev); +int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev); #endif // BITCOIN_MINER_H diff --git a/src/net.cpp b/src/net.cpp index 3cece520de..e4ead3c92e 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -80,9 +80,10 @@ static CNode* pnodeLocalHost = NULL; uint64_t nLocalHostNonce = 0; static std::vector<ListenSocket> vhListenSocket; CAddrMan addrman; -int nMaxConnections = 125; +int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS; int nWhiteConnections = 0; bool fAddressesInitialized = false; +std::string strSubVersion; vector<CNode*> vNodes; CCriticalSection cs_vNodes; @@ -445,7 +446,7 @@ void CNode::PushVersion() else LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id); PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, - nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight, true); + nLocalHostNonce, strSubVersion, nBestHeight, true); } @@ -2060,7 +2061,7 @@ unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); } CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), - addrKnown(5000, 0.001, insecure_rand()), + addrKnown(5000, 0.001), setInventoryKnown(SendBufferSize() / 1000) { nServices = 0; @@ -46,6 +46,8 @@ static const unsigned int MAX_INV_SZ = 50000; static const unsigned int MAX_ADDR_TO_SEND = 1000; /** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */ static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 2 * 1024 * 1024; +/** Maximum length of strSubVer in `version` message */ +static const unsigned int MAX_SUBVERSION_LENGTH = 256; /** -listen default */ static const bool DEFAULT_LISTEN = true; /** -upnp default */ @@ -56,6 +58,8 @@ static const bool DEFAULT_UPNP = false; #endif /** The maximum number of entries in mapAskFor */ static const size_t MAPASKFOR_MAX_SZ = MAX_INV_SZ; +/** The maximum number of peer connections to maintain. */ +static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 125; unsigned int ReceiveFloodSize(); unsigned int SendBufferSize(); @@ -166,6 +170,9 @@ extern CCriticalSection cs_vAddedNodes; extern NodeId nLastNodeId; extern CCriticalSection cs_nLastNodeId; +/** Subversion as sent to the P2P network in `version` messages */ +extern std::string strSubVersion; + struct LocalServiceInfo { int nScore; int nPort; diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index b1491cec01..cdee541d2f 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -249,7 +249,7 @@ unsigned int TxConfirmStats::NewTx(unsigned int nBlockHeight, double val) unsigned int bucketindex = bucketMap.lower_bound(val)->second; unsigned int blockIndex = nBlockHeight % unconfTxs.size(); unconfTxs[blockIndex][bucketindex]++; - LogPrint("estimatefee", "adding to %s\n", dataTypeString); + LogPrint("estimatefee", "adding to %s", dataTypeString); return bucketindex; } @@ -390,8 +390,9 @@ void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry& entry, boo mapMemPoolTxs[hash].bucketIndex = feeStats.NewTx(txHeight, (double)feeRate.GetFeePerK()); } else { - LogPrint("estimatefee", "not adding\n"); + LogPrint("estimatefee", "not adding"); } + LogPrint("estimatefee", "\n"); } void CBlockPolicyEstimator::processBlockTx(unsigned int nBlockHeight, const CTxMemPoolEntry& entry) diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 5817f0ce57..80d49490d2 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -3,6 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" #include "chain.h" #include "chainparams.h" #include "checkpoints.h" @@ -192,7 +193,7 @@ UniValue getrawmempool(const UniValue& params, bool fHelp) "{ (json object)\n" " \"transactionid\" : { (json object)\n" " \"size\" : n, (numeric) transaction size in bytes\n" - " \"fee\" : n, (numeric) transaction fee in bitcoins\n" + " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n" " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n" " \"height\" : n, (numeric) block height when transaction entered pool\n" " \"startingpriority\" : n, (numeric) priority when transaction entered pool\n" @@ -461,7 +462,7 @@ UniValue gettxout(const UniValue& params, bool fHelp) "{\n" " \"bestblock\" : \"hash\", (string) the block hash\n" " \"confirmations\" : n, (numeric) The number of confirmations\n" - " \"value\" : x.xxx, (numeric) The transaction value in btc\n" + " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n" " \"scriptPubKey\" : { (json object)\n" " \"asm\" : \"code\", (string) \n" " \"hex\" : \"hex\", (string) \n" diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 82003e09b9..6d10d1ce15 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -60,8 +60,8 @@ UniValue getinfo(const UniValue& params, bool fHelp) " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n" " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n" " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n" - " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in btc/kb\n" - " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n" + " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in " + CURRENCY_UNIT + "/kB\n" + " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n" " \"errors\": \"...\" (string) any error messages\n" "}\n" "\nExamples:\n" diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index ed903f9fd3..56ec59171d 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -423,7 +423,7 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp) " }\n" " ,...\n" " ],\n" - " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n" + " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n" " \"localaddresses\": [ (array) list of local addresses\n" " {\n" " \"address\": \"xxxx\", (string) network address\n" @@ -443,8 +443,7 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp) UniValue obj(UniValue::VOBJ); obj.push_back(Pair("version", CLIENT_VERSION)); - obj.push_back(Pair("subversion", - FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()))); + obj.push_back(Pair("subversion", strSubVersion)); obj.push_back(Pair("protocolversion",PROTOCOL_VERSION)); obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices))); obj.push_back(Pair("timeoffset", GetTimeOffset())); diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 62d2ef69ef..a3246b41fb 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -149,7 +149,7 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) " ],\n" " \"vout\" : [ (array of json objects)\n" " {\n" - " \"value\" : x.xxx, (numeric) The value in btc\n" + " \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n" " \"n\" : n, (numeric) index\n" " \"scriptPubKey\" : { (json object)\n" " \"asm\" : \"asm\", (string) the asm\n" @@ -335,7 +335,7 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) " ]\n" "2. \"addresses\" (string, required) a json object with addresses as keys and amounts as values\n" " {\n" - " \"address\": x.xxx (numeric, required) The key is the bitcoin address, the value is the btc amount\n" + " \"address\": x.xxx (numeric, required) The key is the bitcoin address, the value is the " + CURRENCY_UNIT + " amount\n" " ,...\n" " }\n" @@ -422,7 +422,7 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp) " ],\n" " \"vout\" : [ (array of json objects)\n" " {\n" - " \"value\" : x.xxx, (numeric) The value in btc\n" + " \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n" " \"n\" : n, (numeric) index\n" " \"scriptPubKey\" : { (json object)\n" " \"asm\" : \"asm\", (string) the asm\n" diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 03c123a361..68091010f7 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -752,14 +752,14 @@ void StopRPCThreads() { acceptor->cancel(ec); if (ec) - LogPrintf("%s: Warning: %s when cancelling acceptor", __func__, ec.message()); + LogPrintf("%s: Warning: %s when cancelling acceptor\n", __func__, ec.message()); } rpc_acceptors.clear(); BOOST_FOREACH(const PAIRTYPE(std::string, boost::shared_ptr<deadline_timer>) &timer, deadlineTimers) { timer.second->cancel(ec); if (ec) - LogPrintf("%s: Warning: %s when cancelling timer", __func__, ec.message()); + LogPrintf("%s: Warning: %s when cancelling timer\n", __func__, ec.message()); } deadlineTimers.clear(); diff --git a/src/sync.cpp b/src/sync.cpp index 1837e8d53d..a422939964 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -33,22 +33,20 @@ void PrintLockContention(const char* pszName, const char* pszFile, int nLine) // struct CLockLocation { - CLockLocation(const char* pszName, const char* pszFile, int nLine, bool fTryIn) + CLockLocation(const char* pszName, const char* pszFile, int nLine) { mutexName = pszName; sourceFile = pszFile; sourceLine = nLine; - fTry = fTryIn; } std::string ToString() const { - return mutexName + " " + sourceFile + ":" + itostr(sourceLine) + (fTry ? " (TRY)" : ""); + return mutexName + " " + sourceFile + ":" + itostr(sourceLine); } std::string MutexName() const { return mutexName; } - bool fTry; private: std::string mutexName; std::string sourceFile; @@ -64,52 +62,23 @@ static boost::thread_specific_ptr<LockStack> lockstack; static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2) { - // We attempt to not assert on probably-not deadlocks by assuming that - // a try lock will immediately have otherwise bailed if it had - // failed to get the lock - // We do this by, for the locks which triggered the potential deadlock, - // in either lockorder, checking that the second of the two which is locked - // is only a TRY_LOCK, ignoring locks if they are reentrant. - bool firstLocked = false; - bool secondLocked = false; - bool onlyMaybeDeadlock = false; - LogPrintf("POTENTIAL DEADLOCK DETECTED\n"); LogPrintf("Previous lock order was:\n"); BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, s2) { - if (i.first == mismatch.first) { + if (i.first == mismatch.first) LogPrintf(" (1)"); - if (!firstLocked && secondLocked && i.second.fTry) - onlyMaybeDeadlock = true; - firstLocked = true; - } - if (i.first == mismatch.second) { + if (i.first == mismatch.second) LogPrintf(" (2)"); - if (!secondLocked && firstLocked && i.second.fTry) - onlyMaybeDeadlock = true; - secondLocked = true; - } LogPrintf(" %s\n", i.second.ToString()); } - firstLocked = false; - secondLocked = false; LogPrintf("Current lock order is:\n"); BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, s1) { - if (i.first == mismatch.first) { + if (i.first == mismatch.first) LogPrintf(" (1)"); - if (!firstLocked && secondLocked && i.second.fTry) - onlyMaybeDeadlock = true; - firstLocked = true; - } - if (i.first == mismatch.second) { + if (i.first == mismatch.second) LogPrintf(" (2)"); - if (!secondLocked && firstLocked && i.second.fTry) - onlyMaybeDeadlock = true; - secondLocked = true; - } LogPrintf(" %s\n", i.second.ToString()); } - assert(onlyMaybeDeadlock); } static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) @@ -132,8 +101,10 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) lockorders[p1] = (*lockstack); std::pair<void*, void*> p2 = std::make_pair(c, i.first); - if (lockorders.count(p2)) + if (lockorders.count(p2)) { potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]); + break; + } } } dd_mutex.unlock(); @@ -148,7 +119,7 @@ static void pop_lock() void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry) { - push_lock(cs, CLockLocation(pszName, pszFile, nLine, fTry), fTry); + push_lock(cs, CLockLocation(pszName, pszFile, nLine), fTry); } void LeaveCritical() diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index b8d5606cc3..dd3c51d09b 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -162,8 +162,8 @@ BOOST_AUTO_TEST_CASE(AlertNotify) SetMockTime(11); const std::vector<unsigned char>& alertKey = Params(CBaseChainParams::MAIN).AlertKey(); - boost::filesystem::path temp = GetTempPath() / "alertnotify.txt"; - boost::filesystem::remove(temp); + boost::filesystem::path temp = GetTempPath() / + boost::filesystem::unique_path("alertnotify-%%%%.txt"); mapArgs["-alertnotify"] = std::string("echo %s >> ") + temp.string(); diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 1bda8a7ea1..6b30d6aa8a 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -469,7 +469,7 @@ static std::vector<unsigned char> RandomData() BOOST_AUTO_TEST_CASE(rolling_bloom) { // last-100-entry, 1% false positive: - CRollingBloomFilter rb1(100, 0.01, 0); + CRollingBloomFilter rb1(100, 0.01); // Overfill: static const int DATASIZE=399; @@ -500,7 +500,7 @@ BOOST_AUTO_TEST_CASE(rolling_bloom) BOOST_CHECK(nHits < 175); BOOST_CHECK(rb1.contains(data[DATASIZE-1])); - rb1.clear(); + rb1.reset(); BOOST_CHECK(!rb1.contains(data[DATASIZE-1])); // Now roll through data, make sure last 100 entries @@ -527,7 +527,7 @@ BOOST_AUTO_TEST_CASE(rolling_bloom) BOOST_CHECK(nHits < 100); // last-1000-entry, 0.01% false positive: - CRollingBloomFilter rb2(1000, 0.001, 0); + CRollingBloomFilter rb2(1000, 0.001); for (int i = 0; i < DATASIZE; i++) { rb2.insert(data[i]); } diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index a0c5592a95..eb61a2884d 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -60,18 +60,18 @@ BOOST_AUTO_TEST_CASE(boolarg) BOOST_CHECK(!GetBoolArg("-foo", false)); BOOST_CHECK(!GetBoolArg("-foo", true)); - ResetArgs("-foo -nofoo"); // -foo should win - BOOST_CHECK(GetBoolArg("-foo", false)); - BOOST_CHECK(GetBoolArg("-foo", true)); - - ResetArgs("-foo=1 -nofoo=1"); // -foo should win - BOOST_CHECK(GetBoolArg("-foo", false)); - BOOST_CHECK(GetBoolArg("-foo", true)); + ResetArgs("-foo -nofoo"); // -nofoo should win + BOOST_CHECK(!GetBoolArg("-foo", false)); + BOOST_CHECK(!GetBoolArg("-foo", true)); - ResetArgs("-foo=0 -nofoo=0"); // -foo should win + ResetArgs("-foo=1 -nofoo=1"); // -nofoo should win BOOST_CHECK(!GetBoolArg("-foo", false)); BOOST_CHECK(!GetBoolArg("-foo", true)); + ResetArgs("-foo=0 -nofoo=0"); // -nofoo=0 should win + BOOST_CHECK(GetBoolArg("-foo", false)); + BOOST_CHECK(GetBoolArg("-foo", true)); + // New 0.6 feature: treat -- same as -: ResetArgs("--foo=1"); BOOST_CHECK(GetBoolArg("-foo", false)); @@ -150,9 +150,9 @@ BOOST_AUTO_TEST_CASE(boolargno) BOOST_CHECK(GetBoolArg("-foo", true)); BOOST_CHECK(GetBoolArg("-foo", false)); - ResetArgs("-foo --nofoo"); - BOOST_CHECK(GetBoolArg("-foo", true)); - BOOST_CHECK(GetBoolArg("-foo", false)); + ResetArgs("-foo --nofoo"); // --nofoo should win + BOOST_CHECK(!GetBoolArg("-foo", true)); + BOOST_CHECK(!GetBoolArg("-foo", false)); ResetArgs("-nofoo -foo"); // foo always wins: BOOST_CHECK(GetBoolArg("-foo", true)); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 5bc06e5056..c921dae45d 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -348,7 +348,7 @@ CTxMemPool::WriteFeeEstimates(CAutoFile& fileout) const minerPolicyEstimator->Write(fileout); } catch (const std::exception&) { - LogPrintf("CTxMemPool::WriteFeeEstimates(): unable to write policy estimator data (non-fatal)"); + LogPrintf("CTxMemPool::WriteFeeEstimates(): unable to write policy estimator data (non-fatal)\n"); return false; } return true; @@ -367,7 +367,7 @@ CTxMemPool::ReadFeeEstimates(CAutoFile& filein) minerPolicyEstimator->Read(filein); } catch (const std::exception&) { - LogPrintf("CTxMemPool::ReadFeeEstimates(): unable to read policy estimator data (non-fatal)"); + LogPrintf("CTxMemPool::ReadFeeEstimates(): unable to read policy estimator data (non-fatal)\n"); return false; } return true; diff --git a/src/util.cpp b/src/util.cpp index 37d52037c0..a7ec740de8 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -315,18 +315,21 @@ int LogPrintStr(const std::string &str) return ret; } -static void InterpretNegativeSetting(string name, map<string, string>& mapSettingsRet) +/** Interpret string as boolean, for argument parsing */ +static bool InterpretBool(const std::string& strValue) { - // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set - if (name.find("-no") == 0) + if (strValue.empty()) + return true; + return (atoi(strValue) != 0); +} + +/** Turn -noX into -X=0 */ +static void InterpretNegativeSetting(std::string& strKey, std::string& strValue) +{ + if (strKey.length()>3 && strKey[0]=='-' && strKey[1]=='n' && strKey[2]=='o') { - std::string positive("-"); - positive.append(name.begin()+3, name.end()); - if (mapSettingsRet.count(positive) == 0) - { - bool value = !GetBoolArg(name, false); - mapSettingsRet[positive] = (value ? "1" : "0"); - } + strKey = "-" + strKey.substr(3); + strValue = InterpretBool(strValue) ? "0" : "1"; } } @@ -358,17 +361,11 @@ void ParseParameters(int argc, const char* const argv[]) // If both --foo and -foo are set, the last takes effect. if (str.length() > 1 && str[1] == '-') str = str.substr(1); + InterpretNegativeSetting(str, strValue); mapArgs[str] = strValue; mapMultiArgs[str].push_back(strValue); } - - // New 0.6 features: - BOOST_FOREACH(const PAIRTYPE(string,string)& entry, mapArgs) - { - // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set - InterpretNegativeSetting(entry.first, mapArgs); - } } std::string GetArg(const std::string& strArg, const std::string& strDefault) @@ -388,11 +385,7 @@ int64_t GetArg(const std::string& strArg, int64_t nDefault) bool GetBoolArg(const std::string& strArg, bool fDefault) { if (mapArgs.count(strArg)) - { - if (mapArgs[strArg].empty()) - return true; - return (atoi(mapArgs[strArg]) != 0); - } + return InterpretBool(mapArgs[strArg]); return fDefault; } @@ -543,13 +536,11 @@ void ReadConfigFile(map<string, string>& mapSettingsRet, { // Don't overwrite existing settings so command line settings override bitcoin.conf string strKey = string("-") + it->string_key; + string strValue = it->value[0]; + InterpretNegativeSetting(strKey, strValue); if (mapSettingsRet.count(strKey) == 0) - { - mapSettingsRet[strKey] = it->value[0]; - // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set) - InterpretNegativeSetting(strKey, mapSettingsRet); - } - mapMultiSettingsRet[strKey].push_back(it->value[0]); + mapSettingsRet[strKey] = strValue; + mapMultiSettingsRet[strKey].push_back(strValue); } // If datadir is changed in .conf file: ClearDatadirCache(); diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index c7f7e21679..0b0fb562e0 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -186,7 +186,7 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn) } if (keyPass && keyFail) { - LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all."); + LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.\n"); assert(false); } if (keyFail || !keyPass) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 342ce13af1..198b5baf60 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -390,7 +390,7 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp) + HelpRequiringPassphrase() + "\nArguments:\n" "1. \"bitcoinaddress\" (string, required) The bitcoin address to send to.\n" - "2. \"amount\" (numeric, required) The amount in btc to send. eg 0.1\n" + "2. \"amount\" (numeric, required) The amount in " + CURRENCY_UNIT + " to send. eg 0.1\n" "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n" " This is not part of the transaction, just kept in your wallet.\n" "4. \"comment-to\" (string, optional) A comment to store the name of the person or organization \n" @@ -452,7 +452,7 @@ UniValue listaddressgroupings(const UniValue& params, bool fHelp) " [\n" " [\n" " \"bitcoinaddress\", (string) The bitcoin address\n" - " amount, (numeric) The amount in btc\n" + " amount, (numeric) The amount in " + CURRENCY_UNIT + "\n" " \"account\" (string, optional) The account (DEPRECATED)\n" " ]\n" " ,...\n" @@ -556,7 +556,7 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp) "1. \"bitcoinaddress\" (string, required) The bitcoin address for transactions.\n" "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" "\nResult:\n" - "amount (numeric) The total amount in btc received at this address.\n" + "amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n" "\nExamples:\n" "\nThe amount from transactions with at least 1 confirmation\n" + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"") + @@ -614,7 +614,7 @@ UniValue getreceivedbyaccount(const UniValue& params, bool fHelp) "1. \"account\" (string, required) The selected account, may be the default account using \"\".\n" "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" "\nResult:\n" - "amount (numeric) The total amount in btc received for this account.\n" + "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n" "\nExamples:\n" "\nAmount received by the default account with at least 1 confirmation\n" + HelpExampleCli("getreceivedbyaccount", "\"\"") + @@ -707,7 +707,7 @@ UniValue getbalance(const UniValue& params, bool fHelp) "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n" "\nResult:\n" - "amount (numeric) The total amount in btc received for this account.\n" + "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n" "\nExamples:\n" "\nThe total amount in the wallet\n" + HelpExampleCli("getbalance", "") + @@ -793,14 +793,15 @@ UniValue movecmd(const UniValue& params, bool fHelp) "\nArguments:\n" "1. \"fromaccount\" (string, required) The name of the account to move funds from. May be the default account using \"\".\n" "2. \"toaccount\" (string, required) The name of the account to move funds to. May be the default account using \"\".\n" - "3. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n" - "4. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n" + "3. amount (numeric) Quantity of " + CURRENCY_UNIT + " to move between accounts.\n" + "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n" + "5. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n" "\nResult:\n" "true|false (boolean) true if successfull.\n" "\nExamples:\n" - "\nMove 0.01 btc from the default account to the account named tabby\n" + "\nMove 0.01 " + CURRENCY_UNIT + " from the default account to the account named tabby\n" + HelpExampleCli("move", "\"\" \"tabby\" 0.01") + - "\nMove 0.01 btc timotei to akiko with a comment and funds have 6 confirmations\n" + "\nMove 0.01 " + CURRENCY_UNIT + " timotei to akiko with a comment and funds have 6 confirmations\n" + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") + "\nAs a json rpc call\n" + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"") @@ -867,7 +868,7 @@ UniValue sendfrom(const UniValue& params, bool fHelp) "\nArguments:\n" "1. \"fromaccount\" (string, required) The name of the account to send funds from. May be the default account using \"\".\n" "2. \"tobitcoinaddress\" (string, required) The bitcoin address to send funds to.\n" - "3. amount (numeric, required) The amount in btc. (transaction fee is added on top).\n" + "3. amount (numeric, required) The amount in " + CURRENCY_UNIT + " (transaction fee is added on top).\n" "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n" "5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n" " This is not part of the transaction, just kept in your wallet.\n" @@ -877,7 +878,7 @@ UniValue sendfrom(const UniValue& params, bool fHelp) "\nResult:\n" "\"transactionid\" (string) The transaction id.\n" "\nExamples:\n" - "\nSend 0.01 btc from the default account to the address, must have at least 1 confirmation\n" + "\nSend 0.01 " + CURRENCY_UNIT + " from the default account to the address, must have at least 1 confirmation\n" + HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") + "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n" + HelpExampleCli("sendfrom", "\"tabby\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") + @@ -932,7 +933,7 @@ UniValue sendmany(const UniValue& params, bool fHelp) "1. \"fromaccount\" (string, required) DEPRECATED. The account to send the funds from. Should be \"\" for the default account\n" "2. \"amounts\" (string, required) A json object with addresses and amounts\n" " {\n" - " \"address\":amount (numeric) The bitcoin address is the key, the numeric amount in btc is the value\n" + " \"address\":amount (numeric) The bitcoin address is the key, the numeric amount in " + CURRENCY_UNIT + " is the value\n" " ,...\n" " }\n" "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n" @@ -1233,7 +1234,7 @@ UniValue listreceivedbyaddress(const UniValue& params, bool fHelp) " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n" " \"address\" : \"receivingaddress\", (string) The receiving address\n" " \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n" - " \"amount\" : x.xxx, (numeric) The total amount in btc received by the address\n" + " \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n" " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n" " }\n" " ,...\n" @@ -1405,11 +1406,11 @@ UniValue listtransactions(const UniValue& params, bool fHelp) " transaction between accounts, and not associated with an address,\n" " transaction id or block. 'send' and 'receive' transactions are \n" " associated with an address, transaction id and block details\n" - " \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the\n" + " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the\n" " 'move' category for moves outbound. It is positive for the 'receive' category,\n" " and for the 'move' category for inbound funds.\n" " \"vout\" : n, (numeric) the vout value\n" - " \"fee\": x.xxx, (numeric) The amount of the fee in btc. This is negative and only available for the \n" + " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n" " 'send' category of transactions.\n" " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n" " 'receive' category of transactions.\n" @@ -1600,10 +1601,10 @@ UniValue listsinceblock(const UniValue& params, bool fHelp) " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n" " \"address\":\"bitcoinaddress\", (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n" " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n" - " \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the 'move' category for moves \n" + " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the 'move' category for moves \n" " outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n" " \"vout\" : n, (numeric) the vout value\n" - " \"fee\": x.xxx, (numeric) The amount of the fee in btc. This is negative and only available for the 'send' category of transactions.\n" + " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the 'send' category of transactions.\n" " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n" " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n" " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n" @@ -1686,7 +1687,7 @@ UniValue gettransaction(const UniValue& params, bool fHelp) "2. \"includeWatchonly\" (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n" "\nResult:\n" "{\n" - " \"amount\" : x.xxx, (numeric) The transaction amount in btc\n" + " \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n" " \"confirmations\" : n, (numeric) The number of confirmations\n" " \"blockhash\" : \"hash\", (string) The block hash\n" " \"blockindex\" : xx, (numeric) The block index\n" @@ -1699,7 +1700,7 @@ UniValue gettransaction(const UniValue& params, bool fHelp) " \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n" " \"address\" : \"bitcoinaddress\", (string) The bitcoin address involved in the transaction\n" " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n" - " \"amount\" : x.xxx (numeric) The amount in btc\n" + " \"amount\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n" " \"vout\" : n, (numeric) the vout value\n" " }\n" " ,...\n" @@ -2165,7 +2166,7 @@ UniValue settxfee(const UniValue& params, bool fHelp) "settxfee amount\n" "\nSet the transaction fee per kB.\n" "\nArguments:\n" - "1. amount (numeric, required) The transaction fee in BTC/kB rounded to the nearest 0.00000001\n" + "1. amount (numeric, required) The transaction fee in " + CURRENCY_UNIT + "/kB rounded to the nearest 0.00000001\n" "\nResult\n" "true|false (boolean) Returns true if successful\n" "\nExamples:\n" @@ -2194,14 +2195,14 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp) "\nResult:\n" "{\n" " \"walletversion\": xxxxx, (numeric) the wallet version\n" - " \"balance\": xxxxxxx, (numeric) the total confirmed bitcoin balance of the wallet\n" - " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed bitcoin balance of the wallet\n" - " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet\n" + " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n" + " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n" + " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n" " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n" " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n" " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n" " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n" - " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in btc/kb\n" + " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n" "}\n" "\nExamples:\n" + HelpExampleCli("getwalletinfo", "") @@ -2278,7 +2279,7 @@ UniValue listunspent(const UniValue& params, bool fHelp) " \"address\" : \"address\", (string) the bitcoin address\n" " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n" " \"scriptPubKey\" : \"key\", (string) the script key\n" - " \"amount\" : x.xxx, (numeric) the transaction amount in btc\n" + " \"amount\" : x.xxx, (numeric) the transaction amount in " + CURRENCY_UNIT + "\n" " \"confirmations\" : n (numeric) The number of confirmations\n" " }\n" " ,...\n" diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 58b9ccc078..dcc2983139 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2109,7 +2109,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) if (!wtxNew.AcceptToMemoryPool(false)) { // This must not fail. The transaction has already been signed and recorded. - LogPrintf("CommitTransaction(): Error: Transaction not valid"); + LogPrintf("CommitTransaction(): Error: Transaction not valid\n"); return false; } wtxNew.RelayWalletTransaction(); |