aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--README.md5
-rw-r--r--contrib/debian/control36
-rw-r--r--contrib/debian/watch2
-rw-r--r--depends/packages/openssl.mk1
-rw-r--r--qa/README.md57
-rwxr-xr-xqa/pull-tester/rpc-tests.py3
-rw-r--r--qa/rpc-tests/README.md49
-rwxr-xr-xqa/rpc-tests/script_test.py259
-rw-r--r--src/httpserver.cpp4
-rw-r--r--src/init.cpp4
-rw-r--r--src/main.cpp61
-rw-r--r--src/net.cpp1
-rw-r--r--src/net.h1
-rw-r--r--src/qt/bitcoin.cpp8
-rw-r--r--src/qt/clientmodel.cpp12
-rw-r--r--src/qt/clientmodel.h6
-rw-r--r--src/qt/forms/debugwindow.ui148
-rw-r--r--src/qt/guiutil.cpp5
-rw-r--r--src/qt/optionsmodel.cpp9
-rw-r--r--src/qt/optionsmodel.h4
-rw-r--r--src/qt/rpcconsole.cpp12
-rw-r--r--src/qt/rpcconsole.h2
-rw-r--r--src/rpcblockchain.cpp6
-rw-r--r--src/rpcnet.cpp2
-rw-r--r--src/secp256k1/Makefile.am2
-rw-r--r--src/test/accounting_tests.cpp8
-rw-r--r--src/timedata.cpp14
-rw-r--r--src/wallet/rpcwallet.cpp17
-rw-r--r--src/wallet/wallet.cpp47
-rw-r--r--src/wallet/wallet.h17
-rw-r--r--src/wallet/walletdb.cpp8
-rw-r--r--src/wallet/walletdb.h4
33 files changed, 344 insertions, 472 deletions
diff --git a/Makefile.am b/Makefile.am
index 303ad3b06f..b2b7811729 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -111,7 +111,7 @@ $(APP_DIST_DIR)/Applications:
$(APP_DIST_EXTRAS): $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt
$(OSX_DMG): $(APP_DIST_EXTRAS)
- $(GENISOIMAGE) -no-cache-inodes -D -l -probe -V "Bitcoin-Core" -no-pad -r -apple -o $@ dist
+ $(GENISOIMAGE) -no-cache-inodes -D -l -probe -V "Bitcoin-Core" -no-pad -r -dir-mode 0755 -apple -o $@ dist
$(APP_DIST_DIR)/.background/$(OSX_BACKGROUND_IMAGE): contrib/macdeploy/$(OSX_BACKGROUND_IMAGE)
$(MKDIR_P) $(@D)
diff --git a/README.md b/README.md
index c08b2fb0bc..b40ad0e396 100644
--- a/README.md
+++ b/README.md
@@ -49,9 +49,10 @@ lots of money.
### Automated Testing
Developers are strongly encouraged to write unit tests for new code, and to
-submit new unit tests for old code. Unit tests can be compiled and run (assuming they weren't disabled in configure) with: `make check`
+submit new unit tests for old code. Unit tests can be compiled and run
+(assuming they weren't disabled in configure) with: `make check`
-There are also regression and integration tests of the RPC interface, written
+There are also [regression and integration tests](/qa) of the RPC interface, written
in Python, that are run automatically on the build server.
These tests can be run with: `qa/pull-tester/rpc-tests.py`
diff --git a/contrib/debian/control b/contrib/debian/control
index 2fd68583ce..490b2571c3 100644
--- a/contrib/debian/control
+++ b/contrib/debian/control
@@ -31,14 +31,11 @@ Package: bitcoind
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: peer-to-peer network based digital currency - daemon
- Bitcoin is a free open source peer-to-peer electronic cash system that
- is completely decentralized, without the need for a central server or
- trusted parties. Users hold the crypto keys to their own money and
- transact directly with each other, with the help of a P2P network to
- check for double-spending.
- .
- Full transaction history is stored locally at each client. This
- requires 20+ GB of space, slowly growing.
+ Bitcoin is an experimental new digital currency that enables instant
+ payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer
+ technology to operate with no central authority: managing transactions
+ and issuing money are carried out collectively by the network. Bitcoin Core
+ is the name of the open source software which enables the use of this currency.
.
This package provides the daemon, bitcoind, and the CLI tool
bitcoin-cli to interact with the daemon.
@@ -47,14 +44,11 @@ Package: bitcoin-qt
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: peer-to-peer network based digital currency - Qt GUI
- Bitcoin is a free open source peer-to-peer electronic cash system that
- is completely decentralized, without the need for a central server or
- trusted parties. Users hold the crypto keys to their own money and
- transact directly with each other, with the help of a P2P network to
- check for double-spending.
- .
- Full transaction history is stored locally at each client. This
- requires 20+ GB of space, slowly growing.
+ Bitcoin is an experimental new digital currency that enables instant
+ payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer
+ technology to operate with no central authority: managing transactions
+ and issuing money are carried out collectively by the network. Bitcoin Core
+ is the name of the open source software which enables the use of this currency.
.
This package provides Bitcoin-Qt, a GUI for Bitcoin based on Qt.
@@ -62,11 +56,11 @@ Package: bitcoin-tx
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: peer-to-peer digital currency - standalone transaction tool
- Bitcoin is a free open source peer-to-peer electronic cash system that
- is completely decentralized, without the need for a central server or
- trusted parties. Users hold the crypto keys to their own money and
- transact directly with each other, with the help of a P2P network to
- check for double-spending.
+ Bitcoin is an experimental new digital currency that enables instant
+ payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer
+ technology to operate with no central authority: managing transactions
+ and issuing money are carried out collectively by the network. Bitcoin Core
+ is the name of the open source software which enables the use of this currency.
.
This package provides bitcoin-tx, a command-line transaction creation
tool which can be used without a bitcoin daemon. Some means of
diff --git a/contrib/debian/watch b/contrib/debian/watch
index c96d2f8e75..4d9e0cfa57 100644
--- a/contrib/debian/watch
+++ b/contrib/debian/watch
@@ -1,7 +1,5 @@
# Run the "uscan" command to check for upstream updates and more.
version=3
# use qa.debian.org redirector; see man uscan
-opts=uversionmangle=s/(\d)(alpha|beta|rc)/$1~$2/;s/\-src//,dversionmangle=s/~dfsg\d*// \
- http://sf.net/bitcoin/bitcoin-(\d.*)-linux\.tar\.gz debian
opts=uversionmangle=s/(\d)(alpha|beta|rc)/$1~$2/,dversionmangle=s/~dfsg\d*// \
http://githubredir.debian.net/github/bitcoin/bitcoin v(.*).tar.gz
diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk
index 687aae6682..c6452820a2 100644
--- a/depends/packages/openssl.mk
+++ b/depends/packages/openssl.mk
@@ -17,6 +17,7 @@ $(package)_config_opts_arm_linux=linux-generic32
$(package)_config_opts_aarch64_linux=linux-generic64
$(package)_config_opts_mipsel_linux=linux-generic32
$(package)_config_opts_mips_linux=linux-generic32
+$(package)_config_opts_powerpc_linux=linux-generic32
$(package)_config_opts_x86_64_darwin=darwin64-x86_64-cc
$(package)_config_opts_x86_64_mingw32=mingw64
$(package)_config_opts_i686_mingw32=mingw
diff --git a/qa/README.md b/qa/README.md
new file mode 100644
index 0000000000..758d1f47e5
--- /dev/null
+++ b/qa/README.md
@@ -0,0 +1,57 @@
+The [pull-tester](/qa/pull-tester/) folder contains a script to call
+multiple tests from the [rpc-tests](/qa/rpc-tests/) folder.
+
+Every pull request to the bitcoin repository is built and run through
+the regression test suite. You can also run all or only individual
+tests locally.
+
+Running tests
+=============
+
+You can run any single test by calling `qa/pull-tester/rpc-tests.py <testname>`.
+
+Or you can run any combination of tests by calling `qa/pull-tester/rpc-tests.py <testname1> <testname2> <testname3> ...`
+
+Run the regression test suite with `qa/pull-tester/rpc-tests.py`
+
+Run all possible tests with `qa/pull-tester/rpc-tests.py -extended`
+
+Possible options:
+
+```
+ -h, --help show this help message and exit
+ --nocleanup Leave bitcoinds and test.* datadir on exit or error
+ --noshutdown Don't stop bitcoinds after the test execution
+ --srcdir=SRCDIR Source directory containing bitcoind/bitcoin-cli
+ (default: ../../src)
+ --tmpdir=TMPDIR Root directory for datadirs
+ --tracerpc Print out all RPC calls as they are made
+ --coveragedir=COVERAGEDIR
+ Write tested RPC commands into this directory
+```
+
+If you set the environment variable `PYTHON_DEBUG=1` you will get some debug
+output (example: `PYTHON_DEBUG=1 qa/pull-tester/rpc-tests.py wallet`).
+
+A 200-block -regtest blockchain and wallets for four nodes
+is created the first time a regression test is run and
+is stored in the cache/ directory. Each node has 25 mature
+blocks (25*50=1250 BTC) in its wallet.
+
+After the first run, the cache/ blockchain and wallets are
+copied into a temporary directory and used as the initial
+test state.
+
+If you get into a bad state, you should be able
+to recover with:
+
+```bash
+rm -rf cache
+killall bitcoind
+```
+
+Writing tests
+=============
+You are encouraged to write tests for new or existing features.
+Further information about the test framework and individual rpc
+tests is found in [qa/rpc-tests](/qa/rpc-tests).
diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py
index 83fc9b8f96..7a30db68dd 100755
--- a/qa/pull-tester/rpc-tests.py
+++ b/qa/pull-tester/rpc-tests.py
@@ -69,6 +69,7 @@ if EXEEXT == ".exe" and "-win" not in opts:
testScripts = [
'wallet.py',
'listtransactions.py',
+ 'receivedby.py',
'mempool_resurrect_test.py',
'txn_doublespend.py --mineblock',
'txn_clone.py',
@@ -104,9 +105,7 @@ testScriptsExt = [
'forknotify.py',
'invalidateblock.py',
'keypool.py',
- 'receivedby.py',
# 'rpcbind_test.py', #temporary, bug in libevent, see #6655
-# 'script_test.py', #used for manual comparison of 2 binaries
'smartfees.py',
'maxblocksinflight.py',
'invalidblockrequest.py',
diff --git a/qa/rpc-tests/README.md b/qa/rpc-tests/README.md
index d2db00362f..898931936b 100644
--- a/qa/rpc-tests/README.md
+++ b/qa/rpc-tests/README.md
@@ -1,10 +1,8 @@
Regression tests
================
-### [python-bitcoinrpc](https://github.com/jgarzik/python-bitcoinrpc)
-Git subtree of [https://github.com/jgarzik/python-bitcoinrpc](https://github.com/jgarzik/python-bitcoinrpc).
-Changes to python-bitcoinrpc should be made upstream, and then
-pulled here using git subtree.
+### [test_framework/authproxy.py](test_framework/authproxy.py)
+Taken from the [python-bitcoinrpc repository](https://github.com/jgarzik/python-bitcoinrpc).
### [test_framework/test_framework.py](test_framework/test_framework.py)
Base class for new regression tests.
@@ -33,49 +31,6 @@ Helpers for script.py
### [test_framework/blocktools.py](test_framework/blocktools.py)
Helper functions for creating blocks and transactions.
-
-Notes
-=====
-
-You can run any single test by calling `qa/pull-tester/rpc-tests.py <testname>`.
-
-Or you can run any combination of tests by calling `qa/pull-tester/rpc-tests.py <testname1> <testname2> <testname3> ...`
-
-Run the regression test suite with `qa/pull-tester/rpc-tests.py`
-
-Run all possible tests with `qa/pull-tester/rpc-tests.py -extended`
-
-Possible options:
-
-```
--h, --help show this help message and exit
- --nocleanup Leave bitcoinds and test.* datadir on exit or error
- --noshutdown Don't stop bitcoinds after the test execution
- --srcdir=SRCDIR Source directory containing bitcoind/bitcoin-cli (default:
- ../../src)
- --tmpdir=TMPDIR Root directory for datadirs
- --tracerpc Print out all RPC calls as they are made
-```
-
-If you set the environment variable `PYTHON_DEBUG=1` you will get some debug output (example: `PYTHON_DEBUG=1 qa/pull-tester/rpc-tests.py wallet`).
-
-A 200-block -regtest blockchain and wallets for four nodes
-is created the first time a regression test is run and
-is stored in the cache/ directory. Each node has 25 mature
-blocks (25*50=1250 BTC) in its wallet.
-
-After the first run, the cache/ blockchain and wallets are
-copied into a temporary directory and used as the initial
-test state.
-
-If you get into a bad state, you should be able
-to recover with:
-
-```bash
-rm -rf cache
-killall bitcoind
-```
-
P2P test design notes
---------------------
diff --git a/qa/rpc-tests/script_test.py b/qa/rpc-tests/script_test.py
deleted file mode 100755
index afc44b51b5..0000000000
--- a/qa/rpc-tests/script_test.py
+++ /dev/null
@@ -1,259 +0,0 @@
-#!/usr/bin/env python2
-#
-# Distributed under the MIT/X11 software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#
-
-'''
-Test notes:
-This test uses the script_valid and script_invalid tests from the unittest
-framework to do end-to-end testing where we compare that two nodes agree on
-whether blocks containing a given test script are valid.
-
-We generally ignore the script flags associated with each test (since we lack
-the precision to test each script using those flags in this framework), but
-for tests with SCRIPT_VERIFY_P2SH, we can use a block time after the BIP16
-switchover date to try to test with that flag enabled (and for tests without
-that flag, we use a block time before the switchover date).
-
-NOTE: This test is very slow and may take more than 40 minutes to run.
-'''
-
-from test_framework.test_framework import ComparisonTestFramework
-from test_framework.util import *
-from test_framework.comptool import TestInstance, TestManager
-from test_framework.mininode import *
-from test_framework.blocktools import *
-from test_framework.script import *
-import logging
-import copy
-import json
-
-script_valid_file = "../../src/test/data/script_valid.json"
-script_invalid_file = "../../src/test/data/script_invalid.json"
-
-# Pass in a set of json files to open.
-class ScriptTestFile(object):
-
- def __init__(self, files):
- self.files = files
- self.index = -1
- self.data = []
-
- def load_files(self):
- for f in self.files:
- self.data.extend(json.loads(open(os.path.dirname(os.path.abspath(__file__))+"/"+f).read()))
-
- # Skip over records that are not long enough to be tests
- def get_records(self):
- while (self.index < len(self.data)):
- if len(self.data[self.index]) >= 3:
- yield self.data[self.index]
- self.index += 1
-
-
-# Helper for parsing the flags specified in the .json files
-SCRIPT_VERIFY_NONE = 0
-SCRIPT_VERIFY_P2SH = 1
-SCRIPT_VERIFY_STRICTENC = 1 << 1
-SCRIPT_VERIFY_DERSIG = 1 << 2
-SCRIPT_VERIFY_LOW_S = 1 << 3
-SCRIPT_VERIFY_NULLDUMMY = 1 << 4
-SCRIPT_VERIFY_SIGPUSHONLY = 1 << 5
-SCRIPT_VERIFY_MINIMALDATA = 1 << 6
-SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = 1 << 7
-SCRIPT_VERIFY_CLEANSTACK = 1 << 8
-
-flag_map = {
- "": SCRIPT_VERIFY_NONE,
- "NONE": SCRIPT_VERIFY_NONE,
- "P2SH": SCRIPT_VERIFY_P2SH,
- "STRICTENC": SCRIPT_VERIFY_STRICTENC,
- "DERSIG": SCRIPT_VERIFY_DERSIG,
- "LOW_S": SCRIPT_VERIFY_LOW_S,
- "NULLDUMMY": SCRIPT_VERIFY_NULLDUMMY,
- "SIGPUSHONLY": SCRIPT_VERIFY_SIGPUSHONLY,
- "MINIMALDATA": SCRIPT_VERIFY_MINIMALDATA,
- "DISCOURAGE_UPGRADABLE_NOPS": SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS,
- "CLEANSTACK": SCRIPT_VERIFY_CLEANSTACK,
-}
-
-def ParseScriptFlags(flag_string):
- flags = 0
- for x in flag_string.split(","):
- if x in flag_map:
- flags |= flag_map[x]
- else:
- print "Error: unrecognized script flag: ", x
- return flags
-
-'''
-Given a string that is a scriptsig or scriptpubkey from the .json files above,
-convert it to a CScript()
-'''
-# Replicates behavior from core_read.cpp
-def ParseScript(json_script):
- script = json_script.split(" ")
- parsed_script = CScript()
- for x in script:
- if len(x) == 0:
- # Empty string, ignore.
- pass
- elif x.isdigit() or (len(x) >= 1 and x[0] == "-" and x[1:].isdigit()):
- # Number
- n = int(x, 0)
- if (n == -1) or (n >= 1 and n <= 16):
- parsed_script = CScript(bytes(parsed_script) + bytes(CScript([n])))
- else:
- parsed_script += CScriptNum(int(x, 0))
- elif x.startswith("0x"):
- # Raw hex data, inserted NOT pushed onto stack:
- for i in xrange(2, len(x), 2):
- parsed_script = CScript(bytes(parsed_script) + bytes(chr(int(x[i:i+2],16))))
- elif x.startswith("'") and x.endswith("'") and len(x) >= 2:
- # Single-quoted string, pushed as data.
- parsed_script += CScript([x[1:-1]])
- else:
- # opcode, e.g. OP_ADD or ADD:
- tryopname = "OP_" + x
- if tryopname in OPCODES_BY_NAME:
- parsed_script += CScriptOp(OPCODES_BY_NAME["OP_" + x])
- else:
- print "ParseScript: error parsing '%s'" % x
- return ""
- return parsed_script
-
-class TestBuilder(object):
- def create_credit_tx(self, scriptPubKey, height):
- # self.tx1 is a coinbase transaction, modeled after the one created by script_tests.cpp
- # This allows us to reuse signatures created in the unit test framework.
- self.tx1 = create_coinbase(height) # this has a bip34 scriptsig,
- self.tx1.vin[0].scriptSig = CScript([0, 0]) # but this matches the unit tests
- self.tx1.vout[0].nValue = 0
- self.tx1.vout[0].scriptPubKey = scriptPubKey
- self.tx1.rehash()
- def create_spend_tx(self, scriptSig):
- self.tx2 = create_transaction(self.tx1, 0, CScript(), 0)
- self.tx2.vin[0].scriptSig = scriptSig
- self.tx2.vout[0].scriptPubKey = CScript()
- self.tx2.rehash()
- def rehash(self):
- self.tx1.rehash()
- self.tx2.rehash()
-
-# This test uses the (default) two nodes provided by ComparisonTestFramework,
-# specified on the command line with --testbinary and --refbinary.
-# See comptool.py
-class ScriptTest(ComparisonTestFramework):
-
- def run_test(self):
- # Set up the comparison tool TestManager
- test = TestManager(self, self.options.tmpdir)
- test.add_all_connections(self.nodes)
-
- # Load scripts
- self.scripts = ScriptTestFile([script_valid_file, script_invalid_file])
- self.scripts.load_files()
-
- # Some variables we re-use between test instances (to build blocks)
- self.tip = None
- self.block_time = None
-
- NetworkThread().start() # Start up network handling in another thread
- test.run()
-
- def generate_test_instance(self, pubkeystring, scriptsigstring):
- scriptpubkey = ParseScript(pubkeystring)
- scriptsig = ParseScript(scriptsigstring)
-
- test = TestInstance(sync_every_block=False)
- test_build = TestBuilder()
- test_build.create_credit_tx(scriptpubkey, self.height)
- test_build.create_spend_tx(scriptsig)
- test_build.rehash()
-
- block = create_block(self.tip, test_build.tx1, self.block_time)
- self.block_time += 1
- block.solve()
- self.tip = block.sha256
- self.height += 1
- test.blocks_and_transactions = [[block, True]]
-
- for i in xrange(100):
- block = create_block(self.tip, create_coinbase(self.height), self.block_time)
- self.block_time += 1
- block.solve()
- self.tip = block.sha256
- self.height += 1
- test.blocks_and_transactions.append([block, True])
-
- block = create_block(self.tip, create_coinbase(self.height), self.block_time)
- self.block_time += 1
- block.vtx.append(test_build.tx2)
- block.hashMerkleRoot = block.calc_merkle_root()
- block.rehash()
- block.solve()
- test.blocks_and_transactions.append([block, None])
- return test
-
- # This generates the tests for TestManager.
- def get_tests(self):
- self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0)
- self.block_time = 1333230000 # before the BIP16 switchover
- self.height = 1
-
- '''
- Create a new block with an anyone-can-spend coinbase
- '''
- block = create_block(self.tip, create_coinbase(self.height), self.block_time)
- self.block_time += 1
- block.solve()
- self.tip = block.sha256
- self.height += 1
- yield TestInstance(objects=[[block, True]])
-
- '''
- Build out to 100 blocks total, maturing the coinbase.
- '''
- test = TestInstance(objects=[], sync_every_block=False, sync_every_tx=False)
- for i in xrange(100):
- b = create_block(self.tip, create_coinbase(self.height), self.block_time)
- b.solve()
- test.blocks_and_transactions.append([b, True])
- self.tip = b.sha256
- self.block_time += 1
- self.height += 1
- yield test
-
- ''' Iterate through script tests. '''
- counter = 0
- for script_test in self.scripts.get_records():
- ''' Reset the blockchain to genesis block + 100 blocks. '''
- if self.nodes[0].getblockcount() > 101:
- self.nodes[0].invalidateblock(self.nodes[0].getblockhash(102))
- self.nodes[1].invalidateblock(self.nodes[1].getblockhash(102))
-
- self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0)
- self.height = 102
-
- [scriptsig, scriptpubkey, flags] = script_test[0:3]
- flags = ParseScriptFlags(flags)
-
- # We can use block time to determine whether the nodes should be
- # enforcing BIP16.
- #
- # We intentionally let the block time grow by 1 each time.
- # This forces the block hashes to differ between tests, so that
- # a call to invalidateblock doesn't interfere with a later test.
- if (flags & SCRIPT_VERIFY_P2SH):
- self.block_time = 1333238400 + counter # Advance to enforcing BIP16
- else:
- self.block_time = 1333230000 + counter # Before the BIP16 switchover
-
- print "Script test: [%s]" % script_test
-
- yield self.generate_test_instance(scriptpubkey, scriptsig)
- counter += 1
-
-if __name__ == '__main__':
- ScriptTest().main()
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index 52f5675e85..91518d7c5f 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -487,7 +487,11 @@ void StopHTTPServer()
// master that appears to be solved, so in the future that solution
// could be used again (if desirable).
// (see discussion in https://github.com/bitcoin/bitcoin/pull/6990)
+#if BOOST_VERSION >= 105000
if (!threadHTTP.try_join_for(boost::chrono::milliseconds(2000))) {
+#else
+ if (!threadHTTP.timed_join(boost::posix_time::milliseconds(2000))) {
+#endif
LogPrintf("HTTP event loop did not exit within allotted time, sending loopbreak\n");
event_base_loopbreak(eventBase);
threadHTTP.join();
diff --git a/src/init.cpp b/src/init.cpp
index 3f53fdcbf6..953980c5b6 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -362,6 +362,9 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-onion=<ip:port>", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy"));
strUsage += HelpMessageOpt("-onlynet=<net>", _("Only connect to nodes in network <net> (ipv4, ipv6 or onion)"));
strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), 1));
+ strUsage += HelpMessageOpt("-peerbloomfilters", strprintf(_("Support filtering of blocks and transaction with bloom filters (default: %u)"), 1));
+ if (showDebug)
+ strUsage += HelpMessageOpt("-enforcenodebloom", strprintf("Enforce minimum protocol version to limit use of bloom filters (default: %u)", 0));
strUsage += HelpMessageOpt("-port=<port>", strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), 8333, 18333));
strUsage += HelpMessageOpt("-proxy=<ip:port>", _("Connect through SOCKS5 proxy"));
strUsage += HelpMessageOpt("-proxyrandomize", strprintf(_("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)"), 1));
@@ -501,6 +504,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-min", _("Start minimized"));
strUsage += HelpMessageOpt("-rootcertificates=<file>", _("Set SSL root certificates for payment request (default: -system-)"));
strUsage += HelpMessageOpt("-splash", _("Show splash screen on startup (default: 1)"));
+ strUsage += HelpMessageOpt("-resetguisettings", _("Reset all settings changes made over the GUI"));
if (showDebug) {
strUsage += HelpMessageOpt("-uiplatform", "Select platform to customize UI for (one of windows, macosx, other; default: platform compiled on)");
}
diff --git a/src/main.cpp b/src/main.cpp
index 8fb121c00d..b0b58141a2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -670,10 +670,11 @@ bool CheckFinalTx(const CTransaction &tx, int flags)
// IsFinalTx() with one more than chainActive.Height().
const int nBlockHeight = chainActive.Height() + 1;
- // Timestamps on the other hand don't get any special treatment,
- // because we can't know what timestamp the next block will have,
- // and there aren't timestamp applications where it matters.
- // However this changes once median past time-locks are enforced:
+ // BIP113 will require that time-locked transactions have nLockTime set to
+ // less than the median time of the previous block they're contained in.
+ // When the next block is created its previous block will be the current
+ // chain tip, so we use that to calculate the median time passed to
+ // IsFinalTx() if LOCKTIME_MEDIAN_TIME_PAST is set.
const int64_t nBlockTime = (flags & LOCKTIME_MEDIAN_TIME_PAST)
? chainActive.Tip()->GetMedianTimePast()
: GetAdjustedTime();
@@ -3988,6 +3989,19 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
+ if (!(nLocalServices & NODE_BLOOM) &&
+ (strCommand == "filterload" ||
+ strCommand == "filteradd" ||
+ strCommand == "filterclear"))
+ {
+ if (pfrom->nVersion >= NO_BLOOM_VERSION) {
+ Misbehaving(pfrom->GetId(), 100);
+ return false;
+ } else if (GetBoolArg("-enforcenodebloom", false)) {
+ pfrom->fDisconnect = true;
+ return false;
+ }
+ }
if (strCommand == "version")
@@ -4210,6 +4224,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return error("message inv size() = %u", vInv.size());
}
+ bool fBlocksOnly = GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY);
+
+ // Allow whitelisted peers to send data other than blocks in blocks only mode if whitelistalwaysrelay is true
+ if (pfrom->fWhitelisted && GetBoolArg("-whitelistalwaysrelay", DEFAULT_WHITELISTALWAYSRELAY))
+ fBlocksOnly = false;
+
LOCK(cs_main);
std::vector<CInv> vToFetch;
@@ -4224,9 +4244,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
bool fAlreadyHave = AlreadyHave(inv);
LogPrint("net", "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id);
- if (!fAlreadyHave && !fImporting && !fReindex && inv.type != MSG_BLOCK && !GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY))
- pfrom->AskFor(inv);
-
if (inv.type == MSG_BLOCK) {
UpdateBlockAvailability(pfrom->GetId(), inv.hash);
if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) {
@@ -4250,6 +4267,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
LogPrint("net", "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->id);
}
}
+ else
+ {
+ if (fBlocksOnly)
+ LogPrint("net", "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->id);
+ else if (!fAlreadyHave && !fImporting && !fReindex)
+ pfrom->AskFor(inv);
+ }
// Track requests for our stuff
GetMainSignals().Inventory(inv.hash);
@@ -4374,6 +4398,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
else if (strCommand == "tx")
{
+ // Stop processing the transaction early if
+ // We are in blocks only mode and peer is either not whitelisted or whitelistalwaysrelay is off
+ if (GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && (!pfrom->fWhitelisted || !GetBoolArg("-whitelistalwaysrelay", DEFAULT_WHITELISTALWAYSRELAY)))
+ {
+ LogPrint("net", "transaction sent in violation of protocol peer=%d\n", pfrom->id);
+ return true;
+ }
+
vector<uint256> vWorkQueue;
vector<uint256> vEraseQueue;
CTransaction tx;
@@ -4731,21 +4763,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
- else if (!(nLocalServices & NODE_BLOOM) &&
- (strCommand == "filterload" ||
- strCommand == "filteradd" ||
- strCommand == "filterclear") &&
- //TODO: Remove this line after reasonable network upgrade
- pfrom->nVersion >= NO_BLOOM_VERSION)
- {
- if (pfrom->nVersion >= NO_BLOOM_VERSION)
- Misbehaving(pfrom->GetId(), 100);
- //TODO: Enable this after reasonable network upgrade
- //else
- // pfrom->fDisconnect = true;
- }
-
-
else if (strCommand == "filterload")
{
CBloomFilter filter;
diff --git a/src/net.cpp b/src/net.cpp
index 000eefc858..cff4c54505 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -617,6 +617,7 @@ void CNode::copyStats(CNodeStats &stats)
{
stats.nodeid = this->GetId();
X(nServices);
+ X(fRelayTxes);
X(nLastSend);
X(nLastRecv);
X(nTimeConnected);
diff --git a/src/net.h b/src/net.h
index ebdbe77565..559cdf0878 100644
--- a/src/net.h
+++ b/src/net.h
@@ -180,6 +180,7 @@ class CNodeStats
public:
NodeId nodeid;
uint64_t nServices;
+ bool fRelayTxes;
int64_t nLastSend;
int64_t nLastRecv;
int64_t nTimeConnected;
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index bda8acff15..06a6c239ef 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -202,7 +202,7 @@ public:
void createPaymentServer();
#endif
/// Create options model
- void createOptionsModel();
+ void createOptionsModel(bool resetSettings);
/// Create main window
void createWindow(const NetworkStyle *networkStyle);
/// Create splash screen
@@ -352,9 +352,9 @@ void BitcoinApplication::createPaymentServer()
}
#endif
-void BitcoinApplication::createOptionsModel()
+void BitcoinApplication::createOptionsModel(bool resetSettings)
{
- optionsModel = new OptionsModel();
+ optionsModel = new OptionsModel(NULL, resetSettings);
}
void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
@@ -645,7 +645,7 @@ int main(int argc, char *argv[])
qInstallMessageHandler(DebugMessageHandler);
#endif
// Load GUI settings from QSettings
- app.createOptionsModel();
+ app.createOptionsModel(mapArgs.count("-resetguisettings") != 0);
// Subscribe to global signals from core
uiInterface.InitMessage.connect(InitMessage);
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 0900a35cc4..566e8fa62d 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -13,6 +13,7 @@
#include "checkpoints.h"
#include "clientversion.h"
#include "net.h"
+#include "txmempool.h"
#include "ui_interface.h"
#include "util.h"
@@ -88,6 +89,16 @@ QDateTime ClientModel::getLastBlockDate() const
return QDateTime::fromTime_t(Params().GenesisBlock().GetBlockTime()); // Genesis block's time of current network
}
+long ClientModel::getMempoolSize() const
+{
+ return mempool.size();
+}
+
+size_t ClientModel::getMempoolDynamicUsage() const
+{
+ return mempool.DynamicMemoryUsage();
+}
+
double ClientModel::getVerificationProgress() const
{
LOCK(cs_main);
@@ -122,6 +133,7 @@ void ClientModel::updateTimer()
Q_EMIT numBlocksChanged(newNumBlocks, newBlockDate);
}
+ Q_EMIT mempoolSizeChanged(getMempoolSize(), getMempoolDynamicUsage());
Q_EMIT bytesChanged(getTotalBytesRecv(), getTotalBytesSent());
}
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 627bdf862d..493a759331 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -51,6 +51,11 @@ public:
int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const;
int getNumBlocks() const;
+ //! Return number of transactions in the mempool
+ long getMempoolSize() const;
+ //! Return the dynamic memory usage of the mempool
+ size_t getMempoolDynamicUsage() const;
+
quint64 getTotalBytesRecv() const;
quint64 getTotalBytesSent() const;
@@ -89,6 +94,7 @@ private:
Q_SIGNALS:
void numConnectionsChanged(int count);
void numBlocksChanged(int count, const QDateTime& blockDate);
+ void mempoolSizeChanged(long count, size_t mempoolSizeInBytes);
void alertsChanged(const QString &warnings);
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut);
diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui
index eb02dd80ff..2471470363 100644
--- a/src/qt/forms/debugwindow.ui
+++ b/src/qt/forms/debugwindow.ui
@@ -23,7 +23,7 @@
<attribute name="title">
<string>&amp;Information</string>
</attribute>
- <layout class="QGridLayout" name="gridLayout" columnstretch="0,1">
+ <layout class="QGridLayout" name="gridLayout" columnstretch="0,1,0">
<property name="horizontalSpacing">
<number>12</number>
</property>
@@ -47,7 +47,7 @@
</property>
</widget>
</item>
- <item row="1" column="1">
+ <item row="1" column="1" colspan="2">
<widget class="QLabel" name="clientName">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -70,7 +70,7 @@
</property>
</widget>
</item>
- <item row="2" column="1">
+ <item row="2" column="1" colspan="2">
<widget class="QLabel" name="clientVersion">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -96,7 +96,7 @@
</property>
</widget>
</item>
- <item row="3" column="1">
+ <item row="3" column="1" colspan="2">
<widget class="QLabel" name="clientUserAgent">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -122,7 +122,7 @@
</property>
</widget>
</item>
- <item row="4" column="1">
+ <item row="4" column="1" colspan="2">
<widget class="QLabel" name="openSSLVersion">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -148,7 +148,7 @@
</property>
</widget>
</item>
- <item row="5" column="1">
+ <item row="5" column="1" colspan="2">
<widget class="QLabel" name="berkeleyDBVersion">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -171,7 +171,7 @@
</property>
</widget>
</item>
- <item row="6" column="1">
+ <item row="6" column="1" colspan="2">
<widget class="QLabel" name="buildDate">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -194,7 +194,7 @@
</property>
</widget>
</item>
- <item row="7" column="1">
+ <item row="7" column="1" colspan="2">
<widget class="QLabel" name="startupTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -210,19 +210,6 @@
</property>
</widget>
</item>
- <item row="8" column="0">
- <widget class="QLabel" name="label_11">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Network</string>
- </property>
- </widget>
- </item>
<item row="9" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
@@ -230,7 +217,7 @@
</property>
</widget>
</item>
- <item row="9" column="1">
+ <item row="9" column="1" colspan="2">
<widget class="QLabel" name="networkName">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -253,7 +240,7 @@
</property>
</widget>
</item>
- <item row="10" column="1">
+ <item row="10" column="1" colspan="2">
<widget class="QLabel" name="numberOfConnections">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -289,7 +276,7 @@
</property>
</widget>
</item>
- <item row="12" column="1">
+ <item row="12" column="1" colspan="2">
<widget class="QLabel" name="numberOfBlocks">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -306,13 +293,13 @@
</widget>
</item>
<item row="13" column="0">
- <widget class="QLabel" name="label_2">
+ <widget class="QLabel" name="labelLastBlockTime">
<property name="text">
<string>Last block time</string>
</property>
</widget>
</item>
- <item row="13" column="1">
+ <item row="13" column="1" colspan="2">
<widget class="QLabel" name="lastBlockTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -329,20 +316,43 @@
</widget>
</item>
<item row="14" column="0">
- <spacer name="verticalSpacer_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
+ <widget class="QLabel" name="labelMempoolTitle">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
</property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
+ <property name="text">
+ <string>Memory Pool</string>
</property>
- </spacer>
+ </widget>
</item>
<item row="15" column="0">
- <widget class="QLabel" name="labelDebugLogfile">
+ <widget class="QLabel" name="labelNumberOfTransactions">
+ <property name="text">
+ <string>Current number of transactions</string>
+ </property>
+ </widget>
+ </item>
+ <item row="15" column="1">
+ <widget class="QLabel" name="mempoolNumberTxs">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="labelNetwork">
<property name="font">
<font>
<weight>75</weight>
@@ -350,24 +360,74 @@
</font>
</property>
<property name="text">
- <string>Debug log file</string>
+ <string>Network</string>
</property>
</widget>
</item>
<item row="16" column="0">
- <widget class="QPushButton" name="openDebugLogfileButton">
- <property name="toolTip">
- <string>Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files.</string>
+ <widget class="QLabel" name="labelMemoryUsage">
+ <property name="text">
+ <string>Memory usage</string>
+ </property>
+ </widget>
+ </item>
+ <item row="16" column="1">
+ <widget class="QLabel" name="mempoolSize">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
- <string>&amp;Open</string>
+ <string>N/A</string>
</property>
- <property name="autoDefault">
- <bool>false</bool>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
- <item row="17" column="0">
+ <item row="14" column="2" rowspan="3">
+ <layout class="QVBoxLayout" name="verticalLayoutDebugButton">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>10</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelDebugLogfile">
+ <property name="text">
+ <string>Debug log file</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="openDebugLogfileButton">
+ <property name="toolTip">
+ <string>Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files.</string>
+ </property>
+ <property name="text">
+ <string>&amp;Open</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="18" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 845459b76a..6dce9370d7 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -681,7 +681,10 @@ boost::filesystem::path static GetAutostartDir()
boost::filesystem::path static GetAutostartFilePath()
{
- return GetAutostartDir() / "bitcoin.desktop";
+ std::string chain = ChainNameFromCommandLine();
+ if (chain == CBaseChainParams::MAIN)
+ return GetAutostartDir() / "bitcoin.desktop";
+ return GetAutostartDir() / strprintf("bitcoin-%s.lnk", chain);
}
bool GetStartOnSystemStartup()
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 65e490570e..3e5c6c72b1 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -26,10 +26,10 @@
#include <QSettings>
#include <QStringList>
-OptionsModel::OptionsModel(QObject *parent) :
+OptionsModel::OptionsModel(QObject *parent, bool resetSettings) :
QAbstractListModel(parent)
{
- Init();
+ Init(resetSettings);
}
void OptionsModel::addOverriddenOption(const std::string &option)
@@ -38,8 +38,11 @@ void OptionsModel::addOverriddenOption(const std::string &option)
}
// Writes all missing QSettings with their default values
-void OptionsModel::Init()
+void OptionsModel::Init(bool resetSettings)
{
+ if (resetSettings)
+ Reset();
+
QSettings settings;
// Ensure restart flag is unset on client startup
diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h
index 8448cad8de..d5bddb1a94 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -24,7 +24,7 @@ class OptionsModel : public QAbstractListModel
Q_OBJECT
public:
- explicit OptionsModel(QObject *parent = 0);
+ explicit OptionsModel(QObject *parent = 0, bool resetSettings = false);
enum OptionID {
StartAtStartup, // bool
@@ -48,7 +48,7 @@ public:
OptionIDRowCount,
};
- void Init();
+ void Init(bool resetSettings = false);
void Reset();
int rowCount(const QModelIndex & parent = QModelIndex()) const;
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 4554281e0f..619c8631ae 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -343,6 +343,8 @@ void RPCConsole::setClientModel(ClientModel *model)
updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent());
connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64)));
+ connect(model, SIGNAL(mempoolSizeChanged(long,size_t)), this, SLOT(setMempoolSize(long,size_t)));
+
// set up peer table
ui->peerWidget->setModel(model->getPeerTableModel());
ui->peerWidget->verticalHeader()->hide();
@@ -523,6 +525,16 @@ void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate)
ui->lastBlockTime->setText(blockDate.toString());
}
+void RPCConsole::setMempoolSize(long numberOfTxs, size_t dynUsage)
+{
+ ui->mempoolNumberTxs->setText(QString::number(numberOfTxs));
+
+ if (dynUsage < 1000000)
+ ui->mempoolSize->setText(QString::number(dynUsage/1000.0, 'f', 2) + " KB");
+ else
+ ui->mempoolSize->setText(QString::number(dynUsage/1000000.0, 'f', 2) + " MB");
+}
+
void RPCConsole::on_lineEdit_returnPressed()
{
QString cmd = ui->lineEdit->text();
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 0914612c3e..4b242affcd 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -84,6 +84,8 @@ public Q_SLOTS:
void setNumConnections(int count);
/** Set number of blocks and last block date shown in the UI */
void setNumBlocks(int count, const QDateTime& blockDate);
+ /** Set size (number of transactions and memory usage) of the mempool in the UI */
+ void setMempoolSize(long numberOfTxs, size_t dynUsage);
/** Go forward or back in history */
void browseHistory(int offset);
/** Scroll console view to end */
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 9c0e78f772..012370ed10 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -71,6 +71,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex)
result.push_back(Pair("version", blockindex->nVersion));
result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex()));
result.push_back(Pair("time", (int64_t)blockindex->nTime));
+ result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast()));
result.push_back(Pair("nonce", (uint64_t)blockindex->nNonce));
result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits)));
result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
@@ -111,6 +112,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
}
result.push_back(Pair("tx", txs));
result.push_back(Pair("time", block.GetBlockTime()));
+ result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast()));
result.push_back(Pair("nonce", (uint64_t)block.nNonce));
result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
@@ -313,6 +315,7 @@ UniValue getblockheader(const UniValue& params, bool fHelp)
" \"version\" : n, (numeric) The block version\n"
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
" \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
+ " \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n"
" \"nonce\" : n, (numeric) The nonce\n"
" \"bits\" : \"1d00ffff\", (string) The bits\n"
" \"difficulty\" : x.xxx, (numeric) The difficulty\n"
@@ -374,6 +377,7 @@ UniValue getblock(const UniValue& params, bool fHelp)
" ,...\n"
" ],\n"
" \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
+ " \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n"
" \"nonce\" : n, (numeric) The nonce\n"
" \"bits\" : \"1d00ffff\", (string) The bits\n"
" \"difficulty\" : x.xxx, (numeric) The difficulty\n"
@@ -608,6 +612,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
" \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n"
" \"bestblockhash\": \"...\", (string) the hash of the currently best block\n"
" \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
+ " \"mediantime\": xxxxxx, (numeric) median time for the current best block\n"
" \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n"
" \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n"
" \"pruned\": xx, (boolean) if the blocks are subject to pruning\n"
@@ -639,6 +644,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1));
obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex()));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
+ obj.push_back(Pair("mediantime", (int64_t)chainActive.Tip()->GetMedianTimePast()));
obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip())));
obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex()));
obj.push_back(Pair("pruned", fPruneMode));
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index 8915010649..2578848891 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -90,6 +90,7 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp)
" \"addr\":\"host:port\", (string) The ip address and port of the peer\n"
" \"addrlocal\":\"ip:port\", (string) local address\n"
" \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n"
+ " \"relaytxes\":true|false, (boolean) Whether peer has asked us to relay transactions to it\n"
" \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
" \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
" \"bytessent\": n, (numeric) The total bytes sent\n"
@@ -134,6 +135,7 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp)
if (!(stats.addrLocal.empty()))
obj.push_back(Pair("addrlocal", stats.addrLocal));
obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
+ obj.push_back(Pair("relaytxes", stats.fRelayTxes));
obj.push_back(Pair("lastsend", stats.nLastSend));
obj.push_back(Pair("lastrecv", stats.nLastRecv));
obj.push_back(Pair("bytessent", stats.nSendBytes));
diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am
index f4121f1705..7772a4e9d2 100644
--- a/src/secp256k1/Makefile.am
+++ b/src/secp256k1/Makefile.am
@@ -75,7 +75,7 @@ TESTS = tests
endif
if USE_ECMULT_STATIC_PRECOMPUTATION
-CPPFLAGS_FOR_BUILD +=-I$(top_srcdir)/
+CPPFLAGS_FOR_BUILD +=-I$(top_srcdir)
CFLAGS_FOR_BUILD += -Wall -Wextra -Wno-unused-function
gen_context_OBJECTS = gen_context.o
diff --git a/src/test/accounting_tests.cpp b/src/test/accounting_tests.cpp
index 0c2ade48d6..4a294c6712 100644
--- a/src/test/accounting_tests.cpp
+++ b/src/test/accounting_tests.cpp
@@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
ae.nTime = 1333333333;
ae.strOtherAccount = "b";
ae.strComment = "";
- walletdb.WriteAccountingEntry(ae);
+ pwalletMain->AddAccountingEntry(ae, walletdb);
wtx.mapValue["comment"] = "z";
pwalletMain->AddToWallet(wtx, false, &walletdb);
@@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
ae.nTime = 1333333336;
ae.strOtherAccount = "c";
- walletdb.WriteAccountingEntry(ae);
+ pwalletMain->AddAccountingEntry(ae, walletdb);
GetResults(walletdb, results);
@@ -71,7 +71,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
ae.nTime = 1333333330;
ae.strOtherAccount = "d";
ae.nOrderPos = pwalletMain->IncOrderPosNext();
- walletdb.WriteAccountingEntry(ae);
+ pwalletMain->AddAccountingEntry(ae, walletdb);
GetResults(walletdb, results);
@@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
ae.nTime = 1333333334;
ae.strOtherAccount = "e";
ae.nOrderPos = -1;
- walletdb.WriteAccountingEntry(ae);
+ pwalletMain->AddAccountingEntry(ae, walletdb);
GetResults(walletdb, results);
diff --git a/src/timedata.cpp b/src/timedata.cpp
index 0641009537..861c375989 100644
--- a/src/timedata.cpp
+++ b/src/timedata.cpp
@@ -55,7 +55,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
// Add data
static CMedianFilter<int64_t> vTimeOffsets(BITCOIN_TIMEDATA_MAX_SAMPLES, 0);
vTimeOffsets.input(nOffsetSample);
- LogPrintf("Added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
+ LogPrint("net","added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
// There is a known issue here (see issue #4521):
//
@@ -105,11 +105,11 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
}
}
}
- if (fDebug) {
- BOOST_FOREACH(int64_t n, vSorted)
- LogPrintf("%+d ", n);
- LogPrintf("| ");
- }
- LogPrintf("nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60);
+
+ BOOST_FOREACH(int64_t n, vSorted)
+ LogPrint("net", "%+d ", n);
+ LogPrint("net", "| ");
+
+ LogPrint("net", "nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60);
}
}
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index bc00c62e9c..b6eaca80b3 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -835,7 +835,7 @@ UniValue movecmd(const UniValue& params, bool fHelp)
debit.nTime = nNow;
debit.strOtherAccount = strTo;
debit.strComment = strComment;
- walletdb.WriteAccountingEntry(debit);
+ pwalletMain->AddAccountingEntry(debit, walletdb);
// Credit
CAccountingEntry credit;
@@ -845,7 +845,7 @@ UniValue movecmd(const UniValue& params, bool fHelp)
credit.nTime = nNow;
credit.strOtherAccount = strFrom;
credit.strComment = strComment;
- walletdb.WriteAccountingEntry(credit);
+ pwalletMain->AddAccountingEntry(credit, walletdb);
if (!walletdb.TxnCommit())
throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
@@ -1417,7 +1417,7 @@ UniValue listtransactions(const UniValue& params, bool fHelp)
" \"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"
+ " \"vout\": n, (numeric) the vout value\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"
@@ -1426,12 +1426,13 @@ UniValue listtransactions(const UniValue& params, bool fHelp)
" category of transactions.\n"
" \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
" category of transactions.\n"
+ " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
" \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
" \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
" \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
" for 'send' and 'receive' category of transactions.\n"
" \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
- " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
+ " \"label\": \"label\" (string) A comment for the address/transaction, if any\n"
" \"otheraccount\": \"accountname\", (string) For the 'move' category of transactions, the account the funds came \n"
" from (for receiving funds, positive amounts), or went to (for sending funds,\n"
" negative amounts).\n"
@@ -1470,11 +1471,10 @@ UniValue listtransactions(const UniValue& params, bool fHelp)
UniValue ret(UniValue::VARR);
- std::list<CAccountingEntry> acentries;
- CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
+ const CWallet::TxItems & txOrdered = pwalletMain->wtxOrdered;
// iterate backwards until we have nCount items to return:
- for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
+ for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
{
CWalletTx *const pwtx = (*it).second.first;
if (pwtx != 0)
@@ -1579,8 +1579,7 @@ UniValue listaccounts(const UniValue& params, bool fHelp)
}
}
- list<CAccountingEntry> acentries;
- CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
+ const list<CAccountingEntry> & acentries = pwalletMain->laccentries;
BOOST_FOREACH(const CAccountingEntry& entry, acentries)
mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index d51b8ddaef..1b152f4192 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -588,31 +588,6 @@ int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
return nRet;
}
-CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
-{
- AssertLockHeld(cs_wallet); // mapWallet
- CWalletDB walletdb(strWalletFile);
-
- // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
- TxItems txOrdered;
-
- // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
- // would make this much faster for applications that do this a lot.
- for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
- {
- CWalletTx* wtx = &((*it).second);
- txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0)));
- }
- acentries.clear();
- walletdb.ListAccountCreditDebit(strAccount, acentries);
- BOOST_FOREACH(CAccountingEntry& entry, acentries)
- {
- txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
- }
-
- return txOrdered;
-}
-
void CWallet::MarkDirty()
{
{
@@ -629,7 +604,9 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
if (fFromLoadWallet)
{
mapWallet[hash] = wtxIn;
- mapWallet[hash].BindWallet(this);
+ CWalletTx& wtx = mapWallet[hash];
+ wtx.BindWallet(this);
+ wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0)));
AddToSpends(hash);
}
else
@@ -644,6 +621,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
{
wtx.nTimeReceived = GetAdjustedTime();
wtx.nOrderPos = IncOrderPosNext(pwalletdb);
+ wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0)));
wtx.nTimeSmart = wtx.nTimeReceived;
if (!wtxIn.hashBlock.IsNull())
@@ -655,9 +633,8 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
{
// Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
int64_t latestTolerated = latestNow + 300;
- std::list<CAccountingEntry> acentries;
- TxItems txOrdered = OrderedTxItems(acentries);
- for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
+ const TxItems & txOrdered = wtxOrdered;
+ for (TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
{
CWalletTx *const pwtx = (*it).second.first;
if (pwtx == &wtx)
@@ -2118,6 +2095,18 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
return true;
}
+bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB & pwalletdb)
+{
+ if (!pwalletdb.WriteAccountingEntry_Backend(acentry))
+ return false;
+
+ laccentries.push_back(acentry);
+ CAccountingEntry & entry = laccentries.back();
+ wtxOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
+
+ return true;
+}
+
CAmount CWallet::GetRequiredFee(unsigned int nTxBytes)
{
return std::max(minTxFee.GetFee(nTxBytes), ::minRelayTxFee.GetFee(nTxBytes));
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 719f11f206..7e846569ff 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -531,6 +531,11 @@ public:
}
std::map<uint256, CWalletTx> mapWallet;
+ std::list<CAccountingEntry> laccentries;
+
+ typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair;
+ typedef std::multimap<int64_t, TxPair > TxItems;
+ TxItems wtxOrdered;
int64_t nOrderPosNext;
std::map<uint256, int> mapRequestCount;
@@ -617,16 +622,6 @@ public:
*/
int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL);
- typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair;
- typedef std::multimap<int64_t, TxPair > TxItems;
-
- /**
- * Get the wallet's activity log
- * @return multimap of ordered transactions and accounting entries
- * @warning Returned pointers are *only* valid within the scope of passed acentries
- */
- TxItems OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount = "");
-
void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb);
void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
@@ -656,6 +651,8 @@ public:
std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true);
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
+ bool AddAccountingEntry(const CAccountingEntry&, CWalletDB & pwalletdb);
+
static CFeeRate minTxFee;
/**
* Estimate the minimum fee considering user set parameters
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index ea8a4eb043..9ce9f53bd9 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -191,7 +191,7 @@ bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccount
return Write(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry);
}
-bool CWalletDB::WriteAccountingEntry(const CAccountingEntry& acentry)
+bool CWalletDB::WriteAccountingEntry_Backend(const CAccountingEntry& acentry)
{
return WriteAccountingEntry(++nAccountingEntryNumber, acentry);
}
@@ -709,6 +709,12 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
if (wss.fAnyUnordered)
result = ReorderTransactions(pwallet);
+ pwallet->laccentries.clear();
+ ListAccountCreditDebit("*", pwallet->laccentries);
+ BOOST_FOREACH(CAccountingEntry& entry, pwallet->laccentries) {
+ pwallet->wtxOrdered.insert(make_pair(entry.nOrderPos, CWallet::TxPair((CWalletTx*)0, &entry)));
+ }
+
return result;
}
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 270f826aed..3ebc05afd1 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -110,6 +110,9 @@ public:
bool WriteMinVersion(int nVersion);
+ /// This writes directly to the database, and will not update the CWallet's cached accounting entries!
+ /// Use wallet.AddAccountingEntry instead, to write *and* update its caches.
+ bool WriteAccountingEntry_Backend(const CAccountingEntry& acentry);
bool ReadAccount(const std::string& strAccount, CAccount& account);
bool WriteAccount(const std::string& strAccount, const CAccount& account);
@@ -118,7 +121,6 @@ public:
/// Erase destination data tuple from wallet database
bool EraseDestData(const std::string &address, const std::string &key);
- bool WriteAccountingEntry(const CAccountingEntry& acentry);
CAmount GetAccountCreditDebit(const std::string& strAccount);
void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);