aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE.md2
-rw-r--r--configure.ac35
-rw-r--r--doc/Doxyfile2
-rw-r--r--doc/release-notes.md6
-rwxr-xr-xqa/rpc-tests/p2p-compactblocks.py16
-rwxr-xr-xqa/rpc-tests/p2p-segwit.py14
-rwxr-xr-xqa/rpc-tests/proxy_test.py16
-rwxr-xr-xqa/rpc-tests/rawtransactions.py39
-rwxr-xr-xqa/rpc-tests/sendheaders.py11
-rwxr-xr-xqa/rpc-tests/test_framework/comptool.py19
-rw-r--r--qa/rpc-tests/test_framework/util.py29
-rwxr-xr-xqa/rpc-tests/wallet.py2
-rw-r--r--src/Makefile.bench.include8
-rw-r--r--src/Makefile.test.include18
-rw-r--r--src/bench/bench.cpp7
-rw-r--r--src/bench/checkblock.cpp4
-rw-r--r--src/bitcoin-tx.cpp2
-rw-r--r--src/blockencodings.cpp14
-rw-r--r--src/blockencodings.h12
-rw-r--r--src/chainparams.cpp2
-rw-r--r--src/consensus/merkle.cpp6
-rw-r--r--src/core_memusage.h4
-rw-r--r--src/init.cpp4
-rw-r--r--src/main.cpp189
-rw-r--r--src/main.h14
-rw-r--r--src/merkleblock.cpp6
-rw-r--r--src/miner.cpp16
-rw-r--r--src/net.h2
-rw-r--r--src/policy/policy.cpp2
-rw-r--r--src/primitives/block.cpp2
-rw-r--r--src/primitives/block.h2
-rw-r--r--src/primitives/transaction.cpp4
-rw-r--r--src/primitives/transaction.h15
-rw-r--r--src/qt/bitcoingui.cpp10
-rw-r--r--src/qt/coincontroldialog.cpp43
-rw-r--r--src/qt/coincontroldialog.h38
-rw-r--r--src/qt/res/icons/network_disabled.pngbin591 -> 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.svg29
-rw-r--r--src/rpc/blockchain.cpp6
-rw-r--r--src/rpc/mining.cpp23
-rw-r--r--src/rpc/rawtransaction.cpp36
-rw-r--r--src/scheduler.cpp7
-rw-r--r--src/serialize.h59
-rw-r--r--src/test/blockencodings_tests.cpp63
-rw-r--r--src/test/data/bitcoin-util-test.json10
-rw-r--r--src/test/mempool_tests.cpp8
-rw-r--r--src/test/merkle_tests.cpp8
-rw-r--r--src/test/miner_tests.cpp37
-rw-r--r--src/test/pmt_tests.cpp4
-rw-r--r--src/test/policyestimator_tests.cpp14
-rw-r--r--src/test/test_bitcoin.cpp11
-rw-r--r--src/test/test_bitcoin.h4
-rw-r--r--src/txmempool.cpp26
-rw-r--r--src/txmempool.h16
-rw-r--r--src/wallet/test/wallet_tests.cpp2
-rw-r--r--src/wallet/wallet.cpp4
-rw-r--r--src/wallet/wallet.h6
62 files changed, 596 insertions, 412 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/configure.ac b/configure.ac
index 705327e816..319e1afe27 100644
--- a/configure.ac
+++ b/configure.ac
@@ -45,7 +45,6 @@ else
CXXFLAGS_overridden=no
fi
AC_PROG_CXX
-m4_ifdef([AC_PROG_OBJCXX],[AC_PROG_OBJCXX])
dnl By default, libtool for mingw refuses to link static libs into a dll for
dnl fear of mixing pic/non-pic objects, and import/export complications. Since
@@ -60,6 +59,15 @@ AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory])
dnl Check if -latomic is required for <std::atomic>
CHECK_ATOMIC
+dnl Unless the user specified OBJCXX, force it to be the same as CXX. This ensures
+dnl that we get the same -std flags for both.
+m4_ifdef([AC_PROG_OBJCXX],[
+if test "x${OBJCXX+set}" = "x"; then
+ OBJCXX="${CXX}"
+fi
+AC_PROG_OBJCXX
+])
+
dnl Libtool init checks.
LT_INIT([pic-only])
@@ -1126,3 +1134,28 @@ case ${OS} in
mv qa/pull-tester/tests_config-2.py qa/pull-tester/tests_config.py
;;
esac
+
+echo
+echo "Options used to compile and link:"
+echo " with wallet = $enable_wallet"
+echo " with gui / qt = $bitcoin_enable_qt"
+if test x$bitcoin_enable_qt != xno; then
+ echo " qt version = $bitcoin_qt_got_major_vers"
+ echo " with qr = $use_qr"
+fi
+echo " with zmq = $use_zmq"
+echo " with test = $use_tests"
+echo " with bench = $use_bench"
+echo " with upnp = $use_upnp"
+echo " debug enabled = $enable_debug"
+echo
+echo " target os = $TARGET_OS"
+echo " build os = $BUILD_OS"
+echo
+echo " CC = $CC"
+echo " CFLAGS = $CFLAGS"
+echo " CPPFLAGS = $CPPFLAGS"
+echo " CXX = $CXX"
+echo " CXXFLAGS = $CXXFLAGS"
+echo " LDFLAGS = $LDFLAGS"
+echo
diff --git a/doc/Doxyfile b/doc/Doxyfile
index a0cbf7139a..ef55acdbc3 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places.
# The default value is: My Project.
-PROJECT_NAME = Bitcoin
+PROJECT_NAME = "Bitcoin Core"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
diff --git a/doc/release-notes.md b/doc/release-notes.md
index f511fee22e..fe7f69d1f8 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -53,11 +53,15 @@ Removal of Priority Estimation
- Estimation of "priority" needed for a transaction to be included within a target
number of blocks has been removed. The rpc calls are deprecated and will either
- return -1 or 1e24 appropriately. The format for fee_estimates.dat has also
+ return -1 or 1e24 appropriately. The format for `fee_estimates.dat` has also
changed to no longer save these priority estimates. It will automatically be
converted to the new format which is not readable by prior versions of the
software.
+- The concept of "priority" transactions is planned to be removed in the next
+ major version. To prepare for this, the default for the rate limit of priority
+ transactions (`-limitfreerelay`) has been set to `0` kB/minute.
+
0.14.0 Change log
=================
diff --git a/qa/rpc-tests/p2p-compactblocks.py b/qa/rpc-tests/p2p-compactblocks.py
index 1b4c8d90e7..ab4b809ded 100755
--- a/qa/rpc-tests/p2p-compactblocks.py
+++ b/qa/rpc-tests/p2p-compactblocks.py
@@ -27,6 +27,7 @@ class TestNode(SingleNodeConnCB):
self.last_cmpctblock = None
self.block_announced = False
self.last_getdata = None
+ self.last_getheaders = None
self.last_getblocktxn = None
self.last_block = None
self.last_blocktxn = None
@@ -64,6 +65,9 @@ class TestNode(SingleNodeConnCB):
def on_getdata(self, conn, message):
self.last_getdata = message
+ def on_getheaders(self, conn, message):
+ self.last_getheaders = message
+
def on_getblocktxn(self, conn, message):
self.last_getblocktxn = message
@@ -186,12 +190,15 @@ class CompactBlocksTest(BitcoinTestFramework):
def check_announcement_of_new_block(node, peer, predicate):
peer.clear_block_announcement()
- node.generate(1)
- got_message = wait_until(lambda: peer.block_announced, timeout=30)
+ block_hash = int(node.generate(1)[0], 16)
+ peer.wait_for_block_announcement(block_hash, timeout=30)
assert(peer.block_announced)
assert(got_message)
+
with mininode_lock:
- assert(predicate(peer))
+ assert predicate(peer), (
+ "block_hash={!r}, cmpctblock={!r}, inv={!r}".format(
+ block_hash, peer.last_cmpctblock, peer.last_inv))
# We shouldn't get any block announcements via cmpctblock yet.
check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None)
@@ -393,6 +400,9 @@ class CompactBlocksTest(BitcoinTestFramework):
if announce == "inv":
test_node.send_message(msg_inv([CInv(2, block.sha256)]))
+ success = wait_until(lambda: test_node.last_getheaders is not None, timeout=30)
+ assert(success)
+ test_node.send_header_for_blocks([block])
else:
test_node.send_header_for_blocks([block])
success = wait_until(lambda: test_node.last_getdata is not None, timeout=30)
diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py
index 09ab1b80fc..6ecd84c3f0 100755
--- a/qa/rpc-tests/p2p-segwit.py
+++ b/qa/rpc-tests/p2p-segwit.py
@@ -64,6 +64,9 @@ class TestNode(NodeConnCB):
self.getdataset.add(inv.hash)
self.last_getdata = message
+ def on_getheaders(self, conn, message):
+ self.last_getheaders = message
+
def on_pong(self, conn, message):
self.last_pong = message
@@ -97,6 +100,10 @@ class TestNode(NodeConnCB):
test_function = lambda: self.last_getdata != None
self.sync(test_function, timeout)
+ def wait_for_getheaders(self, timeout=60):
+ test_function = lambda: self.last_getheaders != None
+ self.sync(test_function, timeout)
+
def wait_for_inv(self, expected_inv, timeout=60):
test_function = lambda: self.last_inv != expected_inv
self.sync(test_function, timeout)
@@ -111,12 +118,15 @@ class TestNode(NodeConnCB):
def announce_block_and_wait_for_getdata(self, block, use_header, timeout=60):
with mininode_lock:
self.last_getdata = None
+ self.last_getheaders = None
+ msg = msg_headers()
+ msg.headers = [ CBlockHeader(block) ]
if use_header:
- msg = msg_headers()
- msg.headers = [ CBlockHeader(block) ]
self.send_message(msg)
else:
self.send_message(msg_inv(inv=[CInv(2, block.sha256)]))
+ self.wait_for_getheaders()
+ self.send_message(msg)
self.wait_for_getdata()
return
diff --git a/qa/rpc-tests/proxy_test.py b/qa/rpc-tests/proxy_test.py
index 27160cae07..9ccc0ffbb0 100755
--- a/qa/rpc-tests/proxy_test.py
+++ b/qa/rpc-tests/proxy_test.py
@@ -4,10 +4,16 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
import socket
+import os
from test_framework.socks5 import Socks5Configuration, Socks5Command, Socks5Server, AddressType
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
+from test_framework.util import (
+ PORT_MIN,
+ PORT_RANGE,
+ start_nodes,
+ assert_equal,
+)
from test_framework.netutil import test_ipv6_local
'''
Test plan:
@@ -33,6 +39,8 @@ addnode connect to onion
addnode connect to generic DNS name
'''
+RANGE_BEGIN = PORT_MIN + 2 * PORT_RANGE # Start after p2p and rpc ports
+
class ProxyTest(BitcoinTestFramework):
def __init__(self):
@@ -44,19 +52,19 @@ class ProxyTest(BitcoinTestFramework):
# Create two proxies on different ports
# ... one unauthenticated
self.conf1 = Socks5Configuration()
- self.conf1.addr = ('127.0.0.1', 13000 + (os.getpid() % 1000))
+ self.conf1.addr = ('127.0.0.1', RANGE_BEGIN + (os.getpid() % 1000))
self.conf1.unauth = True
self.conf1.auth = False
# ... one supporting authenticated and unauthenticated (Tor)
self.conf2 = Socks5Configuration()
- self.conf2.addr = ('127.0.0.1', 14000 + (os.getpid() % 1000))
+ self.conf2.addr = ('127.0.0.1', RANGE_BEGIN + 1000 + (os.getpid() % 1000))
self.conf2.unauth = True
self.conf2.auth = True
if self.have_ipv6:
# ... one on IPv6 with similar configuration
self.conf3 = Socks5Configuration()
self.conf3.af = socket.AF_INET6
- self.conf3.addr = ('::1', 15000 + (os.getpid() % 1000))
+ self.conf3.addr = ('::1', RANGE_BEGIN + 2000 + (os.getpid() % 1000))
self.conf3.unauth = True
self.conf3.auth = True
else:
diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py
index ab6d2e8def..33a6f2b0cc 100755
--- a/qa/rpc-tests/rawtransactions.py
+++ b/qa/rpc-tests/rawtransactions.py
@@ -2,11 +2,15 @@
# Copyright (c) 2014-2016 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""rawtranscation RPCs QA test.
-#
-# Test re-org scenarios with a mempool that contains transactions
-# that spend (directly or indirectly) coinbase transactions.
-#
+# Tests the following RPCs:
+# - createrawtransaction
+# - signrawtransaction
+# - sendrawtransaction
+# - decoderawtransaction
+# - getrawtransaction
+"""
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
@@ -138,6 +142,33 @@ class RawTransactionsTest(BitcoinTestFramework):
self.sync_all()
assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx
+ # getrawtransaction tests
+ # 1. valid parameters - only supply txid
+ txHash = rawTx["hash"]
+ assert_equal(self.nodes[0].getrawtransaction(txHash), rawTxSigned['hex'])
+
+ # 2. valid parameters - supply txid and 0 for non-verbose
+ assert_equal(self.nodes[0].getrawtransaction(txHash, 0), rawTxSigned['hex'])
+
+ # 3. valid parameters - supply txid and False for non-verbose
+ assert_equal(self.nodes[0].getrawtransaction(txHash, False), rawTxSigned['hex'])
+
+ # 4. valid parameters - supply txid and 1 for verbose.
+ # We only check the "hex" field of the output so we don't need to update this test every time the output format changes.
+ assert_equal(self.nodes[0].getrawtransaction(txHash, 1)["hex"], rawTxSigned['hex'])
+
+ # 5. valid parameters - supply txid and True for non-verbose
+ assert_equal(self.nodes[0].getrawtransaction(txHash, True)["hex"], rawTxSigned['hex'])
+
+ # 6. invalid parameters - supply txid and string "Flase"
+ assert_raises(JSONRPCException, self.nodes[0].getrawtransaction, txHash, "Flase")
+
+ # 7. invalid parameters - supply txid and empty array
+ assert_raises(JSONRPCException, self.nodes[0].getrawtransaction, txHash, [])
+
+ # 8. invalid parameters - supply txid and empty dict
+ assert_raises(JSONRPCException, self.nodes[0].getrawtransaction, txHash, {})
+
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 1000}]
outputs = { self.nodes[0].getnewaddress() : 1 }
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
diff --git a/qa/rpc-tests/sendheaders.py b/qa/rpc-tests/sendheaders.py
index 81b2442e6a..37b98c576e 100755
--- a/qa/rpc-tests/sendheaders.py
+++ b/qa/rpc-tests/sendheaders.py
@@ -348,14 +348,13 @@ class SendHeadersTest(BitcoinTestFramework):
if j == 0:
# Announce via inv
test_node.send_block_inv(tip)
- test_node.wait_for_getdata([tip], timeout=5)
+ test_node.wait_for_getheaders(timeout=5)
+ # Should have received a getheaders now
+ test_node.send_header_for_blocks(blocks)
# Test that duplicate inv's won't result in duplicate
# getdata requests, or duplicate headers announcements
- inv_node.send_block_inv(tip)
- # Should have received a getheaders as well!
- test_node.send_header_for_blocks(blocks)
- test_node.wait_for_getdata([x.sha256 for x in blocks[0:-1]], timeout=5)
- [ inv_node.send_block_inv(x.sha256) for x in blocks[0:-1] ]
+ [ inv_node.send_block_inv(x.sha256) for x in blocks ]
+ test_node.wait_for_getdata([x.sha256 for x in blocks], timeout=5)
inv_node.sync_with_ping()
else:
# Announce via headers
diff --git a/qa/rpc-tests/test_framework/comptool.py b/qa/rpc-tests/test_framework/comptool.py
index 7c92d3f828..17679fc7e1 100755
--- a/qa/rpc-tests/test_framework/comptool.py
+++ b/qa/rpc-tests/test_framework/comptool.py
@@ -111,6 +111,11 @@ class TestNode(NodeConnCB):
m.locator = self.block_store.get_locator(self.bestblockhash)
self.conn.send_message(m)
+ def send_header(self, header):
+ m = msg_headers()
+ m.headers.append(header)
+ self.conn.send_message(m)
+
# This assumes BIP31
def send_ping(self, nonce):
self.pingMap[nonce] = True
@@ -345,8 +350,16 @@ class TestManager(object):
# Either send inv's to each node and sync, or add
# to invqueue for later inv'ing.
if (test_instance.sync_every_block):
- [ c.cb.send_inv(block) for c in self.connections ]
- self.sync_blocks(block.sha256, 1)
+ # if we expect success, send inv and sync every block
+ # if we expect failure, just push the block and see what happens.
+ if outcome == True:
+ [ c.cb.send_inv(block) for c in self.connections ]
+ self.sync_blocks(block.sha256, 1)
+ else:
+ [ c.send_message(msg_block(block)) for c in self.connections ]
+ [ c.cb.send_ping(self.ping_counter) for c in self.connections ]
+ self.wait_for_pings(self.ping_counter)
+ self.ping_counter += 1
if (not self.check_results(tip, outcome)):
raise AssertionError("Test failed at test %d" % test_number)
else:
@@ -354,6 +367,8 @@ class TestManager(object):
elif isinstance(b_or_t, CBlockHeader):
block_header = b_or_t
self.block_store.add_header(block_header)
+ [ c.cb.send_header(block_header) for c in self.connections ]
+
else: # Tx test runner
assert(isinstance(b_or_t, CTransaction))
tx = b_or_t
diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py
index b5ef0689b4..0b3585c6b2 100644
--- a/qa/rpc-tests/test_framework/util.py
+++ b/qa/rpc-tests/test_framework/util.py
@@ -123,19 +123,26 @@ def str_to_b64str(string):
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:
+ 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 tips == [tips[0]] * len(tips):
+ if all(t == tips[0] for t in tips):
return
- if heights == [heights[0]] * len(heights):
- raise AssertionError("Block sync failed: (Hashes don't match)")
- timeout -= wait
+ 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 with heights: {}".format(heights))
+ 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, timeout=60):
"""
@@ -524,10 +531,14 @@ def assert_greater_than(thing1, thing2):
raise AssertionError("%s <= %s"%(str(thing1),str(thing2)))
def assert_raises(exc, fun, *args, **kwds):
+ assert_raises_message(exc, None, fun, *args, **kwds)
+
+def assert_raises_message(exc, message, fun, *args, **kwds):
try:
fun(*args, **kwds)
- except exc:
- pass
+ except exc as e:
+ if message is not None and message not in e.error['message']:
+ raise AssertionError("Expected substring not found:"+e.error['message'])
except Exception as e:
raise AssertionError("Unexpected exception raised: "+type(e).__name__)
else:
diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py
index e43f6ea5d2..3c0dc0f4ea 100755
--- a/qa/rpc-tests/wallet.py
+++ b/qa/rpc-tests/wallet.py
@@ -71,7 +71,7 @@ class WalletTest (BitcoinTestFramework):
unspent_0 = self.nodes[2].listunspent()[0]
unspent_0 = {"txid": unspent_0["txid"], "vout": unspent_0["vout"]}
self.nodes[2].lockunspent(False, [unspent_0])
- assert_raises(JSONRPCException, self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 20)
+ assert_raises_message(JSONRPCException, "Insufficient funds", self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 20)
assert_equal([unspent_0], self.nodes[2].listlockunspent())
self.nodes[2].lockunspent(True, [unspent_0])
assert_equal(len(self.nodes[2].listlockunspent()), 0)
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index 840d33c1b5..246797a1b2 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -67,7 +67,9 @@ bitcoin_bench_clean : FORCE
%.raw.h: %.raw
@$(MKDIR_P) $(@D)
- @echo "static unsigned const char $(*F)[] = {" >> $@
- @$(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' >> $@
- @echo "};" >> $@
+ @{ \
+ echo "static unsigned const char $(*F)[] = {" && \
+ $(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' && \
+ echo "};"; \
+ } > "$@.new" && mv -f "$@.new" "$@"
@echo "Generated $@"
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index fa610e300c..a14adc7876 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -149,16 +149,10 @@ endif
%.json.h: %.json
@$(MKDIR_P) $(@D)
- @echo "namespace json_tests{" > $@
- @echo "static unsigned const char $(*F)[] = {" >> $@
- @$(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' >> $@
- @echo "};};" >> $@
- @echo "Generated $@"
-
-%.raw.h: %.raw
- @$(MKDIR_P) $(@D)
- @echo "namespace alert_tests{" > $@
- @echo "static unsigned const char $(*F)[] = {" >> $@
- @$(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' >> $@
- @echo "};};" >> $@
+ @{ \
+ echo "namespace json_tests{" && \
+ echo "static unsigned const char $(*F)[] = {" && \
+ $(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' && \
+ echo "};};"; \
+ } > "$@.new" && mv -f "$@.new" "$@"
@echo "Generated $@"
diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp
index 227546a7a7..8942da8c74 100644
--- a/src/bench/bench.cpp
+++ b/src/bench/bench.cpp
@@ -64,8 +64,11 @@ bool State::KeepRunning()
return true;
}
if (elapsed*16 < maxElapsed) {
- countMask = ((countMask<<1)|1) & ((1LL<<60)-1);
- countMaskInv = 1./(countMask+1);
+ uint64_t newCountMask = ((countMask<<1)|1) & ((1LL<<60)-1);
+ if ((count & newCountMask)==0) {
+ countMask = newCountMask;
+ countMaskInv = 1./(countMask+1);
+ }
}
}
lastTime = now;
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 6c66efcc9c..6d17bc392f 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -638,7 +638,7 @@ static int CommandLineRawTx(int argc, char* argv[])
if (strHexTx == "-") // "-" implies standard input
strHexTx = readStdin();
- if (!DecodeHexTx(txDecodeTmp, strHexTx))
+ if (!DecodeHexTx(txDecodeTmp, strHexTx, true))
throw runtime_error("invalid transaction encoding");
startArg = 2;
diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp
index dbed90583d..f14ae1c412 100644
--- a/src/blockencodings.cpp
+++ b/src/blockencodings.cpp
@@ -24,7 +24,7 @@ CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block, bool f
//TODO: Use our mempool prior to block acceptance to predictively fill more than just the coinbase
prefilledtxn[0] = {0, block.vtx[0]};
for (size_t i = 1; i < block.vtx.size(); i++) {
- const CTransaction& tx = block.vtx[i];
+ const CTransaction& tx = *block.vtx[i];
shorttxids[i - 1] = GetShortID(fUseWTXID ? tx.GetWitnessHash() : tx.GetHash());
}
}
@@ -59,7 +59,7 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c
int32_t lastprefilledindex = -1;
for (size_t i = 0; i < cmpctblock.prefilledtxn.size(); i++) {
- if (cmpctblock.prefilledtxn[i].tx.IsNull())
+ if (cmpctblock.prefilledtxn[i].tx->IsNull())
return READ_STATUS_INVALID;
lastprefilledindex += cmpctblock.prefilledtxn[i].index + 1; //index is a uint16_t, so cant overflow here
@@ -71,7 +71,7 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c
// have neither a prefilled txn or a shorttxid!
return READ_STATUS_INVALID;
}
- txn_available[lastprefilledindex] = std::make_shared<CTransaction>(cmpctblock.prefilledtxn[i].tx);
+ txn_available[lastprefilledindex] = cmpctblock.prefilledtxn[i].tx;
}
prefilled_count = cmpctblock.prefilledtxn.size();
@@ -142,7 +142,7 @@ bool PartiallyDownloadedBlock::IsTxAvailable(size_t index) const {
return txn_available[index] ? true : false;
}
-ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<CTransaction>& vtx_missing) const {
+ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing) const {
assert(!header.IsNull());
block = header;
block.vtx.resize(txn_available.size());
@@ -154,7 +154,7 @@ ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<
return READ_STATUS_INVALID;
block.vtx[i] = vtx_missing[tx_missing_offset++];
} else
- block.vtx[i] = *txn_available[i];
+ block.vtx[i] = txn_available[i];
}
if (vtx_missing.size() != tx_missing_offset)
return READ_STATUS_INVALID;
@@ -172,8 +172,8 @@ ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<
LogPrint("cmpctblock", "Successfully reconstructed block %s with %lu txn prefilled, %lu txn from mempool and %lu txn requested\n", header.GetHash().ToString(), prefilled_count, mempool_count, vtx_missing.size());
if (vtx_missing.size() < 5) {
- for(const CTransaction& tx : vtx_missing)
- LogPrint("cmpctblock", "Reconstructed block %s required tx %s\n", header.GetHash().ToString(), tx.GetHash().ToString());
+ for (const auto& tx : vtx_missing)
+ LogPrint("cmpctblock", "Reconstructed block %s required tx %s\n", header.GetHash().ToString(), tx->GetHash().ToString());
}
return READ_STATUS_OK;
diff --git a/src/blockencodings.h b/src/blockencodings.h
index 1f9491867a..27baf1f8f8 100644
--- a/src/blockencodings.h
+++ b/src/blockencodings.h
@@ -14,9 +14,9 @@ class CTxMemPool;
// Dumb helper to handle CTransaction compression at serialize-time
struct TransactionCompressor {
private:
- CTransaction& tx;
+ CTransactionRef& tx;
public:
- TransactionCompressor(CTransaction& txIn) : tx(txIn) {}
+ TransactionCompressor(CTransactionRef& txIn) : tx(txIn) {}
ADD_SERIALIZE_METHODS;
@@ -72,7 +72,7 @@ class BlockTransactions {
public:
// A BlockTransactions message
uint256 blockhash;
- std::vector<CTransaction> txn;
+ std::vector<CTransactionRef> txn;
BlockTransactions() {}
BlockTransactions(const BlockTransactionsRequest& req) :
@@ -104,7 +104,7 @@ struct PrefilledTransaction {
// Used as an offset since last prefilled tx in CBlockHeaderAndShortTxIDs,
// as a proper transaction-in-block-index in PartiallyDownloadedBlock
uint16_t index;
- CTransaction tx;
+ CTransactionRef tx;
ADD_SERIALIZE_METHODS;
@@ -193,7 +193,7 @@ public:
class PartiallyDownloadedBlock {
protected:
- std::vector<std::shared_ptr<const CTransaction> > txn_available;
+ std::vector<CTransactionRef> txn_available;
size_t prefilled_count = 0, mempool_count = 0;
CTxMemPool* pool;
public:
@@ -202,7 +202,7 @@ public:
ReadStatus InitData(const CBlockHeaderAndShortTxIDs& cmpctblock);
bool IsTxAvailable(size_t index) const;
- ReadStatus FillBlock(CBlock& block, const std::vector<CTransaction>& vtx_missing) const;
+ ReadStatus FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing) const;
};
#endif
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index a57ab632e4..3b3c0a5d3e 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -31,7 +31,7 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi
genesis.nBits = nBits;
genesis.nNonce = nNonce;
genesis.nVersion = nVersion;
- genesis.vtx.push_back(txNew);
+ genesis.vtx.push_back(MakeTransactionRef(std::move(txNew)));
genesis.hashPrevBlock.SetNull();
genesis.hashMerkleRoot = BlockMerkleRoot(genesis);
return genesis;
diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp
index 35f7d2e05a..6fa96ddf45 100644
--- a/src/consensus/merkle.cpp
+++ b/src/consensus/merkle.cpp
@@ -160,7 +160,7 @@ uint256 BlockMerkleRoot(const CBlock& block, bool* mutated)
std::vector<uint256> leaves;
leaves.resize(block.vtx.size());
for (size_t s = 0; s < block.vtx.size(); s++) {
- leaves[s] = block.vtx[s].GetHash();
+ leaves[s] = block.vtx[s]->GetHash();
}
return ComputeMerkleRoot(leaves, mutated);
}
@@ -171,7 +171,7 @@ uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated)
leaves.resize(block.vtx.size());
leaves[0].SetNull(); // The witness hash of the coinbase is 0.
for (size_t s = 1; s < block.vtx.size(); s++) {
- leaves[s] = block.vtx[s].GetWitnessHash();
+ leaves[s] = block.vtx[s]->GetWitnessHash();
}
return ComputeMerkleRoot(leaves, mutated);
}
@@ -181,7 +181,7 @@ std::vector<uint256> BlockMerkleBranch(const CBlock& block, uint32_t position)
std::vector<uint256> leaves;
leaves.resize(block.vtx.size());
for (size_t s = 0; s < block.vtx.size(); s++) {
- leaves[s] = block.vtx[s].GetHash();
+ leaves[s] = block.vtx[s]->GetHash();
}
return ComputeMerkleBranch(leaves, position);
}
diff --git a/src/core_memusage.h b/src/core_memusage.h
index b8e0f08bbf..0dcc24c40c 100644
--- a/src/core_memusage.h
+++ b/src/core_memusage.h
@@ -69,8 +69,8 @@ static inline size_t RecursiveDynamicUsage(const CMutableTransaction& tx) {
static inline size_t RecursiveDynamicUsage(const CBlock& block) {
size_t mem = memusage::DynamicUsage(block.vtx);
- for (std::vector<CTransaction>::const_iterator it = block.vtx.begin(); it != block.vtx.end(); it++) {
- mem += RecursiveDynamicUsage(*it);
+ for (const auto& tx : block.vtx) {
+ mem += memusage::DynamicUsage(tx) + RecursiveDynamicUsage(*tx);
}
return mem;
}
diff --git a/src/init.cpp b/src/init.cpp
index 8c93d34268..ca5437fb91 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -601,6 +601,8 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles)
{
const CChainParams& chainparams = Params();
RenameThread("bitcoin-loadblk");
+
+ {
CImportingNow imp;
// -reindex
@@ -660,7 +662,7 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles)
LogPrintf("Stopping after block import\n");
StartShutdown();
}
-
+ } // End scope of CImportingNow
LoadMempool();
}
diff --git a/src/main.cpp b/src/main.cpp
index e868e3c5f9..4293a6bebf 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -233,7 +233,7 @@ namespace {
int nPeersWithValidatedDownloads = 0;
/** Relay map, protected by cs_main. */
- typedef std::map<uint256, std::shared_ptr<const CTransaction>> MapRelay;
+ typedef std::map<uint256, CTransactionRef> MapRelay;
MapRelay mapRelay;
/** Expiration-time ordered list of (expire time, relay map entry) pairs, protected by cs_main). */
std::deque<std::pair<int64_t, MapRelay::iterator>> vRelayExpiration;
@@ -1639,7 +1639,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::P
LOCK(cs_main);
- std::shared_ptr<const CTransaction> ptx = mempool.get(hash);
+ CTransactionRef ptx = mempool.get(hash);
if (ptx)
{
txOut = *ptx;
@@ -1682,9 +1682,9 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::P
if (pindexSlow) {
CBlock block;
if (ReadBlockFromDisk(block, pindexSlow, consensusParams)) {
- BOOST_FOREACH(const CTransaction &tx, block.vtx) {
- if (tx.GetHash() == hash) {
- txOut = tx;
+ for (const auto& tx : block.vtx) {
+ if (tx->GetHash() == hash) {
+ txOut = *tx;
hashBlock = pindexSlow->GetBlockHash();
return true;
}
@@ -2223,7 +2223,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
// undo transactions in reverse order
for (int i = block.vtx.size() - 1; i >= 0; i--) {
- const CTransaction &tx = block.vtx[i];
+ const CTransaction &tx = *(block.vtx[i]);
uint256 hash = tx.GetHash();
// Check that all outputs are available and match the outputs in the block itself
@@ -2417,8 +2417,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
fEnforceBIP30 = fEnforceBIP30 && (!pindexBIP34height || !(pindexBIP34height->GetBlockHash() == chainparams.GetConsensus().BIP34Hash));
if (fEnforceBIP30) {
- BOOST_FOREACH(const CTransaction& tx, block.vtx) {
- const CCoins* coins = view.AccessCoins(tx.GetHash());
+ for (const auto& tx : block.vtx) {
+ const CCoins* coins = view.AccessCoins(tx->GetHash());
if (coins && !coins->IsPruned())
return state.DoS(100, error("ConnectBlock(): tried to overwrite transaction"),
REJECT_INVALID, "bad-txns-BIP30");
@@ -2474,7 +2474,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated
for (unsigned int i = 0; i < block.vtx.size(); i++)
{
- const CTransaction &tx = block.vtx[i];
+ const CTransaction &tx = *(block.vtx[i]);
nInputs += tx.vin.size();
@@ -2544,10 +2544,10 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime3 - nTime2), 0.001 * (nTime3 - nTime2) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime3 - nTime2) / (nInputs-1), nTimeConnect * 0.000001);
CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus());
- if (block.vtx[0].GetValueOut() > blockReward)
+ if (block.vtx[0]->GetValueOut() > blockReward)
return state.DoS(100,
error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)",
- block.vtx[0].GetValueOut(), blockReward),
+ block.vtx[0]->GetValueOut(), blockReward),
REJECT_INVALID, "bad-cb-amount");
if (!control.Wait())
@@ -2590,7 +2590,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
// Watch for changes to the previous coinbase transaction.
static uint256 hashPrevBestCoinBase;
GetMainSignals().UpdatedTransaction(hashPrevBestCoinBase);
- hashPrevBestCoinBase = block.vtx[0].GetHash();
+ hashPrevBestCoinBase = block.vtx[0]->GetHash();
// Erase orphan transactions include or precluded by this block
if (vOrphanErase.size()) {
@@ -2807,7 +2807,8 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
if (!fBare) {
// Resurrect mempool transactions from the disconnected block.
std::vector<uint256> vHashUpdate;
- BOOST_FOREACH(const CTransaction &tx, block.vtx) {
+ for (const auto& it : block.vtx) {
+ const CTransaction& tx = *it;
// ignore validation errors in resurrected transactions
CValidationState stateDummy;
if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, true)) {
@@ -2828,8 +2829,8 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
UpdateTip(pindexDelete->pprev, chainparams);
// Let wallets know transactions went from 1-confirmed to
// 0-confirmed or conflicted:
- BOOST_FOREACH(const CTransaction &tx, block.vtx) {
- GetMainSignals().SyncTransaction(tx, pindexDelete->pprev, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
+ for (const auto& tx : block.vtx) {
+ GetMainSignals().SyncTransaction(*tx, pindexDelete->pprev, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
}
return true;
}
@@ -2844,7 +2845,7 @@ static int64_t nTimePostConnect = 0;
* Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
* corresponding to pindexNew, to bypass loading it again from disk.
*/
-bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const CBlock* pblock, std::vector<std::shared_ptr<const CTransaction>> &txConflicted, std::vector<std::tuple<CTransaction,CBlockIndex*,int>> &txChanged)
+bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const CBlock* pblock, std::vector<CTransactionRef> &txConflicted, std::vector<std::tuple<CTransactionRef,CBlockIndex*,int>> &txChanged)
{
assert(pindexNew->pprev == chainActive.Tip());
// Read block from disk.
@@ -2884,7 +2885,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
// Update chainActive & related variables.
UpdateTip(pindexNew, chainparams);
- for(unsigned int i=0; i < pblock->vtx.size(); i++)
+ for (unsigned int i=0; i < pblock->vtx.size(); i++)
txChanged.emplace_back(pblock->vtx[i], pindexNew, i);
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
@@ -2967,7 +2968,7 @@ static void PruneBlockIndexCandidates() {
* Try to make some progress towards making pindexMostWork the active block.
* pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
*/
-static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const CBlock* pblock, bool& fInvalidFound, std::vector<std::shared_ptr<const CTransaction>>& txConflicted, std::vector<std::tuple<CTransaction,CBlockIndex*,int>>& txChanged)
+static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const CBlock* pblock, bool& fInvalidFound, std::vector<CTransactionRef>& txConflicted, std::vector<std::tuple<CTransactionRef,CBlockIndex*,int>>& txChanged)
{
AssertLockHeld(cs_main);
const CBlockIndex *pindexOldTip = chainActive.Tip();
@@ -3068,7 +3069,7 @@ static void NotifyHeaderTip() {
bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, const CBlock *pblock) {
CBlockIndex *pindexMostWork = NULL;
CBlockIndex *pindexNewTip = NULL;
- std::vector<std::tuple<CTransaction,CBlockIndex*,int>> txChanged;
+ std::vector<std::tuple<CTransactionRef,CBlockIndex*,int>> txChanged;
if (pblock)
txChanged.reserve(pblock->vtx.size());
do {
@@ -3078,7 +3079,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
break;
const CBlockIndex *pindexFork;
- std::vector<std::shared_ptr<const CTransaction>> txConflicted;
+ std::vector<CTransactionRef> txConflicted;
bool fInitialDownload;
{
LOCK(cs_main);
@@ -3109,13 +3110,13 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
// throw all transactions though the signal-interface
// while _not_ holding the cs_main lock
- for(std::shared_ptr<const CTransaction> tx : txConflicted)
+ for (const auto& tx : txConflicted)
{
GetMainSignals().SyncTransaction(*tx, pindexNewTip, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
}
// ... and about transactions that got confirmed:
- for(unsigned int i = 0; i < txChanged.size(); i++)
- GetMainSignals().SyncTransaction(std::get<0>(txChanged[i]), std::get<1>(txChanged[i]), std::get<2>(txChanged[i]));
+ for (unsigned int i = 0; i < txChanged.size(); i++)
+ GetMainSignals().SyncTransaction(*std::get<0>(txChanged[i]), std::get<1>(txChanged[i]), std::get<2>(txChanged[i]));
// Notify external listeners about the new tip.
GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload);
@@ -3454,22 +3455,22 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
return state.DoS(100, false, REJECT_INVALID, "bad-blk-length", false, "size limits failed");
// First transaction must be coinbase, the rest must not be
- if (block.vtx.empty() || !block.vtx[0].IsCoinBase())
+ if (block.vtx.empty() || !block.vtx[0]->IsCoinBase())
return state.DoS(100, false, REJECT_INVALID, "bad-cb-missing", false, "first tx is not coinbase");
for (unsigned int i = 1; i < block.vtx.size(); i++)
- if (block.vtx[i].IsCoinBase())
+ if (block.vtx[i]->IsCoinBase())
return state.DoS(100, false, REJECT_INVALID, "bad-cb-multiple", false, "more than one coinbase");
// Check transactions
for (const auto& tx : block.vtx)
- if (!CheckTransaction(tx, state, false))
+ 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()));
+ strprintf("Transaction check failed (tx hash %s) %s", tx->GetHash().ToString(), state.GetDebugMessage()));
unsigned int nSigOps = 0;
for (const auto& tx : block.vtx)
{
- nSigOps += GetLegacySigOpCount(tx);
+ nSigOps += GetLegacySigOpCount(*tx);
}
if (nSigOps * WITNESS_SCALE_FACTOR > MAX_BLOCK_SIGOPS_COST)
return state.DoS(100, false, REJECT_INVALID, "bad-blk-sigops", false, "out-of-bounds SigOpCount");
@@ -3505,8 +3506,8 @@ bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& pa
static int GetWitnessCommitmentIndex(const CBlock& block)
{
int commitpos = -1;
- for (size_t o = 0; o < block.vtx[0].vout.size(); o++) {
- if (block.vtx[0].vout[o].scriptPubKey.size() >= 38 && block.vtx[0].vout[o].scriptPubKey[0] == OP_RETURN && block.vtx[0].vout[o].scriptPubKey[1] == 0x24 && block.vtx[0].vout[o].scriptPubKey[2] == 0xaa && block.vtx[0].vout[o].scriptPubKey[3] == 0x21 && block.vtx[0].vout[o].scriptPubKey[4] == 0xa9 && block.vtx[0].vout[o].scriptPubKey[5] == 0xed) {
+ for (size_t o = 0; o < block.vtx[0]->vout.size(); o++) {
+ if (block.vtx[0]->vout[o].scriptPubKey.size() >= 38 && block.vtx[0]->vout[o].scriptPubKey[0] == OP_RETURN && block.vtx[0]->vout[o].scriptPubKey[1] == 0x24 && block.vtx[0]->vout[o].scriptPubKey[2] == 0xaa && block.vtx[0]->vout[o].scriptPubKey[3] == 0x21 && block.vtx[0]->vout[o].scriptPubKey[4] == 0xa9 && block.vtx[0]->vout[o].scriptPubKey[5] == 0xed) {
commitpos = o;
}
}
@@ -3517,10 +3518,12 @@ void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPr
{
int commitpos = GetWitnessCommitmentIndex(block);
static const std::vector<unsigned char> nonce(32, 0x00);
- if (commitpos != -1 && IsWitnessEnabled(pindexPrev, consensusParams) && block.vtx[0].wit.IsEmpty()) {
- block.vtx[0].wit.vtxinwit.resize(1);
- block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.resize(1);
- block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0] = nonce;
+ if (commitpos != -1 && IsWitnessEnabled(pindexPrev, consensusParams) && block.vtx[0]->wit.IsEmpty()) {
+ CMutableTransaction tx(*block.vtx[0]);
+ tx.wit.vtxinwit.resize(1);
+ tx.wit.vtxinwit[0].scriptWitness.stack.resize(1);
+ tx.wit.vtxinwit[0].scriptWitness.stack[0] = nonce;
+ block.vtx[0] = MakeTransactionRef(std::move(tx));
}
}
@@ -3530,7 +3533,7 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
int commitpos = GetWitnessCommitmentIndex(block);
bool fHaveWitness = false;
for (size_t t = 1; t < block.vtx.size(); t++) {
- if (!block.vtx[t].wit.IsNull()) {
+ if (!block.vtx[t]->wit.IsNull()) {
fHaveWitness = true;
break;
}
@@ -3551,8 +3554,8 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
out.scriptPubKey[5] = 0xed;
memcpy(&out.scriptPubKey[6], witnessroot.begin(), 32);
commitment = std::vector<unsigned char>(out.scriptPubKey.begin(), out.scriptPubKey.end());
- const_cast<std::vector<CTxOut>*>(&block.vtx[0].vout)->push_back(out);
- block.vtx[0].UpdateHash();
+ const_cast<std::vector<CTxOut>*>(&block.vtx[0]->vout)->push_back(out);
+ block.vtx[0]->UpdateHash();
}
}
UpdateUncommittedBlockStructures(block, pindexPrev, consensusParams);
@@ -3601,7 +3604,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co
// Check that all transactions are finalized
for (const auto& tx : block.vtx) {
- if (!IsFinalTx(tx, nHeight, nLockTimeCutoff)) {
+ if (!IsFinalTx(*tx, nHeight, nLockTimeCutoff)) {
return state.DoS(10, false, REJECT_INVALID, "bad-txns-nonfinal", false, "non-final transaction");
}
}
@@ -3610,8 +3613,8 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co
if (nHeight >= consensusParams.BIP34Height)
{
CScript expect = CScript() << nHeight;
- if (block.vtx[0].vin[0].scriptSig.size() < expect.size() ||
- !std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin())) {
+ if (block.vtx[0]->vin[0].scriptSig.size() < expect.size() ||
+ !std::equal(expect.begin(), expect.end(), block.vtx[0]->vin[0].scriptSig.begin())) {
return state.DoS(100, false, REJECT_INVALID, "bad-cb-height", false, "block height mismatch in coinbase");
}
}
@@ -3633,11 +3636,11 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co
// The malleation check is ignored; as the transaction tree itself
// already does not permit it, it is impossible to trigger in the
// witness tree.
- if (block.vtx[0].wit.vtxinwit.size() != 1 || block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.size() != 1 || block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0].size() != 32) {
+ if (block.vtx[0]->wit.vtxinwit.size() != 1 || block.vtx[0]->wit.vtxinwit[0].scriptWitness.stack.size() != 1 || block.vtx[0]->wit.vtxinwit[0].scriptWitness.stack[0].size() != 32) {
return state.DoS(100, false, REJECT_INVALID, "bad-witness-nonce-size", true, strprintf("%s : invalid witness nonce size", __func__));
}
- CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin());
- if (memcmp(hashWitness.begin(), &block.vtx[0].vout[commitpos].scriptPubKey[6], 32)) {
+ CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0]->wit.vtxinwit[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin());
+ if (memcmp(hashWitness.begin(), &block.vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
return state.DoS(100, false, REJECT_INVALID, "bad-witness-merkle-match", true, strprintf("%s : witness merkle commitment mismatch", __func__));
}
fHaveWitness = true;
@@ -3647,7 +3650,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co
// No witness data is allowed in blocks that don't commit to witness data, as this would otherwise leave room for spam
if (!fHaveWitness) {
for (size_t i = 0; i < block.vtx.size(); i++) {
- if (!block.vtx[i].wit.IsNull()) {
+ if (!block.vtx[i]->wit.IsNull()) {
return state.DoS(100, false, REJECT_INVALID, "unexpected-witness", true, strprintf("%s : unexpected witness data found", __func__));
}
}
@@ -3788,26 +3791,26 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
return true;
}
-bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool fMayBanPeerIfInvalid)
+bool ProcessNewBlock(const CChainParams& chainparams, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool *fNewBlock)
{
{
LOCK(cs_main);
// Store to disk
CBlockIndex *pindex = NULL;
- bool fNewBlock = false;
- bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fForceProcessing, dbp, &fNewBlock);
- if (pindex && pfrom) {
- mapBlockSource[pindex->GetBlockHash()] = std::make_pair(pfrom->GetId(), fMayBanPeerIfInvalid);
- if (fNewBlock) pfrom->nLastBlockTime = GetTime();
- }
+ if (fNewBlock) *fNewBlock = false;
+ CValidationState state;
+ bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fForceProcessing, dbp, fNewBlock);
CheckBlockIndex(chainparams.GetConsensus());
- if (!ret)
+ if (!ret) {
+ GetMainSignals().BlockChecked(*pblock, state);
return error("%s: AcceptBlock FAILED", __func__);
+ }
}
NotifyHeaderTip();
+ CValidationState state; // Only used to report errors, not invalidity - ignore it
if (!ActivateBestChain(state, chainparams, pblock))
return error("%s: ActivateBestChain failed", __func__);
@@ -4953,7 +4956,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// however we MUST always provide at least what the remote peer needs
typedef std::pair<unsigned int, uint256> PairType;
BOOST_FOREACH(PairType& pair, merkleBlock.vMatchedTxn)
- connman.PushMessageWithFlag(pfrom, SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, block.vtx[pair.first]);
+ connman.PushMessageWithFlag(pfrom, SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *block.vtx[pair.first]);
}
// else
// no response
@@ -5367,28 +5370,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (inv.type == MSG_BLOCK) {
UpdateBlockAvailability(pfrom->GetId(), inv.hash);
if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) {
- // First request the headers preceding the announced block. In the normal fully-synced
- // case where a new block is announced that succeeds the current tip (no reorganization),
- // there are no such headers.
- // Secondly, and only when we are close to being synced, we request the announced block directly,
- // to avoid an extra round-trip. Note that we must *first* ask for the headers, so by the
- // time the block arrives, the header chain leading up to it is already validated. Not
- // doing this will result in the received block being rejected as an orphan in case it is
- // not a direct successor.
+ // We used to request the full block here, but since headers-announcements are now the
+ // primary method of announcement on the network, and since, in the case that a node
+ // fell back to inv we probably have a reorg which we should get the headers for first,
+ // we now only provide a getheaders response here. When we receive the headers, we will
+ // then ask for the blocks we need.
connman.PushMessage(pfrom, NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash);
- CNodeState *nodestate = State(pfrom->GetId());
- if (CanDirectFetch(chainparams.GetConsensus()) &&
- nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER &&
- (!IsWitnessEnabled(chainActive.Tip(), chainparams.GetConsensus()) || State(pfrom->GetId())->fHaveWitness)) {
- inv.type |= nFetchFlags;
- if (nodestate->fSupportsDesiredCmpctVersion)
- vToFetch.push_back(CInv(MSG_CMPCT_BLOCK, inv.hash));
- else
- vToFetch.push_back(inv);
- // Mark block as in flight already, even though the actual "getdata" message only goes out
- // later (within the same cs_main lock, though).
- MarkBlockAsInFlight(pfrom->GetId(), inv.hash, chainparams.GetConsensus());
- }
LogPrint("net", "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->id);
}
}
@@ -5503,10 +5490,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// 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 vInv;
- vInv.type = State(pfrom->GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK;
- vInv.hash = req.blockhash;
- pfrom->vRecvGetData.push_back(vInv);
+ 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;
}
@@ -5927,22 +5914,21 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// updated, reject messages go out, etc.
MarkBlockAsReceived(resp.blockhash); // it is now an empty pointer
fBlockRead = true;
+ // mapBlockSource is only used for sending reject messages and DoS scores,
+ // so the race between here and cs_main in ProcessNewBlock is fine.
+ // BIP 152 permits peers to relay compact blocks after validating
+ // the header only; we should not punish peers if the block turns
+ // out to be invalid.
+ mapBlockSource.emplace(resp.blockhash, std::make_pair(pfrom->GetId(), false));
}
} // Don't hold cs_main when we call into ProcessNewBlock
if (fBlockRead) {
- CValidationState state;
+ bool fNewBlock = false;
// Since we requested this block (it was in mapBlocksInFlight), force it to be processed,
// even if it would not be a candidate for new tip (missing previous block, chain not long enough, etc)
- // BIP 152 permits peers to relay compact blocks after validating
- // the header only; we should not punish peers if the block turns
- // out to be invalid.
- ProcessNewBlock(state, chainparams, pfrom, &block, true, NULL, false);
- int nDoS;
- if (state.IsInvalid(nDoS)) {
- assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
- connman.PushMessage(pfrom, NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
- state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), block.GetHash());
- }
+ ProcessNewBlock(chainparams, &block, true, NULL, &fNewBlock);
+ if (fNewBlock)
+ pfrom->nLastBlockTime = GetTime();
}
}
@@ -6100,30 +6086,25 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
LogPrint("net", "received block %s peer=%d\n", block.GetHash().ToString(), pfrom->id);
- CValidationState state;
// Process all blocks from whitelisted peers, even if not requested,
// unless we're still syncing with the network.
// Such an unrequested block may still be processed, subject to the
// conditions in AcceptBlock().
bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload();
+ const uint256 hash(block.GetHash());
{
LOCK(cs_main);
// Also always process if we requested the block explicitly, as we may
// need it even though it is not a candidate for a new best tip.
- forceProcessing |= MarkBlockAsReceived(block.GetHash());
- }
- ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL, true);
- int nDoS;
- if (state.IsInvalid(nDoS)) {
- assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
- connman.PushMessage(pfrom, NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
- state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), block.GetHash());
- if (nDoS > 0) {
- LOCK(cs_main);
- Misbehaving(pfrom->GetId(), nDoS);
- }
+ forceProcessing |= MarkBlockAsReceived(hash);
+ // mapBlockSource is only used for sending reject messages and DoS scores,
+ // so the race between here and cs_main in ProcessNewBlock is fine.
+ mapBlockSource.emplace(hash, std::make_pair(pfrom->GetId(), true));
}
-
+ bool fNewBlock = false;
+ ProcessNewBlock(chainparams, &block, forceProcessing, NULL, &fNewBlock);
+ if (fNewBlock)
+ pfrom->nLastBlockTime = GetTime();
}
@@ -6970,7 +6951,7 @@ bool SendMessages(CNode* pto, CConnman& connman)
// Message: feefilter
//
// We don't want white listed peers to filter txs to us if we have -whitelistforcerelay
- if (pto->nVersion >= FEEFILTER_VERSION && GetBoolArg("-feefilter", DEFAULT_FEEFILTER) &&
+ if (!pto->fDisconnect && pto->nVersion >= FEEFILTER_VERSION && GetBoolArg("-feefilter", DEFAULT_FEEFILTER) &&
!(pto->fWhitelisted && GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY))) {
CAmount currentFilter = mempool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK();
int64_t timeNow = GetTimeMicros();
diff --git a/src/main.h b/src/main.h
index 21829b6c25..48fc3306f9 100644
--- a/src/main.h
+++ b/src/main.h
@@ -125,7 +125,7 @@ static const int64_t BLOCK_DOWNLOAD_TIMEOUT_BASE = 1000000;
/** Additional block download timeout per parallel downloading peer (i.e. 5 min) */
static const int64_t BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 500000;
-static const unsigned int DEFAULT_LIMITFREERELAY = 15;
+static const unsigned int DEFAULT_LIMITFREERELAY = 0;
static const bool DEFAULT_RELAYPRIORITY = true;
static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
@@ -215,15 +215,21 @@ static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
* Process an incoming block. This only returns after the best known valid
* block is made active. Note that it does not, however, guarantee that the
* specific block passed to it has been checked for validity!
+ *
+ * If you want to *possibly* get feedback on whether pblock is valid, you must
+ * install a CValidationInterface (see validationinterface.h) - this will have
+ * its BlockChecked method called whenever *any* block completes validation.
+ *
+ * Note that we guarantee that either the proof-of-work is valid on pblock, or
+ * (and possibly also) BlockChecked will have been called.
*
- * @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganization; or it may be set to an Invalid state if pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface (see validationinterface.h) - this will have its BlockChecked method called whenever *any* block completes validation.
- * @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid.
* @param[in] pblock The block we want to process.
* @param[in] fForceProcessing Process this block even if unrequested; used for non-network block sources and whitelisted peers.
* @param[out] dbp The already known disk position of pblock, or NULL if not yet stored.
+ * @param[out] fNewBlock A boolean which is set to indicate if the block was first received via this call
* @return True if state.IsValid()
*/
-bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool fMayBanPeerIfInvalid);
+bool ProcessNewBlock(const CChainParams& chainparams, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool* fNewBlock);
/** Check whether enough disk space is available for an incoming block */
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
/** Open a block file (blk?????.dat) */
diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
index 31332526a9..882717ac56 100644
--- a/src/merkleblock.cpp
+++ b/src/merkleblock.cpp
@@ -23,8 +23,8 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
for (unsigned int i = 0; i < block.vtx.size(); i++)
{
- const uint256& hash = block.vtx[i].GetHash();
- if (filter.IsRelevantAndUpdate(block.vtx[i]))
+ const uint256& hash = block.vtx[i]->GetHash();
+ if (filter.IsRelevantAndUpdate(*block.vtx[i]))
{
vMatch.push_back(true);
vMatchedTxn.push_back(make_pair(i, hash));
@@ -49,7 +49,7 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, const std::set<uint256>& txids)
for (unsigned int i = 0; i < block.vtx.size(); i++)
{
- const uint256& hash = block.vtx[i].GetHash();
+ const uint256& hash = block.vtx[i]->GetHash();
if (txids.count(hash))
vMatch.push_back(true);
else
diff --git a/src/miner.cpp b/src/miner.cpp
index ebf2f21ffd..c40b12cd8e 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -134,7 +134,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
pblock = &pblocktemplate->block; // pointer for convenience
// Add dummy coinbase tx as first transaction
- pblock->vtx.push_back(CTransaction());
+ pblock->vtx.emplace_back();
pblocktemplate->vTxFees.push_back(-1); // updated at end
pblocktemplate->vTxSigOpsCost.push_back(-1); // updated at end
@@ -169,7 +169,6 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
nLastBlockTx = nBlockTx;
nLastBlockSize = nBlockSize;
nLastBlockWeight = nBlockWeight;
- LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOpsCost);
// Create coinbase transaction.
CMutableTransaction coinbaseTx;
@@ -179,16 +178,19 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
coinbaseTx.vout[0].scriptPubKey = scriptPubKeyIn;
coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus());
coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0;
- pblock->vtx[0] = coinbaseTx;
+ pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx));
pblocktemplate->vchCoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, chainparams.GetConsensus());
pblocktemplate->vTxFees[0] = -nFees;
+ uint64_t nSerializeSize = GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION);
+ LogPrintf("CreateNewBlock(): total size: %u block weight: %u txs: %u fees: %ld sigops %d\n", nSerializeSize, GetBlockWeight(*pblock), nBlockTx, nFees, nBlockSigOpsCost);
+
// Fill in header
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus());
pblock->nNonce = 0;
- pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(pblock->vtx[0]);
+ pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]);
CValidationState state;
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
@@ -310,7 +312,7 @@ bool BlockAssembler::TestForBlock(CTxMemPool::txiter iter)
void BlockAssembler::AddToBlock(CTxMemPool::txiter iter)
{
- pblock->vtx.push_back(iter->GetTx());
+ pblock->vtx.emplace_back(iter->GetSharedTx());
pblocktemplate->vTxFees.push_back(iter->GetFee());
pblocktemplate->vTxSigOpsCost.push_back(iter->GetSigOpCost());
if (fNeedSizeAccounting) {
@@ -599,10 +601,10 @@ void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned
}
++nExtraNonce;
unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
- CMutableTransaction txCoinbase(pblock->vtx[0]);
+ CMutableTransaction txCoinbase(*pblock->vtx[0]);
txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
assert(txCoinbase.vin[0].scriptSig.size() <= 100);
- pblock->vtx[0] = txCoinbase;
+ pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
}
diff --git a/src/net.h b/src/net.h
index e2d88b478d..7a32e21f4a 100644
--- a/src/net.h
+++ b/src/net.h
@@ -403,7 +403,7 @@ private:
unsigned int nReceiveFloodSize;
std::vector<ListenSocket> vhListenSocket;
- bool fNetworkActive;
+ std::atomic<bool> fNetworkActive;
banmap_t setBanned;
CCriticalSection cs_setBanned;
bool setBannedIsDirty;
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index a3eee474ab..3ad1ff7bae 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -66,7 +66,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnes
// Extremely large transactions with lots of inputs can cost the network
// almost as much to process as they cost the sender in fees, because
// computing signature hashes is O(ninputs*txsize). Limiting transactions
- // to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
+ // to MAX_STANDARD_TX_WEIGHT mitigates CPU exhaustion attacks.
unsigned int sz = GetTransactionWeight(tx);
if (sz >= MAX_STANDARD_TX_WEIGHT) {
reason = "tx-size";
diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp
index 0e6ab4dd71..95bd2211f9 100644
--- a/src/primitives/block.cpp
+++ b/src/primitives/block.cpp
@@ -27,7 +27,7 @@ std::string CBlock::ToString() const
vtx.size());
for (unsigned int i = 0; i < vtx.size(); i++)
{
- s << " " << vtx[i].ToString() << "\n";
+ s << " " << vtx[i]->ToString() << "\n";
}
return s.str();
}
diff --git a/src/primitives/block.h b/src/primitives/block.h
index d148aec1e0..b037fc839c 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -73,7 +73,7 @@ class CBlock : public CBlockHeader
{
public:
// network and disk
- std::vector<CTransaction> vtx;
+ std::vector<CTransactionRef> vtx;
// memory only
mutable bool fChecked;
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index 7acdac17f2..91f4d29488 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -78,6 +78,10 @@ CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion
UpdateHash();
}
+CTransaction::CTransaction(CMutableTransaction &&tx) : nVersion(tx.nVersion), vin(std::move(tx.vin)), vout(std::move(tx.vout)), wit(std::move(tx.wit)), nLockTime(tx.nLockTime) {
+ UpdateHash();
+}
+
CTransaction& CTransaction::operator=(const CTransaction &tx) {
*const_cast<int*>(&nVersion) = tx.nVersion;
*const_cast<std::vector<CTxIn>*>(&vin) = tx.vin;
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 1d176e5d8c..0fa85a1519 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -379,6 +379,7 @@ public:
/** Convert a CMutableTransaction into a CTransaction. */
CTransaction(const CMutableTransaction &tx);
+ CTransaction(CMutableTransaction &&tx);
CTransaction& operator=(const CTransaction& tx);
@@ -392,6 +393,9 @@ public:
}
}
+ template <typename Stream>
+ CTransaction(deserialize_type, Stream& s) : CTransaction(CMutableTransaction(deserialize, s)) {}
+
bool IsNull() const {
return vin.empty() && vout.empty();
}
@@ -460,12 +464,23 @@ struct CMutableTransaction
SerializeTransaction(*this, s, ser_action);
}
+ template <typename Stream>
+ CMutableTransaction(deserialize_type, Stream& s) {
+ Unserialize(s);
+ }
+
/** Compute the hash of this CMutableTransaction. This is computed on the
* fly, as opposed to GetHash() in CTransaction, which uses a cached result.
*/
uint256 GetHash() const;
};
+typedef std::shared_ptr<const CTransaction> CTransactionRef;
+static inline CTransactionRef MakeTransactionRef() { return std::make_shared<const CTransaction>(); }
+template <typename Tx> static inline CTransactionRef MakeTransactionRef(Tx&& txIn) { return std::make_shared<const CTransaction>(std::forward<Tx>(txIn)); }
+static inline CTransactionRef MakeTransactionRef(const CTransactionRef& txIn) { return txIn; }
+static inline CTransactionRef MakeTransactionRef(CTransactionRef&& txIn) { return std::move(txIn); }
+
/** Compute the weight of a transaction, as defined by BIP 141 */
int64_t GetTransactionWeight(const CTransaction &tx);
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index b2c9a704ed..b7302e3969 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -713,13 +713,19 @@ void BitcoinGUI::updateNetworkState()
default: icon = ":/icons/connect_4"; break;
}
+ QString tooltip;
+
if (clientModel->getNetworkActive()) {
- connectionsControl->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count));
+ tooltip = tr("%n active connection(s) to Bitcoin network", "", count) + QString(".<br>") + tr("Click to disable network activity.");
} else {
- connectionsControl->setToolTip(tr("Network activity disabled"));
+ tooltip = tr("Network activity disabled.") + QString("<br>") + tr("Click to enable network activity again.");
icon = ":/icons/network_disabled";
}
+ // Don't word-wrap this (fixed-width) tooltip
+ tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
+ connectionsControl->setToolTip(tooltip);
+
connectionsControl->setPixmap(platformStyle->SingleColorIcon(icon).pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
}
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 1a1671f0ee..1010a62fc4 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -35,6 +35,13 @@ QList<CAmount> CoinControlDialog::payAmounts;
CCoinControl* CoinControlDialog::coinControl = new CCoinControl();
bool CoinControlDialog::fSubtractFeeFromAmount = false;
+bool CCoinControlWidgetItem::operator<(const QTreeWidgetItem &other) const {
+ int column = treeWidget()->sortColumn();
+ if (column == CoinControlDialog::COLUMN_AMOUNT || column == CoinControlDialog::COLUMN_DATE || column == CoinControlDialog::COLUMN_CONFIRMATIONS)
+ return data(column, Qt::UserRole).toLongLong() < other.data(column, Qt::UserRole).toLongLong();
+ return QTreeWidgetItem::operator<(other);
+}
+
CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent),
ui(new Ui::CoinControlDialog),
@@ -128,11 +135,9 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidge
ui->treeWidget->setColumnWidth(COLUMN_CONFIRMATIONS, 110);
ui->treeWidget->setColumnHidden(COLUMN_TXHASH, true); // store transaction hash in this column, but don't show it
ui->treeWidget->setColumnHidden(COLUMN_VOUT_INDEX, true); // store vout index in this column, but don't show it
- ui->treeWidget->setColumnHidden(COLUMN_AMOUNT_INT64, true); // store amount int64 in this column, but don't show it
- ui->treeWidget->setColumnHidden(COLUMN_DATE_INT64, true); // store date int64 in this column, but don't show it
// default view is sorted by amount desc
- sortView(COLUMN_AMOUNT_INT64, Qt::DescendingOrder);
+ sortView(COLUMN_AMOUNT, Qt::DescendingOrder);
// restore list mode and sortorder as a convenience feature
QSettings settings;
@@ -164,15 +169,6 @@ void CoinControlDialog::setModel(WalletModel *_model)
}
}
-// helper function str_pad
-QString CoinControlDialog::strPad(QString s, int nPadLength, QString sPadding)
-{
- while (s.length() < nPadLength)
- s = sPadding + s;
-
- return s;
-}
-
// ok button
void CoinControlDialog::buttonBoxClicked(QAbstractButton* button)
{
@@ -338,7 +334,7 @@ void CoinControlDialog::sortView(int column, Qt::SortOrder order)
sortColumn = column;
sortOrder = order;
ui->treeWidget->sortItems(column, order);
- ui->treeWidget->header()->setSortIndicator(getMappedColumn(sortColumn), sortOrder);
+ ui->treeWidget->header()->setSortIndicator(sortColumn, sortOrder);
}
// treeview: clicked on header
@@ -346,12 +342,10 @@ void CoinControlDialog::headerSectionClicked(int logicalIndex)
{
if (logicalIndex == COLUMN_CHECKBOX) // click on most left column -> do nothing
{
- ui->treeWidget->header()->setSortIndicator(getMappedColumn(sortColumn), sortOrder);
+ ui->treeWidget->header()->setSortIndicator(sortColumn, sortOrder);
}
else
{
- logicalIndex = getMappedColumn(logicalIndex, false);
-
if (sortColumn == logicalIndex)
sortOrder = ((sortOrder == Qt::AscendingOrder) ? Qt::DescendingOrder : Qt::AscendingOrder);
else
@@ -658,7 +652,7 @@ void CoinControlDialog::updateView()
model->listCoins(mapCoins);
BOOST_FOREACH(const PAIRTYPE(QString, std::vector<COutput>)& coins, mapCoins) {
- QTreeWidgetItem *itemWalletAddress = new QTreeWidgetItem();
+ CCoinControlWidgetItem *itemWalletAddress = new CCoinControlWidgetItem();
itemWalletAddress->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked);
QString sWalletAddress = coins.first;
QString sWalletLabel = model->getAddressTableModel()->labelForAddress(sWalletAddress);
@@ -686,9 +680,9 @@ void CoinControlDialog::updateView()
nSum += out.tx->vout[out.i].nValue;
nChildren++;
- QTreeWidgetItem *itemOutput;
- if (treeMode) itemOutput = new QTreeWidgetItem(itemWalletAddress);
- else itemOutput = new QTreeWidgetItem(ui->treeWidget);
+ CCoinControlWidgetItem *itemOutput;
+ if (treeMode) itemOutput = new CCoinControlWidgetItem(itemWalletAddress);
+ else itemOutput = new CCoinControlWidgetItem(ui->treeWidget);
itemOutput->setFlags(flgCheckbox);
itemOutput->setCheckState(COLUMN_CHECKBOX,Qt::Unchecked);
@@ -721,14 +715,15 @@ void CoinControlDialog::updateView()
// amount
itemOutput->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, out.tx->vout[out.i].nValue));
- itemOutput->setText(COLUMN_AMOUNT_INT64, strPad(QString::number(out.tx->vout[out.i].nValue), 15, " ")); // padding so that sorting works correctly
+ itemOutput->setData(COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong)out.tx->vout[out.i].nValue)); // padding so that sorting works correctly
// date
itemOutput->setText(COLUMN_DATE, GUIUtil::dateTimeStr(out.tx->GetTxTime()));
- itemOutput->setText(COLUMN_DATE_INT64, strPad(QString::number(out.tx->GetTxTime()), 20, " "));
+ itemOutput->setData(COLUMN_DATE, Qt::UserRole, QVariant((qlonglong)out.tx->GetTxTime()));
// confirmations
- itemOutput->setText(COLUMN_CONFIRMATIONS, strPad(QString::number(out.nDepth), 8, " "));
+ itemOutput->setText(COLUMN_CONFIRMATIONS, QString::number(out.nDepth));
+ itemOutput->setData(COLUMN_CONFIRMATIONS, Qt::UserRole, QVariant((qlonglong)out.nDepth));
// transaction hash
uint256 txhash = out.tx->GetHash();
@@ -756,7 +751,7 @@ void CoinControlDialog::updateView()
{
itemWalletAddress->setText(COLUMN_CHECKBOX, "(" + QString::number(nChildren) + ")");
itemWalletAddress->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, nSum));
- itemWalletAddress->setText(COLUMN_AMOUNT_INT64, strPad(QString::number(nSum), 15, " "));
+ itemWalletAddress->setData(COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong)nSum));
}
}
diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h
index 7d73421e3a..7c2269b1eb 100644
--- a/src/qt/coincontroldialog.h
+++ b/src/qt/coincontroldialog.h
@@ -28,6 +28,17 @@ namespace Ui {
#define ASYMP_UTF8 "\xE2\x89\x88"
+class CCoinControlWidgetItem : public QTreeWidgetItem
+{
+public:
+ CCoinControlWidgetItem(QTreeWidget *parent, int type = Type) : QTreeWidgetItem(parent, type) {}
+ CCoinControlWidgetItem(int type = Type) : QTreeWidgetItem(type) {}
+ CCoinControlWidgetItem(QTreeWidgetItem *parent, int type = Type) : QTreeWidgetItem(parent, type) {}
+
+ bool operator<(const QTreeWidgetItem &other) const;
+};
+
+
class CoinControlDialog : public QDialog
{
Q_OBJECT
@@ -59,13 +70,12 @@ private:
const PlatformStyle *platformStyle;
- QString strPad(QString, int, QString);
void sortView(int, Qt::SortOrder);
void updateView();
enum
{
- COLUMN_CHECKBOX,
+ COLUMN_CHECKBOX = 0,
COLUMN_AMOUNT,
COLUMN_LABEL,
COLUMN_ADDRESS,
@@ -73,30 +83,8 @@ private:
COLUMN_CONFIRMATIONS,
COLUMN_TXHASH,
COLUMN_VOUT_INDEX,
- COLUMN_AMOUNT_INT64,
- COLUMN_DATE_INT64
};
-
- // some columns have a hidden column containing the value used for sorting
- int getMappedColumn(int column, bool fVisibleColumn = true)
- {
- if (fVisibleColumn)
- {
- if (column == COLUMN_AMOUNT_INT64)
- return COLUMN_AMOUNT;
- else if (column == COLUMN_DATE_INT64)
- return COLUMN_DATE;
- }
- else
- {
- if (column == COLUMN_AMOUNT)
- return COLUMN_AMOUNT_INT64;
- else if (column == COLUMN_DATE)
- return COLUMN_DATE_INT64;
- }
-
- return column;
- }
+ friend class CCoinControlWidgetItem;
private Q_SLOTS:
void showMenu(const QPoint &);
diff --git a/src/qt/res/icons/network_disabled.png b/src/qt/res/icons/network_disabled.png
index 49f728693d..269c3cfab8 100644
--- a/src/qt/res/icons/network_disabled.png
+++ 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
index e95a5eb5bb..a041d77439 100644
--- a/src/qt/res/src/network_disabled.svg
+++ b/src/qt/res/src/network_disabled.svg
@@ -7,8 +7,8 @@
xmlns="http://www.w3.org/2000/svg"
id="svg2"
viewBox="0 0 24 24"
- height="24"
- width="24"
+ width="92"
+ height="92"
version="1.2">
<metadata
id="metadata10">
@@ -37,31 +37,12 @@
id="g4291">
<path
id="path4293"
- d="m -65.35,116.3 0,3 0.5,0 c 0.54,0 1,0.5 1,1 l 0,2.6 c -1.15,0.5 -2,1.6 -2,3 0,2 1.59,3.5 3.5,3.5 1.91,0 3.5,-1.5 3.5,-3.5 0,-1.4 -0.85,-2.5 -2,-3 l 0,-2.6 c 0,-2.3 -1.81,-4 -4,-4 z m 1,1.2 c 1.39,0.3 2.5,1.3 2.5,2.8 l 0,3.2 0.34,0.1 c 0.96,0.3 1.66,1.2 1.66,2.3 0,1.4 -1.11,2.5 -2.5,2.5 -1.39,0 -2.5,-1.1 -2.5,-2.5 0,-1.1 0.69,-2 1.66,-2.3 l 0.34,-0.1 0,-3.2 c 0,-0.9 -0.67,-1.5 -1.5,-1.8 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:1;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
- style="fill:#969696;fill-opacity:1"
- id="g4295">
- <path
- id="path4297"
- d="m -67.35,106.1 c -1.94,0 -3.5,1.6 -3.5,3.5 0,1.4 0.85,2.5 2,3 l 0,2.7 c 0,2.2 1.79,4 4,4 l 0.5,0 0,-0.5 0,-2.5 -0.5,0 c -0.55,0 -1,-0.5 -1,-1 l 0,-2.7 c 1.15,-0.5 2,-1.6 2,-3 0,-1.9 -1.57,-3.5 -3.5,-3.5 z m 0,1 c 1.37,0 2.5,1.2 2.5,2.5 0,1.1 -0.7,2 -1.66,2.3 l -0.34,0.1 0,3.3 c 0,0.9 0.67,1.5 1.5,1.8 l 0,1 c -1.38,-0.3 -2.5,-1.4 -2.5,-2.8 l 0,-3.3 -0.34,-0.1 c -0.96,-0.3 -1.66,-1.2 -1.66,-2.3 0,-1.3 1.12,-2.5 2.5,-2.5 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:1;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" />
- <path
- id="path4299"
- d="m -57.35,106.1 c -1.93,0 -3.5,1.6 -3.5,3.5 0,1.4 0.85,2.5 2,3 l 0,2.7 c 0,0.5 -0.45,1 -1,1 l -4.85,0 3.17,3 1.68,0 c 2.21,0 4,-1.8 4,-4 l 0,-2.7 c 1.15,-0.5 2,-1.6 2,-3 0,-1.9 -1.56,-3.5 -3.5,-3.5 z m 0,1 c 1.38,0 2.5,1.2 2.5,2.5 0,1.1 -0.7,2 -1.66,2.3 l -0.34,0.1 0,3.3 c 0,1.6 -1.35,3 -3,3 l -1.81,0 -2.04,-1 3.85,0 c 1.11,0 2,-0.9 2,-2 l 0,-3.3 -0.34,-0.1 c -0.96,-0.3 -1.66,-1.2 -1.66,-2.3 0,-1.3 1.13,-2.5 2.5,-2.5 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:1;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>
- <path
- id="path4301"
- d="m -69.84,116.3 c -2.19,0 -4,1.7 -4,4 l 0,2.6 c -1.14,0.6 -1.99,1.6 -1.99,3 0,2 1.6,3.5 3.51,3.5 1.91,0 3.5,-1.5 3.5,-3.5 0,-1.4 -0.85,-2.5 -2,-3 l 0,-2.6 c 0,-0.5 0.45,-1 1,-1 l 5.01,0 -3.36,-3 z m 0,1 1.84,0 2.19,1 -4.01,0 c -1.11,0 -2,0.9 -2,2 l 0,3.2 0.34,0.1 c 0.96,0.3 1.66,1.2 1.66,2.3 0,1.4 -1.11,2.5 -2.5,2.5 -1.39,0 -2.51,-1.1 -2.51,-2.5 0,-1.1 0.7,-2 1.66,-2.3 l 0.33,-0.1 0,-0.4 0,-2.8 c 0,-1.7 1.33,-3 3,-3 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:1;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" />
+ 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>
- <path
- id="path4165"
- d="m 12,8.77 c -0.84,0 -1.66,0.341 -2.254,0.937 -0.599,0.593 -0.942,1.403 -0.945,2.253 0,0.85 0.337,1.67 0.933,2.26 a 0.6001,0.6001 0 0 0 0,0 c 0.594,0.6 1.424,0.94 2.264,0.94 0.84,0 1.67,-0.34 2.26,-0.94 0.6,-0.59 0.94,-1.41 0.94,-2.26 0,-0.84 -0.34,-1.66 -0.95,-2.253 C 13.66,9.111 12.84,8.77 12,8.77 Z"
- style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</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;" />
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 8caea14adb..154107c0dc 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -119,16 +119,16 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
result.push_back(Pair("versionHex", strprintf("%08x", block.nVersion)));
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
UniValue txs(UniValue::VARR);
- BOOST_FOREACH(const CTransaction&tx, block.vtx)
+ for(const auto& tx : block.vtx)
{
if(txDetails)
{
UniValue objTx(UniValue::VOBJ);
- TxToJSON(tx, uint256(), objTx);
+ TxToJSON(*tx, uint256(), objTx);
txs.push_back(objTx);
}
else
- txs.push_back(tx.GetHash().GetHex());
+ txs.push_back(tx->GetHash().GetHex());
}
result.push_back(Pair("tx", txs));
result.push_back(Pair("time", block.GetBlockTime()));
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 8824898feb..6b0e52a309 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -131,9 +131,8 @@ UniValue generateBlocks(boost::shared_ptr<CReserveScript> coinbaseScript, int nG
if (pblock->nNonce == nInnerLoopCount) {
continue;
}
- CValidationState state;
- if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL, false))
- throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("ProcessNewBlock: block not accepted: %s", FormatStateMessage(state)));
+ if (!ProcessNewBlock(Params(), pblock, true, NULL, NULL))
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
++nHeight;
blockHashes.push_back(pblock->GetHash().GetHex());
@@ -558,7 +557,8 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
UniValue transactions(UniValue::VARR);
map<uint256, int64_t> setTxIndex;
int i = 0;
- BOOST_FOREACH (CTransaction& tx, pblock->vtx) {
+ for (const auto& it : pblock->vtx) {
+ const CTransaction& tx = *it;
uint256 txHash = tx.GetHash();
setTxIndex[txHash] = i++;
@@ -663,7 +663,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
result.push_back(Pair("transactions", transactions));
result.push_back(Pair("coinbaseaux", aux));
- result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
+ result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue));
result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
result.push_back(Pair("target", hashTarget.GetHex()));
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
@@ -754,10 +754,9 @@ UniValue submitblock(const JSONRPCRequest& request)
}
}
- CValidationState state;
submitblock_StateCatcher sc(block.GetHash());
RegisterValidationInterface(&sc);
- bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL, false);
+ bool fAccepted = ProcessNewBlock(Params(), &block, true, NULL, NULL);
UnregisterValidationInterface(&sc);
if (fBlockPresent)
{
@@ -765,13 +764,9 @@ UniValue submitblock(const JSONRPCRequest& request)
return "duplicate-inconclusive";
return "duplicate";
}
- if (fAccepted)
- {
- if (!sc.found)
- return "inconclusive";
- state = sc.state;
- }
- return BIP22ValidationResult(state);
+ if (!sc.found)
+ return "inconclusive";
+ return BIP22ValidationResult(sc.state);
}
UniValue estimatefee(const JSONRPCRequest& request)
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 0656a61755..370c021ea6 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -135,17 +135,17 @@ UniValue getrawtransaction(const JSONRPCRequest& request)
"or there is an unspent output in the utxo for this transaction. To make it always work,\n"
"you need to maintain a transaction index, using the -txindex command line option.\n"
"\nReturn the raw transaction data.\n"
- "\nIf verbose=0, returns a string that is serialized, hex-encoded data for 'txid'.\n"
- "If verbose is non-zero, returns an Object with information about 'txid'.\n"
+ "\nIf verbose is 'true', returns an Object with information about 'txid'.\n"
+ "If verbose is 'false' or omitted, returns a string that is serialized, hex-encoded data for 'txid'.\n"
"\nArguments:\n"
"1. \"txid\" (string, required) The transaction id\n"
- "2. verbose (numeric, optional, default=0) If 0, return a string, other return a json object\n"
+ "2. verbose (bool, optional, default=false) If true, return a string, other return a json object\n"
- "\nResult (if verbose is not set or set to 0):\n"
+ "\nResult (if verbose is not set or set to false):\n"
"\"data\" (string) The serialized, hex-encoded data for 'txid'\n"
- "\nResult (if verbose > 0):\n"
+ "\nResult (if verbose is set to true):\n"
"{\n"
" \"hex\" : \"data\", (string) The serialized, hex-encoded data for 'txid'\n"
" \"txid\" : \"id\", (string) The transaction id (same as provided)\n"
@@ -192,17 +192,31 @@ UniValue getrawtransaction(const JSONRPCRequest& request)
"\nExamples:\n"
+ HelpExampleCli("getrawtransaction", "\"mytxid\"")
- + HelpExampleCli("getrawtransaction", "\"mytxid\" 1")
- + HelpExampleRpc("getrawtransaction", "\"mytxid\", 1")
+ + HelpExampleCli("getrawtransaction", "\"mytxid\" true")
+ + HelpExampleRpc("getrawtransaction", "\"mytxid\", true")
);
LOCK(cs_main);
uint256 hash = ParseHashV(request.params[0], "parameter 1");
+ // Accept either a bool (true) or a num (>=1) to indicate verbose output.
bool fVerbose = false;
- if (request.params.size() > 1)
- fVerbose = (request.params[1].get_int() != 0);
+ if (request.params.size() > 1) {
+ if (request.params[1].isNum()) {
+ if (request.params[1].get_int() != 0) {
+ fVerbose = true;
+ }
+ }
+ else if(request.params[1].isBool()) {
+ if(request.params[1].isTrue()) {
+ fVerbose = true;
+ }
+ }
+ else {
+ throw JSONRPCError(RPC_TYPE_ERROR, "Invalid type provided. Verbose parameter must be a boolean.");
+ }
+ }
CTransaction tx;
uint256 hashBlock;
@@ -288,8 +302,8 @@ UniValue gettxoutproof(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
unsigned int ntxFound = 0;
- BOOST_FOREACH(const CTransaction&tx, block.vtx)
- if (setTxids.count(tx.GetHash()))
+ for (const auto& tx : block.vtx)
+ if (setTxids.count(tx->GetHash()))
ntxFound++;
if (ntxFound != setTxids.size())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "(Not all) transactions not found in specified block");
diff --git a/src/scheduler.cpp b/src/scheduler.cpp
index 52777b61f9..27c03f154c 100644
--- a/src/scheduler.cpp
+++ b/src/scheduler.cpp
@@ -54,9 +54,10 @@ void CScheduler::serviceQueue()
#else
// Some boost versions have a conflicting overload of wait_until that returns void.
// Explicitly use a template here to avoid hitting that overload.
- while (!shouldStop() && !taskQueue.empty() &&
- newTaskScheduled.wait_until<>(lock, taskQueue.begin()->first) != boost::cv_status::timeout) {
- // Keep waiting until timeout
+ while (!shouldStop() && !taskQueue.empty()) {
+ boost::chrono::system_clock::time_point timeToWaitFor = taskQueue.begin()->first;
+ if (newTaskScheduled.wait_until<>(lock, timeToWaitFor) == boost::cv_status::timeout)
+ break; // Exit loop after timeout, it means we reached the time of the event
}
#endif
// If there are multiple threads, the queue can empty while we're waiting (another
diff --git a/src/serialize.h b/src/serialize.h
index 91864e1b64..e28ca548c0 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -13,6 +13,7 @@
#include <ios>
#include <limits>
#include <map>
+#include <memory>
#include <set>
#include <stdint.h>
#include <string>
@@ -25,6 +26,20 @@
static const unsigned int MAX_SIZE = 0x02000000;
/**
+ * Dummy data type to identify deserializing constructors.
+ *
+ * By convention, a constructor of a type T with signature
+ *
+ * template <typename Stream> T::T(deserialize_type, Stream& s)
+ *
+ * is a deserializing constructor, which builds the type by
+ * deserializing it from s. If T contains const fields, this
+ * is likely the only way to do so.
+ */
+struct deserialize_type {};
+constexpr deserialize_type deserialize {};
+
+/**
* Used to bypass the rule against non-const reference to temporary
* where it makes sense with wrappers such as CFlatData or CTxDB
*/
@@ -521,7 +536,17 @@ template<typename Stream, typename K, typename T, typename Pred, typename A> voi
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);
+/**
+ * shared_ptr
+ */
+template<typename Stream, typename T> void Serialize(Stream& os, const std::shared_ptr<const T>& p);
+template<typename Stream, typename T> void Unserialize(Stream& os, std::shared_ptr<const T>& p);
+/**
+ * unique_ptr
+ */
+template<typename Stream, typename T> void Serialize(Stream& os, const std::unique_ptr<const T>& p);
+template<typename Stream, typename T> void Unserialize(Stream& os, std::unique_ptr<const T>& p);
@@ -776,6 +801,40 @@ void Unserialize(Stream& is, std::set<K, Pred, A>& m)
/**
+ * unique_ptr
+ */
+template<typename Stream, typename T> void
+Serialize(Stream& os, const std::unique_ptr<const T>& p)
+{
+ Serialize(os, *p);
+}
+
+template<typename Stream, typename T>
+void Unserialize(Stream& is, std::unique_ptr<const T>& p)
+{
+ p.reset(new T(deserialize, is));
+}
+
+
+
+/**
+ * shared_ptr
+ */
+template<typename Stream, typename T> void
+Serialize(Stream& os, const std::shared_ptr<const T>& p)
+{
+ Serialize(os, *p);
+}
+
+template<typename Stream, typename T>
+void Unserialize(Stream& is, std::shared_ptr<const T>& p)
+{
+ p = std::make_shared<const T>(deserialize, is);
+}
+
+
+
+/**
* Support for ADD_SERIALIZE_METHODS and READWRITE macro
*/
struct CSerActionSerialize
diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp
index 0ed5d62ef6..b013cda6d7 100644
--- a/src/test/blockencodings_tests.cpp
+++ b/src/test/blockencodings_tests.cpp
@@ -26,21 +26,21 @@ static CBlock BuildBlockTestCase() {
tx.vout[0].nValue = 42;
block.vtx.resize(3);
- block.vtx[0] = tx;
+ block.vtx[0] = MakeTransactionRef(tx);
block.nVersion = 42;
block.hashPrevBlock = GetRandHash();
block.nBits = 0x207fffff;
tx.vin[0].prevout.hash = GetRandHash();
tx.vin[0].prevout.n = 0;
- block.vtx[1] = tx;
+ block.vtx[1] = MakeTransactionRef(tx);
tx.vin.resize(10);
for (size_t i = 0; i < tx.vin.size(); i++) {
tx.vin[i].prevout.hash = GetRandHash();
tx.vin[i].prevout.n = 0;
}
- block.vtx[2] = tx;
+ block.vtx[2] = MakeTransactionRef(tx);
bool mutated;
block.hashMerkleRoot = BlockMerkleRoot(block, &mutated);
@@ -59,8 +59,8 @@ BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
TestMemPoolEntryHelper entry;
CBlock block(BuildBlockTestCase());
- pool.addUnchecked(block.vtx[2].GetHash(), entry.FromTx(block.vtx[2]));
- BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
+ pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(*block.vtx[2]));
+ BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
// Do a simple ShortTxIDs RT
{
@@ -78,14 +78,14 @@ BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
BOOST_CHECK(!partialBlock.IsTxAvailable(1));
BOOST_CHECK( partialBlock.IsTxAvailable(2));
- BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
+ BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
- std::vector<std::shared_ptr<const CTransaction>> removed;
- pool.removeRecursive(block.vtx[2], &removed);
+ std::vector<CTransactionRef> removed;
+ pool.removeRecursive(*block.vtx[2], &removed);
BOOST_CHECK_EQUAL(removed.size(), 1);
CBlock block2;
- std::vector<CTransaction> vtx_missing;
+ std::vector<CTransactionRef> vtx_missing;
BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_INVALID); // No transactions
vtx_missing.push_back(block.vtx[2]); // Wrong transaction
@@ -152,8 +152,10 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
TestMemPoolEntryHelper entry;
CBlock block(BuildBlockTestCase());
- pool.addUnchecked(block.vtx[2].GetHash(), entry.FromTx(block.vtx[2]));
- BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
+ pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(*block.vtx[2]));
+ BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
+
+ uint256 txhash;
// Test with pre-forwarding tx 1, but not coinbase
{
@@ -161,8 +163,8 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
shortIDs.prefilledtxn.resize(1);
shortIDs.prefilledtxn[0] = {1, block.vtx[1]};
shortIDs.shorttxids.resize(2);
- shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[0].GetHash());
- shortIDs.shorttxids[1] = shortIDs.GetShortID(block.vtx[2].GetHash());
+ shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[0]->GetHash());
+ shortIDs.shorttxids[1] = shortIDs.GetShortID(block.vtx[2]->GetHash());
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << shortIDs;
@@ -176,10 +178,10 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
BOOST_CHECK( partialBlock.IsTxAvailable(1));
BOOST_CHECK( partialBlock.IsTxAvailable(2));
- BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
+ BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
CBlock block2;
- std::vector<CTransaction> vtx_missing;
+ std::vector<CTransactionRef> vtx_missing;
BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_INVALID); // No transactions
vtx_missing.push_back(block.vtx[1]); // Wrong transaction
@@ -194,9 +196,13 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString());
BOOST_CHECK(!mutated);
- BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
+ txhash = block.vtx[2]->GetHash();
+ block.vtx.clear();
+ block2.vtx.clear();
+ block3.vtx.clear();
+ BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
}
- BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
+ BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
}
BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
@@ -205,8 +211,10 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
TestMemPoolEntryHelper entry;
CBlock block(BuildBlockTestCase());
- pool.addUnchecked(block.vtx[1].GetHash(), entry.FromTx(block.vtx[1]));
- BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
+ pool.addUnchecked(block.vtx[1]->GetHash(), entry.FromTx(*block.vtx[1]));
+ BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
+
+ uint256 txhash;
// Test with pre-forwarding coinbase + tx 2 with tx 1 in mempool
{
@@ -215,7 +223,7 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
shortIDs.prefilledtxn[0] = {0, block.vtx[0]};
shortIDs.prefilledtxn[1] = {1, block.vtx[2]}; // id == 1 as it is 1 after index 1
shortIDs.shorttxids.resize(1);
- shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[1].GetHash());
+ shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[1]->GetHash());
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << shortIDs;
@@ -229,19 +237,22 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
BOOST_CHECK( partialBlock.IsTxAvailable(1));
BOOST_CHECK( partialBlock.IsTxAvailable(2));
- BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
+ BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
CBlock block2;
- std::vector<CTransaction> vtx_missing;
+ std::vector<CTransactionRef> vtx_missing;
BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_OK);
BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString());
bool mutated;
BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString());
BOOST_CHECK(!mutated);
- BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
+ txhash = block.vtx[1]->GetHash();
+ block.vtx.clear();
+ block2.vtx.clear();
+ BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
}
- BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
+ BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
}
BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest)
@@ -255,7 +266,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest)
CBlock block;
block.vtx.resize(1);
- block.vtx[0] = coinbase;
+ block.vtx[0] = MakeTransactionRef(std::move(coinbase));
block.nVersion = 42;
block.hashPrevBlock = GetRandHash();
block.nBits = 0x207fffff;
@@ -280,7 +291,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest)
BOOST_CHECK(partialBlock.IsTxAvailable(0));
CBlock block2;
- std::vector<CTransaction> vtx_missing;
+ std::vector<CTransactionRef> vtx_missing;
BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_OK);
BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString());
BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString());
diff --git a/src/test/data/bitcoin-util-test.json b/src/test/data/bitcoin-util-test.json
index de95044597..98be75919b 100644
--- a/src/test/data/bitcoin-util-test.json
+++ b/src/test/data/bitcoin-util-test.json
@@ -103,6 +103,16 @@
"description": "Creates a new transaction with a single empty output script (output in json)"
},
{ "exec": "./bitcoin-tx",
+ "args": ["01000000000100000000000000000000000000"],
+ "output_cmp": "txcreate2.hex",
+ "description": "Parses a transation with no inputs and a single output script"
+ },
+ { "exec": "./bitcoin-tx",
+ "args": ["-json", "01000000000100000000000000000000000000"],
+ "output_cmp": "txcreate2.json",
+ "description": "Parses a transation with no inputs and a single output script (output in json)"
+ },
+ { "exec": "./bitcoin-tx",
"args":
["-create",
"in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0",
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index a73dbe725c..1faf8b6aeb 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
CTxMemPool testPool(CFeeRate(0));
- std::vector<std::shared_ptr<const CTransaction>> removed;
+ std::vector<CTransactionRef> removed;
// Nothing in pool, remove should do nothing:
testPool.removeRecursive(txParent, &removed);
@@ -410,8 +410,8 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
CheckSort<ancestor_score>(pool, sortedOrder);
/* after tx6 is mined, tx7 should move up in the sort */
- std::vector<CTransaction> vtx;
- vtx.push_back(tx6);
+ std::vector<CTransactionRef> vtx;
+ vtx.push_back(MakeTransactionRef(tx6));
pool.removeForBlock(vtx, 1, NULL, false);
sortedOrder.erase(sortedOrder.begin()+1);
@@ -546,7 +546,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
pool.addUnchecked(tx5.GetHash(), entry.Fee(1000LL).FromTx(tx5, &pool));
pool.addUnchecked(tx7.GetHash(), entry.Fee(9000LL).FromTx(tx7, &pool));
- std::vector<CTransaction> vtx;
+ std::vector<CTransactionRef> vtx;
SetMockTime(42);
SetMockTime(42 + CTxMemPool::ROLLING_FEE_HALFLIFE);
BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000);
diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp
index 706d30f489..55e6852a15 100644
--- a/src/test/merkle_tests.cpp
+++ b/src/test/merkle_tests.cpp
@@ -15,8 +15,8 @@ static uint256 BlockBuildMerkleTree(const CBlock& block, bool* fMutated, std::ve
{
vMerkleTree.clear();
vMerkleTree.reserve(block.vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes.
- for (std::vector<CTransaction>::const_iterator it(block.vtx.begin()); it != block.vtx.end(); ++it)
- vMerkleTree.push_back(it->GetHash());
+ for (std::vector<CTransactionRef>::const_iterator it(block.vtx.begin()); it != block.vtx.end(); ++it)
+ vMerkleTree.push_back((*it)->GetHash());
int j = 0;
bool mutated = false;
for (int nSize = block.vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
@@ -86,7 +86,7 @@ BOOST_AUTO_TEST_CASE(merkle_test)
for (int j = 0; j < ntx; j++) {
CMutableTransaction mtx;
mtx.nLockTime = j;
- block.vtx[j] = mtx;
+ block.vtx[j] = MakeTransactionRef(std::move(mtx));
}
// Compute the root of the block before mutating it.
bool unmutatedMutated = false;
@@ -126,7 +126,7 @@ BOOST_AUTO_TEST_CASE(merkle_test)
std::vector<uint256> newBranch = BlockMerkleBranch(block, mtx);
std::vector<uint256> oldBranch = BlockGetMerkleBranch(block, merkleTree, mtx);
BOOST_CHECK(oldBranch == newBranch);
- BOOST_CHECK(ComputeMerkleRootFromBranch(block.vtx[mtx].GetHash(), newBranch, mtx) == oldRoot);
+ BOOST_CHECK(ComputeMerkleRootFromBranch(block.vtx[mtx]->GetHash(), newBranch, mtx) == oldRoot);
}
}
}
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 2762cafa38..aea8920936 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -77,7 +77,7 @@ bool TestSequenceLocks(const CTransaction &tx, int flags)
// Implemented as an additional function, rather than a separate test case,
// to allow reusing the blockchain created in CreateNewBlock_validity.
// Note that this test assumes blockprioritysize is 0.
-void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, std::vector<CTransaction *>& txFirst)
+void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, std::vector<CTransactionRef>& txFirst)
{
// Test the ancestor feerate transaction selection.
TestMemPoolEntryHelper entry;
@@ -108,9 +108,9 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey,
mempool.addUnchecked(hashHighFeeTx, entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
- BOOST_CHECK(pblocktemplate->block.vtx[1].GetHash() == hashParentTx);
- BOOST_CHECK(pblocktemplate->block.vtx[2].GetHash() == hashHighFeeTx);
- BOOST_CHECK(pblocktemplate->block.vtx[3].GetHash() == hashMediumFeeTx);
+ BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx);
+ BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashHighFeeTx);
+ BOOST_CHECK(pblocktemplate->block.vtx[3]->GetHash() == hashMediumFeeTx);
// Test that a package below the min relay fee doesn't get included
tx.vin[0].prevout.hash = hashHighFeeTx;
@@ -130,8 +130,8 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey,
pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
// Verify that the free tx and the low fee tx didn't get selected
for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
- BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashFreeTx);
- BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashLowFeeTx);
+ BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx);
+ BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashLowFeeTx);
}
// Test that packages above the min relay fee do get included, even if one
@@ -142,8 +142,8 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey,
hashLowFeeTx = tx.GetHash();
mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse+2).FromTx(tx));
pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
- BOOST_CHECK(pblocktemplate->block.vtx[4].GetHash() == hashFreeTx);
- BOOST_CHECK(pblocktemplate->block.vtx[5].GetHash() == hashLowFeeTx);
+ BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashFreeTx);
+ BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashLowFeeTx);
// Test that transaction selection properly updates ancestor fee
// calculations as ancestor transactions get included in a block.
@@ -166,8 +166,8 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey,
// Verify that this tx isn't selected.
for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
- BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashFreeTx2);
- BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashLowFeeTx2);
+ BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx2);
+ BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashLowFeeTx2);
}
// This tx will be mineable, and should cause hashLowFeeTx2 to be selected
@@ -176,7 +176,7 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey,
tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee
mempool.addUnchecked(tx.GetHash(), entry.Fee(10000).FromTx(tx));
pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
- BOOST_CHECK(pblocktemplate->block.vtx[8].GetHash() == hashLowFeeTx2);
+ BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2);
}
// NOTE: These tests rely on CreateNewBlock doing its own self-validation!
@@ -203,28 +203,26 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
// We can't make transactions until we have inputs
// Therefore, load 100 blocks :)
int baseheight = 0;
- std::vector<CTransaction*>txFirst;
+ std::vector<CTransactionRef> txFirst;
for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i)
{
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
pblock->nVersion = 1;
pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;
- CMutableTransaction txCoinbase(pblock->vtx[0]);
+ CMutableTransaction txCoinbase(*pblock->vtx[0]);
txCoinbase.nVersion = 1;
txCoinbase.vin[0].scriptSig = CScript();
txCoinbase.vin[0].scriptSig.push_back(blockinfo[i].extranonce);
txCoinbase.vin[0].scriptSig.push_back(chainActive.Height());
txCoinbase.vout[0].scriptPubKey = CScript();
- pblock->vtx[0] = CTransaction(txCoinbase);
+ pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
if (txFirst.size() == 0)
baseheight = chainActive.Height();
if (txFirst.size() < 4)
- txFirst.push_back(new CTransaction(pblock->vtx[0]));
+ txFirst.push_back(pblock->vtx[0]);
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
pblock->nNonce = blockinfo[i].nonce;
- CValidationState state;
- BOOST_CHECK(ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL, false));
- BOOST_CHECK(state.IsValid());
+ BOOST_CHECK(ProcessNewBlock(chainparams, pblock, true, NULL, NULL));
pblock->hashPrevBlock = pblock->GetHash();
}
@@ -487,9 +485,6 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
TestPackageSelection(chainparams, scriptPubKey, txFirst);
- BOOST_FOREACH(CTransaction *_tx, txFirst)
- delete _tx;
-
fCheckpointsEnabled = true;
}
diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp
index c773129640..e6b689bc6c 100644
--- a/src/test/pmt_tests.cpp
+++ b/src/test/pmt_tests.cpp
@@ -45,14 +45,14 @@ BOOST_AUTO_TEST_CASE(pmt_test1)
for (unsigned int j=0; j<nTx; j++) {
CMutableTransaction tx;
tx.nLockTime = j; // actual transaction data doesn't matter; just make the nLockTime's unique
- block.vtx.push_back(CTransaction(tx));
+ block.vtx.push_back(MakeTransactionRef(std::move(tx)));
}
// calculate actual merkle root and height
uint256 merkleRoot1 = BlockMerkleRoot(block);
std::vector<uint256> vTxid(nTx, uint256());
for (unsigned int j=0; j<nTx; j++)
- vTxid[j] = block.vtx[j].GetHash();
+ vTxid[j] = block.vtx[j]->GetHash();
int nHeight = 1, nTx_ = nTx;
while (nTx_ > 1) {
nTx_ = (nTx_+1)/2;
diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp
index 38aaaba267..7dc8f226c9 100644
--- a/src/test/policyestimator_tests.cpp
+++ b/src/test/policyestimator_tests.cpp
@@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
CFeeRate baseRate(basefee, GetVirtualTransactionSize(tx));
// Create a fake block
- std::vector<CTransaction> block;
+ std::vector<CTransactionRef> block;
int blocknum = 0;
// Loop through 200 blocks
@@ -66,9 +66,9 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
// 9/10 blocks add 2nd highest and so on until ...
// 1/10 blocks add lowest fee transactions
while (txHashes[9-h].size()) {
- std::shared_ptr<const CTransaction> ptx = mpool.get(txHashes[9-h].back());
+ CTransactionRef ptx = mpool.get(txHashes[9-h].back());
if (ptx)
- block.push_back(*ptx);
+ block.push_back(ptx);
txHashes[9-h].pop_back();
}
}
@@ -143,9 +143,9 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
// Estimates should still not be below original
for (int j = 0; j < 10; j++) {
while(txHashes[j].size()) {
- std::shared_ptr<const CTransaction> ptx = mpool.get(txHashes[j].back());
+ CTransactionRef ptx = mpool.get(txHashes[j].back());
if (ptx)
- block.push_back(*ptx);
+ block.push_back(ptx);
txHashes[j].pop_back();
}
}
@@ -163,9 +163,9 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
tx.vin[0].prevout.n = 10000*blocknum+100*j+k;
uint256 hash = tx.GetHash();
mpool.addUnchecked(hash, entry.Fee(feeV[j]).Time(GetTime()).Priority(0).Height(blocknum).FromTx(tx, &mpool));
- std::shared_ptr<const CTransaction> ptx = mpool.get(hash);
+ CTransactionRef ptx = mpool.get(hash);
if (ptx)
- block.push_back(*ptx);
+ block.push_back(ptx);
}
}
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 3da0be8ca4..6cbe314a76 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -101,7 +101,7 @@ TestChain100Setup::TestChain100Setup() : TestingSetup(CBaseChainParams::REGTEST)
{
std::vector<CMutableTransaction> noTxns;
CBlock b = CreateAndProcessBlock(noTxns, scriptPubKey);
- coinbaseTxns.push_back(b.vtx[0]);
+ coinbaseTxns.push_back(*b.vtx[0]);
}
}
@@ -119,15 +119,14 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>&
// Replace mempool-selected txns with just coinbase plus passed-in txns:
block.vtx.resize(1);
BOOST_FOREACH(const CMutableTransaction& tx, txns)
- block.vtx.push_back(tx);
+ block.vtx.push_back(MakeTransactionRef(tx));
// IncrementExtraNonce creates a valid coinbase and merkleRoot
unsigned int extraNonce = 0;
IncrementExtraNonce(&block, chainActive.Tip(), extraNonce);
while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
- CValidationState state;
- ProcessNewBlock(state, chainparams, NULL, &block, true, NULL, false);
+ ProcessNewBlock(chainparams, &block, true, NULL, NULL);
CBlock result = block;
return result;
@@ -138,12 +137,12 @@ TestChain100Setup::~TestChain100Setup()
}
-CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(CMutableTransaction &tx, CTxMemPool *pool) {
+CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CMutableTransaction &tx, CTxMemPool *pool) {
CTransaction txn(tx);
return FromTx(txn, pool);
}
-CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(CTransaction &txn, CTxMemPool *pool) {
+CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransaction &txn, CTxMemPool *pool) {
bool hasNoDependencies = pool ? pool->HasNoInputsOf(txn) : hadNoDependencies;
// Hack to assume either its completely dependent on other mempool txs or not at all
CAmount inChainValue = hasNoDependencies ? txn.GetValueOut() : 0;
diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h
index 9819a7097d..3dea20445d 100644
--- a/src/test/test_bitcoin.h
+++ b/src/test/test_bitcoin.h
@@ -79,8 +79,8 @@ struct TestMemPoolEntryHelper
nFee(0), nTime(0), dPriority(0.0), nHeight(1),
hadNoDependencies(false), spendsCoinbase(false), sigOpCost(4) { }
- CTxMemPoolEntry FromTx(CMutableTransaction &tx, CTxMemPool *pool = NULL);
- CTxMemPoolEntry FromTx(CTransaction &tx, CTxMemPool *pool = NULL);
+ CTxMemPoolEntry FromTx(const CMutableTransaction &tx, CTxMemPool *pool = NULL);
+ CTxMemPoolEntry FromTx(const CTransaction &tx, CTxMemPool *pool = NULL);
// Change the default value
TestMemPoolEntryHelper &Fee(CAmount _fee) { nFee = _fee; return *this; }
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 45135a5f73..417a88cbef 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -24,7 +24,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
int64_t _nTime, double _entryPriority, unsigned int _entryHeight,
bool poolHasNoInputsOf, CAmount _inChainInputValue,
bool _spendsCoinbase, int64_t _sigOpsCost, LockPoints lp):
- tx(std::make_shared<CTransaction>(_tx)), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), entryHeight(_entryHeight),
+ tx(MakeTransactionRef(_tx)), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), entryHeight(_entryHeight),
hadNoDependencies(poolHasNoInputsOf), inChainInputValue(_inChainInputValue),
spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp)
{
@@ -503,7 +503,7 @@ void CTxMemPool::CalculateDescendants(txiter entryit, setEntries &setDescendants
}
}
-void CTxMemPool::removeRecursive(const CTransaction &origTx, std::vector<std::shared_ptr<const CTransaction>>* removed)
+void CTxMemPool::removeRecursive(const CTransaction &origTx, std::vector<CTransactionRef>* removed)
{
// Remove transaction from memory pool
{
@@ -576,7 +576,7 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem
RemoveStaged(setAllRemoves, false);
}
-void CTxMemPool::removeConflicts(const CTransaction &tx, std::vector<std::shared_ptr<const CTransaction>>* removed)
+void CTxMemPool::removeConflicts(const CTransaction &tx, std::vector<CTransactionRef>* removed)
{
// Remove transactions which depend on inputs of tx, recursively
LOCK(cs);
@@ -596,29 +596,29 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::vector<std::shared
/**
* Called when a block is connected. Removes from mempool and updates the miner fee estimator.
*/
-void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
- std::vector<std::shared_ptr<const CTransaction>>* conflicts, bool fCurrentEstimate)
+void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight,
+ std::vector<CTransactionRef>* conflicts, bool fCurrentEstimate)
{
LOCK(cs);
std::vector<CTxMemPoolEntry> entries;
- BOOST_FOREACH(const CTransaction& tx, vtx)
+ for (const auto& tx : vtx)
{
- uint256 hash = tx.GetHash();
+ uint256 hash = tx->GetHash();
indexed_transaction_set::iterator i = mapTx.find(hash);
if (i != mapTx.end())
entries.push_back(*i);
}
- BOOST_FOREACH(const CTransaction& tx, vtx)
+ for (const auto& tx : vtx)
{
- txiter it = mapTx.find(tx.GetHash());
+ txiter it = mapTx.find(tx->GetHash());
if (it != mapTx.end()) {
setEntries stage;
stage.insert(it);
RemoveStaged(stage, true);
}
- removeConflicts(tx, conflicts);
- ClearPrioritisation(tx.GetHash());
+ removeConflicts(*tx, conflicts);
+ ClearPrioritisation(tx->GetHash());
}
// After the txs in the new block have been removed from the mempool, update policy estimates
minerPolicyEstimator->processBlock(nBlockHeight, entries, fCurrentEstimate);
@@ -851,7 +851,7 @@ std::vector<TxMempoolInfo> CTxMemPool::infoAll() const
return ret;
}
-std::shared_ptr<const CTransaction> CTxMemPool::get(const uint256& hash) const
+CTransactionRef CTxMemPool::get(const uint256& hash) const
{
LOCK(cs);
indexed_transaction_set::const_iterator i = mapTx.find(hash);
@@ -978,7 +978,7 @@ bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) const {
// If an entry in the mempool exists, always return that one, as it's guaranteed to never
// conflict with the underlying cache, and it cannot have pruned entries (as it contains full)
// transactions. First checking the underlying cache risks returning a pruned entry instead.
- shared_ptr<const CTransaction> ptx = mempool.get(txid);
+ CTransactionRef ptx = mempool.get(txid);
if (ptx) {
coins = CCoins(*ptx, MEMPOOL_HEIGHT);
return true;
diff --git a/src/txmempool.h b/src/txmempool.h
index 9b0ca4655e..29b59363a2 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -80,7 +80,7 @@ class CTxMemPool;
class CTxMemPoolEntry
{
private:
- std::shared_ptr<const CTransaction> tx;
+ CTransactionRef tx;
CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups
size_t nTxWeight; //!< ... and avoid recomputing tx weight (also used for GetTxSize())
size_t nModSize; //!< ... and modified size for priority
@@ -118,7 +118,7 @@ public:
CTxMemPoolEntry(const CTxMemPoolEntry& other);
const CTransaction& GetTx() const { return *this->tx; }
- std::shared_ptr<const CTransaction> GetSharedTx() const { return this->tx; }
+ CTransactionRef GetSharedTx() const { return this->tx; }
/**
* Fast calculation of lower bound of current priority as update
* from entry priority. Only inputs that were originally in-chain will age.
@@ -322,7 +322,7 @@ class CBlockPolicyEstimator;
struct TxMempoolInfo
{
/** The transaction itself */
- std::shared_ptr<const CTransaction> tx;
+ CTransactionRef tx;
/** Time the transaction entered the mempool. */
int64_t nTime;
@@ -527,11 +527,11 @@ public:
bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool fCurrentEstimate = true);
bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, setEntries &setAncestors, bool fCurrentEstimate = true);
- void removeRecursive(const CTransaction &tx, std::vector<std::shared_ptr<const CTransaction>>* removed = NULL);
+ void removeRecursive(const CTransaction &tx, std::vector<CTransactionRef>* removed = NULL);
void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags);
- void removeConflicts(const CTransaction &tx, std::vector<std::shared_ptr<const CTransaction>>* removed = NULL);
- void removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
- std::vector<std::shared_ptr<const CTransaction>>* conflicts = NULL, bool fCurrentEstimate = true);
+ void removeConflicts(const CTransaction &tx, std::vector<CTransactionRef>* removed = NULL);
+ void removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight,
+ std::vector<CTransactionRef>* conflicts = NULL, bool fCurrentEstimate = true);
void clear();
void _clear(); //lock free
bool CompareDepthAndScore(const uint256& hasha, const uint256& hashb);
@@ -623,7 +623,7 @@ public:
return (mapTx.count(hash) != 0);
}
- std::shared_ptr<const CTransaction> get(const uint256& hash) const;
+ CTransactionRef get(const uint256& hash) const;
TxMempoolInfo info(const uint256& hash) const;
std::vector<TxMempoolInfo> infoAll() const;
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index acf980c784..ecbbcb145d 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -266,7 +266,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
// test with many inputs
for (CAmount amt=1500; amt < COIN; amt*=10) {
empty_wallet();
- // Create 676 inputs (= MAX_STANDARD_TX_SIZE / 148 bytes per input)
+ // Create 676 inputs (= (old MAX_STANDARD_TX_SIZE == 100000) / 148 bytes per input)
for (uint16_t j = 0; j < 676; j++)
add_coin(amt);
BOOST_CHECK(wallet.SelectCoinsMinConf(2000, 1, 1, vCoins, setCoinsRet, nValueRet));
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 7537604814..9d7ea577de 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1492,7 +1492,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
int posInBlock;
for (posInBlock = 0; posInBlock < (int)block.vtx.size(); posInBlock++)
{
- if (AddToWalletIfInvolvingMe(block.vtx[posInBlock], pindex, posInBlock, fUpdate))
+ if (AddToWalletIfInvolvingMe(*block.vtx[posInBlock], pindex, posInBlock, fUpdate))
ret++;
}
pindex = chainActive.Next(pindex);
@@ -1608,7 +1608,7 @@ CAmount CWalletTx::GetCredit(const isminefilter& filter) const
if (IsCoinBase() && GetBlocksToMaturity() > 0)
return 0;
- int64_t credit = 0;
+ CAmount credit = 0;
if (filter & ISMINE_SPENDABLE)
{
// GetBalance can assume transactions in mapWallet won't change
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index a527c6d84e..409d817046 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -600,7 +600,7 @@ public:
*/
mutable CCriticalSection cs_wallet;
- std::string strWalletFile;
+ const std::string strWalletFile;
void LoadKeyPool(int nIndex, const CKeyPool &keypool)
{
@@ -625,11 +625,9 @@ public:
SetNull();
}
- CWallet(const std::string& strWalletFileIn)
+ CWallet(const std::string& strWalletFileIn) : strWalletFile(strWalletFileIn)
{
SetNull();
-
- strWalletFile = strWalletFileIn;
fFileBacked = true;
}