aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE.md2
-rw-r--r--contrib/debian/copyright3
-rw-r--r--depends/hosts/darwin.mk2
-rw-r--r--doc/developer-notes.md26
-rwxr-xr-xqa/rpc-tests/p2p-compactblocks.py18
-rwxr-xr-xqa/rpc-tests/preciousblock.py65
-rwxr-xr-xqa/rpc-tests/smartfees.py6
-rwxr-xr-xqa/rpc-tests/test_framework/mininode.py26
-rw-r--r--qa/rpc-tests/test_framework/util.py45
-rw-r--r--src/Makefile.qt.include1
-rw-r--r--src/addrdb.h2
-rw-r--r--src/addrman.h11
-rw-r--r--src/amount.h2
-rw-r--r--src/bench/checkblock.cpp4
-rw-r--r--src/bitcoin-tx.cpp2
-rw-r--r--src/blockencodings.cpp2
-rw-r--r--src/blockencodings.h10
-rw-r--r--src/bloom.h2
-rw-r--r--src/chain.h9
-rw-r--r--src/coins.h47
-rw-r--r--src/compressor.h14
-rw-r--r--src/dbwrapper.h15
-rw-r--r--src/hash.h12
-rw-r--r--src/key.h4
-rw-r--r--src/main.cpp35
-rw-r--r--src/main.h2
-rw-r--r--src/merkleblock.h4
-rw-r--r--src/net.cpp31
-rw-r--r--src/net.h5
-rw-r--r--src/netaddress.h6
-rw-r--r--src/policy/fees.h1
-rw-r--r--src/primitives/block.h9
-rw-r--r--src/primitives/transaction.h24
-rw-r--r--src/protocol.cpp6
-rw-r--r--src/protocol.h13
-rw-r--r--src/pubkey.h17
-rw-r--r--src/qt/bitcoin.qrc1
-rw-r--r--src/qt/bitcoingui.cpp49
-rw-r--r--src/qt/bitcoingui.h21
-rw-r--r--src/qt/clientmodel.cpp28
-rw-r--r--src/qt/clientmodel.h6
-rw-r--r--src/qt/guiutil.cpp12
-rw-r--r--src/qt/guiutil.h3
-rw-r--r--src/qt/recentrequeststablemodel.h2
-rw-r--r--src/qt/res/icons/network_disabled.pngbin0 -> 2438 bytes
-rw-r--r--src/qt/res/src/connect-0.svg4
-rw-r--r--src/qt/res/src/connect-1.svg4
-rw-r--r--src/qt/res/src/connect-2.svg4
-rw-r--r--src/qt/res/src/connect-3.svg4
-rw-r--r--src/qt/res/src/connect-4.svg4
-rw-r--r--src/qt/res/src/network_disabled.svg49
-rw-r--r--src/qt/rpcconsole.cpp146
-rw-r--r--src/qt/rpcconsole.h11
-rw-r--r--src/qt/walletmodel.h2
-rw-r--r--src/rest.cpp2
-rw-r--r--src/rpc/client.cpp1
-rw-r--r--src/rpc/net.cpp26
-rw-r--r--src/script/bitcoinconsensus.cpp9
-rw-r--r--src/script/interpreter.cpp30
-rw-r--r--src/serialize.h448
-rw-r--r--src/streams.h111
-rw-r--r--src/test/blockencodings_tests.cpp2
-rw-r--r--src/test/bloom_tests.cpp6
-rw-r--r--src/test/dbwrapper_tests.cpp2
-rw-r--r--src/test/net_tests.cpp8
-rw-r--r--src/test/rpc_tests.cpp22
-rw-r--r--src/test/serialize_tests.cpp4
-rw-r--r--src/test/uint256_tests.cpp46
-rw-r--r--src/txdb.h2
-rw-r--r--src/ui_interface.h3
-rw-r--r--src/uint256.h9
-rw-r--r--src/undo.h26
-rw-r--r--src/wallet/crypter.h2
-rw-r--r--src/wallet/rpcdump.cpp2
-rw-r--r--src/wallet/wallet.h34
-rw-r--r--src/wallet/walletdb.h4
76 files changed, 925 insertions, 707 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index acb54dd354..28c1814998 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -4,6 +4,8 @@ This issue tracker is only for technical issues related to bitcoin-core.
General bitcoin questions and/or support requests and are best directed to the [Bitcoin StackExchange](https://bitcoin.stackexchange.com).
+For reporting security issues, please read instructions at [https://bitcoincore.org/en/contact/](https://bitcoincore.org/en/contact/).
+
### Describe the issue
### Can you reliably reproduce the issue?
diff --git a/contrib/debian/copyright b/contrib/debian/copyright
index 5cac6e533c..0fa06f1aa9 100644
--- a/contrib/debian/copyright
+++ b/contrib/debian/copyright
@@ -47,7 +47,10 @@ Comment: Site: https://github.com/stephenhutchings/typicons.font
Files: src/qt/res/icons/connect*.png
src/qt/res/src/connect-*.svg
+ src/qt/res/icons/network_disabled.png
+ src/qt/res/src/network_disabled.svg
Copyright: Marco Falke
+ Luke Dashjr
License: Expat
Comment: Inspired by Stephan Hutchings Typicons
diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk
index 985649619f..4e58bec74e 100644
--- a/depends/hosts/darwin.mk
+++ b/depends/hosts/darwin.mk
@@ -1,4 +1,4 @@
-OSX_MIN_VERSION=10.7
+OSX_MIN_VERSION=10.8
OSX_SDK_VERSION=10.11
OSX_SDK=$(SDK_PATH)/MacOSX$(OSX_SDK_VERSION).sdk
LD64_VERSION=253.9
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 70c0690ba3..b0794e6d30 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -331,6 +331,32 @@ Strings and formatting
- *Rationale*: Bitcoin Core uses tinyformat, which is type safe. Leave them out to avoid confusion
+Variable names
+--------------
+
+The shadowing warning (`-Wshadow`) is enabled by default. It prevents issues rising
+from using a different variable with the same name.
+
+Please name variables so that their names do not shadow variables defined in the source code.
+
+E.g. in member initializers, prepend `_` to the argument name shadowing the
+member name:
+
+```c++
+class AddressBookPage
+{
+ Mode mode;
+}
+
+AddressBookPage::AddressBookPage(Mode _mode) :
+ mode(_mode)
+...
+```
+
+When using nested cycles, do not name the inner cycle variable the same as in
+upper cycle etc.
+
+
Threads and synchronization
----------------------------
diff --git a/qa/rpc-tests/p2p-compactblocks.py b/qa/rpc-tests/p2p-compactblocks.py
index 6d1fb3fd9a..1b4c8d90e7 100755
--- a/qa/rpc-tests/p2p-compactblocks.py
+++ b/qa/rpc-tests/p2p-compactblocks.py
@@ -300,8 +300,8 @@ class CompactBlocksTest(BitcoinTestFramework):
assert(segwit_tx_generated) # check that our test is not broken
# Wait until we've seen the block announcement for the resulting tip
- tip = int(self.nodes[0].getbestblockhash(), 16)
- assert(self.test_node.wait_for_block_announcement(tip))
+ tip = int(node.getbestblockhash(), 16)
+ assert(test_node.wait_for_block_announcement(tip))
# Now mine a block, and look at the resulting compact block.
test_node.clear_block_announcement()
@@ -589,8 +589,8 @@ class CompactBlocksTest(BitcoinTestFramework):
assert_equal(int(node.getbestblockhash(), 16), block.sha256)
def test_getblocktxn_handler(self, node, test_node, version):
- # bitcoind won't respond for blocks whose height is more than 15 blocks
- # deep.
+ # bitcoind will not send blocktxn responses for blocks whose height is
+ # more than 10 blocks deep.
MAX_GETBLOCKTXN_DEPTH = 10
chain_height = node.getblockcount()
current_height = chain_height
@@ -623,11 +623,17 @@ class CompactBlocksTest(BitcoinTestFramework):
test_node.last_blocktxn = None
current_height -= 1
- # Next request should be ignored, as we're past the allowed depth.
+ # Next request should send a full block response, as we're past the
+ # allowed depth for a blocktxn response.
block_hash = node.getblockhash(current_height)
msg.block_txn_request = BlockTransactionsRequest(int(block_hash, 16), [0])
+ with mininode_lock:
+ test_node.last_block = None
+ test_node.last_blocktxn = None
test_node.send_and_ping(msg)
with mininode_lock:
+ test_node.last_block.block.calc_sha256()
+ assert_equal(test_node.last_block.block.sha256, int(block_hash, 16))
assert_equal(test_node.last_blocktxn, None)
def test_compactblocks_not_at_tip(self, node, test_node):
@@ -648,6 +654,8 @@ class CompactBlocksTest(BitcoinTestFramework):
node.generate(1)
wait_until(test_node.received_block_announcement, timeout=30)
test_node.clear_block_announcement()
+ with mininode_lock:
+ test_node.last_block = None
test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))]))
success = wait_until(lambda: test_node.last_block is not None, timeout=30)
assert(success)
diff --git a/qa/rpc-tests/preciousblock.py b/qa/rpc-tests/preciousblock.py
index 854dcc7251..3cefa51c0a 100755
--- a/qa/rpc-tests/preciousblock.py
+++ b/qa/rpc-tests/preciousblock.py
@@ -8,7 +8,12 @@
#
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
+from test_framework.util import (
+ assert_equal,
+ connect_nodes_bi,
+ sync_chain,
+ sync_blocks,
+)
def unidirectional_node_sync_via_rpc(node_src, node_dest):
blocks_to_copy = []
@@ -33,84 +38,82 @@ def node_sync_via_rpc(nodes):
unidirectional_node_sync_via_rpc(node_src, node_dest)
class PreciousTest(BitcoinTestFramework):
- def setup_chain(self):
- print("Initializing test directory "+self.options.tmpdir)
- initialize_chain_clean(self.options.tmpdir, 3)
+ def __init__(self):
+ super().__init__()
+ self.setup_clean_chain = True
+ self.num_nodes = 3
+ self.extra_args = [["-debug"]] * self.num_nodes
def setup_network(self):
- self.nodes = []
- self.is_network_split = False
- self.nodes.append(start_node(0, self.options.tmpdir, ["-debug"]))
- self.nodes.append(start_node(1, self.options.tmpdir, ["-debug"]))
- self.nodes.append(start_node(2, self.options.tmpdir, ["-debug"]))
+ self.nodes = self.setup_nodes()
def run_test(self):
print("Ensure submitblock can in principle reorg to a competing chain")
self.nodes[0].generate(1)
- assert(self.nodes[0].getblockcount() == 1)
+ assert_equal(self.nodes[0].getblockcount(), 1)
(hashY, hashZ) = self.nodes[1].generate(2)
- assert(self.nodes[1].getblockcount() == 2)
+ assert_equal(self.nodes[1].getblockcount(), 2)
node_sync_via_rpc(self.nodes[0:3])
- assert(self.nodes[0].getbestblockhash() == hashZ)
+ assert_equal(self.nodes[0].getbestblockhash(), hashZ)
print("Mine blocks A-B-C on Node 0")
(hashA, hashB, hashC) = self.nodes[0].generate(3)
- assert(self.nodes[0].getblockcount() == 5)
+ assert_equal(self.nodes[0].getblockcount(), 5)
print("Mine competing blocks E-F-G on Node 1")
(hashE, hashF, hashG) = self.nodes[1].generate(3)
- assert(self.nodes[1].getblockcount() == 5)
+ assert_equal(self.nodes[1].getblockcount(), 5)
assert(hashC != hashG)
print("Connect nodes and check no reorg occurs")
# Submit competing blocks via RPC so any reorg should occur before we proceed (no way to wait on inaction for p2p sync)
node_sync_via_rpc(self.nodes[0:2])
connect_nodes_bi(self.nodes,0,1)
- assert(self.nodes[0].getbestblockhash() == hashC)
- assert(self.nodes[1].getbestblockhash() == hashG)
+ assert_equal(self.nodes[0].getbestblockhash(), hashC)
+ assert_equal(self.nodes[1].getbestblockhash(), hashG)
print("Make Node0 prefer block G")
self.nodes[0].preciousblock(hashG)
- assert(self.nodes[0].getbestblockhash() == hashG)
+ assert_equal(self.nodes[0].getbestblockhash(), hashG)
print("Make Node0 prefer block C again")
self.nodes[0].preciousblock(hashC)
- assert(self.nodes[0].getbestblockhash() == hashC)
+ assert_equal(self.nodes[0].getbestblockhash(), hashC)
print("Make Node1 prefer block C")
self.nodes[1].preciousblock(hashC)
sync_chain(self.nodes[0:2]) # wait because node 1 may not have downloaded hashC
- assert(self.nodes[1].getbestblockhash() == hashC)
+ assert_equal(self.nodes[1].getbestblockhash(), hashC)
print("Make Node1 prefer block G again")
self.nodes[1].preciousblock(hashG)
- assert(self.nodes[1].getbestblockhash() == hashG)
+ assert_equal(self.nodes[1].getbestblockhash(), hashG)
print("Make Node0 prefer block G again")
self.nodes[0].preciousblock(hashG)
- assert(self.nodes[0].getbestblockhash() == hashG)
+ assert_equal(self.nodes[0].getbestblockhash(), hashG)
print("Make Node1 prefer block C again")
self.nodes[1].preciousblock(hashC)
- assert(self.nodes[1].getbestblockhash() == hashC)
+ assert_equal(self.nodes[1].getbestblockhash(), hashC)
print("Mine another block (E-F-G-)H on Node 0 and reorg Node 1")
self.nodes[0].generate(1)
- assert(self.nodes[0].getblockcount() == 6)
+ assert_equal(self.nodes[0].getblockcount(), 6)
sync_blocks(self.nodes[0:2])
hashH = self.nodes[0].getbestblockhash()
- assert(self.nodes[1].getbestblockhash() == hashH)
+ assert_equal(self.nodes[1].getbestblockhash(), hashH)
print("Node1 should not be able to prefer block C anymore")
self.nodes[1].preciousblock(hashC)
- assert(self.nodes[1].getbestblockhash() == hashH)
+ assert_equal(self.nodes[1].getbestblockhash(), hashH)
print("Mine competing blocks I-J-K-L on Node 2")
self.nodes[2].generate(4)
- assert(self.nodes[2].getblockcount() == 6)
+ assert_equal(self.nodes[2].getblockcount(), 6)
hashL = self.nodes[2].getbestblockhash()
print("Connect nodes and check no reorg occurs")
node_sync_via_rpc(self.nodes[0:3])
connect_nodes_bi(self.nodes,1,2)
connect_nodes_bi(self.nodes,0,2)
- assert(self.nodes[0].getbestblockhash() == hashH)
- assert(self.nodes[1].getbestblockhash() == hashH)
- assert(self.nodes[2].getbestblockhash() == hashL)
+ assert_equal(self.nodes[0].getbestblockhash(), hashH)
+ assert_equal(self.nodes[1].getbestblockhash(), hashH)
+ assert_equal(self.nodes[2].getbestblockhash(), hashL)
print("Make Node1 prefer block L")
self.nodes[1].preciousblock(hashL)
- assert(self.nodes[1].getbestblockhash() == hashL)
+ assert_equal(self.nodes[1].getbestblockhash(), hashL)
print("Make Node2 prefer block H")
self.nodes[2].preciousblock(hashH)
- assert(self.nodes[2].getbestblockhash() == hashH)
+ assert_equal(self.nodes[2].getbestblockhash(), hashH)
if __name__ == '__main__':
PreciousTest().main()
diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py
index d76fba4b07..74a74f679a 100755
--- a/qa/rpc-tests/smartfees.py
+++ b/qa/rpc-tests/smartfees.py
@@ -225,9 +225,9 @@ class EstimateFeeTest(BitcoinTestFramework):
self.memutxo, Decimal("0.005"), min_fee, min_fee)
tx_kbytes = (len(txhex) // 2) / 1000.0
self.fees_per_kb.append(float(fee)/tx_kbytes)
- sync_mempools(self.nodes[0:3],.1)
+ sync_mempools(self.nodes[0:3], wait=.1)
mined = mining_node.getblock(mining_node.generate(1)[0],True)["tx"]
- sync_blocks(self.nodes[0:3],.1)
+ sync_blocks(self.nodes[0:3], wait=.1)
# update which txouts are confirmed
newmem = []
for utx in self.memutxo:
@@ -259,7 +259,7 @@ class EstimateFeeTest(BitcoinTestFramework):
while len(self.nodes[1].getrawmempool()) > 0:
self.nodes[1].generate(1)
- sync_blocks(self.nodes[0:3],.1)
+ sync_blocks(self.nodes[0:3], wait=.1)
print("Final estimates after emptying mempools")
check_estimates(self.nodes[1], self.fees_per_kb, 2)
diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py
index 4d238c08d9..495c6bdf35 100755
--- a/qa/rpc-tests/test_framework/mininode.py
+++ b/qa/rpc-tests/test_framework/mininode.py
@@ -41,6 +41,7 @@ from test_framework.siphash import siphash256
BIP0031_VERSION = 60000
MY_VERSION = 70014 # past bip-31 for ping/pong
MY_SUBVERSION = b"/python-mininode-tester:0.0.3/"
+MY_RELAY = 1 # from version 70001 onwards, fRelay should be appended to version messages (BIP37)
MAX_INV_SZ = 50000
MAX_BLOCK_SIZE = 1000000
@@ -951,6 +952,7 @@ class msg_version(object):
self.nNonce = random.getrandbits(64)
self.strSubVer = MY_SUBVERSION
self.nStartingHeight = -1
+ self.nRelay = MY_RELAY
def deserialize(self, f):
self.nVersion = struct.unpack("<i", f.read(4))[0]
@@ -960,21 +962,32 @@ class msg_version(object):
self.nTime = struct.unpack("<q", f.read(8))[0]
self.addrTo = CAddress()
self.addrTo.deserialize(f)
+
if self.nVersion >= 106:
self.addrFrom = CAddress()
self.addrFrom.deserialize(f)
self.nNonce = struct.unpack("<Q", f.read(8))[0]
self.strSubVer = deser_string(f)
- if self.nVersion >= 209:
- self.nStartingHeight = struct.unpack("<i", f.read(4))[0]
- else:
- self.nStartingHeight = None
else:
self.addrFrom = None
self.nNonce = None
self.strSubVer = None
self.nStartingHeight = None
+ if self.nVersion >= 209:
+ self.nStartingHeight = struct.unpack("<i", f.read(4))[0]
+ else:
+ self.nStartingHeight = None
+
+ if self.nVersion >= 70001:
+ # Relay field is optional for version 70001 onwards
+ try:
+ self.nRelay = struct.unpack("<b", f.read(1))[0]
+ except:
+ self.nRelay = 0
+ else:
+ self.nRelay = 0
+
def serialize(self):
r = b""
r += struct.pack("<i", self.nVersion)
@@ -985,13 +998,14 @@ class msg_version(object):
r += struct.pack("<Q", self.nNonce)
r += ser_string(self.strSubVer)
r += struct.pack("<i", self.nStartingHeight)
+ r += struct.pack("<b", self.nRelay)
return r
def __repr__(self):
- return 'msg_version(nVersion=%i nServices=%i nTime=%s addrTo=%s addrFrom=%s nNonce=0x%016X strSubVer=%s nStartingHeight=%i)' \
+ return 'msg_version(nVersion=%i nServices=%i nTime=%s addrTo=%s addrFrom=%s nNonce=0x%016X strSubVer=%s nStartingHeight=%i nRelay=%i)' \
% (self.nVersion, self.nServices, time.ctime(self.nTime),
repr(self.addrTo), repr(self.addrFrom), self.nNonce,
- self.strSubVer, self.nStartingHeight)
+ self.strSubVer, self.nStartingHeight, self.nRelay)
class msg_verack(object):
diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py
index c0c2b3a6ef..bf13b7fd84 100644
--- a/qa/rpc-tests/test_framework/util.py
+++ b/qa/rpc-tests/test_framework/util.py
@@ -121,33 +121,42 @@ def hex_str_to_bytes(hex_str):
def str_to_b64str(string):
return b64encode(string.encode('utf-8')).decode('ascii')
-def sync_blocks(rpc_connections, wait=1, timeout=60):
+def sync_blocks(rpc_connections, *, wait=1, timeout=60):
"""
- Wait until everybody has the same tip
+ Wait until everybody has the same tip.
+
+ sync_blocks needs to be called with an rpc_connections set that has least
+ one node already synced to the latest, stable tip, otherwise there's a
+ chance it might return before all nodes are stably synced.
"""
maxheight = 0
- while timeout > 0:
- tips = [ x.waitforblockheight(maxheight, int(wait * 1000)) for x in rpc_connections ]
- heights = [ x["height"] for x in tips ]
- if tips == [ tips[0] ]*len(tips):
- return True
- if heights == [ heights[0] ]*len(heights): #heights are the same but hashes are not
- raise AssertionError("Block sync failed")
- timeout -= wait
+ start_time = cur_time = time.time()
+ while cur_time <= start_time + timeout:
+ tips = [r.waitforblockheight(maxheight, int(wait * 1000)) for r in rpc_connections]
+ heights = [t["height"] for t in tips]
+ if all(t == tips[0] for t in tips):
+ return
+ if all(h == heights[0] for h in heights):
+ raise AssertionError("Block sync failed, mismatched block hashes:{}".format(
+ "".join("\n {!r}".format(tip) for tip in tips)))
maxheight = max(heights)
- raise AssertionError("Block sync failed")
+ cur_time = time.time()
+ raise AssertionError("Block sync to height {} timed out:{}".format(
+ maxheight, "".join("\n {!r}".format(tip) for tip in tips)))
-def sync_chain(rpc_connections, wait=1):
+def sync_chain(rpc_connections, *, wait=1, timeout=60):
"""
Wait until everybody has the same best block
"""
- while True:
- counts = [ x.getbestblockhash() for x in rpc_connections ]
- if counts == [ counts[0] ]*len(counts):
- break
+ while timeout > 0:
+ best_hash = [x.getbestblockhash() for x in rpc_connections]
+ if best_hash == [best_hash[0]]*len(best_hash):
+ return
time.sleep(wait)
+ timeout -= wait
+ raise AssertionError("Chain sync failed: Best block hashes don't match")
-def sync_mempools(rpc_connections, wait=1, timeout=60):
+def sync_mempools(rpc_connections, *, wait=1, timeout=60):
"""
Wait until everybody has the same transactions in their memory
pools
@@ -159,7 +168,7 @@ def sync_mempools(rpc_connections, wait=1, timeout=60):
if set(rpc_connections[i].getrawmempool()) == pool:
num_match = num_match+1
if num_match == len(rpc_connections):
- return True
+ return
time.sleep(wait)
timeout -= wait
raise AssertionError("Mempool sync failed")
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 1f9a901d75..48abb9b4a2 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -271,6 +271,7 @@ RES_ICONS = \
qt/res/icons/key.png \
qt/res/icons/lock_closed.png \
qt/res/icons/lock_open.png \
+ qt/res/icons/network_disabled.png \
qt/res/icons/open.png \
qt/res/icons/overview.png \
qt/res/icons/quit.png \
diff --git a/src/addrdb.h b/src/addrdb.h
index 62835a6fb4..339943ca5a 100644
--- a/src/addrdb.h
+++ b/src/addrdb.h
@@ -46,7 +46,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(this->nVersion);
READWRITE(nCreateTime);
READWRITE(nBanUntil);
diff --git a/src/addrman.h b/src/addrman.h
index e9e137c978..cabacbbea9 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -58,7 +58,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(*(CAddress*)this);
READWRITE(source);
READWRITE(nLastSuccess);
@@ -293,7 +293,7 @@ public:
* very little in common.
*/
template<typename Stream>
- void Serialize(Stream &s, int nType, int nVersionDummy) const
+ void Serialize(Stream &s) const
{
LOCK(cs);
@@ -343,7 +343,7 @@ public:
}
template<typename Stream>
- void Unserialize(Stream& s, int nType, int nVersionDummy)
+ void Unserialize(Stream& s)
{
LOCK(cs);
@@ -448,11 +448,6 @@ public:
Check();
}
- unsigned int GetSerializeSize(int nType, int nVersion) const
- {
- return (CSizeComputer(nType, nVersion) << *this).size();
- }
-
void Clear()
{
std::vector<int>().swap(vRandom);
diff --git a/src/amount.h b/src/amount.h
index 5e52f37f23..ba0c86040f 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -64,7 +64,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(nSatoshisPerK);
}
};
diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp
index bb596ce7f9..4a564d3fc8 100644
--- a/src/bench/checkblock.cpp
+++ b/src/bench/checkblock.cpp
@@ -46,8 +46,8 @@ static void DeserializeAndCheckBlockTest(benchmark::State& state)
stream >> block;
assert(stream.Rewind(sizeof(block_bench::block413567)));
- CValidationState state;
- assert(CheckBlock(block, state, params));
+ CValidationState validationState;
+ assert(CheckBlock(block, validationState, params));
}
}
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index ecc19c44ad..6c66efcc9c 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -48,7 +48,7 @@ static int AppInitRawTx(int argc, char* argv[])
SelectParams(ChainNameFromCommandLine());
} catch (const std::exception& e) {
fprintf(stderr, "Error: %s\n", e.what());
- return false;
+ return EXIT_FAILURE;
}
fCreateBlank = GetBoolArg("-create", false);
diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp
index 737102f168..dbed90583d 100644
--- a/src/blockencodings.cpp
+++ b/src/blockencodings.cpp
@@ -131,7 +131,7 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c
break;
}
- LogPrint("cmpctblock", "Initialized PartiallyDownloadedBlock for block %s using a cmpctblock of size %lu\n", cmpctblock.header.GetHash().ToString(), cmpctblock.GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION));
+ LogPrint("cmpctblock", "Initialized PartiallyDownloadedBlock for block %s using a cmpctblock of size %lu\n", cmpctblock.header.GetHash().ToString(), GetSerializeSize(cmpctblock, SER_NETWORK, PROTOCOL_VERSION));
return READ_STATUS_OK;
}
diff --git a/src/blockencodings.h b/src/blockencodings.h
index 705eaf28aa..1f9491867a 100644
--- a/src/blockencodings.h
+++ b/src/blockencodings.h
@@ -21,7 +21,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(tx); //TODO: Compress tx encoding
}
};
@@ -35,7 +35,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(blockhash);
uint64_t indexes_size = (uint64_t)indexes.size();
READWRITE(COMPACTSIZE(indexes_size));
@@ -81,7 +81,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(blockhash);
uint64_t txn_size = (uint64_t)txn.size();
READWRITE(COMPACTSIZE(txn_size));
@@ -109,7 +109,7 @@ struct PrefilledTransaction {
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
uint64_t idx = index;
READWRITE(COMPACTSIZE(idx));
if (idx > std::numeric_limits<uint16_t>::max())
@@ -157,7 +157,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(header);
READWRITE(nonce);
diff --git a/src/bloom.h b/src/bloom.h
index ad6de625d8..d3a017371f 100644
--- a/src/bloom.h
+++ b/src/bloom.h
@@ -73,7 +73,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(vData);
READWRITE(nHashFuncs);
READWRITE(nTweak);
diff --git a/src/chain.h b/src/chain.h
index 46a16a3061..0aac5de5c2 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -28,7 +28,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(VARINT(nBlocks));
READWRITE(VARINT(nSize));
READWRITE(VARINT(nUndoSize));
@@ -76,7 +76,7 @@ struct CDiskBlockPos
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(VARINT(nFile));
READWRITE(VARINT(nPos));
}
@@ -357,8 +357,9 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- if (!(nType & SER_GETHASH))
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ int nVersion = s.GetVersion();
+ if (!(s.GetType() & SER_GETHASH))
READWRITE(VARINT(nVersion));
READWRITE(VARINT(nHeight));
diff --git a/src/coins.h b/src/coins.h
index 033651a435..d295b3c940 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -153,31 +153,8 @@ public:
return fCoinBase;
}
- unsigned int GetSerializeSize(int nType, int nVersion) const {
- unsigned int nSize = 0;
- unsigned int nMaskSize = 0, nMaskCode = 0;
- CalcMaskSize(nMaskSize, nMaskCode);
- bool fFirst = vout.size() > 0 && !vout[0].IsNull();
- bool fSecond = vout.size() > 1 && !vout[1].IsNull();
- assert(fFirst || fSecond || nMaskCode);
- unsigned int nCode = 8*(nMaskCode - (fFirst || fSecond ? 0 : 1)) + (fCoinBase ? 1 : 0) + (fFirst ? 2 : 0) + (fSecond ? 4 : 0);
- // version
- nSize += ::GetSerializeSize(VARINT(this->nVersion), nType, nVersion);
- // size of header code
- nSize += ::GetSerializeSize(VARINT(nCode), nType, nVersion);
- // spentness bitmask
- nSize += nMaskSize;
- // txouts themself
- for (unsigned int i = 0; i < vout.size(); i++)
- if (!vout[i].IsNull())
- nSize += ::GetSerializeSize(CTxOutCompressor(REF(vout[i])), nType, nVersion);
- // height
- nSize += ::GetSerializeSize(VARINT(nHeight), nType, nVersion);
- return nSize;
- }
-
template<typename Stream>
- void Serialize(Stream &s, int nType, int nVersion) const {
+ void Serialize(Stream &s) const {
unsigned int nMaskSize = 0, nMaskCode = 0;
CalcMaskSize(nMaskSize, nMaskCode);
bool fFirst = vout.size() > 0 && !vout[0].IsNull();
@@ -185,33 +162,33 @@ public:
assert(fFirst || fSecond || nMaskCode);
unsigned int nCode = 8*(nMaskCode - (fFirst || fSecond ? 0 : 1)) + (fCoinBase ? 1 : 0) + (fFirst ? 2 : 0) + (fSecond ? 4 : 0);
// version
- ::Serialize(s, VARINT(this->nVersion), nType, nVersion);
+ ::Serialize(s, VARINT(this->nVersion));
// header code
- ::Serialize(s, VARINT(nCode), nType, nVersion);
+ ::Serialize(s, VARINT(nCode));
// spentness bitmask
for (unsigned int b = 0; b<nMaskSize; b++) {
unsigned char chAvail = 0;
for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++)
if (!vout[2+b*8+i].IsNull())
chAvail |= (1 << i);
- ::Serialize(s, chAvail, nType, nVersion);
+ ::Serialize(s, chAvail);
}
// txouts themself
for (unsigned int i = 0; i < vout.size(); i++) {
if (!vout[i].IsNull())
- ::Serialize(s, CTxOutCompressor(REF(vout[i])), nType, nVersion);
+ ::Serialize(s, CTxOutCompressor(REF(vout[i])));
}
// coinbase height
- ::Serialize(s, VARINT(nHeight), nType, nVersion);
+ ::Serialize(s, VARINT(nHeight));
}
template<typename Stream>
- void Unserialize(Stream &s, int nType, int nVersion) {
+ void Unserialize(Stream &s) {
unsigned int nCode = 0;
// version
- ::Unserialize(s, VARINT(this->nVersion), nType, nVersion);
+ ::Unserialize(s, VARINT(this->nVersion));
// header code
- ::Unserialize(s, VARINT(nCode), nType, nVersion);
+ ::Unserialize(s, VARINT(nCode));
fCoinBase = nCode & 1;
std::vector<bool> vAvail(2, false);
vAvail[0] = (nCode & 2) != 0;
@@ -220,7 +197,7 @@ public:
// spentness bitmask
while (nMaskCode > 0) {
unsigned char chAvail = 0;
- ::Unserialize(s, chAvail, nType, nVersion);
+ ::Unserialize(s, chAvail);
for (unsigned int p = 0; p < 8; p++) {
bool f = (chAvail & (1 << p)) != 0;
vAvail.push_back(f);
@@ -232,10 +209,10 @@ public:
vout.assign(vAvail.size(), CTxOut());
for (unsigned int i = 0; i < vAvail.size(); i++) {
if (vAvail[i])
- ::Unserialize(s, REF(CTxOutCompressor(vout[i])), nType, nVersion);
+ ::Unserialize(s, REF(CTxOutCompressor(vout[i])));
}
// coinbase height
- ::Unserialize(s, VARINT(nHeight), nType, nVersion);
+ ::Unserialize(s, VARINT(nHeight));
Cleanup();
}
diff --git a/src/compressor.h b/src/compressor.h
index fa702f0dfa..961365d261 100644
--- a/src/compressor.h
+++ b/src/compressor.h
@@ -55,16 +55,8 @@ protected:
public:
CScriptCompressor(CScript &scriptIn) : script(scriptIn) { }
- unsigned int GetSerializeSize(int nType, int nVersion) const {
- std::vector<unsigned char> compr;
- if (Compress(compr))
- return compr.size();
- unsigned int nSize = script.size() + nSpecialScripts;
- return script.size() + VARINT(nSize).GetSerializeSize(nType, nVersion);
- }
-
template<typename Stream>
- void Serialize(Stream &s, int nType, int nVersion) const {
+ void Serialize(Stream &s) const {
std::vector<unsigned char> compr;
if (Compress(compr)) {
s << CFlatData(compr);
@@ -76,7 +68,7 @@ public:
}
template<typename Stream>
- void Unserialize(Stream &s, int nType, int nVersion) {
+ void Unserialize(Stream &s) {
unsigned int nSize = 0;
s >> VARINT(nSize);
if (nSize < nSpecialScripts) {
@@ -112,7 +104,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
if (!ser_action.ForRead()) {
uint64_t nVal = CompressAmount(txout.nValue);
READWRITE(VARINT(nVal));
diff --git a/src/dbwrapper.h b/src/dbwrapper.h
index 47bdb31b5b..4a79bbd17d 100644
--- a/src/dbwrapper.h
+++ b/src/dbwrapper.h
@@ -17,6 +17,9 @@
#include <leveldb/db.h>
#include <leveldb/write_batch.h>
+static const size_t DBWRAPPER_PREALLOC_KEY_SIZE = 64;
+static const size_t DBWRAPPER_PREALLOC_VALUE_SIZE = 1024;
+
class dbwrapper_error : public std::runtime_error
{
public:
@@ -60,12 +63,12 @@ public:
void Write(const K& key, const V& value)
{
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
- ssKey.reserve(ssKey.GetSerializeSize(key));
+ ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey << key;
leveldb::Slice slKey(&ssKey[0], ssKey.size());
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
- ssValue.reserve(ssValue.GetSerializeSize(value));
+ ssValue.reserve(DBWRAPPER_PREALLOC_VALUE_SIZE);
ssValue << value;
ssValue.Xor(dbwrapper_private::GetObfuscateKey(parent));
leveldb::Slice slValue(&ssValue[0], ssValue.size());
@@ -77,7 +80,7 @@ public:
void Erase(const K& key)
{
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
- ssKey.reserve(ssKey.GetSerializeSize(key));
+ ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey << key;
leveldb::Slice slKey(&ssKey[0], ssKey.size());
@@ -107,7 +110,7 @@ public:
template<typename K> void Seek(const K& key) {
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
- ssKey.reserve(ssKey.GetSerializeSize(key));
+ ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey << key;
leveldb::Slice slKey(&ssKey[0], ssKey.size());
piter->Seek(slKey);
@@ -200,7 +203,7 @@ public:
bool Read(const K& key, V& value) const
{
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
- ssKey.reserve(ssKey.GetSerializeSize(key));
+ ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey << key;
leveldb::Slice slKey(&ssKey[0], ssKey.size());
@@ -234,7 +237,7 @@ public:
bool Exists(const K& key) const
{
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
- ssKey.reserve(ssKey.GetSerializeSize(key));
+ ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey << key;
leveldb::Slice slKey(&ssKey[0], ssKey.size());
diff --git a/src/hash.h b/src/hash.h
index db4e130ae7..94e7f5ea6c 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -132,15 +132,17 @@ class CHashWriter
private:
CHash256 ctx;
+ const int nType;
+ const int nVersion;
public:
- int nType;
- int nVersion;
CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) {}
- CHashWriter& write(const char *pch, size_t size) {
+ int GetType() const { return nType; }
+ int GetVersion() const { return nVersion; }
+
+ void write(const char *pch, size_t size) {
ctx.Write((const unsigned char*)pch, size);
- return (*this);
}
// invalidates the object
@@ -153,7 +155,7 @@ public:
template<typename T>
CHashWriter& operator<<(const T& obj) {
// Serialize to this stream
- ::Serialize(*this, obj, nType, nVersion);
+ ::Serialize(*this, obj);
return (*this);
}
};
diff --git a/src/key.h b/src/key.h
index 48a07d62c9..ff5252b7a0 100644
--- a/src/key.h
+++ b/src/key.h
@@ -162,7 +162,7 @@ struct CExtKey {
CExtPubKey Neuter() const;
void SetMaster(const unsigned char* seed, unsigned int nSeedLen);
template <typename Stream>
- void Serialize(Stream& s, int nType, int nVersion) const
+ void Serialize(Stream& s) const
{
unsigned int len = BIP32_EXTKEY_SIZE;
::WriteCompactSize(s, len);
@@ -171,7 +171,7 @@ struct CExtKey {
s.write((const char *)&code[0], len);
}
template <typename Stream>
- void Unserialize(Stream& s, int nType, int nVersion)
+ void Unserialize(Stream& s)
{
unsigned int len = ::ReadCompactSize(s);
unsigned char code[BIP32_EXTKEY_SIZE];
diff --git a/src/main.cpp b/src/main.cpp
index 7e5b9528b9..10f9b15ec6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1104,7 +1104,7 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i
-bool CheckTransaction(const CTransaction& tx, CValidationState &state)
+bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fCheckDuplicateInputs)
{
// Basic checks that don't depend on any context
if (tx.vin.empty())
@@ -1128,13 +1128,14 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
}
- // Check for duplicate inputs
- set<COutPoint> vInOutPoints;
- for (const auto& txin : tx.vin)
- {
- if (vInOutPoints.count(txin.prevout))
- return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
- vInOutPoints.insert(txin.prevout);
+ // Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock
+ if (fCheckDuplicateInputs) {
+ set<COutPoint> vInOutPoints;
+ for (const auto& txin : tx.vin)
+ {
+ if (!vInOutPoints.insert(txin.prevout).second)
+ return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
+ }
}
if (tx.IsCoinBase())
@@ -1712,7 +1713,7 @@ bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHea
return error("WriteBlockToDisk: OpenBlockFile failed");
// Write index header
- unsigned int nSize = fileout.GetSerializeSize(block);
+ unsigned int nSize = GetSerializeSize(fileout, block);
fileout << FLATDATA(messageStart) << nSize;
// Write block
@@ -2102,7 +2103,7 @@ bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint
return error("%s: OpenUndoFile failed", __func__);
// Write index header
- unsigned int nSize = fileout.GetSerializeSize(blockundo);
+ unsigned int nSize = GetSerializeSize(fileout, blockundo);
fileout << FLATDATA(messageStart) << nSize;
// Write undo data
@@ -3461,7 +3462,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
// Check transactions
for (const auto& tx : block.vtx)
- if (!CheckTransaction(tx, state))
+ if (!CheckTransaction(tx, state, false))
return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(),
strprintf("Transaction check failed (tx hash %s) %s", tx.GetHash().ToString(), state.GetDebugMessage()));
@@ -5494,7 +5495,19 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
if (it->second->nHeight < chainActive.Height() - MAX_BLOCKTXN_DEPTH) {
+ // If an older block is requested (should never happen in practice,
+ // but can happen in tests) send a block response instead of a
+ // blocktxn response. Sending a full block response instead of a
+ // small blocktxn response is preferable in the case where a peer
+ // might maliciously send lots of getblocktxn requests to trigger
+ // expensive disk reads, because it will require the peer to
+ // actually receive all the data read from disk over the network.
LogPrint("net", "Peer %d sent us a getblocktxn for a block > %i deep", pfrom->id, MAX_BLOCKTXN_DEPTH);
+ CInv inv;
+ inv.type = State(pfrom->GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK;
+ inv.hash = req.blockhash;
+ pfrom->vRecvGetData.push_back(inv);
+ ProcessGetData(pfrom, chainparams.GetConsensus(), connman);
return true;
}
diff --git a/src/main.h b/src/main.h
index 9343330587..21829b6c25 100644
--- a/src/main.h
+++ b/src/main.h
@@ -343,7 +343,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight);
/** Transaction validation functions */
/** Context-independent validity checks */
-bool CheckTransaction(const CTransaction& tx, CValidationState& state);
+bool CheckTransaction(const CTransaction& tx, CValidationState& state, bool fCheckDuplicateInputs=true);
namespace Consensus {
diff --git a/src/merkleblock.h b/src/merkleblock.h
index 835cbcce55..17c33194a9 100644
--- a/src/merkleblock.h
+++ b/src/merkleblock.h
@@ -85,7 +85,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(nTransactions);
READWRITE(vHash);
std::vector<unsigned char> vBytes;
@@ -148,7 +148,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(header);
READWRITE(txn);
}
diff --git a/src/net.cpp b/src/net.cpp
index e47a8bb168..15c4514f15 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -985,6 +985,12 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
return;
}
+ if (!fNetworkActive) {
+ LogPrintf("connection from %s dropped: not accepting new connections\n", addr.ToString());
+ CloseSocket(hSocket);
+ return;
+ }
+
if (!IsSelectableSocket(hSocket))
{
LogPrintf("connection from %s dropped: non-selectable socket\n", addr.ToString());
@@ -1784,6 +1790,9 @@ bool CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
// Initiate outbound network connection
//
boost::this_thread::interruption_point();
+ if (!fNetworkActive) {
+ return false;
+ }
if (!pszDest) {
if (IsLocal(addrConnect) ||
FindNode((CNetAddr)addrConnect) || IsBanned(addrConnect) ||
@@ -2025,8 +2034,30 @@ void Discover(boost::thread_group& threadGroup)
#endif
}
+void CConnman::SetNetworkActive(bool active)
+{
+ if (fDebug) {
+ LogPrint("net", "SetNetworkActive: %s\n", active);
+ }
+
+ if (!active) {
+ fNetworkActive = false;
+
+ LOCK(cs_vNodes);
+ // Close sockets to all nodes
+ BOOST_FOREACH(CNode* pnode, vNodes) {
+ pnode->CloseSocketDisconnect();
+ }
+ } else {
+ fNetworkActive = true;
+ }
+
+ uiInterface.NotifyNetworkActiveChanged(fNetworkActive);
+}
+
CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) : nSeed0(nSeed0In), nSeed1(nSeed1In)
{
+ fNetworkActive = true;
setBannedIsDirty = false;
fAddressesInitialized = false;
nLastNodeId = 0;
diff --git a/src/net.h b/src/net.h
index e712953be3..e2d88b478d 100644
--- a/src/net.h
+++ b/src/net.h
@@ -131,6 +131,8 @@ public:
bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError, Options options);
void Stop();
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false);
+ bool GetNetworkActive() const { return fNetworkActive; };
+ void SetNetworkActive(bool active);
bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false);
bool CheckIncomingNonce(uint64_t nonce);
@@ -140,7 +142,7 @@ public:
void PushMessageWithVersionAndFlag(CNode* pnode, int nVersion, int flag, const std::string& sCommand, Args&&... args)
{
auto msg(BeginMessage(pnode, nVersion, flag, sCommand));
- ::SerializeMany(msg, msg.nType, msg.nVersion, std::forward<Args>(args)...);
+ ::SerializeMany(msg, std::forward<Args>(args)...);
EndMessage(msg);
PushMessage(pnode, msg, sCommand);
}
@@ -401,6 +403,7 @@ private:
unsigned int nReceiveFloodSize;
std::vector<ListenSocket> vhListenSocket;
+ bool fNetworkActive;
banmap_t setBanned;
CCriticalSection cs_setBanned;
bool setBannedIsDirty;
diff --git a/src/netaddress.h b/src/netaddress.h
index 9330fe3328..9dffaa57e7 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -85,7 +85,7 @@ class CNetAddr
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(FLATDATA(ip));
}
@@ -122,7 +122,7 @@ class CSubNet
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(network);
READWRITE(FLATDATA(netmask));
READWRITE(FLATDATA(valid));
@@ -159,7 +159,7 @@ class CService : public CNetAddr
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(FLATDATA(ip));
unsigned short portN = htons(port);
READWRITE(FLATDATA(portN));
diff --git a/src/policy/fees.h b/src/policy/fees.h
index c7d2febfa5..ea4c70e616 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -174,7 +174,6 @@ static const double DEFAULT_DECAY = .998;
/** Require greater than 95% of X feerate transactions to be confirmed within Y blocks for X to be big enough */
static const double MIN_SUCCESS_PCT = .95;
-static const double UNLIKELY_PCT = .5;
/** Require an avg of 1 tx in the combined feerate bucket per block to have stat significance */
static const double SUFFICIENT_FEETXS = 1;
diff --git a/src/primitives/block.h b/src/primitives/block.h
index 72dfed985a..d148aec1e0 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -36,7 +36,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(this->nVersion);
READWRITE(hashPrevBlock);
READWRITE(hashMerkleRoot);
@@ -92,7 +92,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(*(CBlockHeader*)this);
READWRITE(vtx);
}
@@ -137,8 +137,9 @@ struct CBlockLocator
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- if (!(nType & SER_GETHASH))
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ int nVersion = s.GetVersion();
+ if (!(s.GetType() & SER_GETHASH))
READWRITE(nVersion);
READWRITE(vHave);
}
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 1afeb87039..1d176e5d8c 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -28,7 +28,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(hash);
READWRITE(n);
}
@@ -104,7 +104,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(prevout);
READWRITE(*(CScriptBase*)(&scriptSig));
READWRITE(nSequence);
@@ -144,7 +144,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(nValue);
READWRITE(*(CScriptBase*)(&scriptPubKey));
}
@@ -177,7 +177,7 @@ public:
if (scriptPubKey.IsUnspendable())
return 0;
- size_t nSize = GetSerializeSize(SER_DISK, 0);
+ size_t nSize = GetSerializeSize(*this, SER_DISK, 0);
int witnessversion = 0;
std::vector<unsigned char> witnessprogram;
@@ -219,7 +219,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
+ inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(scriptWitness.stack);
}
@@ -255,7 +255,7 @@ public:
}
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
+ inline void SerializationOp(Stream& s, Operation ser_action)
{
for (size_t n = 0; n < vtxinwit.size(); n++) {
READWRITE(vtxinwit[n]);
@@ -287,8 +287,8 @@ struct CMutableTransaction;
* - uint32_t nLockTime
*/
template<typename Stream, typename Operation, typename TxType>
-inline void SerializeTransaction(TxType& tx, Stream& s, Operation ser_action, int nType, int nVersion) {
- const bool fAllowWitness = !(nVersion & SERIALIZE_TRANSACTION_NO_WITNESS);
+inline void SerializeTransaction(TxType& tx, Stream& s, Operation ser_action) {
+ const bool fAllowWitness = !(s.GetVersion() & SERIALIZE_TRANSACTION_NO_WITNESS);
READWRITE(*const_cast<int32_t*>(&tx.nVersion));
unsigned char flags = 0;
@@ -385,8 +385,8 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- SerializeTransaction(*this, s, ser_action, nType, nVersion);
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ SerializeTransaction(*this, s, ser_action);
if (ser_action.ForRead()) {
UpdateHash();
}
@@ -456,8 +456,8 @@ struct CMutableTransaction
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- SerializeTransaction(*this, s, ser_action, nType, nVersion);
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ SerializeTransaction(*this, s, ser_action);
}
/** Compute the hash of this CMutableTransaction. This is computed on the
diff --git a/src/protocol.cpp b/src/protocol.cpp
index 54ad62b1a2..87d6e06848 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -181,7 +181,11 @@ std::string CInv::GetCommand() const
std::string CInv::ToString() const
{
- return strprintf("%s %s", GetCommand(), hash.ToString());
+ try {
+ return strprintf("%s %s", GetCommand(), hash.ToString());
+ } catch(const std::out_of_range &) {
+ return strprintf("0x%08x %s", type, hash.ToString());
+ }
}
const std::vector<std::string> &getAllNetMessageTypes()
diff --git a/src/protocol.h b/src/protocol.h
index d19e0d3a5e..a52d9a67b0 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -48,7 +48,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
+ inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(FLATDATA(pchMessageStart));
READWRITE(FLATDATA(pchCommand));
@@ -289,14 +289,15 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
+ inline void SerializationOp(Stream& s, Operation ser_action)
{
if (ser_action.ForRead())
Init();
- if (nType & SER_DISK)
+ int nVersion = s.GetVersion();
+ if (s.GetType() & SER_DISK)
READWRITE(nVersion);
- if ((nType & SER_DISK) ||
- (nVersion >= CADDR_TIME_VERSION && !(nType & SER_GETHASH)))
+ if ((s.GetType() & SER_DISK) ||
+ (nVersion >= CADDR_TIME_VERSION && !(s.GetType() & SER_GETHASH)))
READWRITE(nTime);
uint64_t nServicesInt = nServices;
READWRITE(nServicesInt);
@@ -343,7 +344,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
+ inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(type);
READWRITE(hash);
diff --git a/src/pubkey.h b/src/pubkey.h
index 3a554877f8..9499862210 100644
--- a/src/pubkey.h
+++ b/src/pubkey.h
@@ -116,19 +116,15 @@ public:
}
//! Implement serialization, as if this was a byte vector.
- unsigned int GetSerializeSize(int nType, int nVersion) const
- {
- return size() + 1;
- }
template <typename Stream>
- void Serialize(Stream& s, int nType, int nVersion) const
+ void Serialize(Stream& s) const
{
unsigned int len = size();
::WriteCompactSize(s, len);
s.write((char*)vch, len);
}
template <typename Stream>
- void Unserialize(Stream& s, int nType, int nVersion)
+ void Unserialize(Stream& s)
{
unsigned int len = ::ReadCompactSize(s);
if (len <= 65) {
@@ -214,12 +210,13 @@ struct CExtPubKey {
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
bool Derive(CExtPubKey& out, unsigned int nChild) const;
- unsigned int GetSerializeSize(int nType, int nVersion) const
+ void Serialize(CSizeComputer& s) const
{
- return BIP32_EXTKEY_SIZE+1; //add one byte for the size (compact int)
+ // Optimized implementation for ::GetSerializeSize that avoids copying.
+ s.seek(BIP32_EXTKEY_SIZE + 1); // add one byte for the size (compact int)
}
template <typename Stream>
- void Serialize(Stream& s, int nType, int nVersion) const
+ void Serialize(Stream& s) const
{
unsigned int len = BIP32_EXTKEY_SIZE;
::WriteCompactSize(s, len);
@@ -228,7 +225,7 @@ struct CExtPubKey {
s.write((const char *)&code[0], len);
}
template <typename Stream>
- void Unserialize(Stream& s, int nType, int nVersion)
+ void Unserialize(Stream& s)
{
unsigned int len = ::ReadCompactSize(s);
unsigned char code[BIP32_EXTKEY_SIZE];
diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc
index ca5b1fa673..451d391237 100644
--- a/src/qt/bitcoin.qrc
+++ b/src/qt/bitcoin.qrc
@@ -52,6 +52,7 @@
<file alias="transaction_abandoned">res/icons/transaction_abandoned.png</file>
<file alias="hd_enabled">res/icons/hd_enabled.png</file>
<file alias="hd_disabled">res/icons/hd_disabled.png</file>
+ <file alias="network_disabled">res/icons/network_disabled.png</file>
</qresource>
<qresource prefix="/movies">
<file alias="spinner-000">res/movies/spinner-000.png</file>
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index ee5102c4f9..b2c9a704ed 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -86,7 +86,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *
unitDisplayControl(0),
labelWalletEncryptionIcon(0),
labelWalletHDStatusIcon(0),
- labelConnectionsIcon(0),
+ connectionsControl(0),
labelBlocksIcon(0),
progressBarLabel(0),
progressBar(0),
@@ -199,7 +199,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *
unitDisplayControl = new UnitDisplayStatusBarControl(platformStyle);
labelWalletEncryptionIcon = new QLabel();
labelWalletHDStatusIcon = new QLabel();
- labelConnectionsIcon = new QLabel();
+ connectionsControl = new NetworkToggleStatusBarControl();
labelBlocksIcon = new QLabel();
if(enableWallet)
{
@@ -210,7 +210,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *
frameBlocksLayout->addWidget(labelWalletHDStatusIcon);
}
frameBlocksLayout->addStretch();
- frameBlocksLayout->addWidget(labelConnectionsIcon);
+ frameBlocksLayout->addWidget(connectionsControl);
frameBlocksLayout->addStretch();
frameBlocksLayout->addWidget(labelBlocksIcon);
frameBlocksLayout->addStretch();
@@ -469,8 +469,9 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
createTrayIconMenu();
// Keep up to date with client
- setNumConnections(_clientModel->getNumConnections());
+ updateNetworkState();
connect(_clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
+ connect(_clientModel, SIGNAL(networkActiveChanged(bool)), this, SLOT(setNetworkActive(bool)));
setNumBlocks(_clientModel->getNumBlocks(), _clientModel->getLastBlockDate(), _clientModel->getVerificationProgress(NULL), false);
connect(_clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool)));
@@ -489,6 +490,7 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
}
#endif // ENABLE_WALLET
unitDisplayControl->setOptionsModel(_clientModel->getOptionsModel());
+ connectionsControl->setClientModel(_clientModel);
OptionsModel* optionsModel = _clientModel->getOptionsModel();
if(optionsModel)
@@ -698,8 +700,9 @@ void BitcoinGUI::gotoVerifyMessageTab(QString addr)
}
#endif // ENABLE_WALLET
-void BitcoinGUI::setNumConnections(int count)
+void BitcoinGUI::updateNetworkState()
{
+ int count = clientModel->getNumConnections();
QString icon;
switch(count)
{
@@ -709,8 +712,25 @@ void BitcoinGUI::setNumConnections(int count)
case 7: case 8: case 9: icon = ":/icons/connect_3"; break;
default: icon = ":/icons/connect_4"; break;
}
- labelConnectionsIcon->setPixmap(platformStyle->SingleColorIcon(icon).pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
- labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count));
+
+ if (clientModel->getNetworkActive()) {
+ connectionsControl->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count));
+ } else {
+ connectionsControl->setToolTip(tr("Network activity disabled"));
+ icon = ":/icons/network_disabled";
+ }
+
+ connectionsControl->setPixmap(platformStyle->SingleColorIcon(icon).pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
+}
+
+void BitcoinGUI::setNumConnections(int count)
+{
+ updateNetworkState();
+}
+
+void BitcoinGUI::setNetworkActive(bool networkActive)
+{
+ updateNetworkState();
}
void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool header)
@@ -1211,3 +1231,18 @@ void UnitDisplayStatusBarControl::onMenuSelection(QAction* action)
optionsModel->setDisplayUnit(action->data());
}
}
+
+void NetworkToggleStatusBarControl::mousePressEvent(QMouseEvent *event)
+{
+ if (clientModel) {
+ clientModel->setNetworkActive(!clientModel->getNetworkActive());
+ }
+}
+
+/** Lets the control know about the Client Model */
+void NetworkToggleStatusBarControl::setClientModel(ClientModel *_clientModel)
+{
+ if (_clientModel) {
+ this->clientModel = _clientModel;
+ }
+}
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 0eaa44b263..1b02e77fc4 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -26,6 +26,7 @@ class PlatformStyle;
class RPCConsole;
class SendCoinsRecipient;
class UnitDisplayStatusBarControl;
+class NetworkToggleStatusBarControl;
class WalletFrame;
class WalletModel;
class HelpMessageDialog;
@@ -85,7 +86,7 @@ private:
UnitDisplayStatusBarControl *unitDisplayControl;
QLabel *labelWalletEncryptionIcon;
QLabel *labelWalletHDStatusIcon;
- QLabel *labelConnectionsIcon;
+ NetworkToggleStatusBarControl *connectionsControl;
QLabel *labelBlocksIcon;
QLabel *progressBarLabel;
QProgressBar *progressBar;
@@ -146,6 +147,9 @@ private:
/** Disconnect core signals from GUI client */
void unsubscribeFromCoreSignals();
+ /** Update UI with latest network info from model. */
+ void updateNetworkState();
+
Q_SIGNALS:
/** Signal raised when a URI was entered or dragged to the GUI */
void receivedURI(const QString &uri);
@@ -153,6 +157,8 @@ Q_SIGNALS:
public Q_SLOTS:
/** Set number of connections shown in the UI */
void setNumConnections(int count);
+ /** Set network state shown in the UI */
+ void setNetworkActive(bool networkActive);
/** Set number of blocks and last block date shown in the UI */
void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers);
@@ -264,4 +270,17 @@ private Q_SLOTS:
void onMenuSelection(QAction* action);
};
+class NetworkToggleStatusBarControl : public QLabel
+{
+ Q_OBJECT
+
+public:
+ void setClientModel(ClientModel *clientModel);
+protected:
+ void mousePressEvent(QMouseEvent *event);
+
+private:
+ ClientModel *clientModel;
+};
+
#endif // BITCOIN_QT_BITCOINGUI_H
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index f9caca6878..a4bb2f77fe 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -145,6 +145,11 @@ void ClientModel::updateNumConnections(int numConnections)
Q_EMIT numConnectionsChanged(numConnections);
}
+void ClientModel::updateNetworkActive(bool networkActive)
+{
+ Q_EMIT networkActiveChanged(networkActive);
+}
+
void ClientModel::updateAlert()
{
Q_EMIT alertsChanged(getStatusBarWarnings());
@@ -167,6 +172,21 @@ enum BlockSource ClientModel::getBlockSource() const
return BLOCK_SOURCE_NONE;
}
+void ClientModel::setNetworkActive(bool active)
+{
+ if (g_connman) {
+ g_connman->SetNetworkActive(active);
+ }
+}
+
+bool ClientModel::getNetworkActive() const
+{
+ if (g_connman) {
+ return g_connman->GetNetworkActive();
+ }
+ return false;
+}
+
QString ClientModel::getStatusBarWarnings() const
{
return QString::fromStdString(GetWarnings("gui"));
@@ -233,6 +253,12 @@ static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConn
Q_ARG(int, newNumConnections));
}
+static void NotifyNetworkActiveChanged(ClientModel *clientmodel, bool networkActive)
+{
+ QMetaObject::invokeMethod(clientmodel, "updateNetworkActive", Qt::QueuedConnection,
+ Q_ARG(bool, networkActive));
+}
+
static void NotifyAlertChanged(ClientModel *clientmodel)
{
qDebug() << "NotifyAlertChanged";
@@ -273,6 +299,7 @@ void ClientModel::subscribeToCoreSignals()
// Connect signals to client
uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1));
+ uiInterface.NotifyNetworkActiveChanged.connect(boost::bind(NotifyNetworkActiveChanged, this, _1));
uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this));
uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this));
uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2, false));
@@ -284,6 +311,7 @@ void ClientModel::unsubscribeFromCoreSignals()
// Disconnect signals from client
uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
+ uiInterface.NotifyNetworkActiveChanged.disconnect(boost::bind(NotifyNetworkActiveChanged, this, _1));
uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this));
uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this));
uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2, false));
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 3fd8404cbb..a641401425 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -68,6 +68,10 @@ public:
bool inInitialBlockDownload() const;
//! Return true if core is importing blocks
enum BlockSource getBlockSource() const;
+ //! Return true if network activity in core is enabled
+ bool getNetworkActive() const;
+ //! Toggle network activity state in core
+ void setNetworkActive(bool active);
//! Return warnings to be displayed in status bar
QString getStatusBarWarnings() const;
@@ -91,6 +95,7 @@ Q_SIGNALS:
void numConnectionsChanged(int count);
void numBlocksChanged(int count, const QDateTime& blockDate, double nVerificationProgress, bool header);
void mempoolSizeChanged(long count, size_t mempoolSizeInBytes);
+ void networkActiveChanged(bool networkActive);
void alertsChanged(const QString &warnings);
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut);
@@ -103,6 +108,7 @@ Q_SIGNALS:
public Q_SLOTS:
void updateTimer();
void updateNumConnections(int numConnections);
+ void updateNetworkActive(bool networkActive);
void updateAlert();
void updateBanlist();
};
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 42dafa1175..9dc75c2e1a 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -291,17 +291,11 @@ void copyEntryData(QAbstractItemView *view, int column, int role)
}
}
-QVariant getEntryData(QAbstractItemView *view, int column, int role)
+QList<QModelIndex> getEntryData(QAbstractItemView *view, int column)
{
if(!view || !view->selectionModel())
- return QVariant();
- QModelIndexList selection = view->selectionModel()->selectedRows(column);
-
- if(!selection.isEmpty()) {
- // Return first item
- return (selection.at(0).data(role));
- }
- return QVariant();
+ return QList<QModelIndex>();
+ return view->selectionModel()->selectedRows(column);
}
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir,
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index e28f68930f..64cbd51eb6 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -67,10 +67,9 @@ namespace GUIUtil
/** Return a field of the currently selected entry as a QString. Does nothing if nothing
is selected.
@param[in] column Data column to extract from the model
- @param[in] role Data role to extract from the model
@see TransactionView::copyLabel, TransactionView::copyAmount, TransactionView::copyAddress
*/
- QVariant getEntryData(QAbstractItemView *view, int column, int role);
+ QList<QModelIndex> getEntryData(QAbstractItemView *view, int column);
void setClipboard(const QString& str);
diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h
index 0193e748d7..8ee2c9cbac 100644
--- a/src/qt/recentrequeststablemodel.h
+++ b/src/qt/recentrequeststablemodel.h
@@ -27,7 +27,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
unsigned int nDate = date.toTime_t();
READWRITE(this->nVersion);
diff --git a/src/qt/res/icons/network_disabled.png b/src/qt/res/icons/network_disabled.png
new file mode 100644
index 0000000000..269c3cfab8
--- /dev/null
+++ b/src/qt/res/icons/network_disabled.png
Binary files differ
diff --git a/src/qt/res/src/connect-0.svg b/src/qt/res/src/connect-0.svg
index 7d2afac622..0920555b96 100644
--- a/src/qt/res/src/connect-0.svg
+++ b/src/qt/res/src/connect-0.svg
@@ -7,8 +7,8 @@
xmlns="http://www.w3.org/2000/svg"
id="svg2"
viewBox="0 0 24 24"
- height="24"
- width="24"
+ height="92"
+ width="92"
version="1.2">
<metadata
id="metadata10">
diff --git a/src/qt/res/src/connect-1.svg b/src/qt/res/src/connect-1.svg
index d17928c97d..25dea4cd3a 100644
--- a/src/qt/res/src/connect-1.svg
+++ b/src/qt/res/src/connect-1.svg
@@ -6,8 +6,8 @@
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.2"
- width="24"
- height="24"
+ width="92"
+ height="92"
viewBox="0 0 24 24"
id="svg2">
<metadata
diff --git a/src/qt/res/src/connect-2.svg b/src/qt/res/src/connect-2.svg
index 841ca6071d..bb98333d23 100644
--- a/src/qt/res/src/connect-2.svg
+++ b/src/qt/res/src/connect-2.svg
@@ -6,8 +6,8 @@
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.2"
- width="24"
- height="24"
+ width="92"
+ height="92"
viewBox="0 0 24 24"
id="svg2">
<metadata
diff --git a/src/qt/res/src/connect-3.svg b/src/qt/res/src/connect-3.svg
index b06e67daf8..a54a55ef61 100644
--- a/src/qt/res/src/connect-3.svg
+++ b/src/qt/res/src/connect-3.svg
@@ -7,8 +7,8 @@
xmlns="http://www.w3.org/2000/svg"
id="svg2"
viewBox="0 0 24 24"
- height="24"
- width="24"
+ height="92"
+ width="92"
version="1.2">
<metadata
id="metadata10">
diff --git a/src/qt/res/src/connect-4.svg b/src/qt/res/src/connect-4.svg
index 0abc7955fd..b83b9f9d03 100644
--- a/src/qt/res/src/connect-4.svg
+++ b/src/qt/res/src/connect-4.svg
@@ -6,8 +6,8 @@
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.2"
- width="24"
- height="24"
+ width="92"
+ height="92"
viewBox="0 0 24 24"
id="svg2">
<metadata
diff --git a/src/qt/res/src/network_disabled.svg b/src/qt/res/src/network_disabled.svg
new file mode 100644
index 0000000000..a041d77439
--- /dev/null
+++ b/src/qt/res/src/network_disabled.svg
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ id="svg2"
+ viewBox="0 0 24 24"
+ width="92"
+ height="92"
+ version="1.2">
+ <metadata
+ id="metadata10">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs8" />
+ <g
+ id="g4142"
+ transform="matrix(0,-1,-1,0,23.96,24)">
+ <g
+ id="g4210"
+ transform="matrix(-1,0,0,1,59.86,-106.6)">
+ <g
+ id="g4289"
+ transform="matrix(-1,0,0,1,-16.98,0.8136)">
+ <g
+ id="g4291">
+ <path
+ id="path4293"
+ transform="matrix(0,-1,-1,0,-52.84,129.7464)"
+ d="M 20.146484 1.0097656 C 18.746484 1.0097656 17.646484 1.8597656 17.146484 3.0097656 L 14.447266 3.0097656 C 12.247266 3.0097656 10.447266 4.7997656 10.447266 7.0097656 L 10.447266 8.1425781 C 10.128283 8.0634395 9.7980674 8.0097656 9.4472656 8.0097656 L 6.8457031 8.0097656 C 6.3457031 6.8597656 5.2457031 6.0097656 3.8457031 6.0097656 C 1.8457031 6.0097656 0.34570312 7.5997656 0.34570312 9.5097656 C 0.34570312 11.419766 1.8457031 13.009766 3.8457031 13.009766 C 5.2457031 13.009766 6.3457031 12.159766 6.8457031 11.009766 L 8.9746094 11.009766 C 8.8693536 11.330059 8.8007812 11.663345 8.8007812 12.001953 C 8.8007813 12.841953 9.1402344 13.671625 9.7402344 14.265625 C 9.9479364 14.475439 10.191281 14.640988 10.447266 14.783203 L 10.447266 16.980469 C 10.447266 17.530469 9.9472656 17.980469 9.4472656 17.980469 L 6.8457031 17.980469 C 6.3457031 16.830469 5.2457031 15.980469 3.8457031 15.980469 C 1.8457031 15.980469 0.34570312 17.570469 0.34570312 19.480469 C 0.34570312 21.390469 1.8457031 22.990234 3.8457031 22.990234 C 5.2457031 22.990234 6.2457031 22.14 6.8457031 21 L 9.4472656 21 C 11.747266 21 13.447266 19.19 13.447266 17 L 13.447266 15.869141 C 13.768504 15.952624 14.100702 16.009766 14.447266 16.009766 L 17.146484 16.009766 C 17.646484 17.159766 18.746484 18.009766 20.146484 18.009766 C 22.046484 18.009766 23.646484 16.449766 23.646484 14.509766 C 23.646484 12.579766 22.046484 11.009766 20.146484 11.009766 C 18.746484 11.009766 17.646484 11.859766 17.146484 13.009766 L 15.009766 13.009766 C 15.119625 12.684735 15.189453 12.346256 15.189453 12 C 15.189453 11.16 14.849906 10.339953 14.253906 9.7519531 C 14.0189 9.51021 13.74069 9.3244522 13.447266 9.171875 L 13.447266 7.0097656 C 13.447266 6.4597656 13.947266 6.0097656 14.447266 6.0097656 L 17.146484 6.0097656 C 17.646484 7.1597656 18.746484 8.0097656 20.146484 8.0097656 C 22.046484 8.0097656 23.646484 6.4397656 23.646484 4.5097656 C 23.646484 2.5697656 22.046484 1.0097656 20.146484 1.0097656 z M 20.146484 2.0097656 C 21.446484 2.0097656 22.646484 3.1297656 22.646484 4.5097656 C 22.646484 5.8797656 21.446484 7.0097656 20.146484 7.0097656 C 19.046484 7.0097656 18.145703 6.3096094 17.845703 5.3496094 L 17.746094 5.0097656 L 14.447266 5.0097656 C 13.347266 5.0097656 12.447266 5.8997656 12.447266 7.0097656 L 12.447266 8.8476562 C 12.298996 8.8261586 12.150754 8.8027344 12 8.8027344 C 11.954455 8.8027344 11.910576 8.8144662 11.865234 8.8164062 C 11.733157 8.716719 11.592447 8.6297054 11.447266 8.546875 L 11.447266 7.0097656 C 11.447266 5.3597656 12.847266 4.0097656 14.447266 4.0097656 L 17.746094 4.0097656 L 17.845703 3.6699219 C 18.145703 2.7099219 19.046484 2.0097656 20.146484 2.0097656 z M 3.8457031 7.0097656 C 4.9457031 7.0097656 5.8464844 7.7099219 6.1464844 8.6699219 L 6.2460938 9.0097656 L 9.4472656 9.0097656 C 9.8222656 9.0097656 10.165234 9.0792969 10.474609 9.2050781 C 10.207952 9.3508551 9.9554097 9.5233651 9.7402344 9.7421875 C 9.6554755 9.8255337 9.5878282 9.9233484 9.5136719 10.015625 C 9.4909069 10.014746 9.470428 10.009766 9.4472656 10.009766 L 6.2460938 10.009766 L 6.1464844 10.349609 C 5.8464844 11.319609 4.9457031 12.009766 3.8457031 12.009766 C 2.4457031 12.009766 1.3457031 10.899766 1.3457031 9.5097656 C 1.3457031 8.1197656 2.4457031 7.0097656 3.8457031 7.0097656 z M 20.146484 12.009766 C 21.446484 12.009766 22.646484 13.139766 22.646484 14.509766 C 22.646484 15.889766 21.446484 17.009766 20.146484 17.009766 C 19.046484 17.009766 18.145703 16.309609 17.845703 15.349609 L 17.746094 15.009766 L 14.447266 15.009766 C 14.100959 15.009766 13.772729 14.94045 13.470703 14.816406 C 13.754756 14.666178 14.02454 14.485593 14.253906 14.253906 C 14.328913 14.179151 14.386367 14.091269 14.453125 14.009766 L 17.746094 14.009766 L 17.845703 13.669922 C 18.145703 12.709922 19.046484 12.009766 20.146484 12.009766 z M 11.447266 15.144531 C 11.629002 15.17624 11.813246 15.199219 12 15.199219 C 12.018544 15.199153 12.036184 15.193748 12.054688 15.193359 C 12.180437 15.288088 12.3107 15.373496 12.447266 15.453125 L 12.447266 17 C 12.447266 18.67 11.147266 20 9.4472656 20 L 6.6464844 20 L 6.2460938 20 L 6.1464844 20.330078 C 5.8464844 21.290078 4.9457031 21.990234 3.8457031 21.990234 C 2.4457031 21.990234 1.3457031 20.870469 1.3457031 19.480469 C 1.3457031 18.090469 2.4457031 16.980469 3.8457031 16.980469 C 4.9457031 16.980469 5.8464844 17.680625 6.1464844 18.640625 L 6.2460938 18.980469 L 9.4472656 18.980469 C 10.547266 18.980469 11.447266 18.090469 11.447266 16.980469 L 11.447266 15.144531 z "
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.5;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <path d="M 3,3 l 18,18" style="stroke-width: 3; stroke: #000000; stroke-linecap: round;" />
+ <path d="M 21,3 l -18,18" style="stroke-width: 3; stroke: #000000; stroke-linecap: round;" />
+</svg>
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index f10dddf589..47af6a5724 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -343,7 +343,6 @@ RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) :
ui(new Ui::RPCConsole),
clientModel(0),
historyPtr(0),
- cachedNodeid(-1),
platformStyle(_platformStyle),
peersTableContextMenu(0),
banTableContextMenu(0),
@@ -459,6 +458,9 @@ void RPCConsole::setClientModel(ClientModel *model)
setNumBlocks(model->getNumBlocks(), model->getLastBlockDate(), model->getVerificationProgress(NULL), false);
connect(model, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool)));
+ updateNetworkState();
+ connect(model, SIGNAL(networkActiveChanged(bool)), this, SLOT(setNetworkActive(bool)));
+
updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent());
connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64)));
@@ -469,7 +471,7 @@ void RPCConsole::setClientModel(ClientModel *model)
ui->peerWidget->verticalHeader()->hide();
ui->peerWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
- ui->peerWidget->setSelectionMode(QAbstractItemView::SingleSelection);
+ ui->peerWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
ui->peerWidget->setContextMenuPolicy(Qt::CustomContextMenu);
ui->peerWidget->setColumnWidth(PeerTableModel::Address, ADDRESS_COLUMN_WIDTH);
ui->peerWidget->setColumnWidth(PeerTableModel::Subversion, SUBVERSION_COLUMN_WIDTH);
@@ -477,11 +479,11 @@ void RPCConsole::setClientModel(ClientModel *model)
ui->peerWidget->horizontalHeader()->setStretchLastSection(true);
// create peer table context menu actions
- QAction* disconnectAction = new QAction(tr("&Disconnect Node"), this);
- QAction* banAction1h = new QAction(tr("Ban Node for") + " " + tr("1 &hour"), this);
- QAction* banAction24h = new QAction(tr("Ban Node for") + " " + tr("1 &day"), this);
- QAction* banAction7d = new QAction(tr("Ban Node for") + " " + tr("1 &week"), this);
- QAction* banAction365d = new QAction(tr("Ban Node for") + " " + tr("1 &year"), this);
+ QAction* disconnectAction = new QAction(tr("&Disconnect"), this);
+ QAction* banAction1h = new QAction(tr("Ban for") + " " + tr("1 &hour"), this);
+ QAction* banAction24h = new QAction(tr("Ban for") + " " + tr("1 &day"), this);
+ QAction* banAction7d = new QAction(tr("Ban for") + " " + tr("1 &week"), this);
+ QAction* banAction365d = new QAction(tr("Ban for") + " " + tr("1 &year"), this);
// create peer table context menu
peersTableContextMenu = new QMenu();
@@ -514,7 +516,9 @@ void RPCConsole::setClientModel(ClientModel *model)
this, SLOT(peerSelected(const QItemSelection &, const QItemSelection &)));
// peer table signal handling - update peer details when new nodes are added to the model
connect(model->getPeerTableModel(), SIGNAL(layoutChanged()), this, SLOT(peerLayoutChanged()));
-
+ // peer table signal handling - cache selected node ids
+ connect(model->getPeerTableModel(), SIGNAL(layoutAboutToChange()), this, SLOT(peerLayoutAboutToChange()));
+
// set up ban table
ui->banlistWidget->setModel(model->getBanTableModel());
ui->banlistWidget->verticalHeader()->hide();
@@ -527,7 +531,7 @@ void RPCConsole::setClientModel(ClientModel *model)
ui->banlistWidget->horizontalHeader()->setStretchLastSection(true);
// create ban table context menu action
- QAction* unbanAction = new QAction(tr("&Unban Node"), this);
+ QAction* unbanAction = new QAction(tr("&Unban"), this);
// create ban table context menu
banTableContextMenu = new QMenu();
@@ -673,16 +677,30 @@ void RPCConsole::message(int category, const QString &message, bool html)
ui->messagesWidget->append(out);
}
+void RPCConsole::updateNetworkState()
+{
+ QString connections = QString::number(clientModel->getNumConnections()) + " (";
+ connections += tr("In:") + " " + QString::number(clientModel->getNumConnections(CONNECTIONS_IN)) + " / ";
+ connections += tr("Out:") + " " + QString::number(clientModel->getNumConnections(CONNECTIONS_OUT)) + ")";
+
+ if(!clientModel->getNetworkActive()) {
+ connections += " (" + tr("Network activity disabled") + ")";
+ }
+
+ ui->numberOfConnections->setText(connections);
+}
+
void RPCConsole::setNumConnections(int count)
{
if (!clientModel)
return;
- QString connections = QString::number(count) + " (";
- connections += tr("In:") + " " + QString::number(clientModel->getNumConnections(CONNECTIONS_IN)) + " / ";
- connections += tr("Out:") + " " + QString::number(clientModel->getNumConnections(CONNECTIONS_OUT)) + ")";
+ updateNetworkState();
+}
- ui->numberOfConnections->setText(connections);
+void RPCConsole::setNetworkActive(bool networkActive)
+{
+ updateNetworkState();
}
void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers)
@@ -825,6 +843,17 @@ void RPCConsole::peerSelected(const QItemSelection &selected, const QItemSelecti
updateNodeDetail(stats);
}
+void RPCConsole::peerLayoutAboutToChange()
+{
+ QModelIndexList selected = ui->peerWidget->selectionModel()->selectedIndexes();
+ cachedNodeids.clear();
+ for(int i = 0; i < selected.size(); i++)
+ {
+ const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected.at(i).row());
+ cachedNodeids.append(stats->nodeStats.nodeid);
+ }
+}
+
void RPCConsole::peerLayoutChanged()
{
if (!clientModel || !clientModel->getPeerTableModel())
@@ -834,7 +863,7 @@ void RPCConsole::peerLayoutChanged()
bool fUnselect = false;
bool fReselect = false;
- if (cachedNodeid == -1) // no node selected yet
+ if (cachedNodeids.empty()) // no node selected yet
return;
// find the currently selected row
@@ -846,7 +875,7 @@ void RPCConsole::peerLayoutChanged()
// check if our detail node has a row in the table (it may not necessarily
// be at selectedRow since its position can change after a layout change)
- int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(cachedNodeid);
+ int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(cachedNodeids.first());
if (detailNodeRow < 0)
{
@@ -872,7 +901,10 @@ void RPCConsole::peerLayoutChanged()
if (fReselect)
{
- ui->peerWidget->selectRow(detailNodeRow);
+ for(int i = 0; i < cachedNodeids.size(); i++)
+ {
+ ui->peerWidget->selectRow(clientModel->getPeerTableModel()->getRowByNodeId(cachedNodeids.at(i)));
+ }
}
if (stats)
@@ -881,9 +913,6 @@ void RPCConsole::peerLayoutChanged()
void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats)
{
- // Update cached nodeid
- cachedNodeid = stats->nodeStats.nodeid;
-
// update the detail ui with latest node information
QString peerAddrDetails(QString::fromStdString(stats->nodeStats.addrName) + " ");
peerAddrDetails += tr("(node id: %1)").arg(QString::number(stats->nodeStats.nodeid));
@@ -973,33 +1002,44 @@ void RPCConsole::disconnectSelectedNode()
{
if(!g_connman)
return;
- // Get currently selected peer address
- NodeId id = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::NetNodeId).toInt();
- // Find the node, disconnect it and clear the selected node
- if(g_connman->DisconnectNode(id))
- clearSelectedNode();
+
+ // Get selected peer addresses
+ QList<QModelIndex> nodes = GUIUtil::getEntryData(ui->peerWidget, 0);
+ for(int i = 0; i < nodes.count(); i++)
+ {
+ // Get currently selected peer address
+ NodeId id = nodes.at(i).data(PeerTableModel::NetNodeId).toInt();
+ // Find the node, disconnect it and clear the selected node
+ if(g_connman->DisconnectNode(id))
+ clearSelectedNode();
+ }
}
void RPCConsole::banSelectedNode(int bantime)
{
if (!clientModel || !g_connman)
return;
-
- if(cachedNodeid == -1)
- return;
-
- // Get currently selected peer address
- int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(cachedNodeid);
- if(detailNodeRow < 0)
- return;
-
- // Find possible nodes, ban it and clear the selected node
- const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow);
- if(stats) {
- g_connman->Ban(stats->nodeStats.addr, BanReasonManuallyAdded, bantime);
- clearSelectedNode();
- clientModel->getBanTableModel()->refresh();
+
+ // Get selected peer addresses
+ QList<QModelIndex> nodes = GUIUtil::getEntryData(ui->peerWidget, 0);
+ for(int i = 0; i < nodes.count(); i++)
+ {
+ // Get currently selected peer address
+ NodeId id = nodes.at(i).data(PeerTableModel::NetNodeId).toInt();
+
+ // Get currently selected peer address
+ int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(id);
+ if(detailNodeRow < 0)
+ return;
+
+ // Find possible nodes, ban it and clear the selected node
+ const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow);
+ if(stats) {
+ g_connman->Ban(stats->nodeStats.addr, BanReasonManuallyAdded, bantime);
+ }
}
+ clearSelectedNode();
+ clientModel->getBanTableModel()->refresh();
}
void RPCConsole::unbanSelectedNode()
@@ -1007,22 +1047,27 @@ void RPCConsole::unbanSelectedNode()
if (!clientModel)
return;
- // Get currently selected ban address
- QString strNode = GUIUtil::getEntryData(ui->banlistWidget, 0, BanTableModel::Address).toString();
- CSubNet possibleSubnet;
-
- LookupSubNet(strNode.toStdString().c_str(), possibleSubnet);
- if (possibleSubnet.IsValid() && g_connman)
+ // Get selected ban addresses
+ QList<QModelIndex> nodes = GUIUtil::getEntryData(ui->banlistWidget, 0);
+ for(int i = 0; i < nodes.count(); i++)
{
- g_connman->Unban(possibleSubnet);
- clientModel->getBanTableModel()->refresh();
+ // Get currently selected ban address
+ QString strNode = nodes.at(i).data(BanTableModel::Address).toString();
+ CSubNet possibleSubnet;
+
+ LookupSubNet(strNode.toStdString().c_str(), possibleSubnet);
+ if (possibleSubnet.IsValid() && g_connman)
+ {
+ g_connman->Unban(possibleSubnet);
+ clientModel->getBanTableModel()->refresh();
+ }
}
}
void RPCConsole::clearSelectedNode()
{
ui->peerWidget->selectionModel()->clearSelection();
- cachedNodeid = -1;
+ cachedNodeids.clear();
ui->detailWidget->hide();
ui->peerHeading->setText(tr("Select a peer to view detailed information."));
}
@@ -1041,3 +1086,8 @@ void RPCConsole::setTabFocus(enum TabTypes tabType)
{
ui->tabWidget->setCurrentIndex(tabType);
}
+
+void RPCConsole::on_toggleNetworkActiveButton_clicked()
+{
+ clientModel->setNetworkActive(!clientModel->getNetworkActive());
+}
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 50224a1cc0..8c20379a8c 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -61,6 +61,8 @@ protected:
private Q_SLOTS:
void on_lineEdit_returnPressed();
void on_tabWidget_currentChanged(int index);
+ /** toggle network activity */
+ void on_toggleNetworkActiveButton_clicked();
/** open the debug.log from the current datadir */
void on_openDebugLogfileButton_clicked();
/** change the time range of the network traffic graph */
@@ -88,6 +90,8 @@ public Q_SLOTS:
void message(int category, const QString &message, bool html = false);
/** Set number of connections shown in the UI */
void setNumConnections(int count);
+ /** Set network state shown in the UI */
+ void setNetworkActive(bool networkActive);
/** Set number of blocks and last block date shown in the UI */
void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers);
/** Set size (number of transactions and memory usage) of the mempool in the UI */
@@ -98,6 +102,8 @@ public Q_SLOTS:
void scrollToEnd();
/** Handle selection of peer in peers list */
void peerSelected(const QItemSelection &selected, const QItemSelection &deselected);
+ /** Handle selection caching before update */
+ void peerLayoutAboutToChange();
/** Handle updated peer information */
void peerLayoutChanged();
/** Disconnect a selected node on the Peers tab */
@@ -135,13 +141,16 @@ private:
ClientModel *clientModel;
QStringList history;
int historyPtr;
- NodeId cachedNodeid;
+ QList<NodeId> cachedNodeids;
const PlatformStyle *platformStyle;
RPCTimerInterface *rpcTimerInterface;
QMenu *peersTableContextMenu;
QMenu *banTableContextMenu;
int consoleFontSize;
QCompleter *autoCompleter;
+
+ /** Update UI with latest network info from model. */
+ void updateNetworkState();
};
#endif // BITCOIN_QT_RPCCONSOLE_H
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 6a5670e378..eedf6e8cea 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -65,7 +65,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
std::string sAddress = address.toStdString();
std::string sLabel = label.toStdString();
std::string sMessage = message.toStdString();
diff --git a/src/rest.cpp b/src/rest.cpp
index b8b5420626..90cca6f480 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -50,7 +50,7 @@ struct CCoin {
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
+ inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(nTxVer);
READWRITE(nHeight);
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index 8370a0f43e..03992a278d 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -109,6 +109,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "prioritisetransaction", 2 },
{ "setban", 2 },
{ "setban", 3 },
+ { "setnetworkactive", 0 },
{ "getmempoolancestors", 1 },
{ "getmempooldescendants", 1 },
};
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 2b43f08f0b..f57ba76d3a 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -331,7 +331,7 @@ UniValue getnettotals(const JSONRPCRequest& request)
"{\n"
" \"totalbytesrecv\": n, (numeric) Total bytes received\n"
" \"totalbytessent\": n, (numeric) Total bytes sent\n"
- " \"timemillis\": t, (numeric) Total cpu time\n"
+ " \"timemillis\": t, (numeric) Current UNIX time in milliseconds\n"
" \"uploadtarget\":\n"
" {\n"
" \"timeframe\": n, (numeric) Length of the measuring timeframe in seconds\n"
@@ -401,6 +401,7 @@ UniValue getnetworkinfo(const JSONRPCRequest& request)
" \"localrelay\": true|false, (bool) true if transaction relay is requested from peers\n"
" \"timeoffset\": xxxxx, (numeric) the time offset\n"
" \"connections\": xxxxx, (numeric) the number of connections\n"
+ " \"networkactive\": true|false, (bool) whether p2p networking is enabled\n"
" \"networks\": [ (array) information per network\n"
" {\n"
" \"name\": \"xxx\", (string) network (ipv4, ipv6 or onion)\n"
@@ -435,8 +436,10 @@ UniValue getnetworkinfo(const JSONRPCRequest& request)
obj.push_back(Pair("localservices", strprintf("%016x", g_connman->GetLocalServices())));
obj.push_back(Pair("localrelay", fRelayTxes));
obj.push_back(Pair("timeoffset", GetTimeOffset()));
- if(g_connman)
+ if (g_connman) {
+ obj.push_back(Pair("networkactive", g_connman->GetNetworkActive()));
obj.push_back(Pair("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL)));
+ }
obj.push_back(Pair("networks", GetNetworksInfo()));
obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
UniValue localAddresses(UniValue::VARR);
@@ -571,6 +574,24 @@ UniValue clearbanned(const JSONRPCRequest& request)
return NullUniValue;
}
+UniValue setnetworkactive(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() != 1) {
+ throw runtime_error(
+ "setnetworkactive true|false\n"
+ "Disable/enable all p2p network activity."
+ );
+ }
+
+ if (!g_connman) {
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
+ }
+
+ g_connman->SetNetworkActive(request.params[0].get_bool());
+
+ return g_connman->GetNetworkActive();
+}
+
static const CRPCCommand commands[] =
{ // category name actor (function) okSafeMode
// --------------------- ------------------------ ----------------------- ----------
@@ -585,6 +606,7 @@ static const CRPCCommand commands[] =
{ "network", "setban", &setban, true },
{ "network", "listbanned", &listbanned, true },
{ "network", "clearbanned", &clearbanned, true },
+ { "network", "setnetworkactive", &setnetworkactive, true, },
};
void RegisterNetRPCCommands(CRPCTable &t)
diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp
index 1d0ca0c5ac..069ac55bfb 100644
--- a/src/script/bitcoinconsensus.cpp
+++ b/src/script/bitcoinconsensus.cpp
@@ -23,7 +23,7 @@ public:
m_remaining(txToLen)
{}
- TxInputStream& read(char* pch, size_t nSize)
+ void read(char* pch, size_t nSize)
{
if (nSize > m_remaining)
throw std::ios_base::failure(std::string(__func__) + ": end of data");
@@ -37,16 +37,17 @@ public:
memcpy(pch, m_data, nSize);
m_remaining -= nSize;
m_data += nSize;
- return *this;
}
template<typename T>
TxInputStream& operator>>(T& obj)
{
- ::Unserialize(*this, obj, m_type, m_version);
+ ::Unserialize(*this, obj);
return *this;
}
+ int GetVersion() const { return m_version; }
+ int GetType() const { return m_type; }
private:
const int m_type;
const int m_version;
@@ -88,7 +89,7 @@ static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptP
stream >> tx;
if (nIn >= tx.vin.size())
return set_error(err, bitcoinconsensus_ERR_TX_INDEX);
- if (tx.GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION) != txToLen)
+ if (GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) != txToLen)
return set_error(err, bitcoinconsensus_ERR_TX_SIZE_MISMATCH);
// Regardless of the verification result, the tx did not error.
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 0e17ddc130..a6403f9363 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1069,7 +1069,7 @@ public:
/** Serialize the passed scriptCode, skipping OP_CODESEPARATORs */
template<typename S>
- void SerializeScriptCode(S &s, int nType, int nVersion) const {
+ void SerializeScriptCode(S &s) const {
CScript::const_iterator it = scriptCode.begin();
CScript::const_iterator itBegin = it;
opcodetype opcode;
@@ -1092,53 +1092,53 @@ public:
/** Serialize an input of txTo */
template<typename S>
- void SerializeInput(S &s, unsigned int nInput, int nType, int nVersion) const {
+ void SerializeInput(S &s, unsigned int nInput) const {
// In case of SIGHASH_ANYONECANPAY, only the input being signed is serialized
if (fAnyoneCanPay)
nInput = nIn;
// Serialize the prevout
- ::Serialize(s, txTo.vin[nInput].prevout, nType, nVersion);
+ ::Serialize(s, txTo.vin[nInput].prevout);
// Serialize the script
if (nInput != nIn)
// Blank out other inputs' signatures
- ::Serialize(s, CScriptBase(), nType, nVersion);
+ ::Serialize(s, CScriptBase());
else
- SerializeScriptCode(s, nType, nVersion);
+ SerializeScriptCode(s);
// Serialize the nSequence
if (nInput != nIn && (fHashSingle || fHashNone))
// let the others update at will
- ::Serialize(s, (int)0, nType, nVersion);
+ ::Serialize(s, (int)0);
else
- ::Serialize(s, txTo.vin[nInput].nSequence, nType, nVersion);
+ ::Serialize(s, txTo.vin[nInput].nSequence);
}
/** Serialize an output of txTo */
template<typename S>
- void SerializeOutput(S &s, unsigned int nOutput, int nType, int nVersion) const {
+ void SerializeOutput(S &s, unsigned int nOutput) const {
if (fHashSingle && nOutput != nIn)
// Do not lock-in the txout payee at other indices as txin
- ::Serialize(s, CTxOut(), nType, nVersion);
+ ::Serialize(s, CTxOut());
else
- ::Serialize(s, txTo.vout[nOutput], nType, nVersion);
+ ::Serialize(s, txTo.vout[nOutput]);
}
/** Serialize txTo */
template<typename S>
- void Serialize(S &s, int nType, int nVersion) const {
+ void Serialize(S &s) const {
// Serialize nVersion
- ::Serialize(s, txTo.nVersion, nType, nVersion);
+ ::Serialize(s, txTo.nVersion);
// Serialize vin
unsigned int nInputs = fAnyoneCanPay ? 1 : txTo.vin.size();
::WriteCompactSize(s, nInputs);
for (unsigned int nInput = 0; nInput < nInputs; nInput++)
- SerializeInput(s, nInput, nType, nVersion);
+ SerializeInput(s, nInput);
// Serialize vout
unsigned int nOutputs = fHashNone ? 0 : (fHashSingle ? nIn+1 : txTo.vout.size());
::WriteCompactSize(s, nOutputs);
for (unsigned int nOutput = 0; nOutput < nOutputs; nOutput++)
- SerializeOutput(s, nOutput, nType, nVersion);
+ SerializeOutput(s, nOutput);
// Serialize nLockTime
- ::Serialize(s, txTo.nLockTime, nType, nVersion);
+ ::Serialize(s, txTo.nLockTime);
}
};
diff --git a/src/serialize.h b/src/serialize.h
index 82870c45b3..91864e1b64 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -151,6 +151,8 @@ inline float ser_uint32_to_float(uint32_t y)
// i.e. anything that supports .read(char*, size_t) and .write(char*, size_t)
//
+class CSizeComputer;
+
enum
{
// primary actions
@@ -159,8 +161,8 @@ enum
SER_GETHASH = (1 << 2),
};
-#define READWRITE(obj) (::SerReadWrite(s, (obj), nType, nVersion, ser_action))
-#define READWRITEMANY(...) (::SerReadWriteMany(s, nType, nVersion, ser_action, __VA_ARGS__))
+#define READWRITE(obj) (::SerReadWrite(s, (obj), ser_action))
+#define READWRITEMANY(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
/**
* Implement three methods for serializable objects. These are actually wrappers over
@@ -168,63 +170,42 @@ enum
* code. Adding "ADD_SERIALIZE_METHODS" in the body of the class causes these wrappers to be
* added as members.
*/
-#define ADD_SERIALIZE_METHODS \
- size_t GetSerializeSize(int nType, int nVersion) const { \
- CSizeComputer s(nType, nVersion); \
- NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize(), nType, nVersion);\
- return s.size(); \
- } \
- template<typename Stream> \
- void Serialize(Stream& s, int nType, int nVersion) const { \
- NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize(), nType, nVersion);\
- } \
- template<typename Stream> \
- void Unserialize(Stream& s, int nType, int nVersion) { \
- SerializationOp(s, CSerActionUnserialize(), nType, nVersion); \
+#define ADD_SERIALIZE_METHODS \
+ template<typename Stream> \
+ void Serialize(Stream& s) const { \
+ NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize()); \
+ } \
+ template<typename Stream> \
+ void Unserialize(Stream& s) { \
+ SerializationOp(s, CSerActionUnserialize()); \
}
-/*
- * Basic Types
- */
-inline unsigned int GetSerializeSize(char a, int, int=0) { return 1; }
-inline unsigned int GetSerializeSize(int8_t a, int, int=0) { return 1; }
-inline unsigned int GetSerializeSize(uint8_t a, int, int=0) { return 1; }
-inline unsigned int GetSerializeSize(int16_t a, int, int=0) { return 2; }
-inline unsigned int GetSerializeSize(uint16_t a, int, int=0) { return 2; }
-inline unsigned int GetSerializeSize(int32_t a, int, int=0) { return 4; }
-inline unsigned int GetSerializeSize(uint32_t a, int, int=0) { return 4; }
-inline unsigned int GetSerializeSize(int64_t a, int, int=0) { return 8; }
-inline unsigned int GetSerializeSize(uint64_t a, int, int=0) { return 8; }
-inline unsigned int GetSerializeSize(float a, int, int=0) { return 4; }
-inline unsigned int GetSerializeSize(double a, int, int=0) { return 8; }
-
-template<typename Stream> inline void Serialize(Stream& s, char a, int, int=0) { ser_writedata8(s, a); } // TODO Get rid of bare char
-template<typename Stream> inline void Serialize(Stream& s, int8_t a, int, int=0) { ser_writedata8(s, a); }
-template<typename Stream> inline void Serialize(Stream& s, uint8_t a, int, int=0) { ser_writedata8(s, a); }
-template<typename Stream> inline void Serialize(Stream& s, int16_t a, int, int=0) { ser_writedata16(s, a); }
-template<typename Stream> inline void Serialize(Stream& s, uint16_t a, int, int=0) { ser_writedata16(s, a); }
-template<typename Stream> inline void Serialize(Stream& s, int32_t a, int, int=0) { ser_writedata32(s, a); }
-template<typename Stream> inline void Serialize(Stream& s, uint32_t a, int, int=0) { ser_writedata32(s, a); }
-template<typename Stream> inline void Serialize(Stream& s, int64_t a, int, int=0) { ser_writedata64(s, a); }
-template<typename Stream> inline void Serialize(Stream& s, uint64_t a, int, int=0) { ser_writedata64(s, a); }
-template<typename Stream> inline void Serialize(Stream& s, float a, int, int=0) { ser_writedata32(s, ser_float_to_uint32(a)); }
-template<typename Stream> inline void Serialize(Stream& s, double a, int, int=0) { ser_writedata64(s, ser_double_to_uint64(a)); }
-
-template<typename Stream> inline void Unserialize(Stream& s, char& a, int, int=0) { a = ser_readdata8(s); } // TODO Get rid of bare char
-template<typename Stream> inline void Unserialize(Stream& s, int8_t& a, int, int=0) { a = ser_readdata8(s); }
-template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a, int, int=0) { a = ser_readdata8(s); }
-template<typename Stream> inline void Unserialize(Stream& s, int16_t& a, int, int=0) { a = ser_readdata16(s); }
-template<typename Stream> inline void Unserialize(Stream& s, uint16_t& a, int, int=0) { a = ser_readdata16(s); }
-template<typename Stream> inline void Unserialize(Stream& s, int32_t& a, int, int=0) { a = ser_readdata32(s); }
-template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a, int, int=0) { a = ser_readdata32(s); }
-template<typename Stream> inline void Unserialize(Stream& s, int64_t& a, int, int=0) { a = ser_readdata64(s); }
-template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a, int, int=0) { a = ser_readdata64(s); }
-template<typename Stream> inline void Unserialize(Stream& s, float& a, int, int=0) { a = ser_uint32_to_float(ser_readdata32(s)); }
-template<typename Stream> inline void Unserialize(Stream& s, double& a, int, int=0) { a = ser_uint64_to_double(ser_readdata64(s)); }
-
-inline unsigned int GetSerializeSize(bool a, int, int=0) { return sizeof(char); }
-template<typename Stream> inline void Serialize(Stream& s, bool a, int, int=0) { char f=a; ser_writedata8(s, f); }
-template<typename Stream> inline void Unserialize(Stream& s, bool& a, int, int=0) { char f=ser_readdata8(s); a=f; }
+template<typename Stream> inline void Serialize(Stream& s, char a ) { ser_writedata8(s, a); } // TODO Get rid of bare char
+template<typename Stream> inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, uint16_t a) { ser_writedata16(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, int32_t a ) { ser_writedata32(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
+template<typename Stream> inline void Serialize(Stream& s, float a ) { ser_writedata32(s, ser_float_to_uint32(a)); }
+template<typename Stream> inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(a)); }
+
+template<typename Stream> inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char
+template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); }
+template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); }
+template<typename Stream> inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); }
+template<typename Stream> inline void Unserialize(Stream& s, uint16_t& a) { a = ser_readdata16(s); }
+template<typename Stream> inline void Unserialize(Stream& s, int32_t& a ) { a = ser_readdata32(s); }
+template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); }
+template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); }
+template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
+template<typename Stream> inline void Unserialize(Stream& s, float& a ) { a = ser_uint32_to_float(ser_readdata32(s)); }
+template<typename Stream> inline void Unserialize(Stream& s, double& a ) { a = ser_uint64_to_double(ser_readdata64(s)); }
+
+template<typename Stream> inline void Serialize(Stream& s, bool a) { char f=a; ser_writedata8(s, f); }
+template<typename Stream> inline void Unserialize(Stream& s, bool& a) { char f=ser_readdata8(s); a=f; }
@@ -246,6 +227,8 @@ inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
else return sizeof(unsigned char) + sizeof(uint64_t);
}
+inline void WriteCompactSize(CSizeComputer& os, uint64_t nSize);
+
template<typename Stream>
void WriteCompactSize(Stream& os, uint64_t nSize)
{
@@ -340,6 +323,9 @@ inline unsigned int GetSizeOfVarInt(I n)
return nRet;
}
+template<typename I>
+inline void WriteVarInt(CSizeComputer& os, I n);
+
template<typename Stream, typename I>
void WriteVarInt(Stream& os, I n)
{
@@ -403,19 +389,14 @@ public:
char* end() { return pend; }
const char* end() const { return pend; }
- unsigned int GetSerializeSize(int, int=0) const
- {
- return pend - pbegin;
- }
-
template<typename Stream>
- void Serialize(Stream& s, int, int=0) const
+ void Serialize(Stream& s) const
{
s.write(pbegin, pend - pbegin);
}
template<typename Stream>
- void Unserialize(Stream& s, int, int=0)
+ void Unserialize(Stream& s)
{
s.read(pbegin, pend - pbegin);
}
@@ -429,17 +410,13 @@ protected:
public:
CVarInt(I& nIn) : n(nIn) { }
- unsigned int GetSerializeSize(int, int) const {
- return GetSizeOfVarInt<I>(n);
- }
-
template<typename Stream>
- void Serialize(Stream &s, int, int) const {
+ void Serialize(Stream &s) const {
WriteVarInt<Stream,I>(s, n);
}
template<typename Stream>
- void Unserialize(Stream& s, int, int) {
+ void Unserialize(Stream& s) {
n = ReadVarInt<Stream,I>(s);
}
};
@@ -451,17 +428,13 @@ protected:
public:
CCompactSize(uint64_t& nIn) : n(nIn) { }
- unsigned int GetSerializeSize(int, int) const {
- return GetSizeOfCompactSize(n);
- }
-
template<typename Stream>
- void Serialize(Stream &s, int, int) const {
+ void Serialize(Stream &s) const {
WriteCompactSize<Stream>(s, n);
}
template<typename Stream>
- void Unserialize(Stream& s, int, int) {
+ void Unserialize(Stream& s) {
n = ReadCompactSize<Stream>(s);
}
};
@@ -472,10 +445,10 @@ class LimitedString
protected:
std::string& string;
public:
- LimitedString(std::string& string) : string(string) {}
+ LimitedString(std::string& _string) : string(_string) {}
template<typename Stream>
- void Unserialize(Stream& s, int, int=0)
+ void Unserialize(Stream& s)
{
size_t size = ReadCompactSize(s);
if (size > Limit) {
@@ -487,17 +460,12 @@ public:
}
template<typename Stream>
- void Serialize(Stream& s, int, int=0) const
+ void Serialize(Stream& s) const
{
WriteCompactSize(s, string.size());
if (!string.empty())
s.write((char*)&string[0], string.size());
}
-
- unsigned int GetSerializeSize(int, int=0) const
- {
- return GetSizeOfCompactSize(string.size()) + string.size();
- }
};
template<typename I>
@@ -510,58 +478,48 @@ CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); }
/**
* string
*/
-template<typename C> unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int=0);
-template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str, int, int=0);
-template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str, int, int=0);
+template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str);
+template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str);
/**
* prevector
* prevectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
*/
-template<unsigned int N, typename T> unsigned int GetSerializeSize_impl(const prevector<N, T>& v, int nType, int nVersion, const unsigned char&);
-template<unsigned int N, typename T, typename V> unsigned int GetSerializeSize_impl(const prevector<N, T>& v, int nType, int nVersion, const V&);
-template<unsigned int N, typename T> inline unsigned int GetSerializeSize(const prevector<N, T>& v, int nType, int nVersion);
-template<typename Stream, unsigned int N, typename T> void Serialize_impl(Stream& os, const prevector<N, T>& v, int nType, int nVersion, const unsigned char&);
-template<typename Stream, unsigned int N, typename T, typename V> void Serialize_impl(Stream& os, const prevector<N, T>& v, int nType, int nVersion, const V&);
-template<typename Stream, unsigned int N, typename T> inline void Serialize(Stream& os, const prevector<N, T>& v, int nType, int nVersion);
-template<typename Stream, unsigned int N, typename T> void Unserialize_impl(Stream& is, prevector<N, T>& v, int nType, int nVersion, const unsigned char&);
-template<typename Stream, unsigned int N, typename T, typename V> void Unserialize_impl(Stream& is, prevector<N, T>& v, int nType, int nVersion, const V&);
-template<typename Stream, unsigned int N, typename T> inline void Unserialize(Stream& is, prevector<N, T>& v, int nType, int nVersion);
+template<typename Stream, unsigned int N, typename T> void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&);
+template<typename Stream, unsigned int N, typename T, typename V> void Serialize_impl(Stream& os, const prevector<N, T>& v, const V&);
+template<typename Stream, unsigned int N, typename T> inline void Serialize(Stream& os, const prevector<N, T>& v);
+template<typename Stream, unsigned int N, typename T> void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&);
+template<typename Stream, unsigned int N, typename T, typename V> void Unserialize_impl(Stream& is, prevector<N, T>& v, const V&);
+template<typename Stream, unsigned int N, typename T> inline void Unserialize(Stream& is, prevector<N, T>& v);
/**
* vector
* vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
*/
-template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&);
-template<typename T, typename A, typename V> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const V&);
-template<typename T, typename A> inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion);
-template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&);
-template<typename Stream, typename T, typename A, typename V> void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const V&);
-template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion);
-template<typename Stream, typename T, typename A> void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const unsigned char&);
-template<typename Stream, typename T, typename A, typename V> void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const V&);
-template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion);
+template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, const unsigned char&);
+template<typename Stream, typename T, typename A, typename V> void Serialize_impl(Stream& os, const std::vector<T, A>& v, const V&);
+template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v);
+template<typename Stream, typename T, typename A> void Unserialize_impl(Stream& is, std::vector<T, A>& v, const unsigned char&);
+template<typename Stream, typename T, typename A, typename V> void Unserialize_impl(Stream& is, std::vector<T, A>& v, const V&);
+template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v);
/**
* pair
*/
-template<typename K, typename T> unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion);
-template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion);
-template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion);
+template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item);
+template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item);
/**
* map
*/
-template<typename K, typename T, typename Pred, typename A> unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion);
-template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion);
-template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion);
+template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m);
+template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m);
/**
* set
*/
-template<typename K, typename Pred, typename A> unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion);
-template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion);
-template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion);
+template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m);
+template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m);
@@ -569,26 +527,17 @@ template<typename Stream, typename K, typename Pred, typename A> void Unserializ
/**
* If none of the specialized versions above matched, default to calling member function.
- * "int nType" is changed to "long nType" to keep from getting an ambiguous overload error.
- * The compiler will only cast int to long if none of the other templates matched.
- * Thanks to Boost serialization for this idea.
*/
-template<typename T>
-inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion)
-{
- return a.GetSerializeSize((int)nType, nVersion);
-}
-
template<typename Stream, typename T>
-inline void Serialize(Stream& os, const T& a, long nType, int nVersion)
+inline void Serialize(Stream& os, const T& a)
{
- a.Serialize(os, (int)nType, nVersion);
+ a.Serialize(os);
}
template<typename Stream, typename T>
-inline void Unserialize(Stream& is, T& a, long nType, int nVersion)
+inline void Unserialize(Stream& is, T& a)
{
- a.Unserialize(is, (int)nType, nVersion);
+ a.Unserialize(is);
}
@@ -598,14 +547,8 @@ inline void Unserialize(Stream& is, T& a, long nType, int nVersion)
/**
* string
*/
-template<typename C>
-unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int)
-{
- return GetSizeOfCompactSize(str.size()) + str.size() * sizeof(str[0]);
-}
-
template<typename Stream, typename C>
-void Serialize(Stream& os, const std::basic_string<C>& str, int, int)
+void Serialize(Stream& os, const std::basic_string<C>& str)
{
WriteCompactSize(os, str.size());
if (!str.empty())
@@ -613,7 +556,7 @@ void Serialize(Stream& os, const std::basic_string<C>& str, int, int)
}
template<typename Stream, typename C>
-void Unserialize(Stream& is, std::basic_string<C>& str, int, int)
+void Unserialize(Stream& is, std::basic_string<C>& str)
{
unsigned int nSize = ReadCompactSize(is);
str.resize(nSize);
@@ -626,30 +569,8 @@ void Unserialize(Stream& is, std::basic_string<C>& str, int, int)
/**
* prevector
*/
-template<unsigned int N, typename T>
-unsigned int GetSerializeSize_impl(const prevector<N, T>& v, int nType, int nVersion, const unsigned char&)
-{
- return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T));
-}
-
-template<unsigned int N, typename T, typename V>
-unsigned int GetSerializeSize_impl(const prevector<N, T>& v, int nType, int nVersion, const V&)
-{
- unsigned int nSize = GetSizeOfCompactSize(v.size());
- for (typename prevector<N, T>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
- nSize += GetSerializeSize((*vi), nType, nVersion);
- return nSize;
-}
-
-template<unsigned int N, typename T>
-inline unsigned int GetSerializeSize(const prevector<N, T>& v, int nType, int nVersion)
-{
- return GetSerializeSize_impl(v, nType, nVersion, T());
-}
-
-
template<typename Stream, unsigned int N, typename T>
-void Serialize_impl(Stream& os, const prevector<N, T>& v, int nType, int nVersion, const unsigned char&)
+void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&)
{
WriteCompactSize(os, v.size());
if (!v.empty())
@@ -657,22 +578,22 @@ void Serialize_impl(Stream& os, const prevector<N, T>& v, int nType, int nVersio
}
template<typename Stream, unsigned int N, typename T, typename V>
-void Serialize_impl(Stream& os, const prevector<N, T>& v, int nType, int nVersion, const V&)
+void Serialize_impl(Stream& os, const prevector<N, T>& v, const V&)
{
WriteCompactSize(os, v.size());
for (typename prevector<N, T>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
- ::Serialize(os, (*vi), nType, nVersion);
+ ::Serialize(os, (*vi));
}
template<typename Stream, unsigned int N, typename T>
-inline void Serialize(Stream& os, const prevector<N, T>& v, int nType, int nVersion)
+inline void Serialize(Stream& os, const prevector<N, T>& v)
{
- Serialize_impl(os, v, nType, nVersion, T());
+ Serialize_impl(os, v, T());
}
template<typename Stream, unsigned int N, typename T>
-void Unserialize_impl(Stream& is, prevector<N, T>& v, int nType, int nVersion, const unsigned char&)
+void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&)
{
// Limit size per read so bogus size value won't cause out of memory
v.clear();
@@ -688,7 +609,7 @@ void Unserialize_impl(Stream& is, prevector<N, T>& v, int nType, int nVersion, c
}
template<typename Stream, unsigned int N, typename T, typename V>
-void Unserialize_impl(Stream& is, prevector<N, T>& v, int nType, int nVersion, const V&)
+void Unserialize_impl(Stream& is, prevector<N, T>& v, const V&)
{
v.clear();
unsigned int nSize = ReadCompactSize(is);
@@ -701,14 +622,14 @@ void Unserialize_impl(Stream& is, prevector<N, T>& v, int nType, int nVersion, c
nMid = nSize;
v.resize(nMid);
for (; i < nMid; i++)
- Unserialize(is, v[i], nType, nVersion);
+ Unserialize(is, v[i]);
}
}
template<typename Stream, unsigned int N, typename T>
-inline void Unserialize(Stream& is, prevector<N, T>& v, int nType, int nVersion)
+inline void Unserialize(Stream& is, prevector<N, T>& v)
{
- Unserialize_impl(is, v, nType, nVersion, T());
+ Unserialize_impl(is, v, T());
}
@@ -716,30 +637,8 @@ inline void Unserialize(Stream& is, prevector<N, T>& v, int nType, int nVersion)
/**
* vector
*/
-template<typename T, typename A>
-unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&)
-{
- return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T));
-}
-
-template<typename T, typename A, typename V>
-unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const V&)
-{
- unsigned int nSize = GetSizeOfCompactSize(v.size());
- for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
- nSize += GetSerializeSize((*vi), nType, nVersion);
- return nSize;
-}
-
-template<typename T, typename A>
-inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion)
-{
- return GetSerializeSize_impl(v, nType, nVersion, T());
-}
-
-
template<typename Stream, typename T, typename A>
-void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&)
+void Serialize_impl(Stream& os, const std::vector<T, A>& v, const unsigned char&)
{
WriteCompactSize(os, v.size());
if (!v.empty())
@@ -747,22 +646,22 @@ void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVers
}
template<typename Stream, typename T, typename A, typename V>
-void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVersion, const V&)
+void Serialize_impl(Stream& os, const std::vector<T, A>& v, const V&)
{
WriteCompactSize(os, v.size());
for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
- ::Serialize(os, (*vi), nType, nVersion);
+ ::Serialize(os, (*vi));
}
template<typename Stream, typename T, typename A>
-inline void Serialize(Stream& os, const std::vector<T, A>& v, int nType, int nVersion)
+inline void Serialize(Stream& os, const std::vector<T, A>& v)
{
- Serialize_impl(os, v, nType, nVersion, T());
+ Serialize_impl(os, v, T());
}
template<typename Stream, typename T, typename A>
-void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const unsigned char&)
+void Unserialize_impl(Stream& is, std::vector<T, A>& v, const unsigned char&)
{
// Limit size per read so bogus size value won't cause out of memory
v.clear();
@@ -778,7 +677,7 @@ void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion,
}
template<typename Stream, typename T, typename A, typename V>
-void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const V&)
+void Unserialize_impl(Stream& is, std::vector<T, A>& v, const V&)
{
v.clear();
unsigned int nSize = ReadCompactSize(is);
@@ -791,14 +690,14 @@ void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion,
nMid = nSize;
v.resize(nMid);
for (; i < nMid; i++)
- Unserialize(is, v[i], nType, nVersion);
+ Unserialize(is, v[i]);
}
}
template<typename Stream, typename T, typename A>
-inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion)
+inline void Unserialize(Stream& is, std::vector<T, A>& v)
{
- Unserialize_impl(is, v, nType, nVersion, T());
+ Unserialize_impl(is, v, T());
}
@@ -806,24 +705,18 @@ inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersio
/**
* pair
*/
-template<typename K, typename T>
-unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion)
-{
- return GetSerializeSize(item.first, nType, nVersion) + GetSerializeSize(item.second, nType, nVersion);
-}
-
template<typename Stream, typename K, typename T>
-void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion)
+void Serialize(Stream& os, const std::pair<K, T>& item)
{
- Serialize(os, item.first, nType, nVersion);
- Serialize(os, item.second, nType, nVersion);
+ Serialize(os, item.first);
+ Serialize(os, item.second);
}
template<typename Stream, typename K, typename T>
-void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion)
+void Unserialize(Stream& is, std::pair<K, T>& item)
{
- Unserialize(is, item.first, nType, nVersion);
- Unserialize(is, item.second, nType, nVersion);
+ Unserialize(is, item.first);
+ Unserialize(is, item.second);
}
@@ -831,25 +724,16 @@ void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion)
/**
* map
*/
-template<typename K, typename T, typename Pred, typename A>
-unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion)
-{
- unsigned int nSize = GetSizeOfCompactSize(m.size());
- for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
- nSize += GetSerializeSize((*mi), nType, nVersion);
- return nSize;
-}
-
template<typename Stream, typename K, typename T, typename Pred, typename A>
-void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion)
+void Serialize(Stream& os, const std::map<K, T, Pred, A>& m)
{
WriteCompactSize(os, m.size());
for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
- Serialize(os, (*mi), nType, nVersion);
+ Serialize(os, (*mi));
}
template<typename Stream, typename K, typename T, typename Pred, typename A>
-void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion)
+void Unserialize(Stream& is, std::map<K, T, Pred, A>& m)
{
m.clear();
unsigned int nSize = ReadCompactSize(is);
@@ -857,7 +741,7 @@ void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion
for (unsigned int i = 0; i < nSize; i++)
{
std::pair<K, T> item;
- Unserialize(is, item, nType, nVersion);
+ Unserialize(is, item);
mi = m.insert(mi, item);
}
}
@@ -867,25 +751,16 @@ void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion
/**
* set
*/
-template<typename K, typename Pred, typename A>
-unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion)
-{
- unsigned int nSize = GetSizeOfCompactSize(m.size());
- for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
- nSize += GetSerializeSize((*it), nType, nVersion);
- return nSize;
-}
-
template<typename Stream, typename K, typename Pred, typename A>
-void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion)
+void Serialize(Stream& os, const std::set<K, Pred, A>& m)
{
WriteCompactSize(os, m.size());
for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
- Serialize(os, (*it), nType, nVersion);
+ Serialize(os, (*it));
}
template<typename Stream, typename K, typename Pred, typename A>
-void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion)
+void Unserialize(Stream& is, std::set<K, Pred, A>& m)
{
m.clear();
unsigned int nSize = ReadCompactSize(is);
@@ -893,7 +768,7 @@ void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion)
for (unsigned int i = 0; i < nSize; i++)
{
K key;
- Unserialize(is, key, nType, nVersion);
+ Unserialize(is, key);
it = m.insert(it, key);
}
}
@@ -905,23 +780,23 @@ void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion)
*/
struct CSerActionSerialize
{
- bool ForRead() const { return false; }
+ constexpr bool ForRead() const { return false; }
};
struct CSerActionUnserialize
{
- bool ForRead() const { return true; }
+ constexpr bool ForRead() const { return true; }
};
template<typename Stream, typename T>
-inline void SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action)
+inline void SerReadWrite(Stream& s, const T& obj, CSerActionSerialize ser_action)
{
- ::Serialize(s, obj, nType, nVersion);
+ ::Serialize(s, obj);
}
template<typename Stream, typename T>
-inline void SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action)
+inline void SerReadWrite(Stream& s, T& obj, CSerActionUnserialize ser_action)
{
- ::Unserialize(s, obj, nType, nVersion);
+ ::Unserialize(s, obj);
}
@@ -932,81 +807,122 @@ inline void SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionU
+/* ::GetSerializeSize implementations
+ *
+ * Computing the serialized size of objects is done through a special stream
+ * object of type CSizeComputer, which only records the number of bytes written
+ * to it.
+ *
+ * If your Serialize or SerializationOp method has non-trivial overhead for
+ * serialization, it may be worthwhile to implement a specialized version for
+ * CSizeComputer, which uses the s.seek() method to record bytes that would
+ * be written instead.
+ */
class CSizeComputer
{
protected:
size_t nSize;
+ const int nType;
+ const int nVersion;
public:
- int nType;
- int nVersion;
-
CSizeComputer(int nTypeIn, int nVersionIn) : nSize(0), nType(nTypeIn), nVersion(nVersionIn) {}
- CSizeComputer& write(const char *psz, size_t nSize)
+ void write(const char *psz, size_t _nSize)
+ {
+ this->nSize += _nSize;
+ }
+
+ /** Pretend _nSize bytes are written, without specifying them. */
+ void seek(size_t _nSize)
{
- this->nSize += nSize;
- return *this;
+ this->nSize += _nSize;
}
template<typename T>
CSizeComputer& operator<<(const T& obj)
{
- ::Serialize(*this, obj, nType, nVersion);
+ ::Serialize(*this, obj);
return (*this);
}
size_t size() const {
return nSize;
}
+
+ int GetVersion() const { return nVersion; }
+ int GetType() const { return nType; }
};
template<typename Stream>
-void SerializeMany(Stream& s, int nType, int nVersion)
+void SerializeMany(Stream& s)
{
}
template<typename Stream, typename Arg>
-void SerializeMany(Stream& s, int nType, int nVersion, Arg&& arg)
+void SerializeMany(Stream& s, Arg&& arg)
{
- ::Serialize(s, std::forward<Arg>(arg), nType, nVersion);
+ ::Serialize(s, std::forward<Arg>(arg));
}
template<typename Stream, typename Arg, typename... Args>
-void SerializeMany(Stream& s, int nType, int nVersion, Arg&& arg, Args&&... args)
+void SerializeMany(Stream& s, Arg&& arg, Args&&... args)
{
- ::Serialize(s, std::forward<Arg>(arg), nType, nVersion);
- ::SerializeMany(s, nType, nVersion, std::forward<Args>(args)...);
+ ::Serialize(s, std::forward<Arg>(arg));
+ ::SerializeMany(s, std::forward<Args>(args)...);
}
template<typename Stream>
-inline void UnserializeMany(Stream& s, int nType, int nVersion)
+inline void UnserializeMany(Stream& s)
{
}
template<typename Stream, typename Arg>
-inline void UnserializeMany(Stream& s, int nType, int nVersion, Arg& arg)
+inline void UnserializeMany(Stream& s, Arg& arg)
{
- ::Unserialize(s, arg, nType, nVersion);
+ ::Unserialize(s, arg);
}
template<typename Stream, typename Arg, typename... Args>
-inline void UnserializeMany(Stream& s, int nType, int nVersion, Arg& arg, Args&... args)
+inline void UnserializeMany(Stream& s, Arg& arg, Args&... args)
{
- ::Unserialize(s, arg, nType, nVersion);
- ::UnserializeMany(s, nType, nVersion, args...);
+ ::Unserialize(s, arg);
+ ::UnserializeMany(s, args...);
}
template<typename Stream, typename... Args>
-inline void SerReadWriteMany(Stream& s, int nType, int nVersion, CSerActionSerialize ser_action, Args&&... args)
+inline void SerReadWriteMany(Stream& s, CSerActionSerialize ser_action, Args&&... args)
{
- ::SerializeMany(s, nType, nVersion, std::forward<Args>(args)...);
+ ::SerializeMany(s, std::forward<Args>(args)...);
}
template<typename Stream, typename... Args>
-inline void SerReadWriteMany(Stream& s, int nType, int nVersion, CSerActionUnserialize ser_action, Args&... args)
+inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&... args)
+{
+ ::UnserializeMany(s, args...);
+}
+
+template<typename I>
+inline void WriteVarInt(CSizeComputer &s, I n)
+{
+ s.seek(GetSizeOfVarInt<I>(n));
+}
+
+inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize)
+{
+ s.seek(GetSizeOfCompactSize(nSize));
+}
+
+template <typename T>
+size_t GetSerializeSize(const T& t, int nType, int nVersion = 0)
+{
+ return (CSizeComputer(nType, nVersion) << t).size();
+}
+
+template <typename S, typename T>
+size_t GetSerializeSize(const S& s, const T& t)
{
- ::UnserializeMany(s, nType, nVersion, args...);
+ return (CSizeComputer(s.GetType(), s.GetVersion()) << t).size();
}
#endif // BITCOIN_SERIALIZE_H
diff --git a/src/streams.h b/src/streams.h
index fa001c112a..c3e7c9e9e4 100644
--- a/src/streams.h
+++ b/src/streams.h
@@ -26,17 +26,18 @@ template<typename Stream>
class OverrideStream
{
Stream* stream;
-public:
+
const int nType;
const int nVersion;
+public:
OverrideStream(Stream* stream_, int nType_, int nVersion_) : stream(stream_), nType(nType_), nVersion(nVersion_) {}
template<typename T>
OverrideStream<Stream>& operator<<(const T& obj)
{
// Serialize to this stream
- ::Serialize(*this->stream, obj, nType, nVersion);
+ ::Serialize(*this, obj);
return (*this);
}
@@ -44,9 +45,22 @@ public:
OverrideStream<Stream>& operator>>(T& obj)
{
// Unserialize from this stream
- ::Unserialize(*this->stream, obj, nType, nVersion);
+ ::Unserialize(*this, obj);
return (*this);
}
+
+ void write(const char* pch, size_t nSize)
+ {
+ stream->write(pch, nSize);
+ }
+
+ void read(char* pch, size_t nSize)
+ {
+ stream->read(pch, nSize);
+ }
+
+ int GetVersion() const { return nVersion; }
+ int GetType() const { return nType; }
};
template<typename S>
@@ -66,9 +80,10 @@ protected:
typedef CSerializeData vector_type;
vector_type vch;
unsigned int nReadPos;
-public:
+
int nType;
int nVersion;
+public:
typedef vector_type::allocator_type allocator_type;
typedef vector_type::size_type size_type;
@@ -116,7 +131,7 @@ public:
CDataStream(int nTypeIn, int nVersionIn, Args&&... args)
{
Init(nTypeIn, nVersionIn);
- ::SerializeMany(*this, nType, nVersion, std::forward<Args>(args)...);
+ ::SerializeMany(*this, std::forward<Args>(args)...);
}
void Init(int nTypeIn, int nVersionIn)
@@ -251,13 +266,11 @@ public:
int in_avail() { return size(); }
void SetType(int n) { nType = n; }
- int GetType() { return nType; }
+ int GetType() const { return nType; }
void SetVersion(int n) { nVersion = n; }
- int GetVersion() { return nVersion; }
- void ReadVersion() { *this >> nVersion; }
- void WriteVersion() { *this << nVersion; }
+ int GetVersion() const { return nVersion; }
- CDataStream& read(char* pch, size_t nSize)
+ void read(char* pch, size_t nSize)
{
// Read from the beginning of the buffer
unsigned int nReadPosNext = nReadPos + nSize;
@@ -270,14 +283,13 @@ public:
memcpy(pch, &vch[nReadPos], nSize);
nReadPos = 0;
vch.clear();
- return (*this);
+ return;
}
memcpy(pch, &vch[nReadPos], nSize);
nReadPos = nReadPosNext;
- return (*this);
}
- CDataStream& ignore(int nSize)
+ void ignore(int nSize)
{
// Ignore from the beginning of the buffer
if (nSize < 0) {
@@ -290,21 +302,19 @@ public:
throw std::ios_base::failure("CDataStream::ignore(): end of data");
nReadPos = 0;
vch.clear();
- return (*this);
+ return;
}
nReadPos = nReadPosNext;
- return (*this);
}
- CDataStream& write(const char* pch, size_t nSize)
+ void write(const char* pch, size_t nSize)
{
// Write to the end of the buffer
vch.insert(vch.end(), pch, pch + nSize);
- return (*this);
}
template<typename Stream>
- void Serialize(Stream& s, int nType, int nVersion) const
+ void Serialize(Stream& s) const
{
// Special case: stream << stream concatenates like stream += stream
if (!vch.empty())
@@ -312,17 +322,10 @@ public:
}
template<typename T>
- unsigned int GetSerializeSize(const T& obj)
- {
- // Tells the size of the object if serialized to this stream
- return ::GetSerializeSize(obj, nType, nVersion);
- }
-
- template<typename T>
CDataStream& operator<<(const T& obj)
{
// Serialize to this stream
- ::Serialize(*this, obj, nType, nVersion);
+ ::Serialize(*this, obj);
return (*this);
}
@@ -330,7 +333,7 @@ public:
CDataStream& operator>>(T& obj)
{
// Unserialize from this stream
- ::Unserialize(*this, obj, nType, nVersion);
+ ::Unserialize(*this, obj);
return (*this);
}
@@ -385,17 +388,15 @@ private:
CAutoFile(const CAutoFile&);
CAutoFile& operator=(const CAutoFile&);
- int nType;
- int nVersion;
-
+ const int nType;
+ const int nVersion;
+
FILE* file;
public:
- CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn)
+ CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn)
{
file = filenew;
- nType = nTypeIn;
- nVersion = nVersionIn;
}
~CAutoFile()
@@ -430,23 +431,18 @@ public:
//
// Stream subset
//
- void SetType(int n) { nType = n; }
- int GetType() { return nType; }
- void SetVersion(int n) { nVersion = n; }
- int GetVersion() { return nVersion; }
- void ReadVersion() { *this >> nVersion; }
- void WriteVersion() { *this << nVersion; }
+ int GetType() const { return nType; }
+ int GetVersion() const { return nVersion; }
- CAutoFile& read(char* pch, size_t nSize)
+ void read(char* pch, size_t nSize)
{
if (!file)
throw std::ios_base::failure("CAutoFile::read: file handle is NULL");
if (fread(pch, 1, nSize, file) != nSize)
throw std::ios_base::failure(feof(file) ? "CAutoFile::read: end of file" : "CAutoFile::read: fread failed");
- return (*this);
}
- CAutoFile& ignore(size_t nSize)
+ void ignore(size_t nSize)
{
if (!file)
throw std::ios_base::failure("CAutoFile::ignore: file handle is NULL");
@@ -457,23 +453,14 @@ public:
throw std::ios_base::failure(feof(file) ? "CAutoFile::ignore: end of file" : "CAutoFile::read: fread failed");
nSize -= nNow;
}
- return (*this);
}
- CAutoFile& write(const char* pch, size_t nSize)
+ void write(const char* pch, size_t nSize)
{
if (!file)
throw std::ios_base::failure("CAutoFile::write: file handle is NULL");
if (fwrite(pch, 1, nSize, file) != nSize)
throw std::ios_base::failure("CAutoFile::write: write failed");
- return (*this);
- }
-
- template<typename T>
- unsigned int GetSerializeSize(const T& obj)
- {
- // Tells the size of the object if serialized to this stream
- return ::GetSerializeSize(obj, nType, nVersion);
}
template<typename T>
@@ -482,7 +469,7 @@ public:
// Serialize to this stream
if (!file)
throw std::ios_base::failure("CAutoFile::operator<<: file handle is NULL");
- ::Serialize(*this, obj, nType, nVersion);
+ ::Serialize(*this, obj);
return (*this);
}
@@ -492,7 +479,7 @@ public:
// Unserialize from this stream
if (!file)
throw std::ios_base::failure("CAutoFile::operator>>: file handle is NULL");
- ::Unserialize(*this, obj, nType, nVersion);
+ ::Unserialize(*this, obj);
return (*this);
}
};
@@ -510,8 +497,8 @@ private:
CBufferedFile(const CBufferedFile&);
CBufferedFile& operator=(const CBufferedFile&);
- int nType;
- int nVersion;
+ const int nType;
+ const int nVersion;
FILE *src; // source file
uint64_t nSrcPos; // how many bytes have been read from source
@@ -541,11 +528,9 @@ protected:
public:
CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) :
- nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0)
+ nType(nTypeIn), nVersion(nVersionIn), nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0)
{
src = fileIn;
- nType = nTypeIn;
- nVersion = nVersionIn;
}
~CBufferedFile()
@@ -553,6 +538,9 @@ public:
fclose();
}
+ int GetVersion() const { return nVersion; }
+ int GetType() const { return nType; }
+
void fclose()
{
if (src) {
@@ -567,7 +555,7 @@ public:
}
// read a number of bytes
- CBufferedFile& read(char *pch, size_t nSize) {
+ void read(char *pch, size_t nSize) {
if (nSize + nReadPos > nReadLimit)
throw std::ios_base::failure("Read attempted past buffer limit");
if (nSize + nRewind > vchBuf.size())
@@ -586,7 +574,6 @@ public:
pch += nNow;
nSize -= nNow;
}
- return (*this);
}
// return the current reading position
@@ -632,7 +619,7 @@ public:
template<typename T>
CBufferedFile& operator>>(T& obj) {
// Unserialize from this stream
- ::Unserialize(*this, obj, nType, nVersion);
+ ::Unserialize(*this, obj);
return (*this);
}
diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp
index b0d9184816..0ed5d62ef6 100644
--- a/src/test/blockencodings_tests.cpp
+++ b/src/test/blockencodings_tests.cpp
@@ -129,7 +129,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(header);
READWRITE(nonce);
size_t shorttxids_size = shorttxids.size();
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index 042fad42da..25fb9ea2b7 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -41,7 +41,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize)
BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")), "BloomFilter doesn't contain just-inserted object (3)!");
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
- filter.Serialize(stream, SER_NETWORK, PROTOCOL_VERSION);
+ stream << filter;
vector<unsigned char> vch = ParseHex("03614e9b050000000000000001");
vector<char> expected(vch.size());
@@ -73,7 +73,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak)
BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")), "BloomFilter doesn't contain just-inserted object (3)!");
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
- filter.Serialize(stream, SER_NETWORK, PROTOCOL_VERSION);
+ stream << filter;
vector<unsigned char> vch = ParseHex("03ce4299050000000100008001");
vector<char> expected(vch.size());
@@ -100,7 +100,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_key)
filter.insert(vector<unsigned char>(hash.begin(), hash.end()));
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
- filter.Serialize(stream, SER_NETWORK, PROTOCOL_VERSION);
+ stream << filter;
vector<unsigned char> vch = ParseHex("038fc16b080000000000000001");
vector<char> expected(vch.size());
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
index d4d825d199..2d791ee18d 100644
--- a/src/test/dbwrapper_tests.cpp
+++ b/src/test/dbwrapper_tests.cpp
@@ -254,7 +254,7 @@ struct StringContentsSerializer {
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
if (ser_action.ForRead()) {
str.clear();
char c = 0;
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index e0460109d5..87cb38daac 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -17,7 +17,7 @@ using namespace std;
class CAddrManSerializationMock : public CAddrMan
{
public:
- virtual void Serialize(CDataStream& s, int nType, int nVersionDummy) const = 0;
+ virtual void Serialize(CDataStream& s) const = 0;
//! Ensure that bucket placement is always the same for testing purposes.
void MakeDeterministic()
@@ -30,16 +30,16 @@ public:
class CAddrManUncorrupted : public CAddrManSerializationMock
{
public:
- void Serialize(CDataStream& s, int nType, int nVersionDummy) const
+ void Serialize(CDataStream& s) const
{
- CAddrMan::Serialize(s, nType, nVersionDummy);
+ CAddrMan::Serialize(s);
}
};
class CAddrManCorrupted : public CAddrManSerializationMock
{
public:
- void Serialize(CDataStream& s, int nType, int nVersionDummy) const
+ void Serialize(CDataStream& s) const
{
// Produces corrupt output that claims addrman has 20 addrs when it only has one addr.
unsigned char nVersion = 1;
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index a3d1a25589..a359598ddc 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -84,6 +84,28 @@ BOOST_AUTO_TEST_CASE(rpc_rawparams)
BOOST_CHECK_THROW(CallRPC(string("sendrawtransaction ")+rawtx+" extra"), runtime_error);
}
+BOOST_AUTO_TEST_CASE(rpc_togglenetwork)
+{
+ UniValue r;
+
+ r = CallRPC("getnetworkinfo");
+ bool netState = find_value(r.get_obj(), "networkactive").get_bool();
+ BOOST_CHECK_EQUAL(netState, true);
+
+ BOOST_CHECK_NO_THROW(CallRPC("setnetworkactive false"));
+ r = CallRPC("getnetworkinfo");
+ int numConnection = find_value(r.get_obj(), "connections").get_int();
+ BOOST_CHECK_EQUAL(numConnection, 0);
+
+ netState = find_value(r.get_obj(), "networkactive").get_bool();
+ BOOST_CHECK_EQUAL(netState, false);
+
+ BOOST_CHECK_NO_THROW(CallRPC("setnetworkactive true"));
+ r = CallRPC("getnetworkinfo");
+ netState = find_value(r.get_obj(), "networkactive").get_bool();
+ BOOST_CHECK_EQUAL(netState, true);
+}
+
BOOST_AUTO_TEST_CASE(rpc_rawsign)
{
UniValue r;
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index 4c0fdc77f7..bbadf57957 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -28,7 +28,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(intval);
READWRITE(boolval);
READWRITE(stringval);
@@ -53,7 +53,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITEMANY(intval, boolval, stringval, FLATDATA(charstrval), txval);
}
};
diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp
index da0a3d73e0..2732948060 100644
--- a/src/test/uint256_tests.cpp
+++ b/src/test/uint256_tests.cpp
@@ -184,25 +184,25 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G
BOOST_CHECK(OneL.begin() + 32 == OneL.end());
BOOST_CHECK(MaxL.begin() + 32 == MaxL.end());
BOOST_CHECK(TmpL.begin() + 32 == TmpL.end());
- BOOST_CHECK(R1L.GetSerializeSize(0,PROTOCOL_VERSION) == 32);
- BOOST_CHECK(ZeroL.GetSerializeSize(0,PROTOCOL_VERSION) == 32);
+ BOOST_CHECK(GetSerializeSize(R1L, 0, PROTOCOL_VERSION) == 32);
+ BOOST_CHECK(GetSerializeSize(ZeroL, 0, PROTOCOL_VERSION) == 32);
- std::stringstream ss;
- R1L.Serialize(ss,0,PROTOCOL_VERSION);
+ CDataStream ss(0, PROTOCOL_VERSION);
+ ss << R1L;
BOOST_CHECK(ss.str() == std::string(R1Array,R1Array+32));
- TmpL.Unserialize(ss,0,PROTOCOL_VERSION);
+ ss >> TmpL;
BOOST_CHECK(R1L == TmpL);
- ss.str("");
- ZeroL.Serialize(ss,0,PROTOCOL_VERSION);
+ ss.clear();
+ ss << ZeroL;
BOOST_CHECK(ss.str() == std::string(ZeroArray,ZeroArray+32));
- TmpL.Unserialize(ss,0,PROTOCOL_VERSION);
+ ss >> TmpL;
BOOST_CHECK(ZeroL == TmpL);
- ss.str("");
- MaxL.Serialize(ss,0,PROTOCOL_VERSION);
+ ss.clear();
+ ss << MaxL;
BOOST_CHECK(ss.str() == std::string(MaxArray,MaxArray+32));
- TmpL.Unserialize(ss,0,PROTOCOL_VERSION);
+ ss >> TmpL;
BOOST_CHECK(MaxL == TmpL);
- ss.str("");
+ ss.clear();
BOOST_CHECK(R1S.GetHex() == R1S.ToString());
BOOST_CHECK(R2S.GetHex() == R2S.ToString());
@@ -230,24 +230,24 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G
BOOST_CHECK(OneS.begin() + 20 == OneS.end());
BOOST_CHECK(MaxS.begin() + 20 == MaxS.end());
BOOST_CHECK(TmpS.begin() + 20 == TmpS.end());
- BOOST_CHECK(R1S.GetSerializeSize(0,PROTOCOL_VERSION) == 20);
- BOOST_CHECK(ZeroS.GetSerializeSize(0,PROTOCOL_VERSION) == 20);
+ BOOST_CHECK(GetSerializeSize(R1S, 0, PROTOCOL_VERSION) == 20);
+ BOOST_CHECK(GetSerializeSize(ZeroS, 0, PROTOCOL_VERSION) == 20);
- R1S.Serialize(ss,0,PROTOCOL_VERSION);
+ ss << R1S;
BOOST_CHECK(ss.str() == std::string(R1Array,R1Array+20));
- TmpS.Unserialize(ss,0,PROTOCOL_VERSION);
+ ss >> TmpS;
BOOST_CHECK(R1S == TmpS);
- ss.str("");
- ZeroS.Serialize(ss,0,PROTOCOL_VERSION);
+ ss.clear();
+ ss << ZeroS;
BOOST_CHECK(ss.str() == std::string(ZeroArray,ZeroArray+20));
- TmpS.Unserialize(ss,0,PROTOCOL_VERSION);
+ ss >> TmpS;
BOOST_CHECK(ZeroS == TmpS);
- ss.str("");
- MaxS.Serialize(ss,0,PROTOCOL_VERSION);
+ ss.clear();
+ ss << MaxS;
BOOST_CHECK(ss.str() == std::string(MaxArray,MaxArray+20));
- TmpS.Unserialize(ss,0,PROTOCOL_VERSION);
+ ss >> TmpS;
BOOST_CHECK(MaxS == TmpS);
- ss.str("");
+ ss.clear();
}
BOOST_AUTO_TEST_CASE( conversion )
diff --git a/src/txdb.h b/src/txdb.h
index adb3f66327..687c686775 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -43,7 +43,7 @@ struct CDiskTxPos : public CDiskBlockPos
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(*(CDiskBlockPos*)this);
READWRITE(VARINT(nTxOffset));
}
diff --git a/src/ui_interface.h b/src/ui_interface.h
index 177ff238db..15b9614f63 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -85,6 +85,9 @@ public:
/** Number of network connections changed. */
boost::signals2::signal<void (int newNumConnections)> NotifyNumConnectionsChanged;
+ /** Network activity state changed. */
+ boost::signals2::signal<void (bool networkActive)> NotifyNetworkActiveChanged;
+
/**
* Status bar alerts changed.
*/
diff --git a/src/uint256.h b/src/uint256.h
index dd8432d74c..86e7c0b6c6 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -78,11 +78,6 @@ public:
return sizeof(data);
}
- unsigned int GetSerializeSize(int nType, int nVersion) const
- {
- return sizeof(data);
- }
-
uint64_t GetUint64(int pos) const
{
const uint8_t* ptr = data + pos * 8;
@@ -97,13 +92,13 @@ public:
}
template<typename Stream>
- void Serialize(Stream& s, int nType, int nVersion) const
+ void Serialize(Stream& s) const
{
s.write((char*)data, sizeof(data));
}
template<typename Stream>
- void Unserialize(Stream& s, int nType, int nVersion)
+ void Unserialize(Stream& s)
{
s.read((char*)data, sizeof(data));
}
diff --git a/src/undo.h b/src/undo.h
index d4fc84c90c..a5d276e7f3 100644
--- a/src/undo.h
+++ b/src/undo.h
@@ -27,29 +27,23 @@ public:
CTxInUndo() : txout(), fCoinBase(false), nHeight(0), nVersion(0) {}
CTxInUndo(const CTxOut &txoutIn, bool fCoinBaseIn = false, unsigned int nHeightIn = 0, int nVersionIn = 0) : txout(txoutIn), fCoinBase(fCoinBaseIn), nHeight(nHeightIn), nVersion(nVersionIn) { }
- unsigned int GetSerializeSize(int nType, int nVersion) const {
- return ::GetSerializeSize(VARINT(nHeight*2+(fCoinBase ? 1 : 0)), nType, nVersion) +
- (nHeight > 0 ? ::GetSerializeSize(VARINT(this->nVersion), nType, nVersion) : 0) +
- ::GetSerializeSize(CTxOutCompressor(REF(txout)), nType, nVersion);
- }
-
template<typename Stream>
- void Serialize(Stream &s, int nType, int nVersion) const {
- ::Serialize(s, VARINT(nHeight*2+(fCoinBase ? 1 : 0)), nType, nVersion);
+ void Serialize(Stream &s) const {
+ ::Serialize(s, VARINT(nHeight*2+(fCoinBase ? 1 : 0)));
if (nHeight > 0)
- ::Serialize(s, VARINT(this->nVersion), nType, nVersion);
- ::Serialize(s, CTxOutCompressor(REF(txout)), nType, nVersion);
+ ::Serialize(s, VARINT(this->nVersion));
+ ::Serialize(s, CTxOutCompressor(REF(txout)));
}
template<typename Stream>
- void Unserialize(Stream &s, int nType, int nVersion) {
+ void Unserialize(Stream &s) {
unsigned int nCode = 0;
- ::Unserialize(s, VARINT(nCode), nType, nVersion);
+ ::Unserialize(s, VARINT(nCode));
nHeight = nCode / 2;
fCoinBase = nCode & 1;
if (nHeight > 0)
- ::Unserialize(s, VARINT(this->nVersion), nType, nVersion);
- ::Unserialize(s, REF(CTxOutCompressor(REF(txout))), nType, nVersion);
+ ::Unserialize(s, VARINT(this->nVersion));
+ ::Unserialize(s, REF(CTxOutCompressor(REF(txout))));
}
};
@@ -63,7 +57,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(vprevout);
}
};
@@ -77,7 +71,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(vtxundo);
}
};
diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h
index f00f7fa731..e89c15b5d4 100644
--- a/src/wallet/crypter.h
+++ b/src/wallet/crypter.h
@@ -47,7 +47,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(vchCryptedKey);
READWRITE(vchSalt);
READWRITE(nDerivationMethod);
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index c5feb47899..bb5337c4ad 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -1017,7 +1017,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
bool fRunScan = false;
const int64_t minimumTimestamp = 1;
- int64_t nLowestTimestamp;
+ int64_t nLowestTimestamp = 0;
if (fRescan && chainActive.Tip()) {
nLowestTimestamp = chainActive.Tip()->GetBlockTime();
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 57b17d87ad..409d817046 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -100,8 +100,9 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- if (!(nType & SER_GETHASH))
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ int nVersion = s.GetVersion();
+ if (!(s.GetType() & SER_GETHASH))
READWRITE(nVersion);
READWRITE(nTime);
READWRITE(vchPubKey);
@@ -195,7 +196,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
std::vector<uint256> vMerkleBranch; // For compatibility with older versions.
READWRITE(*(CTransaction*)this);
READWRITE(hashBlock);
@@ -315,7 +316,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
if (ser_action.ForRead())
Init(NULL);
char fSpent = false;
@@ -448,8 +449,9 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- if (!(nType & SER_GETHASH))
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ int nVersion = s.GetVersion();
+ if (!(s.GetType() & SER_GETHASH))
READWRITE(nVersion);
READWRITE(vchPrivKey);
READWRITE(nTimeCreated);
@@ -493,8 +495,9 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- if (!(nType & SER_GETHASH))
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ int nVersion = s.GetVersion();
+ if (!(s.GetType() & SER_GETHASH))
READWRITE(nVersion);
//! Note: strAccount is serialized as part of the key, not here.
READWRITE(nCreditDebit);
@@ -507,7 +510,7 @@ public:
if (!(mapValue.empty() && _ssExtra.empty()))
{
- CDataStream ss(nType, nVersion);
+ CDataStream ss(s.GetType(), s.GetVersion());
ss.insert(ss.begin(), '\0');
ss << mapValue;
ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());
@@ -523,7 +526,7 @@ public:
mapValue.clear();
if (std::string::npos != nSepPos)
{
- CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), nType, nVersion);
+ CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), s.GetType(), s.GetVersion());
ss >> mapValue;
_ssExtra = std::vector<char>(ss.begin(), ss.end());
}
@@ -597,7 +600,7 @@ public:
*/
mutable CCriticalSection cs_wallet;
- std::string strWalletFile;
+ const std::string strWalletFile;
void LoadKeyPool(int nIndex, const CKeyPool &keypool)
{
@@ -622,11 +625,9 @@ public:
SetNull();
}
- CWallet(const std::string& strWalletFileIn)
+ CWallet(const std::string& strWalletFileIn) : strWalletFile(strWalletFileIn)
{
SetNull();
-
- strWalletFile = strWalletFileIn;
fFileBacked = true;
}
@@ -986,8 +987,9 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- if (!(nType & SER_GETHASH))
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ int nVersion = s.GetVersion();
+ if (!(s.GetType() & SER_GETHASH))
READWRITE(nVersion);
READWRITE(vchPubKey);
}
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index a0525bd9a7..eb25ac613d 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -54,7 +54,7 @@ public:
CHDChain() { SetNull(); }
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
+ inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(this->nVersion);
READWRITE(nExternalChainCounter);
@@ -93,7 +93,7 @@ public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(this->nVersion);
READWRITE(nCreateTime);
if (this->nVersion >= VERSION_WITH_HDDATA)