aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcontrib/devtools/check-doc.py2
-rwxr-xr-xqa/pull-tester/rpc-tests.py2
-rwxr-xr-xqa/rpc-tests/maxuploadtarget.py14
-rwxr-xr-xqa/rpc-tests/p2p-segwit.py1646
-rwxr-xr-xqa/rpc-tests/segwit.py209
-rw-r--r--qa/rpc-tests/test_framework/blocktools.py25
-rwxr-xr-xqa/rpc-tests/test_framework/mininode.py212
-rw-r--r--qa/rpc-tests/test_framework/script.py52
-rw-r--r--src/bitcoin-tx.cpp35
-rw-r--r--src/blockencodings.cpp4
-rw-r--r--src/chain.h2
-rw-r--r--src/chainparams.cpp14
-rw-r--r--src/consensus/consensus.h12
-rw-r--r--src/consensus/merkle.cpp11
-rw-r--r--src/consensus/merkle.h6
-rw-r--r--src/consensus/params.h1
-rw-r--r--src/consensus/validation.h3
-rw-r--r--src/core_io.h2
-rw-r--r--src/core_memusage.h24
-rw-r--r--src/core_read.cpp16
-rw-r--r--src/init.cpp21
-rw-r--r--src/main.cpp440
-rw-r--r--src/main.h27
-rw-r--r--src/merkleblock.cpp2
-rw-r--r--src/miner.cpp119
-rw-r--r--src/miner.h18
-rw-r--r--src/net.cpp10
-rw-r--r--src/net.h22
-rw-r--r--src/policy/policy.cpp16
-rw-r--r--src/policy/policy.h14
-rw-r--r--src/primitives/block.cpp9
-rw-r--r--src/primitives/block.h5
-rw-r--r--src/primitives/transaction.cpp23
-rw-r--r--src/primitives/transaction.h182
-rw-r--r--src/protocol.cpp46
-rw-r--r--src/protocol.h33
-rw-r--r--src/qt/coincontroldialog.cpp18
-rw-r--r--src/qt/guiutil.cpp3
-rw-r--r--src/qt/walletmodeltransaction.cpp3
-rw-r--r--src/rpc/blockchain.cpp5
-rw-r--r--src/rpc/mining.cpp36
-rw-r--r--src/rpc/misc.cpp38
-rw-r--r--src/rpc/rawtransaction.cpp53
-rw-r--r--src/script/bitcoinconsensus.cpp29
-rw-r--r--src/script/bitcoinconsensus.h10
-rw-r--r--src/script/interpreter.cpp240
-rw-r--r--src/script/interpreter.h33
-rw-r--r--src/script/ismine.cpp19
-rw-r--r--src/script/script.cpp38
-rw-r--r--src/script/script.h16
-rw-r--r--src/script/script_error.cpp14
-rw-r--r--src/script/script_error.h9
-rw-r--r--src/script/sigcache.h2
-rw-r--r--src/script/sign.cpp283
-rw-r--r--src/script/sign.h37
-rw-r--r--src/script/standard.cpp41
-rw-r--r--src/script/standard.h3
-rw-r--r--src/streams.h33
-rw-r--r--src/test/DoS_tests.cpp4
-rw-r--r--src/test/data/script_tests.json291
-rw-r--r--src/test/data/tx_invalid.json67
-rw-r--r--src/test/data/tx_valid.json170
-rw-r--r--src/test/mempool_tests.cpp11
-rw-r--r--src/test/miner_tests.cpp5
-rw-r--r--src/test/multisig_tests.cpp21
-rw-r--r--src/test/policyestimator_tests.cpp3
-rw-r--r--src/test/script_P2SH_tests.cpp13
-rw-r--r--src/test/script_tests.cpp370
-rw-r--r--src/test/sighash_tests.cpp6
-rw-r--r--src/test/sigopcount_tests.cpp177
-rw-r--r--src/test/test_bitcoin.cpp2
-rw-r--r--src/test/test_bitcoin.h6
-rw-r--r--src/test/transaction_tests.cpp318
-rw-r--r--src/test/txvalidationcache_tests.cpp2
-rw-r--r--src/txmempool.cpp44
-rw-r--r--src/txmempool.h23
-rw-r--r--src/versionbits.cpp4
-rw-r--r--src/wallet/rpcwallet.cpp82
-rw-r--r--src/wallet/wallet.cpp14
-rw-r--r--src/wallet/walletdb.h1
80 files changed, 5305 insertions, 571 deletions
diff --git a/contrib/devtools/check-doc.py b/contrib/devtools/check-doc.py
index 8c73cf1e8a..06c9551ceb 100755
--- a/contrib/devtools/check-doc.py
+++ b/contrib/devtools/check-doc.py
@@ -21,7 +21,7 @@ CMD_GREP_DOCS = r"egrep -r -I 'HelpMessageOpt\(\"\-[^\"=]+?(=|\")' %s" % (CMD_RO
REGEX_ARG = re.compile(r'(?:map(?:Multi)?Args(?:\.count\(|\[)|Get(?:Bool)?Arg\()\"(\-[^\"]+?)\"')
REGEX_DOC = re.compile(r'HelpMessageOpt\(\"(\-[^\"=]+?)(?:=|\")')
# list unsupported, deprecated and duplicate args as they need no documentation
-SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay'])
+SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay', '-prematurewitness', '-walletprematurewitness', '-promiscuousmempoolflags'])
def main():
used = check_output(CMD_GREP_ARGS, shell=True)
diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py
index 6c0ed4510f..37979a933f 100755
--- a/qa/pull-tester/rpc-tests.py
+++ b/qa/pull-tester/rpc-tests.py
@@ -136,6 +136,8 @@ testScripts = [
'invalidtxrequest.py',
'abandonconflict.py',
'p2p-versionbits-warning.py',
+ 'p2p-segwit.py',
+ 'segwit.py',
'importprunedfunds.py',
'signmessages.py',
]
diff --git a/qa/rpc-tests/maxuploadtarget.py b/qa/rpc-tests/maxuploadtarget.py
index 5087f07620..125d4eb275 100755
--- a/qa/rpc-tests/maxuploadtarget.py
+++ b/qa/rpc-tests/maxuploadtarget.py
@@ -97,7 +97,7 @@ class MaxUploadTest(BitcoinTestFramework):
def setup_network(self):
# Start a node with maxuploadtarget of 200 MB (/24h)
self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-maxuploadtarget=200", "-blockmaxsize=999000"]))
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-maxuploadtarget=800", "-blockmaxsize=999000"]))
def mine_full_block(self, node, address):
# Want to create a full block
@@ -175,13 +175,13 @@ class MaxUploadTest(BitcoinTestFramework):
getdata_request = msg_getdata()
getdata_request.inv.append(CInv(2, big_old_block))
- max_bytes_per_day = 200*1024*1024
- daily_buffer = 144 * MAX_BLOCK_SIZE
+ max_bytes_per_day = 800*1024*1024
+ daily_buffer = 144 * 4000000
max_bytes_available = max_bytes_per_day - daily_buffer
success_count = max_bytes_available // old_block_size
- # 144MB will be reserved for relaying new blocks, so expect this to
- # succeed for ~70 tries.
+ # 576MB will be reserved for relaying new blocks, so expect this to
+ # succeed for ~235 tries.
for i in range(success_count):
test_nodes[0].send_message(getdata_request)
test_nodes[0].sync_with_ping()
@@ -198,9 +198,9 @@ class MaxUploadTest(BitcoinTestFramework):
# Requesting the current block on test_nodes[1] should succeed indefinitely,
# even when over the max upload target.
- # We'll try 200 times
+ # We'll try 800 times
getdata_request.inv = [CInv(2, big_new_block)]
- for i in range(200):
+ for i in range(800):
test_nodes[1].send_message(getdata_request)
test_nodes[1].sync_with_ping()
assert_equal(test_nodes[1].block_receive_map[big_new_block], i+1)
diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py
new file mode 100755
index 0000000000..cf78954f28
--- /dev/null
+++ b/qa/rpc-tests/p2p-segwit.py
@@ -0,0 +1,1646 @@
+#!/usr/bin/env python3
+# Copyright (c) 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.
+
+from test_framework.mininode import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+from test_framework.script import *
+from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment, WITNESS_COMMITMENT_HEADER
+from test_framework.key import CECKey, CPubKey
+import time
+import random
+from binascii import hexlify
+
+# The versionbit bit used to signal activation of SegWit
+VB_WITNESS_BIT = 1
+VB_PERIOD = 144
+VB_ACTIVATION_THRESHOLD = 108
+VB_TOP_BITS = 0x20000000
+
+MAX_SIGOP_COST = 80000
+
+'''
+SegWit p2p test.
+'''
+
+# Calculate the virtual size of a witness block:
+# (base + witness/4)
+def get_virtual_size(witness_block):
+ base_size = len(witness_block.serialize())
+ total_size = len(witness_block.serialize(with_witness=True))
+ # the "+3" is so we round up
+ vsize = int((3*base_size + total_size + 3)/4)
+ return vsize
+
+# Note: we can reduce code by using SingleNodeConnCB (in master, not 0.12)
+class TestNode(NodeConnCB):
+ def __init__(self):
+ NodeConnCB.__init__(self)
+ self.connection = None
+ self.ping_counter = 1
+ self.last_pong = msg_pong(0)
+ self.sleep_time = 0.05
+ self.getdataset = set()
+
+ def add_connection(self, conn):
+ self.connection = conn
+
+ # Wrapper for the NodeConn's send_message function
+ def send_message(self, message):
+ self.connection.send_message(message)
+
+ def on_inv(self, conn, message):
+ self.last_inv = message
+
+ def on_block(self, conn, message):
+ self.last_block = message.block
+ self.last_block.calc_sha256()
+
+ def on_getdata(self, conn, message):
+ for inv in message.inv:
+ self.getdataset.add(inv.hash)
+ self.last_getdata = message
+
+ def on_pong(self, conn, message):
+ self.last_pong = message
+
+ def on_reject(self, conn, message):
+ self.last_reject = message
+ #print message
+
+ # Syncing helpers
+ def sync(self, test_function, timeout=60):
+ while timeout > 0:
+ with mininode_lock:
+ if test_function():
+ return
+ time.sleep(self.sleep_time)
+ timeout -= self.sleep_time
+ raise AssertionError("Sync failed to complete")
+
+ def sync_with_ping(self, timeout=60):
+ self.send_message(msg_ping(nonce=self.ping_counter))
+ test_function = lambda: self.last_pong.nonce == self.ping_counter
+ self.sync(test_function, timeout)
+ self.ping_counter += 1
+ return
+
+ def wait_for_block(self, blockhash, timeout=60):
+ test_function = lambda: self.last_block != None and self.last_block.sha256 == blockhash
+ self.sync(test_function, timeout)
+ return
+
+ def wait_for_getdata(self, timeout=60):
+ test_function = lambda: self.last_getdata != 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)
+
+ def announce_tx_and_wait_for_getdata(self, tx, timeout=60):
+ with mininode_lock:
+ self.last_getdata = None
+ self.send_message(msg_inv(inv=[CInv(1, tx.sha256)]))
+ self.wait_for_getdata(timeout)
+ return
+
+ def announce_block_and_wait_for_getdata(self, block, use_header, timeout=60):
+ with mininode_lock:
+ self.last_getdata = None
+ 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_getdata()
+ return
+
+ def announce_block(self, block, use_header):
+ with mininode_lock:
+ self.last_getdata = None
+ 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)]))
+
+ def request_block(self, blockhash, inv_type, timeout=60):
+ with mininode_lock:
+ self.last_block = None
+ self.send_message(msg_getdata(inv=[CInv(inv_type, blockhash)]))
+ self.wait_for_block(blockhash, timeout)
+ return self.last_block
+
+ def test_transaction_acceptance(self, tx, with_witness, accepted):
+ tx_message = msg_tx(tx)
+ if with_witness:
+ tx_message = msg_witness_tx(tx)
+ self.send_message(tx_message)
+ self.sync_with_ping()
+ assert_equal(tx.hash in self.connection.rpc.getrawmempool(), accepted)
+
+ # Test whether a witness block had the correct effect on the tip
+ def test_witness_block(self, block, accepted, with_witness=True):
+ if with_witness:
+ self.send_message(msg_witness_block(block))
+ else:
+ self.send_message(msg_block(block))
+ self.sync_with_ping()
+ assert_equal(self.connection.rpc.getbestblockhash() == block.hash, accepted)
+
+
+# Used to keep track of anyone-can-spend outputs that we can use in the tests
+class UTXO(object):
+ def __init__(self, sha256, n, nValue):
+ self.sha256 = sha256
+ self.n = n
+ self.nValue = nValue
+
+
+class SegWitTest(BitcoinTestFramework):
+ def setup_chain(self):
+ initialize_chain_clean(self.options.tmpdir, 3)
+
+ def add_options(self, parser):
+ parser.add_option("--oldbinary", dest="oldbinary",
+ default=None,
+ help="pre-segwit bitcoind binary for upgrade testing")
+
+ def setup_network(self):
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-logtimemicros=1", "-whitelist=127.0.0.1"]))
+ # Start a node for testing IsStandard rules.
+ self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-logtimemicros=1", "-whitelist=127.0.0.1", "-acceptnonstdtxn=0"]))
+ connect_nodes(self.nodes[0], 1)
+
+ # If an old bitcoind is given, do the upgrade-after-activation test.
+ self.test_upgrade = False
+ if (self.options.oldbinary != None):
+ self.nodes.append(start_node(2, self.options.tmpdir, ["-debug", "-whitelist=127.0.0.1"], binary=self.options.oldbinary))
+ connect_nodes(self.nodes[0], 2)
+ self.test_upgrade = True
+
+ ''' Helpers '''
+ # Build a block on top of node0's tip.
+ def build_next_block(self, nVersion=4):
+ tip = self.nodes[0].getbestblockhash()
+ height = self.nodes[0].getblockcount() + 1
+ block_time = self.nodes[0].getblockheader(tip)["mediantime"] + 1
+ block = create_block(int(tip, 16), create_coinbase(height), block_time)
+ block.nVersion = nVersion
+ block.rehash()
+ return block
+
+ # Adds list of transactions to block, adds witness commitment, then solves.
+ def update_witness_block_with_transactions(self, block, tx_list, nonce=0):
+ block.vtx.extend(tx_list)
+ add_witness_commitment(block, nonce)
+ block.solve()
+ return
+
+ ''' Individual tests '''
+ def test_witness_services(self):
+ print("\tVerifying NODE_WITNESS service bit")
+ assert((self.test_node.connection.nServices & NODE_WITNESS) != 0)
+
+
+ # See if sending a regular transaction works, and create a utxo
+ # to use in later tests.
+ def test_non_witness_transaction(self):
+ # Mine a block with an anyone-can-spend coinbase,
+ # let it mature, then try to spend it.
+ print("\tTesting non-witness transaction")
+ block = self.build_next_block(nVersion=1)
+ block.solve()
+ self.test_node.send_message(msg_block(block))
+ self.test_node.sync_with_ping() # make sure the block was processed
+ txid = block.vtx[0].sha256
+
+ self.nodes[0].generate(99) # let the block mature
+
+ # Create a transaction that spends the coinbase
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(txid, 0), b""))
+ tx.vout.append(CTxOut(49*100000000, CScript([OP_TRUE])))
+ tx.calc_sha256()
+
+ # Check that serializing it with or without witness is the same
+ # This is a sanity check of our testing framework.
+ assert_equal(msg_tx(tx).serialize(), msg_witness_tx(tx).serialize())
+
+ self.test_node.send_message(msg_witness_tx(tx))
+ self.test_node.sync_with_ping() # make sure the tx was processed
+ assert(tx.hash in self.nodes[0].getrawmempool())
+ # Save this transaction for later
+ self.utxo.append(UTXO(tx.sha256, 0, 49*100000000))
+ self.nodes[0].generate(1)
+
+
+ # Verify that blocks with witnesses are rejected before activation.
+ def test_unnecessary_witness_before_segwit_activation(self):
+ print("\tTesting behavior of unnecessary witnesses")
+ # For now, rely on earlier tests to have created at least one utxo for
+ # us to use
+ assert(len(self.utxo) > 0)
+ assert(get_bip9_status(self.nodes[0], 'segwit')['status'] != 'active')
+
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+ tx.vout.append(CTxOut(self.utxo[0].nValue-1000, CScript([OP_TRUE])))
+ tx.wit.vtxinwit.append(CTxinWitness())
+ tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)])]
+
+ # Verify the hash with witness differs from the txid
+ # (otherwise our testing framework must be broken!)
+ tx.rehash()
+ assert(tx.sha256 != tx.calc_sha256(with_witness=True))
+
+ # Construct a segwit-signaling block that includes the transaction.
+ block = self.build_next_block(nVersion=(VB_TOP_BITS|(1 << VB_WITNESS_BIT)))
+ self.update_witness_block_with_transactions(block, [tx])
+ # Sending witness data before activation is not allowed (anti-spam
+ # rule).
+ self.test_node.test_witness_block(block, accepted=False)
+ # TODO: fix synchronization so we can test reject reason
+ # Right now, bitcoind delays sending reject messages for blocks
+ # until the future, making synchronization here difficult.
+ #assert_equal(self.test_node.last_reject.reason, "unexpected-witness")
+
+ # But it should not be permanently marked bad...
+ # Resend without witness information.
+ self.test_node.send_message(msg_block(block))
+ self.test_node.sync_with_ping()
+ assert_equal(self.nodes[0].getbestblockhash(), block.hash)
+
+ # Update our utxo list; we spent the first entry.
+ self.utxo.pop(0)
+ self.utxo.append(UTXO(tx.sha256, 0, tx.vout[0].nValue))
+
+
+ # Mine enough blocks for segwit's vb state to be 'started'.
+ def advance_to_segwit_started(self):
+ height = self.nodes[0].getblockcount()
+ # Will need to rewrite the tests here if we are past the first period
+ assert(height < VB_PERIOD - 1)
+ # Genesis block is 'defined'.
+ assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'defined')
+ # Advance to end of period, status should now be 'started'
+ self.nodes[0].generate(VB_PERIOD-height-1)
+ assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started')
+
+ # Mine enough blocks to lock in segwit, but don't activate.
+ # TODO: we could verify that lockin only happens at the right threshold of
+ # signalling blocks, rather than just at the right period boundary.
+ def advance_to_segwit_lockin(self):
+ height = self.nodes[0].getblockcount()
+ assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started')
+ # Advance to end of period, and verify lock-in happens at the end
+ self.nodes[0].generate(VB_PERIOD-1)
+ height = self.nodes[0].getblockcount()
+ assert((height % VB_PERIOD) == VB_PERIOD - 2)
+ assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started')
+ self.nodes[0].generate(1)
+ assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in')
+
+
+ # Mine enough blocks to activate segwit.
+ # TODO: we could verify that activation only happens at the right threshold
+ # of signalling blocks, rather than just at the right period boundary.
+ def advance_to_segwit_active(self):
+ assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in')
+ height = self.nodes[0].getblockcount()
+ self.nodes[0].generate(VB_PERIOD - (height%VB_PERIOD) - 2)
+ assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in')
+ self.nodes[0].generate(1)
+ assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'active')
+
+
+ # This test can only be run after segwit has activated
+ def test_witness_commitments(self):
+ print("\tTesting witness commitments")
+
+ # First try a correct witness commitment.
+ block = self.build_next_block()
+ add_witness_commitment(block)
+ block.solve()
+
+ # Test the test -- witness serialization should be different
+ assert(msg_witness_block(block).serialize() != msg_block(block).serialize())
+
+ # This empty block should be valid.
+ self.test_node.test_witness_block(block, accepted=True)
+
+ # Try to tweak the nonce
+ block_2 = self.build_next_block()
+ add_witness_commitment(block_2, nonce=28)
+ block_2.solve()
+
+ # The commitment should have changed!
+ assert(block_2.vtx[0].vout[-1] != block.vtx[0].vout[-1])
+
+ # This should also be valid.
+ self.test_node.test_witness_block(block_2, accepted=True)
+
+ # Now test commitments with actual transactions
+ assert (len(self.utxo) > 0)
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+
+ # Let's construct a witness program
+ witness_program = CScript([OP_TRUE])
+ witness_hash = sha256(witness_program)
+ scriptPubKey = CScript([OP_0, witness_hash])
+ tx.vout.append(CTxOut(self.utxo[0].nValue-1000, scriptPubKey))
+ tx.rehash()
+
+ # tx2 will spend tx1, and send back to a regular anyone-can-spend address
+ tx2 = CTransaction()
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
+ tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, witness_program))
+ tx2.wit.vtxinwit.append(CTxinWitness())
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
+ tx2.rehash()
+
+ block_3 = self.build_next_block()
+ self.update_witness_block_with_transactions(block_3, [tx, tx2], nonce=1)
+ # Add an extra OP_RETURN output that matches the witness commitment template,
+ # even though it has extra data after the incorrect commitment.
+ # This block should fail.
+ block_3.vtx[0].vout.append(CTxOut(0, CScript([OP_RETURN, WITNESS_COMMITMENT_HEADER + ser_uint256(2), 10])))
+ block_3.vtx[0].rehash()
+ block_3.hashMerkleRoot = block_3.calc_merkle_root()
+ block_3.rehash()
+ block_3.solve()
+
+ self.test_node.test_witness_block(block_3, accepted=False)
+
+ # Add a different commitment with different nonce, but in the
+ # right location, and with some funds burned(!).
+ # This should succeed (nValue shouldn't affect finding the
+ # witness commitment).
+ add_witness_commitment(block_3, nonce=0)
+ block_3.vtx[0].vout[0].nValue -= 1
+ block_3.vtx[0].vout[-1].nValue += 1
+ block_3.vtx[0].rehash()
+ block_3.hashMerkleRoot = block_3.calc_merkle_root()
+ block_3.rehash()
+ assert(len(block_3.vtx[0].vout) == 4) # 3 OP_returns
+ block_3.solve()
+ self.test_node.test_witness_block(block_3, accepted=True)
+
+ # Finally test that a block with no witness transactions can
+ # omit the commitment.
+ block_4 = self.build_next_block()
+ tx3 = CTransaction()
+ tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), b""))
+ tx3.vout.append(CTxOut(tx.vout[0].nValue-1000, witness_program))
+ tx3.rehash()
+ block_4.vtx.append(tx3)
+ block_4.hashMerkleRoot = block_4.calc_merkle_root()
+ block_4.solve()
+ self.test_node.test_witness_block(block_4, with_witness=False, accepted=True)
+
+ # Update available utxo's for use in later test.
+ self.utxo.pop(0)
+ self.utxo.append(UTXO(tx3.sha256, 0, tx3.vout[0].nValue))
+
+
+ def test_block_malleability(self):
+ print("\tTesting witness block malleability")
+
+ # Make sure that a block that has too big a virtual size
+ # because of a too-large coinbase witness is not permanently
+ # marked bad.
+ block = self.build_next_block()
+ add_witness_commitment(block)
+ block.solve()
+
+ block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.append(b'a'*5000000)
+ assert(get_virtual_size(block) > MAX_BLOCK_SIZE)
+
+ # We can't send over the p2p network, because this is too big to relay
+ # TODO: repeat this test with a block that can be relayed
+ self.nodes[0].submitblock(bytes_to_hex_str(block.serialize(True)))
+
+ assert(self.nodes[0].getbestblockhash() != block.hash)
+
+ block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.pop()
+ assert(get_virtual_size(block) < MAX_BLOCK_SIZE)
+ self.nodes[0].submitblock(bytes_to_hex_str(block.serialize(True)))
+
+ assert(self.nodes[0].getbestblockhash() == block.hash)
+
+ # Now make sure that malleating the witness nonce doesn't
+ # result in a block permanently marked bad.
+ block = self.build_next_block()
+ add_witness_commitment(block)
+ block.solve()
+
+ # Change the nonce -- should not cause the block to be permanently
+ # failed
+ block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ ser_uint256(1) ]
+ self.test_node.test_witness_block(block, accepted=False)
+
+ # Changing the witness nonce doesn't change the block hash
+ block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ ser_uint256(0) ]
+ self.test_node.test_witness_block(block, accepted=True)
+
+
+ def test_witness_block_size(self):
+ print("\tTesting witness block size limit")
+ # TODO: Test that non-witness carrying blocks can't exceed 1MB
+ # Skipping this test for now; this is covered in p2p-fullblocktest.py
+
+ # Test that witness-bearing blocks are limited at ceil(base + wit/4) <= 1MB.
+ block = self.build_next_block()
+
+ assert(len(self.utxo) > 0)
+
+ # Create a P2WSH transaction.
+ # The witness program will be a bunch of OP_2DROP's, followed by OP_TRUE.
+ # This should give us plenty of room to tweak the spending tx's
+ # virtual size.
+ NUM_DROPS = 200 # 201 max ops per script!
+ NUM_OUTPUTS = 50
+
+ witness_program = CScript([OP_2DROP]*NUM_DROPS + [OP_TRUE])
+ witness_hash = uint256_from_str(sha256(witness_program))
+ scriptPubKey = CScript([OP_0, ser_uint256(witness_hash)])
+
+ prevout = COutPoint(self.utxo[0].sha256, self.utxo[0].n)
+ value = self.utxo[0].nValue
+
+ parent_tx = CTransaction()
+ parent_tx.vin.append(CTxIn(prevout, b""))
+ child_value = int(value/NUM_OUTPUTS)
+ for i in range(NUM_OUTPUTS):
+ parent_tx.vout.append(CTxOut(child_value, scriptPubKey))
+ parent_tx.vout[0].nValue -= 50000
+ assert(parent_tx.vout[0].nValue > 0)
+ parent_tx.rehash()
+
+ child_tx = CTransaction()
+ for i in range(NUM_OUTPUTS):
+ child_tx.vin.append(CTxIn(COutPoint(parent_tx.sha256, i), b""))
+ child_tx.vout = [CTxOut(value - 100000, CScript([OP_TRUE]))]
+ for i in range(NUM_OUTPUTS):
+ child_tx.wit.vtxinwit.append(CTxinWitness())
+ child_tx.wit.vtxinwit[-1].scriptWitness.stack = [b'a'*195]*(2*NUM_DROPS) + [witness_program]
+ child_tx.rehash()
+ self.update_witness_block_with_transactions(block, [parent_tx, child_tx])
+
+ vsize = get_virtual_size(block)
+ additional_bytes = (MAX_BLOCK_SIZE - vsize)*4
+ i = 0
+ while additional_bytes > 0:
+ # Add some more bytes to each input until we hit MAX_BLOCK_SIZE+1
+ extra_bytes = min(additional_bytes+1, 55)
+ block.vtx[-1].wit.vtxinwit[int(i/(2*NUM_DROPS))].scriptWitness.stack[i%(2*NUM_DROPS)] = b'a'*(195+extra_bytes)
+ additional_bytes -= extra_bytes
+ i += 1
+
+ block.vtx[0].vout.pop() # Remove old commitment
+ add_witness_commitment(block)
+ block.solve()
+ vsize = get_virtual_size(block)
+ assert_equal(vsize, MAX_BLOCK_SIZE + 1)
+ # Make sure that our test case would exceed the old max-network-message
+ # limit
+ assert(len(block.serialize(True)) > 2*1024*1024)
+
+ self.test_node.test_witness_block(block, accepted=False)
+
+ # Now resize the second transaction to make the block fit.
+ cur_length = len(block.vtx[-1].wit.vtxinwit[0].scriptWitness.stack[0])
+ block.vtx[-1].wit.vtxinwit[0].scriptWitness.stack[0] = b'a'*(cur_length-1)
+ block.vtx[0].vout.pop()
+ add_witness_commitment(block)
+ block.solve()
+ assert(get_virtual_size(block) == MAX_BLOCK_SIZE)
+
+ self.test_node.test_witness_block(block, accepted=True)
+
+ # Update available utxo's
+ self.utxo.pop(0)
+ self.utxo.append(UTXO(block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue))
+
+
+ # submitblock will try to add the nonce automatically, so that mining
+ # software doesn't need to worry about doing so itself.
+ def test_submit_block(self):
+ block = self.build_next_block()
+
+ # Try using a custom nonce and then don't supply it.
+ # This shouldn't possibly work.
+ add_witness_commitment(block, nonce=1)
+ block.vtx[0].wit = CTxWitness() # drop the nonce
+ block.solve()
+ self.nodes[0].submitblock(bytes_to_hex_str(block.serialize(True)))
+ assert(self.nodes[0].getbestblockhash() != block.hash)
+
+ # Now redo commitment with the standard nonce, but let bitcoind fill it in.
+ add_witness_commitment(block, nonce=0)
+ block.vtx[0].wit = CTxWitness()
+ block.solve()
+ self.nodes[0].submitblock(bytes_to_hex_str(block.serialize(True)))
+ assert_equal(self.nodes[0].getbestblockhash(), block.hash)
+
+ # This time, add a tx with non-empty witness, but don't supply
+ # the commitment.
+ block_2 = self.build_next_block()
+
+ add_witness_commitment(block_2)
+
+ block_2.solve()
+
+ # Drop commitment and nonce -- submitblock should not fill in.
+ block_2.vtx[0].vout.pop()
+ block_2.vtx[0].wit = CTxWitness()
+
+ self.nodes[0].submitblock(bytes_to_hex_str(block_2.serialize(True)))
+ # Tip should not advance!
+ assert(self.nodes[0].getbestblockhash() != block_2.hash)
+
+
+ # Consensus tests of extra witness data in a transaction.
+ def test_extra_witness_data(self):
+ print("\tTesting extra witness data in tx")
+
+ assert(len(self.utxo) > 0)
+
+ block = self.build_next_block()
+
+ witness_program = CScript([OP_DROP, OP_TRUE])
+ witness_hash = sha256(witness_program)
+ scriptPubKey = CScript([OP_0, witness_hash])
+
+ # First try extra witness data on a tx that doesn't require a witness
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+ tx.vout.append(CTxOut(self.utxo[0].nValue-2000, scriptPubKey))
+ tx.vout.append(CTxOut(1000, CScript([OP_TRUE]))) # non-witness output
+ tx.wit.vtxinwit.append(CTxinWitness())
+ tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([])]
+ tx.rehash()
+ self.update_witness_block_with_transactions(block, [tx])
+
+ # Extra witness data should not be allowed.
+ self.test_node.test_witness_block(block, accepted=False)
+
+ # Try extra signature data. Ok if we're not spending a witness output.
+ block.vtx[1].wit.vtxinwit = []
+ block.vtx[1].vin[0].scriptSig = CScript([OP_0])
+ block.vtx[1].rehash()
+ add_witness_commitment(block)
+ block.solve()
+
+ self.test_node.test_witness_block(block, accepted=True)
+
+ # Now try extra witness/signature data on an input that DOES require a
+ # witness
+ tx2 = CTransaction()
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) # witness output
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, 1), b"")) # non-witness
+ tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE])))
+ tx2.wit.vtxinwit.extend([CTxinWitness(), CTxinWitness()])
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [ CScript([CScriptNum(1)]), CScript([CScriptNum(1)]), witness_program ]
+ tx2.wit.vtxinwit[1].scriptWitness.stack = [ CScript([OP_TRUE]) ]
+
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx2])
+
+ # This has extra witness data, so it should fail.
+ self.test_node.test_witness_block(block, accepted=False)
+
+ # Now get rid of the extra witness, but add extra scriptSig data
+ tx2.vin[0].scriptSig = CScript([OP_TRUE])
+ tx2.vin[1].scriptSig = CScript([OP_TRUE])
+ tx2.wit.vtxinwit[0].scriptWitness.stack.pop(0)
+ tx2.wit.vtxinwit[1].scriptWitness.stack = []
+ tx2.rehash()
+ add_witness_commitment(block)
+ block.solve()
+
+ # This has extra signature data for a witness input, so it should fail.
+ self.test_node.test_witness_block(block, accepted=False)
+
+ # Now get rid of the extra scriptsig on the witness input, and verify
+ # success (even with extra scriptsig data in the non-witness input)
+ tx2.vin[0].scriptSig = b""
+ tx2.rehash()
+ add_witness_commitment(block)
+ block.solve()
+
+ self.test_node.test_witness_block(block, accepted=True)
+
+ # Update utxo for later tests
+ self.utxo.pop(0)
+ self.utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue))
+
+
+ def test_max_witness_push_length(self):
+ ''' Should only allow up to 520 byte pushes in witness stack '''
+ print("\tTesting maximum witness push size")
+ MAX_SCRIPT_ELEMENT_SIZE = 520
+ assert(len(self.utxo))
+
+ block = self.build_next_block()
+
+ witness_program = CScript([OP_DROP, OP_TRUE])
+ witness_hash = sha256(witness_program)
+ scriptPubKey = CScript([OP_0, witness_hash])
+
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+ tx.vout.append(CTxOut(self.utxo[0].nValue-1000, scriptPubKey))
+ tx.rehash()
+
+ tx2 = CTransaction()
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
+ tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE])))
+ tx2.wit.vtxinwit.append(CTxinWitness())
+ # First try a 521-byte stack element
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [ b'a'*(MAX_SCRIPT_ELEMENT_SIZE+1), witness_program ]
+ tx2.rehash()
+
+ self.update_witness_block_with_transactions(block, [tx, tx2])
+ self.test_node.test_witness_block(block, accepted=False)
+
+ # Now reduce the length of the stack element
+ tx2.wit.vtxinwit[0].scriptWitness.stack[0] = b'a'*(MAX_SCRIPT_ELEMENT_SIZE)
+
+ add_witness_commitment(block)
+ block.solve()
+ self.test_node.test_witness_block(block, accepted=True)
+
+ # Update the utxo for later tests
+ self.utxo.pop()
+ self.utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue))
+
+ def test_max_witness_program_length(self):
+ # Can create witness outputs that are long, but can't be greater than
+ # 10k bytes to successfully spend
+ print("\tTesting maximum witness program length")
+ assert(len(self.utxo))
+ MAX_PROGRAM_LENGTH = 10000
+
+ # This program is 19 max pushes (9937 bytes), then 64 more opcode-bytes.
+ long_witness_program = CScript([b'a'*520]*19 + [OP_DROP]*63 + [OP_TRUE])
+ assert(len(long_witness_program) == MAX_PROGRAM_LENGTH+1)
+ long_witness_hash = sha256(long_witness_program)
+ long_scriptPubKey = CScript([OP_0, long_witness_hash])
+
+ block = self.build_next_block()
+
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+ tx.vout.append(CTxOut(self.utxo[0].nValue-1000, long_scriptPubKey))
+ tx.rehash()
+
+ tx2 = CTransaction()
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
+ tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE])))
+ tx2.wit.vtxinwit.append(CTxinWitness())
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a']*44 + [long_witness_program]
+ tx2.rehash()
+
+ self.update_witness_block_with_transactions(block, [tx, tx2])
+
+ self.test_node.test_witness_block(block, accepted=False)
+
+ # Try again with one less byte in the witness program
+ witness_program = CScript([b'a'*520]*19 + [OP_DROP]*62 + [OP_TRUE])
+ assert(len(witness_program) == MAX_PROGRAM_LENGTH)
+ witness_hash = sha256(witness_program)
+ scriptPubKey = CScript([OP_0, witness_hash])
+
+ tx.vout[0] = CTxOut(tx.vout[0].nValue, scriptPubKey)
+ tx.rehash()
+ tx2.vin[0].prevout.hash = tx.sha256
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a']*43 + [witness_program]
+ tx2.rehash()
+ block.vtx = [block.vtx[0]]
+ self.update_witness_block_with_transactions(block, [tx, tx2])
+ self.test_node.test_witness_block(block, accepted=True)
+
+ self.utxo.pop()
+ self.utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue))
+
+
+ def test_witness_input_length(self):
+ ''' Ensure that vin length must match vtxinwit length '''
+ print("\tTesting witness input length")
+ assert(len(self.utxo))
+
+ witness_program = CScript([OP_DROP, OP_TRUE])
+ witness_hash = sha256(witness_program)
+ scriptPubKey = CScript([OP_0, witness_hash])
+
+ # Create a transaction that splits our utxo into many outputs
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+ nValue = self.utxo[0].nValue
+ for i in range(10):
+ tx.vout.append(CTxOut(int(nValue/10), scriptPubKey))
+ tx.vout[0].nValue -= 1000
+ assert(tx.vout[0].nValue >= 0)
+
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx])
+ self.test_node.test_witness_block(block, accepted=True)
+
+ # Try various ways to spend tx that should all break.
+ # This "broken" transaction serializer will not normalize
+ # the length of vtxinwit.
+ class BrokenCTransaction(CTransaction):
+ def serialize_with_witness(self):
+ flags = 0
+ if not self.wit.is_null():
+ flags |= 1
+ r = b""
+ r += struct.pack("<i", self.nVersion)
+ if flags:
+ dummy = []
+ r += ser_vector(dummy)
+ r += struct.pack("<B", flags)
+ r += ser_vector(self.vin)
+ r += ser_vector(self.vout)
+ if flags & 1:
+ r += self.wit.serialize()
+ r += struct.pack("<I", self.nLockTime)
+ return r
+
+ tx2 = BrokenCTransaction()
+ for i in range(10):
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, i), b""))
+ tx2.vout.append(CTxOut(nValue-3000, CScript([OP_TRUE])))
+
+ # First try using a too long vtxinwit
+ for i in range(11):
+ tx2.wit.vtxinwit.append(CTxinWitness())
+ tx2.wit.vtxinwit[i].scriptWitness.stack = [b'a', witness_program]
+
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx2])
+ self.test_node.test_witness_block(block, accepted=False)
+
+ # Now try using a too short vtxinwit
+ tx2.wit.vtxinwit.pop()
+ tx2.wit.vtxinwit.pop()
+
+ block.vtx = [block.vtx[0]]
+ self.update_witness_block_with_transactions(block, [tx2])
+ self.test_node.test_witness_block(block, accepted=False)
+
+ # Now make one of the intermediate witnesses be incorrect
+ tx2.wit.vtxinwit.append(CTxinWitness())
+ tx2.wit.vtxinwit[-1].scriptWitness.stack = [b'a', witness_program]
+ tx2.wit.vtxinwit[5].scriptWitness.stack = [ witness_program ]
+
+ block.vtx = [block.vtx[0]]
+ self.update_witness_block_with_transactions(block, [tx2])
+ self.test_node.test_witness_block(block, accepted=False)
+
+ # Fix the broken witness and the block should be accepted.
+ tx2.wit.vtxinwit[5].scriptWitness.stack = [b'a', witness_program]
+ block.vtx = [block.vtx[0]]
+ self.update_witness_block_with_transactions(block, [tx2])
+ self.test_node.test_witness_block(block, accepted=True)
+
+ self.utxo.pop()
+ self.utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue))
+
+
+ def test_witness_tx_relay_before_segwit_activation(self):
+ print("\tTesting relay of witness transactions")
+ # Generate a transaction that doesn't require a witness, but send it
+ # with a witness. Should be rejected for premature-witness, but should
+ # not be added to recently rejected list.
+ assert(len(self.utxo))
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+ tx.vout.append(CTxOut(self.utxo[0].nValue-1000, CScript([OP_TRUE])))
+ tx.wit.vtxinwit.append(CTxinWitness())
+ tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a' ]
+ tx.rehash()
+
+ tx_hash = tx.sha256
+ tx_value = tx.vout[0].nValue
+
+ # Verify that if a peer doesn't set nServices to include NODE_WITNESS,
+ # the getdata is just for the non-witness portion.
+ self.old_node.announce_tx_and_wait_for_getdata(tx)
+ assert(self.old_node.last_getdata.inv[0].type == 1)
+
+ # Since we haven't delivered the tx yet, inv'ing the same tx from
+ # a witness transaction ought not result in a getdata.
+ try:
+ self.test_node.announce_tx_and_wait_for_getdata(tx, timeout=2)
+ print("Error: duplicate tx getdata!")
+ assert(False)
+ except AssertionError as e:
+ pass
+
+ # Delivering this transaction with witness should fail (no matter who
+ # its from)
+ assert_equal(len(self.nodes[0].getrawmempool()), 0)
+ assert_equal(len(self.nodes[1].getrawmempool()), 0)
+ self.old_node.test_transaction_acceptance(tx, with_witness=True, accepted=False)
+ self.test_node.test_transaction_acceptance(tx, with_witness=True, accepted=False)
+
+ # But eliminating the witness should fix it
+ self.test_node.test_transaction_acceptance(tx, with_witness=False, accepted=True)
+
+ # Verify that inv's to test_node come with getdata's for non-witness tx's
+ # Just tweak the transaction, announce it, and verify we get a getdata
+ # for a normal tx
+ tx.vout[0].scriptPubKey = CScript([OP_TRUE, OP_TRUE])
+ tx.rehash()
+ self.test_node.announce_tx_and_wait_for_getdata(tx)
+ assert(self.test_node.last_getdata.inv[0].type == 1)
+
+ # Cleanup: mine the first transaction and update utxo
+ self.nodes[0].generate(1)
+ assert_equal(len(self.nodes[0].getrawmempool()), 0)
+
+ self.utxo.pop(0)
+ self.utxo.append(UTXO(tx_hash, 0, tx_value))
+
+
+ # After segwit activates, verify that mempool:
+ # - rejects transactions with unnecessary/extra witnesses
+ # - accepts transactions with valid witnesses
+ # and that witness transactions are relayed to non-upgraded peers.
+ def test_tx_relay_after_segwit_activation(self):
+ print("\tTesting relay of witness transactions")
+ # Generate a transaction that doesn't require a witness, but send it
+ # with a witness. Should be rejected because we can't use a witness
+ # when spending a non-witness output.
+ assert(len(self.utxo))
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+ tx.vout.append(CTxOut(self.utxo[0].nValue-1000, CScript([OP_TRUE])))
+ tx.wit.vtxinwit.append(CTxinWitness())
+ tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a' ]
+ tx.rehash()
+
+ tx_hash = tx.sha256
+ tx_value = tx.vout[0].nValue
+
+ # Verify that unnecessary witnesses are rejected.
+ self.test_node.announce_tx_and_wait_for_getdata(tx)
+ assert_equal(len(self.nodes[0].getrawmempool()), 0)
+ self.test_node.test_transaction_acceptance(tx, with_witness=True, accepted=False)
+
+ # Verify that removing the witness succeeds.
+ # Re-announcing won't result in a getdata for ~2.5 minutes, so just
+ # deliver the modified transaction.
+ self.test_node.test_transaction_acceptance(tx, with_witness=False, accepted=True)
+
+ # Now try to add extra witness data to a valid witness tx.
+ witness_program = CScript([OP_TRUE])
+ witness_hash = sha256(witness_program)
+ scriptPubKey = CScript([OP_0, witness_hash])
+ tx2 = CTransaction()
+ tx2.vin.append(CTxIn(COutPoint(tx_hash, 0), b""))
+ tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, scriptPubKey))
+ tx2.rehash()
+
+ tx3 = CTransaction()
+ tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), b""))
+ tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, CScript([OP_TRUE])))
+ tx3.wit.vtxinwit.append(CTxinWitness())
+ tx3.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), witness_program ]
+ tx3.rehash()
+
+ self.test_node.test_transaction_acceptance(tx2, with_witness=True, accepted=True)
+ self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=False)
+
+ # Get rid of the extra witness, and verify acceptance.
+ tx3.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ]
+ # Also check that old_node gets a tx announcement, even though this is
+ # a witness transaction.
+ self.old_node.wait_for_inv(CInv(1, tx2.sha256)) # wait until tx2 was inv'ed
+ self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=True)
+ self.old_node.wait_for_inv(CInv(1, tx3.sha256))
+
+ # Test that getrawtransaction returns correct witness information
+ # hash, size, vsize
+ raw_tx = self.nodes[0].getrawtransaction(tx3.hash, 1)
+ assert_equal(int(raw_tx["hash"], 16), tx3.calc_sha256(True))
+ assert_equal(raw_tx["size"], len(tx3.serialize_with_witness()))
+ vsize = (len(tx3.serialize_with_witness()) + 3*len(tx3.serialize_without_witness()) + 3) / 4
+ assert_equal(raw_tx["vsize"], vsize)
+ assert_equal(len(raw_tx["vin"][0]["txinwitness"]), 1)
+ assert_equal(raw_tx["vin"][0]["txinwitness"][0], hexlify(witness_program).decode('ascii'))
+ assert(vsize != raw_tx["size"])
+
+ # Cleanup: mine the transactions and update utxo for next test
+ self.nodes[0].generate(1)
+ assert_equal(len(self.nodes[0].getrawmempool()), 0)
+
+ self.utxo.pop(0)
+ self.utxo.append(UTXO(tx3.sha256, 0, tx3.vout[0].nValue))
+
+
+ # Test that block requests to NODE_WITNESS peer are with MSG_WITNESS_FLAG
+ # This is true regardless of segwit activation.
+ # Also test that we don't ask for blocks from unupgraded peers
+ def test_block_relay(self, segwit_activated):
+ print("\tTesting block relay")
+
+ blocktype = 2|MSG_WITNESS_FLAG if segwit_activated else 2
+
+ # test_node has set NODE_WITNESS, so all getdata requests should be for
+ # witness blocks.
+ # Test announcing a block via inv results in a getdata, and that
+ # announcing a version 4 or random VB block with a header results in a getdata
+ block1 = self.build_next_block()
+ block1.solve()
+
+ self.test_node.announce_block_and_wait_for_getdata(block1, use_header=False)
+ assert(self.test_node.last_getdata.inv[0].type == blocktype)
+ self.test_node.test_witness_block(block1, True)
+
+ block2 = self.build_next_block(nVersion=4)
+ block2.solve()
+
+ self.test_node.announce_block_and_wait_for_getdata(block2, use_header=True)
+ assert(self.test_node.last_getdata.inv[0].type == blocktype)
+ self.test_node.test_witness_block(block2, True)
+
+ block3 = self.build_next_block(nVersion=(VB_TOP_BITS | (1<<15)))
+ block3.solve()
+ self.test_node.announce_block_and_wait_for_getdata(block3, use_header=True)
+ assert(self.test_node.last_getdata.inv[0].type == blocktype)
+ self.test_node.test_witness_block(block3, True)
+
+ # Check that we can getdata for witness blocks or regular blocks,
+ # and the right thing happens.
+ if segwit_activated == False:
+ # Before activation, we should be able to request old blocks with
+ # or without witness, and they should be the same.
+ chain_height = self.nodes[0].getblockcount()
+ # Pick 10 random blocks on main chain, and verify that getdata's
+ # for MSG_BLOCK, MSG_WITNESS_BLOCK, and rpc getblock() are equal.
+ all_heights = list(range(chain_height+1))
+ random.shuffle(all_heights)
+ all_heights = all_heights[0:10]
+ for height in all_heights:
+ block_hash = self.nodes[0].getblockhash(height)
+ rpc_block = self.nodes[0].getblock(block_hash, False)
+ block_hash = int(block_hash, 16)
+ block = self.test_node.request_block(block_hash, 2)
+ wit_block = self.test_node.request_block(block_hash, 2|MSG_WITNESS_FLAG)
+ assert_equal(block.serialize(True), wit_block.serialize(True))
+ assert_equal(block.serialize(), hex_str_to_bytes(rpc_block))
+ else:
+ # After activation, witness blocks and non-witness blocks should
+ # be different. Verify rpc getblock() returns witness blocks, while
+ # getdata respects the requested type.
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [])
+ # This gives us a witness commitment.
+ assert(len(block.vtx[0].wit.vtxinwit) == 1)
+ assert(len(block.vtx[0].wit.vtxinwit[0].scriptWitness.stack) == 1)
+ self.test_node.test_witness_block(block, accepted=True)
+ # Now try to retrieve it...
+ rpc_block = self.nodes[0].getblock(block.hash, False)
+ non_wit_block = self.test_node.request_block(block.sha256, 2)
+ wit_block = self.test_node.request_block(block.sha256, 2|MSG_WITNESS_FLAG)
+ assert_equal(wit_block.serialize(True), hex_str_to_bytes(rpc_block))
+ assert_equal(wit_block.serialize(False), non_wit_block.serialize())
+ assert_equal(wit_block.serialize(True), block.serialize(True))
+
+ # Test size, vsize, cost
+ rpc_details = self.nodes[0].getblock(block.hash, True)
+ assert_equal(rpc_details["size"], len(block.serialize(True)))
+ assert_equal(rpc_details["strippedsize"], len(block.serialize(False)))
+ cost = 3*len(block.serialize(False)) + len(block.serialize(True))
+ assert_equal(rpc_details["cost"], cost)
+
+ # Upgraded node should not ask for blocks from unupgraded
+ block4 = self.build_next_block(nVersion=4)
+ block4.solve()
+ self.old_node.getdataset = set()
+ # Blocks can be requested via direct-fetch (immediately upon processing the announcement)
+ # or via parallel download (with an indeterminate delay from processing the announcement)
+ # so to test that a block is NOT requested, we could guess a time period to sleep for,
+ # and then check. We can avoid the sleep() by taking advantage of transaction getdata's
+ # being processed after block getdata's, and announce a transaction as well,
+ # and then check to see if that particular getdata has been received.
+ self.old_node.announce_block(block4, use_header=False)
+ self.old_node.announce_tx_and_wait_for_getdata(block4.vtx[0])
+ assert(block4.sha256 not in self.old_node.getdataset)
+
+ # Verify that future segwit upgraded transactions are non-standard,
+ # but valid in blocks. Can run this before and after segwit activation.
+ def test_segwit_versions(self):
+ print("\tTesting standardness/consensus for segwit versions (0-16)")
+ assert(len(self.utxo))
+ NUM_TESTS = 17 # will test OP_0, OP1, ..., OP_16
+ if (len(self.utxo) < NUM_TESTS):
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+ split_value = (self.utxo[0].nValue - 4000) // NUM_TESTS
+ for i in range(NUM_TESTS):
+ tx.vout.append(CTxOut(split_value, CScript([OP_TRUE])))
+ tx.rehash()
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx])
+ self.test_node.test_witness_block(block, accepted=True)
+ self.utxo.pop(0)
+ for i in range(NUM_TESTS):
+ self.utxo.append(UTXO(tx.sha256, i, split_value))
+
+ sync_blocks(self.nodes)
+ temp_utxo = []
+ tx = CTransaction()
+ count = 0
+ witness_program = CScript([OP_TRUE])
+ witness_hash = sha256(witness_program)
+ assert_equal(len(self.nodes[1].getrawmempool()), 0)
+ for version in list(range(OP_1, OP_16+1)) + [OP_0]:
+ count += 1
+ # First try to spend to a future version segwit scriptPubKey.
+ scriptPubKey = CScript([CScriptOp(version), witness_hash])
+ tx.vin = [CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")]
+ tx.vout = [CTxOut(self.utxo[0].nValue-1000, scriptPubKey)]
+ tx.rehash()
+ self.std_node.test_transaction_acceptance(tx, with_witness=True, accepted=False)
+ self.test_node.test_transaction_acceptance(tx, with_witness=True, accepted=True)
+ self.utxo.pop(0)
+ temp_utxo.append(UTXO(tx.sha256, 0, tx.vout[0].nValue))
+
+ self.nodes[0].generate(1) # Mine all the transactions
+ sync_blocks(self.nodes)
+ assert(len(self.nodes[0].getrawmempool()) == 0)
+
+ # Finally, verify that version 0 -> version 1 transactions
+ # are non-standard
+ scriptPubKey = CScript([CScriptOp(OP_1), witness_hash])
+ tx2 = CTransaction()
+ tx2.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")]
+ tx2.vout = [CTxOut(tx.vout[0].nValue-1000, scriptPubKey)]
+ tx2.wit.vtxinwit.append(CTxinWitness())
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ]
+ tx2.rehash()
+ # Gets accepted to test_node, because standardness of outputs isn't
+ # checked with fRequireStandard
+ self.test_node.test_transaction_acceptance(tx2, with_witness=True, accepted=True)
+ self.std_node.test_transaction_acceptance(tx2, with_witness=True, accepted=False)
+ temp_utxo.pop() # last entry in temp_utxo was the output we just spent
+ temp_utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue))
+
+ # Spend everything in temp_utxo back to an OP_TRUE output.
+ tx3 = CTransaction()
+ total_value = 0
+ for i in temp_utxo:
+ tx3.vin.append(CTxIn(COutPoint(i.sha256, i.n), b""))
+ tx3.wit.vtxinwit.append(CTxinWitness())
+ total_value += i.nValue
+ tx3.wit.vtxinwit[-1].scriptWitness.stack = [witness_program]
+ tx3.vout.append(CTxOut(total_value - 1000, CScript([OP_TRUE])))
+ tx3.rehash()
+ # Spending a higher version witness output is not allowed by policy,
+ # even with fRequireStandard=false.
+ self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=False)
+ self.test_node.sync_with_ping()
+ with mininode_lock:
+ assert(b"reserved for soft-fork upgrades" in self.test_node.last_reject.reason)
+
+ # Building a block with the transaction must be valid, however.
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx2, tx3])
+ self.test_node.test_witness_block(block, accepted=True)
+ sync_blocks(self.nodes)
+
+ # Add utxo to our list
+ self.utxo.append(UTXO(tx3.sha256, 0, tx3.vout[0].nValue))
+
+
+ def test_premature_coinbase_witness_spend(self):
+ print("\tTesting premature coinbase witness spend")
+ block = self.build_next_block()
+ # Change the output of the block to be a witness output.
+ witness_program = CScript([OP_TRUE])
+ witness_hash = sha256(witness_program)
+ scriptPubKey = CScript([OP_0, witness_hash])
+ block.vtx[0].vout[0].scriptPubKey = scriptPubKey
+ # This next line will rehash the coinbase and update the merkle
+ # root, and solve.
+ self.update_witness_block_with_transactions(block, [])
+ self.test_node.test_witness_block(block, accepted=True)
+
+ spend_tx = CTransaction()
+ spend_tx.vin = [CTxIn(COutPoint(block.vtx[0].sha256, 0), b"")]
+ spend_tx.vout = [CTxOut(block.vtx[0].vout[0].nValue, witness_program)]
+ spend_tx.wit.vtxinwit.append(CTxinWitness())
+ spend_tx.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ]
+ spend_tx.rehash()
+
+ # Now test a premature spend.
+ self.nodes[0].generate(98)
+ sync_blocks(self.nodes)
+ block2 = self.build_next_block()
+ self.update_witness_block_with_transactions(block2, [spend_tx])
+ self.test_node.test_witness_block(block2, accepted=False)
+
+ # Advancing one more block should allow the spend.
+ self.nodes[0].generate(1)
+ block2 = self.build_next_block()
+ self.update_witness_block_with_transactions(block2, [spend_tx])
+ self.test_node.test_witness_block(block2, accepted=True)
+ sync_blocks(self.nodes)
+
+
+ def test_signature_version_1(self):
+ print("\tTesting segwit signature hash version 1")
+ key = CECKey()
+ key.set_secretbytes(b"9")
+ pubkey = CPubKey(key.get_pubkey())
+
+ witness_program = CScript([pubkey, CScriptOp(OP_CHECKSIG)])
+ witness_hash = sha256(witness_program)
+ scriptPubKey = CScript([OP_0, witness_hash])
+
+ # First create a witness output for use in the tests.
+ assert(len(self.utxo))
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+ tx.vout.append(CTxOut(self.utxo[0].nValue-1000, scriptPubKey))
+ tx.rehash()
+
+ self.test_node.test_transaction_acceptance(tx, with_witness=True, accepted=True)
+ # Mine this transaction in preparation for following tests.
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx])
+ self.test_node.test_witness_block(block, accepted=True)
+ sync_blocks(self.nodes)
+ self.utxo.pop(0)
+
+ # Add signature for a P2PK witness program.
+ def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key):
+ tx_hash = SegwitVersion1SignatureHash(script, txTo, inIdx, hashtype, value)
+ signature = key.sign(tx_hash) + chr(hashtype).encode('latin-1')
+ txTo.wit.vtxinwit[inIdx].scriptWitness.stack = [signature, script]
+ txTo.rehash()
+
+ # Test each hashtype
+ prev_utxo = UTXO(tx.sha256, 0, tx.vout[0].nValue)
+ for sigflag in [ 0, SIGHASH_ANYONECANPAY ]:
+ for hashtype in [SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE]:
+ hashtype |= sigflag
+ block = self.build_next_block()
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(prev_utxo.sha256, prev_utxo.n), b""))
+ tx.vout.append(CTxOut(prev_utxo.nValue - 1000, scriptPubKey))
+ tx.wit.vtxinwit.append(CTxinWitness())
+ # Too-large input value
+ sign_P2PK_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue+1, key)
+ self.update_witness_block_with_transactions(block, [tx])
+ self.test_node.test_witness_block(block, accepted=False)
+
+ # Too-small input value
+ sign_P2PK_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue-1, key)
+ block.vtx.pop() # remove last tx
+ self.update_witness_block_with_transactions(block, [tx])
+ self.test_node.test_witness_block(block, accepted=False)
+
+ # Now try correct value
+ sign_P2PK_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue, key)
+ block.vtx.pop()
+ self.update_witness_block_with_transactions(block, [tx])
+ self.test_node.test_witness_block(block, accepted=True)
+
+ prev_utxo = UTXO(tx.sha256, 0, tx.vout[0].nValue)
+
+ # Test combinations of signature hashes.
+ # Split the utxo into a lot of outputs.
+ # Randomly choose up to 10 to spend, sign with different hashtypes, and
+ # output to a random number of outputs. Repeat NUM_TESTS times.
+ # Ensure that we've tested a situation where we use SIGHASH_SINGLE with
+ # an input index > number of outputs.
+ NUM_TESTS = 500
+ temp_utxos = []
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(prev_utxo.sha256, prev_utxo.n), b""))
+ split_value = prev_utxo.nValue // NUM_TESTS
+ for i in range(NUM_TESTS):
+ tx.vout.append(CTxOut(split_value, scriptPubKey))
+ tx.wit.vtxinwit.append(CTxinWitness())
+ sign_P2PK_witness_input(witness_program, tx, 0, SIGHASH_ALL, prev_utxo.nValue, key)
+ for i in range(NUM_TESTS):
+ temp_utxos.append(UTXO(tx.sha256, i, split_value))
+
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx])
+ self.test_node.test_witness_block(block, accepted=True)
+
+ block = self.build_next_block()
+ used_sighash_single_out_of_bounds = False
+ for i in range(NUM_TESTS):
+ # Choose random number of inputs to use.
+ num_inputs = random.randint(1, 10)
+ # Create a slight bias for producing more utxos
+ num_outputs = random.randint(1, 11)
+ random.shuffle(temp_utxos)
+ assert(len(temp_utxos) > num_inputs)
+ tx = CTransaction()
+ total_value = 0
+ for i in range(num_inputs):
+ tx.vin.append(CTxIn(COutPoint(temp_utxos[i].sha256, temp_utxos[i].n), b""))
+ tx.wit.vtxinwit.append(CTxinWitness())
+ total_value += temp_utxos[i].nValue
+ split_value = total_value // num_outputs
+ for i in range(num_outputs):
+ tx.vout.append(CTxOut(split_value, scriptPubKey))
+ for i in range(num_inputs):
+ # Now try to sign each input, using a random hashtype.
+ anyonecanpay = 0
+ if random.randint(0, 1):
+ anyonecanpay = SIGHASH_ANYONECANPAY
+ hashtype = random.randint(1, 3) | anyonecanpay
+ sign_P2PK_witness_input(witness_program, tx, i, hashtype, temp_utxos[i].nValue, key)
+ if (hashtype == SIGHASH_SINGLE and i >= num_outputs):
+ used_sighash_single_out_of_bounds = True
+ tx.rehash()
+ for i in range(num_outputs):
+ temp_utxos.append(UTXO(tx.sha256, i, split_value))
+ temp_utxos = temp_utxos[num_inputs:]
+
+ block.vtx.append(tx)
+
+ # Test the block periodically, if we're close to maxblocksize
+ if (get_virtual_size(block) > MAX_BLOCK_SIZE - 1000):
+ self.update_witness_block_with_transactions(block, [])
+ self.test_node.test_witness_block(block, accepted=True)
+ block = self.build_next_block()
+
+ if (not used_sighash_single_out_of_bounds):
+ print("WARNING: this test run didn't attempt SIGHASH_SINGLE with out-of-bounds index value")
+ # Test the transactions we've added to the block
+ if (len(block.vtx) > 1):
+ self.update_witness_block_with_transactions(block, [])
+ self.test_node.test_witness_block(block, accepted=True)
+
+ # Now test witness version 0 P2PKH transactions
+ pubkeyhash = hash160(pubkey)
+ scriptPKH = CScript([OP_0, pubkeyhash])
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(temp_utxos[0].sha256, temp_utxos[0].n), b""))
+ tx.vout.append(CTxOut(temp_utxos[0].nValue, scriptPKH))
+ tx.wit.vtxinwit.append(CTxinWitness())
+ sign_P2PK_witness_input(witness_program, tx, 0, SIGHASH_ALL, temp_utxos[0].nValue, key)
+ tx2 = CTransaction()
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
+ tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE])))
+
+ script = CScript([CScriptOp(OP_DUP), CScriptOp(OP_HASH160), pubkeyhash, CScriptOp(OP_EQUALVERIFY), CScriptOp(OP_CHECKSIG)])
+ sig_hash = SegwitVersion1SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue)
+ signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL
+
+ # Check that we can't have a scriptSig
+ tx2.vin[0].scriptSig = CScript([signature, pubkey])
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx, tx2])
+ self.test_node.test_witness_block(block, accepted=False)
+
+ # Move the signature to the witness.
+ block.vtx.pop()
+ tx2.wit.vtxinwit.append(CTxinWitness())
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [signature, pubkey]
+ tx2.vin[0].scriptSig = b""
+ tx2.rehash()
+
+ self.update_witness_block_with_transactions(block, [tx2])
+ self.test_node.test_witness_block(block, accepted=True)
+
+ temp_utxos.pop(0)
+
+ # Update self.utxos for later tests. Just spend everything in
+ # temp_utxos to a corresponding entry in self.utxos
+ tx = CTransaction()
+ index = 0
+ for i in temp_utxos:
+ # Just spend to our usual anyone-can-spend output
+ # Use SIGHASH_SINGLE|SIGHASH_ANYONECANPAY so we can build up
+ # the signatures as we go.
+ tx.vin.append(CTxIn(COutPoint(i.sha256, i.n), b""))
+ tx.vout.append(CTxOut(i.nValue, CScript([OP_TRUE])))
+ tx.wit.vtxinwit.append(CTxinWitness())
+ sign_P2PK_witness_input(witness_program, tx, index, SIGHASH_SINGLE|SIGHASH_ANYONECANPAY, i.nValue, key)
+ index += 1
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx])
+ self.test_node.test_witness_block(block, accepted=True)
+
+ for i in range(len(tx.vout)):
+ self.utxo.append(UTXO(tx.sha256, i, tx.vout[i].nValue))
+
+
+ # Test P2SH wrapped witness programs.
+ def test_p2sh_witness(self, segwit_activated):
+ print("\tTesting P2SH witness transactions")
+
+ assert(len(self.utxo))
+
+ # Prepare the p2sh-wrapped witness output
+ witness_program = CScript([OP_DROP, OP_TRUE])
+ witness_hash = sha256(witness_program)
+ p2wsh_pubkey = CScript([OP_0, witness_hash])
+ p2sh_witness_hash = hash160(p2wsh_pubkey)
+ scriptPubKey = CScript([OP_HASH160, p2sh_witness_hash, OP_EQUAL])
+ scriptSig = CScript([p2wsh_pubkey]) # a push of the redeem script
+
+ # Fund the P2SH output
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+ tx.vout.append(CTxOut(self.utxo[0].nValue-1000, scriptPubKey))
+ tx.rehash()
+
+ # Verify mempool acceptance and block validity
+ self.test_node.test_transaction_acceptance(tx, with_witness=False, accepted=True)
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx])
+ self.test_node.test_witness_block(block, accepted=True, with_witness=segwit_activated)
+ sync_blocks(self.nodes)
+
+ # Now test attempts to spend the output.
+ spend_tx = CTransaction()
+ spend_tx.vin.append(CTxIn(COutPoint(tx.sha256, 0), scriptSig))
+ spend_tx.vout.append(CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE])))
+ spend_tx.rehash()
+
+ # This transaction should not be accepted into the mempool pre- or
+ # post-segwit. Mempool acceptance will use SCRIPT_VERIFY_WITNESS which
+ # will require a witness to spend a witness program regardless of
+ # segwit activation. Note that older bitcoind's that are not
+ # segwit-aware would also reject this for failing CLEANSTACK.
+ self.test_node.test_transaction_acceptance(spend_tx, with_witness=False, accepted=False)
+
+ # Try to put the witness script in the scriptSig, should also fail.
+ spend_tx.vin[0].scriptSig = CScript([p2wsh_pubkey, b'a'])
+ spend_tx.rehash()
+ self.test_node.test_transaction_acceptance(spend_tx, with_witness=False, accepted=False)
+
+ # Now put the witness script in the witness, should succeed after
+ # segwit activates.
+ spend_tx.vin[0].scriptSig = scriptSig
+ spend_tx.rehash()
+ spend_tx.wit.vtxinwit.append(CTxinWitness())
+ spend_tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a', witness_program ]
+
+ # Verify mempool acceptance
+ self.test_node.test_transaction_acceptance(spend_tx, with_witness=True, accepted=segwit_activated)
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [spend_tx])
+
+ # If we're before activation, then sending this without witnesses
+ # should be valid. If we're after activation, then sending this with
+ # witnesses should be valid.
+ if segwit_activated:
+ self.test_node.test_witness_block(block, accepted=True)
+ else:
+ self.test_node.test_witness_block(block, accepted=True, with_witness=False)
+
+ # Update self.utxo
+ self.utxo.pop(0)
+ self.utxo.append(UTXO(spend_tx.sha256, 0, spend_tx.vout[0].nValue))
+
+ # Test the behavior of starting up a segwit-aware node after the softfork
+ # has activated. As segwit requires different block data than pre-segwit
+ # nodes would have stored, this requires special handling.
+ # To enable this test, pass --oldbinary=<path-to-pre-segwit-bitcoind> to
+ # the test.
+ def test_upgrade_after_activation(self, node, node_id):
+ print("\tTesting software upgrade after softfork activation")
+
+ assert(node_id != 0) # node0 is assumed to be a segwit-active bitcoind
+
+ # Make sure the nodes are all up
+ sync_blocks(self.nodes)
+
+ # Restart with the new binary
+ stop_node(node, node_id)
+ self.nodes[node_id] = start_node(node_id, self.options.tmpdir, ["-debug"])
+ connect_nodes(self.nodes[0], node_id)
+
+ sync_blocks(self.nodes)
+
+ # Make sure that this peer thinks segwit has activated.
+ assert(get_bip9_status(node, 'segwit')['status'] == "active")
+
+ # Make sure this peers blocks match those of node0.
+ height = node.getblockcount()
+ while height >= 0:
+ block_hash = node.getblockhash(height)
+ assert_equal(block_hash, self.nodes[0].getblockhash(height))
+ assert_equal(self.nodes[0].getblock(block_hash), node.getblock(block_hash))
+ height -= 1
+
+
+ def test_witness_sigops(self):
+ '''Ensure sigop counting is correct inside witnesses.'''
+ print("\tTesting sigops limit")
+
+ assert(len(self.utxo))
+
+ # Keep this under MAX_OPS_PER_SCRIPT (201)
+ witness_program = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKMULTISIG]*5 + [OP_CHECKSIG]*193 + [OP_ENDIF])
+ witness_hash = sha256(witness_program)
+ scriptPubKey = CScript([OP_0, witness_hash])
+
+ sigops_per_script = 20*5 + 193*1
+ # We'll produce 2 extra outputs, one with a program that would take us
+ # over max sig ops, and one with a program that would exactly reach max
+ # sig ops
+ outputs = (MAX_SIGOP_COST // sigops_per_script) + 2
+ extra_sigops_available = MAX_SIGOP_COST % sigops_per_script
+
+ # We chose the number of checkmultisigs/checksigs to make this work:
+ assert(extra_sigops_available < 100) # steer clear of MAX_OPS_PER_SCRIPT
+
+ # This script, when spent with the first
+ # N(=MAX_SIGOP_COST//sigops_per_script) outputs of our transaction,
+ # would push us just over the block sigop limit.
+ witness_program_toomany = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKSIG]*(extra_sigops_available + 1) + [OP_ENDIF])
+ witness_hash_toomany = sha256(witness_program_toomany)
+ scriptPubKey_toomany = CScript([OP_0, witness_hash_toomany])
+
+ # If we spend this script instead, we would exactly reach our sigop
+ # limit (for witness sigops).
+ witness_program_justright = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKSIG]*(extra_sigops_available) + [OP_ENDIF])
+ witness_hash_justright = sha256(witness_program_justright)
+ scriptPubKey_justright = CScript([OP_0, witness_hash_justright])
+
+ # First split our available utxo into a bunch of outputs
+ split_value = self.utxo[0].nValue // outputs
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+ for i in range(outputs):
+ tx.vout.append(CTxOut(split_value, scriptPubKey))
+ tx.vout[-2].scriptPubKey = scriptPubKey_toomany
+ tx.vout[-1].scriptPubKey = scriptPubKey_justright
+ tx.rehash()
+
+ block_1 = self.build_next_block()
+ self.update_witness_block_with_transactions(block_1, [tx])
+ self.test_node.test_witness_block(block_1, accepted=True)
+
+ tx2 = CTransaction()
+ # If we try to spend the first n-1 outputs from tx, that should be
+ # too many sigops.
+ total_value = 0
+ for i in range(outputs-1):
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, i), b""))
+ tx2.wit.vtxinwit.append(CTxinWitness())
+ tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program ]
+ total_value += tx.vout[i].nValue
+ tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_toomany ]
+ tx2.vout.append(CTxOut(total_value, CScript([OP_TRUE])))
+ tx2.rehash()
+
+ block_2 = self.build_next_block()
+ self.update_witness_block_with_transactions(block_2, [tx2])
+ self.test_node.test_witness_block(block_2, accepted=False)
+
+ # Try dropping the last input in tx2, and add an output that has
+ # too many sigops (contributing to legacy sigop count).
+ checksig_count = (extra_sigops_available // 4) + 1
+ scriptPubKey_checksigs = CScript([OP_CHECKSIG]*checksig_count)
+ tx2.vout.append(CTxOut(0, scriptPubKey_checksigs));
+ tx2.vin.pop()
+ tx2.wit.vtxinwit.pop()
+ tx2.vout[0].nValue -= tx.vout[-2].nValue
+ tx2.rehash()
+ block_3 = self.build_next_block()
+ self.update_witness_block_with_transactions(block_3, [tx2])
+ self.test_node.test_witness_block(block_3, accepted=False)
+
+ # If we drop the last checksig in this output, the tx should succeed.
+ block_4 = self.build_next_block()
+ tx2.vout[-1].scriptPubKey = CScript([OP_CHECKSIG]*(checksig_count-1))
+ tx2.rehash()
+ self.update_witness_block_with_transactions(block_4, [tx2])
+ self.test_node.test_witness_block(block_4, accepted=True)
+
+ # Reset the tip back down for the next test
+ sync_blocks(self.nodes)
+ for x in self.nodes:
+ x.invalidateblock(block_4.hash)
+
+ # Try replacing the last input of tx2 to be spending the last
+ # output of tx
+ block_5 = self.build_next_block()
+ tx2.vout.pop()
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, outputs-1), b""))
+ tx2.wit.vtxinwit.append(CTxinWitness())
+ tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_justright ]
+ tx2.rehash()
+ self.update_witness_block_with_transactions(block_5, [tx2])
+ self.test_node.test_witness_block(block_5, accepted=True)
+
+ # TODO: test p2sh sigop counting
+
+ def test_getblocktemplate_before_lockin(self):
+ print("\tTesting getblocktemplate setting of segwit versionbit (before lockin)")
+ block_version = (self.nodes[0].getblocktemplate())['version']
+ assert_equal(block_version & (1 << VB_WITNESS_BIT), 0)
+
+ # Workaround:
+ # Can either change the tip, or change the mempool and wait 5 seconds
+ # to trigger a recomputation of getblocktemplate.
+ self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
+ # Using mocktime lets us avoid sleep()
+ self.nodes[0].setmocktime(int(time.time())+10)
+
+ block_version = self.nodes[0].getblocktemplate({"rules" : ["segwit"]})['version']
+ assert(block_version & (1 << VB_WITNESS_BIT) != 0)
+ self.nodes[0].setmocktime(0) # undo mocktime
+
+ def run_test(self):
+ # Setup the p2p connections and start up the network thread.
+ self.test_node = TestNode() # sets NODE_WITNESS|NODE_NETWORK
+ self.old_node = TestNode() # only NODE_NETWORK
+ self.std_node = TestNode() # for testing node1 (fRequireStandard=true)
+
+ self.p2p_connections = [self.test_node, self.old_node]
+
+ self.connections = []
+ self.connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], self.test_node, services=NODE_NETWORK|NODE_WITNESS))
+ self.connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], self.old_node, services=NODE_NETWORK))
+ self.connections.append(NodeConn('127.0.0.1', p2p_port(1), self.nodes[1], self.std_node, services=NODE_NETWORK|NODE_WITNESS))
+ self.test_node.add_connection(self.connections[0])
+ self.old_node.add_connection(self.connections[1])
+ self.std_node.add_connection(self.connections[2])
+
+ NetworkThread().start() # Start up network handling in another thread
+
+ # Keep a place to store utxo's that can be used in later tests
+ self.utxo = []
+
+ # Test logic begins here
+ self.test_node.wait_for_verack()
+
+ print("\nStarting tests before segwit lock in:")
+
+ self.test_witness_services() # Verifies NODE_WITNESS
+ self.test_non_witness_transaction() # non-witness tx's are accepted
+ self.test_unnecessary_witness_before_segwit_activation()
+ self.test_block_relay(segwit_activated=False)
+
+ # Advance to segwit being 'started'
+ self.advance_to_segwit_started()
+ self.test_getblocktemplate_before_lockin()
+
+ sync_blocks(self.nodes)
+
+ # At lockin, nothing should change.
+ print("\nTesting behavior post lockin, pre-activation")
+ self.advance_to_segwit_lockin()
+
+ # Retest unnecessary witnesses
+ self.test_unnecessary_witness_before_segwit_activation()
+ self.test_witness_tx_relay_before_segwit_activation()
+ self.test_block_relay(segwit_activated=False)
+ self.test_p2sh_witness(segwit_activated=False)
+
+ sync_blocks(self.nodes)
+
+ # Now activate segwit
+ print("\nTesting behavior after segwit activation")
+ self.advance_to_segwit_active()
+
+ sync_blocks(self.nodes)
+
+ # Test P2SH witness handling again
+ self.test_p2sh_witness(segwit_activated=True)
+ self.test_witness_commitments()
+ self.test_block_malleability()
+ self.test_witness_block_size()
+ self.test_submit_block()
+ self.test_extra_witness_data()
+ self.test_max_witness_push_length()
+ self.test_max_witness_program_length()
+ self.test_witness_input_length()
+ self.test_block_relay(segwit_activated=True)
+ self.test_tx_relay_after_segwit_activation()
+ self.test_segwit_versions()
+ self.test_premature_coinbase_witness_spend()
+ self.test_signature_version_1()
+ sync_blocks(self.nodes)
+ if self.test_upgrade:
+ self.test_upgrade_after_activation(self.nodes[2], 2)
+ else:
+ print("\tSkipping upgrade-after-activation test (use --oldbinary to enable)")
+ self.test_witness_sigops()
+
+
+if __name__ == '__main__':
+ SegWitTest().main()
diff --git a/qa/rpc-tests/segwit.py b/qa/rpc-tests/segwit.py
new file mode 100755
index 0000000000..d4c9a8afed
--- /dev/null
+++ b/qa/rpc-tests/segwit.py
@@ -0,0 +1,209 @@
+#!/usr/bin/env python3
+# Copyright (c) 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.
+
+#
+# Test the SegWit changeover logic
+#
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+from test_framework.mininode import sha256, ripemd160
+import os
+import shutil
+
+NODE_0 = 0
+NODE_1 = 1
+NODE_2 = 2
+WIT_V0 = 0
+WIT_V1 = 1
+
+def witness_script(version, pubkey):
+ if (version == 0):
+ pubkeyhash = bytes_to_hex_str(ripemd160(sha256(hex_str_to_bytes(pubkey))))
+ pkscript = "0014" + pubkeyhash
+ elif (version == 1):
+ # 1-of-1 multisig
+ scripthash = bytes_to_hex_str(sha256(hex_str_to_bytes("5121" + pubkey + "51ae")))
+ pkscript = "0020" + scripthash
+ else:
+ assert("Wrong version" == "0 or 1")
+ return pkscript
+
+def addlength(script):
+ scriptlen = format(len(script)//2, 'x')
+ assert(len(scriptlen) == 2)
+ return scriptlen + script
+
+def create_witnessprogram(version, node, utxo, pubkey, encode_p2sh, amount):
+ pkscript = witness_script(version, pubkey);
+ if (encode_p2sh):
+ p2sh_hash = bytes_to_hex_str(ripemd160(sha256(hex_str_to_bytes(pkscript))))
+ pkscript = "a914"+p2sh_hash+"87"
+ inputs = []
+ outputs = {}
+ inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]} )
+ DUMMY_P2SH = "2MySexEGVzZpRgNQ1JdjdP5bRETznm3roQ2" # P2SH of "OP_1 OP_DROP"
+ outputs[DUMMY_P2SH] = amount
+ tx_to_witness = node.createrawtransaction(inputs,outputs)
+ #replace dummy output with our own
+ tx_to_witness = tx_to_witness[0:110] + addlength(pkscript) + tx_to_witness[-8:]
+ return tx_to_witness
+
+def send_to_witness(version, node, utxo, pubkey, encode_p2sh, amount, sign=True, insert_redeem_script=""):
+ tx_to_witness = create_witnessprogram(version, node, utxo, pubkey, encode_p2sh, amount)
+ if (sign):
+ signed = node.signrawtransaction(tx_to_witness)
+ assert("errors" not in signed or len(["errors"]) == 0)
+ return node.sendrawtransaction(signed["hex"])
+ else:
+ if (insert_redeem_script):
+ tx_to_witness = tx_to_witness[0:82] + addlength(insert_redeem_script) + tx_to_witness[84:]
+
+ return node.sendrawtransaction(tx_to_witness)
+
+def getutxo(txid):
+ utxo = {}
+ utxo["vout"] = 0
+ utxo["txid"] = txid
+ return utxo
+
+class SegWitTest(BitcoinTestFramework):
+
+ def setup_chain(self):
+ print("Initializing test directory "+self.options.tmpdir)
+ initialize_chain_clean(self.options.tmpdir, 3)
+
+ def setup_network(self):
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-logtimemicros", "-debug", "-walletprematurewitness"]))
+ self.nodes.append(start_node(1, self.options.tmpdir, ["-logtimemicros", "-debug", "-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness"]))
+ self.nodes.append(start_node(2, self.options.tmpdir, ["-logtimemicros", "-debug", "-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness"]))
+ connect_nodes(self.nodes[1], 0)
+ connect_nodes(self.nodes[2], 1)
+ connect_nodes(self.nodes[0], 2)
+ self.is_network_split = False
+ self.sync_all()
+
+ def success_mine(self, node, txid, sign, redeem_script=""):
+ send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, Decimal("49.998"), sign, redeem_script)
+ block = node.generate(1)
+ assert_equal(len(node.getblock(block[0])["tx"]), 2)
+ sync_blocks(self.nodes)
+
+ def skip_mine(self, node, txid, sign, redeem_script=""):
+ send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, Decimal("49.998"), sign, redeem_script)
+ block = node.generate(1)
+ assert_equal(len(node.getblock(block[0])["tx"]), 1)
+ sync_blocks(self.nodes)
+
+ def fail_accept(self, node, txid, sign, redeem_script=""):
+ try:
+ send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, Decimal("49.998"), sign, redeem_script)
+ except JSONRPCException as exp:
+ assert(exp.error["code"] == -26)
+ else:
+ raise AssertionError("Tx should not have been accepted")
+
+ def fail_mine(self, node, txid, sign, redeem_script=""):
+ send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, Decimal("49.998"), sign, redeem_script)
+ try:
+ node.generate(1)
+ except JSONRPCException as exp:
+ assert(exp.error["code"] == -1)
+ else:
+ raise AssertionError("Created valid block when TestBlockValidity should have failed")
+ sync_blocks(self.nodes)
+
+ def run_test(self):
+ self.nodes[0].generate(160) #block 160
+
+ self.pubkey = []
+ p2sh_ids = [] # p2sh_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE embedded in p2sh
+ wit_ids = [] # wit_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE via bare witness
+ for i in range(3):
+ newaddress = self.nodes[i].getnewaddress()
+ self.pubkey.append(self.nodes[i].validateaddress(newaddress)["pubkey"])
+ multiaddress = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]])
+ self.nodes[i].addwitnessaddress(newaddress)
+ self.nodes[i].addwitnessaddress(multiaddress)
+ p2sh_ids.append([])
+ wit_ids.append([])
+ for v in range(2):
+ p2sh_ids[i].append([])
+ wit_ids[i].append([])
+
+ for i in range(5):
+ for n in range(3):
+ for v in range(2):
+ wit_ids[n][v].append(send_to_witness(v, self.nodes[0], self.nodes[0].listunspent()[0], self.pubkey[n], False, Decimal("49.999")))
+ p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], self.nodes[0].listunspent()[0], self.pubkey[n], True, Decimal("49.999")))
+
+ self.nodes[0].generate(1) #block 161
+ sync_blocks(self.nodes)
+
+ # Make sure all nodes recognize the transactions as theirs
+ assert_equal(self.nodes[0].getbalance(), 60*50 - 60*50 + 20*Decimal("49.999") + 50)
+ assert_equal(self.nodes[1].getbalance(), 20*Decimal("49.999"))
+ assert_equal(self.nodes[2].getbalance(), 20*Decimal("49.999"))
+
+ self.nodes[0].generate(262) #block 423
+ sync_blocks(self.nodes)
+
+ print("Verify default node can't accept any witness format txs before fork")
+ # unsigned, no scriptsig
+ self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], False)
+ self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], False)
+ self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], False)
+ self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], False)
+ # unsigned with redeem script
+ self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], False, addlength(witness_script(0, self.pubkey[0])))
+ self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], False, addlength(witness_script(1, self.pubkey[0])))
+ # signed
+ self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True)
+ self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], True)
+ self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], True)
+ self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], True)
+
+ print("Verify witness txs are skipped for mining before the fork")
+ self.skip_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][0], True) #block 424
+ self.skip_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][0], True) #block 425
+ self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][0], True) #block 426
+ self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][0], True) #block 427
+
+ # TODO: An old node would see these txs without witnesses and be able to mine them
+
+ print("Verify unsigned bare witness txs in versionbits-setting blocks are valid before the fork")
+ self.success_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][1], False) #block 428
+ self.success_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][1], False) #block 429
+
+ print("Verify unsigned p2sh witness txs without a redeem script are invalid")
+ self.fail_accept(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][1], False)
+ self.fail_accept(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False)
+
+ print("Verify unsigned p2sh witness txs with a redeem script in versionbits-settings blocks are valid before the fork")
+ self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][1], False, addlength(witness_script(0, self.pubkey[2]))) #block 430
+ self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False, addlength(witness_script(1, self.pubkey[2]))) #block 431
+
+ print("Verify previous witness txs skipped for mining can now be mined")
+ assert_equal(len(self.nodes[2].getrawmempool()), 4)
+ block = self.nodes[2].generate(1) #block 432 (first block with new rules; 432 = 144 * 3)
+ sync_blocks(self.nodes)
+ assert_equal(len(self.nodes[2].getrawmempool()), 0)
+ assert_equal(len(self.nodes[2].getblock(block[0])["tx"]), 5)
+
+ print("Verify witness txs without witness data are invalid after the fork")
+ self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][2], False)
+ self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][2], False)
+ self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][2], False, addlength(witness_script(0, self.pubkey[2])))
+ self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][2], False, addlength(witness_script(1, self.pubkey[2])))
+
+ print("Verify default node can now use witness txs")
+ self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True) #block 432
+ self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], True) #block 433
+ self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], True) #block 434
+ self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], True) #block 435
+
+if __name__ == '__main__':
+ SegWitTest().main()
diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py
index 26cc396315..df4fe13e5c 100644
--- a/qa/rpc-tests/test_framework/blocktools.py
+++ b/qa/rpc-tests/test_framework/blocktools.py
@@ -5,7 +5,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from .mininode import *
-from .script import CScript, OP_TRUE, OP_CHECKSIG
+from .script import CScript, OP_TRUE, OP_CHECKSIG, OP_RETURN
# Create a block (with regtest difficulty)
def create_block(hashprev, coinbase, nTime=None):
@@ -22,6 +22,29 @@ def create_block(hashprev, coinbase, nTime=None):
block.calc_sha256()
return block
+# From BIP141
+WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed"
+
+# According to BIP141, blocks with witness rules active must commit to the
+# hash of all in-block transactions including witness.
+def add_witness_commitment(block, nonce=0):
+ # First calculate the merkle root of the block's
+ # transactions, with witnesses.
+ witness_nonce = nonce
+ witness_root = block.calc_witness_merkle_root()
+ witness_commitment = uint256_from_str(hash256(ser_uint256(witness_root)+ser_uint256(witness_nonce)))
+ # witness_nonce should go to coinbase witness.
+ block.vtx[0].wit.vtxinwit = [CTxinWitness()]
+ block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ser_uint256(witness_nonce)]
+
+ # witness commitment is the last OP_RETURN output in coinbase
+ output_data = WITNESS_COMMITMENT_HEADER + ser_uint256(witness_commitment)
+ block.vtx[0].vout.append(CTxOut(0, CScript([OP_RETURN, output_data])))
+ block.vtx[0].rehash()
+ block.hashMerkleRoot = block.calc_merkle_root()
+ block.rehash()
+
+
def serialize_script_num(value):
r = bytearray(0)
if value == 0:
diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py
index 6612b99b84..4548e2e7c0 100755
--- a/qa/rpc-tests/test_framework/mininode.py
+++ b/qa/rpc-tests/test_framework/mininode.py
@@ -28,7 +28,7 @@ import asyncore
import time
import sys
import random
-from binascii import hexlify, unhexlify
+from .util import hex_str_to_bytes, bytes_to_hex_str
from io import BytesIO
from codecs import encode
import hashlib
@@ -46,6 +46,11 @@ MAX_BLOCK_SIZE = 1000000
COIN = 100000000 # 1 btc in satoshis
+NODE_NETWORK = (1 << 0)
+NODE_GETUTXO = (1 << 1)
+NODE_BLOOM = (1 << 2)
+NODE_WITNESS = (1 << 3)
+
# Keep our own socket map for asyncore, so that we can track disconnects
# ourselves (to workaround an issue with closing an asyncore socket when
# using select)
@@ -63,6 +68,8 @@ mininode_lock = RLock()
def sha256(s):
return hashlib.new('sha256', s).digest()
+def ripemd160(s):
+ return hashlib.new('ripemd160', s).digest()
def hash256(s):
return sha256(sha256(s))
@@ -133,7 +140,10 @@ def deser_vector(f, c):
return r
-def ser_vector(l):
+# ser_function_name: Allow for an alternate serialization function on the
+# entries in the vector (we use this for serializing the vector of transactions
+# for a witness block).
+def ser_vector(l, ser_function_name=None):
r = b""
if len(l) < 253:
r = struct.pack("B", len(l))
@@ -144,7 +154,10 @@ def ser_vector(l):
else:
r = struct.pack("<BQ", 255, len(l))
for i in l:
- r += i.serialize()
+ if ser_function_name:
+ r += getattr(i, ser_function_name)()
+ else:
+ r += i.serialize()
return r
@@ -239,12 +252,12 @@ def ser_int_vector(l):
# Deserialize from a hex string representation (eg from RPC)
def FromHex(obj, hex_string):
- obj.deserialize(BytesIO(unhexlify(hex_string.encode('ascii'))))
+ obj.deserialize(BytesIO(hex_str_to_bytes(hex_string)))
return obj
# Convert a binary-serializable object to hex (eg for submission via RPC)
def ToHex(obj):
- return hexlify(obj.serialize()).decode('ascii')
+ return bytes_to_hex_str(obj.serialize())
# Objects that map to bitcoind objects, which can be serialized/deserialized
@@ -273,12 +286,16 @@ class CAddress(object):
return "CAddress(nServices=%i ip=%s port=%i)" % (self.nServices,
self.ip, self.port)
+MSG_WITNESS_FLAG = 1<<30
class CInv(object):
typemap = {
0: "Error",
1: "TX",
- 2: "Block"}
+ 2: "Block",
+ 1|MSG_WITNESS_FLAG: "WitnessTx",
+ 2|MSG_WITNESS_FLAG : "WitnessBlock"
+ }
def __init__(self, t=0, h=0):
self.type = t
@@ -362,7 +379,7 @@ class CTxIn(object):
def __repr__(self):
return "CTxIn(prevout=%s scriptSig=%s nSequence=%i)" \
- % (repr(self.prevout), hexlify(self.scriptSig),
+ % (repr(self.prevout), bytes_to_hex_str(self.scriptSig),
self.nSequence)
@@ -384,7 +401,67 @@ class CTxOut(object):
def __repr__(self):
return "CTxOut(nValue=%i.%08i scriptPubKey=%s)" \
% (self.nValue // COIN, self.nValue % COIN,
- hexlify(self.scriptPubKey))
+ bytes_to_hex_str(self.scriptPubKey))
+
+
+class CScriptWitness(object):
+ def __init__(self):
+ # stack is a vector of strings
+ self.stack = []
+
+ def __repr__(self):
+ return "CScriptWitness(%s)" % \
+ (",".join([bytes_to_hex_str(x) for x in self.stack]))
+
+ def is_null(self):
+ if self.stack:
+ return False
+ return True
+
+
+class CTxinWitness(object):
+ def __init__(self):
+ self.scriptWitness = CScriptWitness()
+
+ def deserialize(self, f):
+ self.scriptWitness.stack = deser_string_vector(f)
+
+ def serialize(self):
+ return ser_string_vector(self.scriptWitness.stack)
+
+ def __repr__(self):
+ return repr(self.scriptWitness)
+
+ def is_null(self):
+ return self.scriptWitness.is_null()
+
+
+class CTxWitness(object):
+ def __init__(self):
+ self.vtxinwit = []
+
+ def deserialize(self, f):
+ for i in range(len(self.vtxinwit)):
+ self.vtxinwit[i].deserialize(f)
+
+ def serialize(self):
+ r = b""
+ # This is different than the usual vector serialization --
+ # we omit the length of the vector, which is required to be
+ # the same length as the transaction's vin vector.
+ for x in self.vtxinwit:
+ r += x.serialize()
+ return r
+
+ def __repr__(self):
+ return "CTxWitness(%s)" % \
+ (';'.join([repr(x) for x in self.vtxinwit]))
+
+ def is_null(self):
+ for x in self.vtxinwit:
+ if not x.is_null():
+ return False
+ return True
class CTransaction(object):
@@ -393,6 +470,7 @@ class CTransaction(object):
self.nVersion = 1
self.vin = []
self.vout = []
+ self.wit = CTxWitness()
self.nLockTime = 0
self.sha256 = None
self.hash = None
@@ -401,32 +479,80 @@ class CTransaction(object):
self.vin = copy.deepcopy(tx.vin)
self.vout = copy.deepcopy(tx.vout)
self.nLockTime = tx.nLockTime
- self.sha256 = None
- self.hash = None
+ self.sha256 = tx.sha256
+ self.hash = tx.hash
+ self.wit = copy.deepcopy(tx.wit)
def deserialize(self, f):
self.nVersion = struct.unpack("<i", f.read(4))[0]
self.vin = deser_vector(f, CTxIn)
- self.vout = deser_vector(f, CTxOut)
+ flags = 0
+ if len(self.vin) == 0:
+ flags = struct.unpack("<B", f.read(1))[0]
+ # Not sure why flags can't be zero, but this
+ # matches the implementation in bitcoind
+ if (flags != 0):
+ self.vin = deser_vector(f, CTxIn)
+ self.vout = deser_vector(f, CTxOut)
+ else:
+ self.vout = deser_vector(f, CTxOut)
+ if flags != 0:
+ self.wit.vtxinwit = [CTxinWitness()]*len(self.vin)
+ self.wit.deserialize(f)
self.nLockTime = struct.unpack("<I", f.read(4))[0]
self.sha256 = None
self.hash = None
- def serialize(self):
+ def serialize_without_witness(self):
+ r = b""
+ r += struct.pack("<i", self.nVersion)
+ r += ser_vector(self.vin)
+ r += ser_vector(self.vout)
+ r += struct.pack("<I", self.nLockTime)
+ return r
+
+ # Only serialize with witness when explicitly called for
+ def serialize_with_witness(self):
+ flags = 0
+ if not self.wit.is_null():
+ flags |= 1
r = b""
r += struct.pack("<i", self.nVersion)
+ if flags:
+ dummy = []
+ r += ser_vector(dummy)
+ r += struct.pack("<B", flags)
r += ser_vector(self.vin)
r += ser_vector(self.vout)
+ if flags & 1:
+ if (len(self.wit.vtxinwit) != len(self.vin)):
+ # vtxinwit must have the same length as vin
+ self.wit.vtxinwit = self.wit.vtxinwit[:len(self.vin)]
+ for i in range(len(self.wit.vtxinwit), len(self.vin)):
+ self.wit.vtxinwit.append(CTxinWitness())
+ r += self.wit.serialize()
r += struct.pack("<I", self.nLockTime)
return r
+ # Regular serialization is without witness -- must explicitly
+ # call serialize_with_witness to include witness data.
+ def serialize(self):
+ return self.serialize_without_witness()
+
+ # Recalculate the txid (transaction hash without witness)
def rehash(self):
self.sha256 = None
self.calc_sha256()
- def calc_sha256(self):
+ # We will only cache the serialization without witness in
+ # self.sha256 and self.hash -- those are expected to be the txid.
+ def calc_sha256(self, with_witness=False):
+ if with_witness:
+ # Don't cache the result, just return it
+ return uint256_from_str(hash256(self.serialize_with_witness()))
+
if self.sha256 is None:
- self.sha256 = uint256_from_str(hash256(self.serialize()))
+ self.sha256 = uint256_from_str(hash256(self.serialize_without_witness()))
self.hash = encode(hash256(self.serialize())[::-1], 'hex_codec').decode('ascii')
def is_valid(self):
@@ -518,17 +644,17 @@ class CBlock(CBlockHeader):
super(CBlock, self).deserialize(f)
self.vtx = deser_vector(f, CTransaction)
- def serialize(self):
+ def serialize(self, with_witness=False):
r = b""
r += super(CBlock, self).serialize()
- r += ser_vector(self.vtx)
+ if with_witness:
+ r += ser_vector(self.vtx, "serialize_with_witness")
+ else:
+ r += ser_vector(self.vtx)
return r
- def calc_merkle_root(self):
- hashes = []
- for tx in self.vtx:
- tx.calc_sha256()
- hashes.append(ser_uint256(tx.sha256))
+ # Calculate the merkle root given a vector of transaction hashes
+ def get_merkle_root(self, hashes):
while len(hashes) > 1:
newhashes = []
for i in range(0, len(hashes), 2):
@@ -537,6 +663,24 @@ class CBlock(CBlockHeader):
hashes = newhashes
return uint256_from_str(hashes[0])
+ def calc_merkle_root(self):
+ hashes = []
+ for tx in self.vtx:
+ tx.calc_sha256()
+ hashes.append(ser_uint256(tx.sha256))
+ return self.get_merkle_root(hashes)
+
+ def calc_witness_merkle_root(self):
+ # For witness root purposes, the hash of the
+ # coinbase, with witness, is defined to be 0...0
+ hashes = [ser_uint256(0)]
+
+ for tx in self.vtx[1:]:
+ # Calculate the hashes with witness data
+ hashes.append(ser_uint256(tx.calc_sha256(True)))
+
+ return self.get_merkle_root(hashes)
+
def is_valid(self):
self.calc_sha256()
target = uint256_from_compact(self.nBits)
@@ -812,11 +956,16 @@ class msg_tx(object):
self.tx.deserialize(f)
def serialize(self):
- return self.tx.serialize()
+ return self.tx.serialize_without_witness()
def __repr__(self):
return "msg_tx(tx=%s)" % (repr(self.tx))
+class msg_witness_tx(msg_tx):
+
+ def serialize(self):
+ return self.tx.serialize_with_witness()
+
class msg_block(object):
command = b"block"
@@ -849,6 +998,12 @@ class msg_generic(object):
def __repr__(self):
return "msg_generic()"
+class msg_witness_block(msg_block):
+
+ def serialize(self):
+ r = self.block.serialize(with_witness=True)
+ return r
+
class msg_getaddr(object):
command = b"getaddr"
@@ -947,6 +1102,7 @@ class msg_sendheaders(object):
def __repr__(self):
return "msg_sendheaders()"
+
# getheaders message has
# number of entries
# vector of hashes
@@ -1068,6 +1224,8 @@ class NodeConnCB(object):
# tests; it causes message delivery to sleep for the specified time
# before acquiring the global lock and delivering the next message.
self.deliver_sleep_time = None
+ # Remember the services our peer has advertised
+ self.peer_services = None
def set_deliver_sleep_time(self, value):
with mininode_lock:
@@ -1105,6 +1263,7 @@ class NodeConnCB(object):
conn.ver_send = min(MY_VERSION, message.nVersion)
if message.nVersion < 209:
conn.ver_recv = conn.ver_send
+ conn.nServices = message.nServices
def on_verack(self, conn, message):
conn.ver_recv = conn.ver_send
@@ -1135,6 +1294,7 @@ class NodeConnCB(object):
def on_mempool(self, conn): pass
def on_pong(self, conn, message): pass
def on_feefilter(self, conn, message): pass
+ def on_sendheaders(self, conn, message): pass
# More useful callbacks and functions for NodeConnCB's which have a single NodeConn
class SingleNodeConnCB(NodeConnCB):
@@ -1183,15 +1343,16 @@ class NodeConn(asyncore.dispatcher):
b"getheaders": msg_getheaders,
b"reject": msg_reject,
b"mempool": msg_mempool,
- b"feefilter": msg_feefilter
+ b"feefilter": msg_feefilter,
+ b"sendheaders": msg_sendheaders
}
MAGIC_BYTES = {
"mainnet": b"\xf9\xbe\xb4\xd9", # mainnet
"testnet3": b"\x0b\x11\x09\x07", # testnet3
- "regtest": b"\xfa\xbf\xb5\xda" # regtest
+ "regtest": b"\xfa\xbf\xb5\xda", # regtest
}
- def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", services=1):
+ def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", services=NODE_NETWORK):
asyncore.dispatcher.__init__(self, map=mininode_socket_map)
self.log = logging.getLogger("NodeConn(%s:%d)" % (dstaddr, dstport))
self.dstaddr = dstaddr
@@ -1206,6 +1367,7 @@ class NodeConn(asyncore.dispatcher):
self.network = net
self.cb = callback
self.disconnect = False
+ self.nServices = 0
# stuff version msg into sendbuf
vt = msg_version()
diff --git a/qa/rpc-tests/test_framework/script.py b/qa/rpc-tests/test_framework/script.py
index 44a894fc8f..7678228c42 100644
--- a/qa/rpc-tests/test_framework/script.py
+++ b/qa/rpc-tests/test_framework/script.py
@@ -15,8 +15,9 @@ Functionality to build scripts, as well as SignatureHash().
"""
-from .mininode import CTransaction, CTxOut, hash256
+from .mininode import CTransaction, CTxOut, sha256, hash256, uint256_from_str, ser_uint256, ser_string
from binascii import hexlify
+import hashlib
import sys
bchr = chr
@@ -36,6 +37,10 @@ MAX_SCRIPT_OPCODES = 201
OPCODE_NAMES = {}
+def hash160(s):
+ return hashlib.new('ripemd160', sha256(s)).digest()
+
+
_opcode_instances = []
class CScriptOp(int):
"""A single script opcode"""
@@ -895,3 +900,48 @@ def SignatureHash(script, txTo, inIdx, hashtype):
hash = hash256(s)
return (hash, None)
+
+# TODO: Allow cached hashPrevouts/hashSequence/hashOutputs to be provided.
+# Performance optimization probably not necessary for python tests, however.
+# Note that this corresponds to sigversion == 1 in EvalScript, which is used
+# for version 0 witnesses.
+def SegwitVersion1SignatureHash(script, txTo, inIdx, hashtype, amount):
+
+ hashPrevouts = 0
+ hashSequence = 0
+ hashOutputs = 0
+
+ if not (hashtype & SIGHASH_ANYONECANPAY):
+ serialize_prevouts = bytes()
+ for i in txTo.vin:
+ serialize_prevouts += i.prevout.serialize()
+ hashPrevouts = uint256_from_str(hash256(serialize_prevouts))
+
+ if (not (hashtype & SIGHASH_ANYONECANPAY) and (hashtype & 0x1f) != SIGHASH_SINGLE and (hashtype & 0x1f) != SIGHASH_NONE):
+ serialize_sequence = bytes()
+ for i in txTo.vin:
+ serialize_sequence += struct.pack("<I", i.nSequence)
+ hashSequence = uint256_from_str(hash256(serialize_sequence))
+
+ if ((hashtype & 0x1f) != SIGHASH_SINGLE and (hashtype & 0x1f) != SIGHASH_NONE):
+ serialize_outputs = bytes()
+ for o in txTo.vout:
+ serialize_outputs += o.serialize()
+ hashOutputs = uint256_from_str(hash256(serialize_outputs))
+ elif ((hashtype & 0x1f) == SIGHASH_SINGLE and inIdx < len(txTo.vout)):
+ serialize_outputs = txTo.vout[inIdx].serialize()
+ hashOutputs = uint256_from_str(hash256(serialize_outputs))
+
+ ss = bytes()
+ ss += struct.pack("<i", txTo.nVersion)
+ ss += ser_uint256(hashPrevouts)
+ ss += ser_uint256(hashSequence)
+ ss += txTo.vin[inIdx].prevout.serialize()
+ ss += ser_string(script)
+ ss += struct.pack("<q", amount)
+ ss += struct.pack("<I", txTo.vin[inIdx].nSequence)
+ ss += ser_uint256(hashOutputs)
+ ss += struct.pack("<i", txTo.nLockTime)
+ ss += struct.pack("<I", hashtype)
+
+ return hash256(ss)
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index f9ea94b9f4..8e8ac47455 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -195,7 +195,7 @@ static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput)
uint256 txid(uint256S(strTxid));
static const unsigned int minTxOutSz = 9;
- static const unsigned int maxVout = MAX_BLOCK_SIZE / minTxOutSz;
+ static const unsigned int maxVout = MAX_BLOCK_BASE_SIZE / minTxOutSz;
// extract and validate vout
string strVout = vStrInputParts[1];
@@ -363,6 +363,18 @@ vector<unsigned char> ParseHexUO(map<string,UniValue>& o, string strKey)
return ParseHexUV(o[strKey], strKey);
}
+static CAmount AmountFromValue(const UniValue& value)
+{
+ if (!value.isNum() && !value.isStr())
+ throw runtime_error("Amount is not a number or string");
+ CAmount amount;
+ if (!ParseFixedPoint(value.getValStr(), 8, &amount))
+ throw runtime_error("Invalid amount");
+ if (!MoneyRange(amount))
+ throw runtime_error("Amount out of range");
+ return amount;
+}
+
static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
{
int nHashType = SIGHASH_ALL;
@@ -434,12 +446,15 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
if ((unsigned int)nOut >= coins->vout.size())
coins->vout.resize(nOut+1);
coins->vout[nOut].scriptPubKey = scriptPubKey;
- coins->vout[nOut].nValue = 0; // we don't know the actual output value
+ coins->vout[nOut].nValue = 0;
+ if (prevOut.exists("amount")) {
+ coins->vout[nOut].nValue = AmountFromValue(prevOut["amount"]);
+ }
}
// if redeemScript given and private keys given,
// add redeemScript to the tempKeystore so it can be signed:
- if (fGivenKeys && scriptPubKey.IsPayToScriptHash() &&
+ if (fGivenKeys && (scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash()) &&
prevOut.exists("redeemScript")) {
UniValue v = prevOut["redeemScript"];
vector<unsigned char> rsData(ParseHexUV(v, "redeemScript"));
@@ -462,17 +477,19 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
continue;
}
const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
+ const CAmount& amount = coins->vout[txin.prevout.n].nValue;
- txin.scriptSig.clear();
+ SignatureData sigdata;
// Only sign SIGHASH_SINGLE if there's a corresponding output:
if (!fHashSingle || (i < mergedTx.vout.size()))
- SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
+ ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata);
// ... and merge in other signatures:
- BOOST_FOREACH(const CTransaction& txv, txVariants) {
- txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
- }
- if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i)))
+ BOOST_FOREACH(const CTransaction& txv, txVariants)
+ sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i));
+ UpdateTransaction(mergedTx, i, sigdata);
+
+ if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount)))
fComplete = false;
}
diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp
index 7fd6a9cf52..5c4c3bd274 100644
--- a/src/blockencodings.cpp
+++ b/src/blockencodings.cpp
@@ -15,7 +15,7 @@
#include <unordered_map>
-#define MIN_TRANSACTION_SIZE (::GetSerializeSize(CTransaction(), SER_NETWORK, PROTOCOL_VERSION))
+#define MIN_TRANSACTION_BASE_SIZE (::GetSerializeSize(CTransaction(), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS))
CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block) :
nonce(GetRand(std::numeric_limits<uint64_t>::max())),
@@ -50,7 +50,7 @@ uint64_t CBlockHeaderAndShortTxIDs::GetShortID(const uint256& txhash) const {
ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& cmpctblock) {
if (cmpctblock.header.IsNull() || (cmpctblock.shorttxids.empty() && cmpctblock.prefilledtxn.empty()))
return READ_STATUS_INVALID;
- if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() > MAX_BLOCK_SIZE / MIN_TRANSACTION_SIZE)
+ if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() > MAX_BLOCK_BASE_SIZE / MIN_TRANSACTION_BASE_SIZE)
return READ_STATUS_INVALID;
assert(header.IsNull() && txn_available.empty());
diff --git a/src/chain.h b/src/chain.h
index a13dae33d1..76a774c123 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -144,6 +144,8 @@ enum BlockStatus: uint32_t {
BLOCK_FAILED_VALID = 32, //! stage after last reached validness failed
BLOCK_FAILED_CHILD = 64, //! descends from failed block
BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
+
+ BLOCK_OPT_WITNESS = 128, //! block data in blk*.data was received with a witness-enforcing client
};
/** The block chain is a tree shaped structure starting with the
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index d888aae096..86bef1e105 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -92,6 +92,11 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1462060800; // May 1st, 2016
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017
+ // Deployment of SegWit (BIP141 and BIP143)
+ consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
+ consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 0;
+ consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 0; // Never / undefined
+
/**
* The message start string is designed to be unlikely to occur in normal data.
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
@@ -183,6 +188,11 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1456790400; // March 1st, 2016
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017
+ // Deployment of SegWit (BIP141 and BIP143)
+ consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
+ consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1462060800; // May 1st 2016
+ consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1493596800; // May 1st 2017
+
pchMessageStart[0] = 0x0b;
pchMessageStart[1] = 0x11;
pchMessageStart[2] = 0x09;
@@ -255,6 +265,9 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 999999999999ULL;
+ consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
+ consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 0;
+ consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 999999999999ULL;
pchMessageStart[0] = 0xfa;
pchMessageStart[1] = 0xbf;
@@ -317,3 +330,4 @@ void SelectParams(const std::string& network)
SelectBaseParams(network);
pCurrentParams = &Params(network);
}
+
diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h
index ad9cc26175..81f40593b2 100644
--- a/src/consensus/consensus.h
+++ b/src/consensus/consensus.h
@@ -6,10 +6,16 @@
#ifndef BITCOIN_CONSENSUS_CONSENSUS_H
#define BITCOIN_CONSENSUS_CONSENSUS_H
-/** The maximum allowed size for a serialized block, in bytes (network rule) */
-static const unsigned int MAX_BLOCK_SIZE = 1000000;
+#include <stdint.h>
+
+/** The maximum allowed size for a serialized block, in bytes (only for buffer size limits) */
+static const unsigned int MAX_BLOCK_SERIALIZED_SIZE = 4000000;
+/** The maximum allowed cost for a block, see BIP 141 (network rule) */
+static const unsigned int MAX_BLOCK_COST = 4000000;
+/** The maximum allowed size for a block excluding witness data, in bytes (network rule) */
+static const unsigned int MAX_BLOCK_BASE_SIZE = 1000000;
/** The maximum allowed number of signature check operations in a block (network rule) */
-static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
+static const int64_t MAX_BLOCK_SIGOPS_COST = 80000;
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
static const int COINBASE_MATURITY = 100;
diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp
index 22eb7159a2..35f7d2e05a 100644
--- a/src/consensus/merkle.cpp
+++ b/src/consensus/merkle.cpp
@@ -165,6 +165,17 @@ uint256 BlockMerkleRoot(const CBlock& block, bool* mutated)
return ComputeMerkleRoot(leaves, mutated);
}
+uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated)
+{
+ std::vector<uint256> leaves;
+ 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();
+ }
+ return ComputeMerkleRoot(leaves, mutated);
+}
+
std::vector<uint256> BlockMerkleBranch(const CBlock& block, uint32_t position)
{
std::vector<uint256> leaves;
diff --git a/src/consensus/merkle.h b/src/consensus/merkle.h
index 6ef59745ac..194aea9b75 100644
--- a/src/consensus/merkle.h
+++ b/src/consensus/merkle.h
@@ -23,6 +23,12 @@ uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector<uint2
uint256 BlockMerkleRoot(const CBlock& block, bool* mutated = NULL);
/*
+ * Compute the Merkle root of the witness transactions in a block.
+ * *mutated is set to true if a duplicated subtree was found.
+ */
+uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated = NULL);
+
+/*
* Compute the Merkle branch for the tree of transactions in a block, for a
* given position.
* This can be verified using ComputeMerkleRootFromBranch.
diff --git a/src/consensus/params.h b/src/consensus/params.h
index 6c4cc49479..822ec87d69 100644
--- a/src/consensus/params.h
+++ b/src/consensus/params.h
@@ -16,6 +16,7 @@ enum DeploymentPos
{
DEPLOYMENT_TESTDUMMY,
DEPLOYMENT_CSV, // Deployment of BIP68, BIP112, and BIP113.
+ DEPLOYMENT_SEGWIT, // Deployment of BIP141 and BIP143
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in versionbits.cpp
MAX_VERSION_BITS_DEPLOYMENTS
};
diff --git a/src/consensus/validation.h b/src/consensus/validation.h
index d7e57f5b5e..000b197270 100644
--- a/src/consensus/validation.h
+++ b/src/consensus/validation.h
@@ -77,6 +77,9 @@ public:
bool CorruptionPossible() const {
return corruptionPossible;
}
+ void SetCorruptionPossible() {
+ corruptionPossible = true;
+ }
unsigned int GetRejectCode() const { return chRejectCode; }
std::string GetRejectReason() const { return strRejectReason; }
std::string GetDebugMessage() const { return strDebugMessage; }
diff --git a/src/core_io.h b/src/core_io.h
index e8c0c49e84..b559d44bf5 100644
--- a/src/core_io.h
+++ b/src/core_io.h
@@ -17,7 +17,7 @@ class UniValue;
// core_read.cpp
extern CScript ParseScript(const std::string& s);
extern std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false);
-extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);
+extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx, bool fTryNoWitness = false);
extern bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
extern uint256 ParseHashUV(const UniValue& v, const std::string& strName);
extern uint256 ParseHashStr(const std::string&, const std::string& strName);
diff --git a/src/core_memusage.h b/src/core_memusage.h
index 450537d059..dd86f805fe 100644
--- a/src/core_memusage.h
+++ b/src/core_memusage.h
@@ -25,8 +25,28 @@ static inline size_t RecursiveDynamicUsage(const CTxOut& out) {
return RecursiveDynamicUsage(out.scriptPubKey);
}
+static inline size_t RecursiveDynamicUsage(const CScriptWitness& scriptWit) {
+ size_t mem = memusage::DynamicUsage(scriptWit.stack);
+ for (std::vector<std::vector<unsigned char> >::const_iterator it = scriptWit.stack.begin(); it != scriptWit.stack.end(); it++) {
+ mem += memusage::DynamicUsage(*it);
+ }
+ return mem;
+}
+
+static inline size_t RecursiveDynamicUsage(const CTxinWitness& txinwit) {
+ return RecursiveDynamicUsage(txinwit.scriptWitness);
+}
+
+static inline size_t RecursiveDynamicUsage(const CTxWitness& txwit) {
+ size_t mem = memusage::DynamicUsage(txwit.vtxinwit);
+ for (std::vector<CTxinWitness>::const_iterator it = txwit.vtxinwit.begin(); it != txwit.vtxinwit.end(); it++) {
+ mem += RecursiveDynamicUsage(*it);
+ }
+ return mem;
+}
+
static inline size_t RecursiveDynamicUsage(const CTransaction& tx) {
- size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout);
+ size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout) + RecursiveDynamicUsage(tx.wit);
for (std::vector<CTxIn>::const_iterator it = tx.vin.begin(); it != tx.vin.end(); it++) {
mem += RecursiveDynamicUsage(*it);
}
@@ -37,7 +57,7 @@ static inline size_t RecursiveDynamicUsage(const CTransaction& tx) {
}
static inline size_t RecursiveDynamicUsage(const CMutableTransaction& tx) {
- size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout);
+ size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout) + RecursiveDynamicUsage(tx.wit);
for (std::vector<CTxIn>::const_iterator it = tx.vin.begin(); it != tx.vin.end(); it++) {
mem += RecursiveDynamicUsage(*it);
}
diff --git a/src/core_read.cpp b/src/core_read.cpp
index 444a4c7eba..7cfda6dd6d 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -90,12 +90,26 @@ CScript ParseScript(const std::string& s)
return result;
}
-bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx)
+bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx, bool fTryNoWitness)
{
if (!IsHex(strHexTx))
return false;
vector<unsigned char> txData(ParseHex(strHexTx));
+
+ if (fTryNoWitness) {
+ CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
+ try {
+ ssData >> tx;
+ if (ssData.eof()) {
+ return true;
+ }
+ }
+ catch (const std::exception&) {
+ // Fall through.
+ }
+ }
+
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
try {
ssData >> tx;
diff --git a/src/init.cpp b/src/init.cpp
index b572bfc327..5d29f14eb8 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -452,6 +452,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-mempoolreplacement", strprintf(_("Enable transaction replacement in the memory pool (default: %u)"), DEFAULT_ENABLE_REPLACEMENT));
strUsage += HelpMessageGroup(_("Block creation options:"));
+ strUsage += HelpMessageOpt("-blockmaxcost=<n>", strprintf(_("Set maximum block cost (default: %d)"), DEFAULT_BLOCK_MAX_COST));
strUsage += HelpMessageOpt("-blockminsize=<n>", strprintf(_("Set minimum block size in bytes (default: %u)"), DEFAULT_BLOCK_MIN_SIZE));
strUsage += HelpMessageOpt("-blockmaxsize=<n>", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE));
strUsage += HelpMessageOpt("-blockprioritysize=<n>", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE));
@@ -1283,6 +1284,14 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
break;
}
+ if (!fReindex) {
+ uiInterface.InitMessage(_("Rewinding blocks..."));
+ if (!RewindBlockIndex(chainparams)) {
+ strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain");
+ break;
+ }
+ }
+
uiInterface.InitMessage(_("Verifying blocks..."));
if (fHavePruned && GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks",
@@ -1377,6 +1386,18 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
}
}
+ if (Params().GetConsensus().vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout != 0) {
+ // Only advertize witness capabilities if they have a reasonable start time.
+ // This allows us to have the code merged without a defined softfork, by setting its
+ // end time to 0.
+ // Note that setting NODE_WITNESS is never required: the only downside from not
+ // doing so is that after activation, no upgraded nodes will fetch from you.
+ nLocalServices = ServiceFlags(nLocalServices | NODE_WITNESS);
+ // Only care about others providing witness capabilities if there is a softfork
+ // defined.
+ nRelevantServices = ServiceFlags(nRelevantServices | NODE_WITNESS);
+ }
+
// ********************************************************* Step 10: import blocks
if (mapArgs.count("-blocknotify"))
diff --git a/src/main.cpp b/src/main.cpp
index ae195ecc40..6cdd55e397 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -293,6 +293,8 @@ struct CNodeState {
bool fPreferHeaderAndIDs;
//! Whether this peer will send us cmpctblocks if we request them
bool fProvidesHeaderAndIDs;
+ //! Whether this peer can give us witnesses
+ bool fHaveWitness;
CNodeState() {
fCurrentlyConnected = false;
@@ -311,6 +313,7 @@ struct CNodeState {
fPreferHeaders = false;
fPreferHeaderAndIDs = false;
fProvidesHeaderAndIDs = false;
+ fHaveWitness = false;
}
};
@@ -470,6 +473,10 @@ void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) {
}
void MaybeSetPeerAsAnnouncingHeaderAndIDs(const CNodeState* nodestate, CNode* pfrom) {
+ if (nLocalServices & NODE_WITNESS) {
+ // Don't ever request compact blocks when segwit is enabled.
+ return;
+ }
if (nodestate->fProvidesHeaderAndIDs) {
BOOST_FOREACH(const NodeId nodeid, lNodesAnnouncingHeaderAndIDs)
if (nodeid == pfrom->GetId())
@@ -655,6 +662,9 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc
CBlockIndex* pindex = (*mi).second;
if (chain.Contains(pindex))
return pindex;
+ if (pindex->GetAncestor(chain.Height()) == chain.Tip()) {
+ return chain.Tip();
+ }
}
}
return chain.Genesis();
@@ -681,8 +691,8 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(c
// have been mined or received.
// 100 orphans, each of which is at most 99,999 bytes big is
// at most 10 megabytes of orphans and somewhat more byprev index (in the worst case):
- unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
- if (sz >= MAX_STANDARD_TX_SIZE)
+ unsigned int sz = GetTransactionCost(tx);
+ if (sz >= MAX_STANDARD_TX_COST)
{
LogPrint("mempool", "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString());
return false;
@@ -1015,8 +1025,24 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
return nSigOps;
}
+int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags)
+{
+ int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR;
+ if (tx.IsCoinBase())
+ return nSigOps;
+ if (flags & SCRIPT_VERIFY_P2SH) {
+ nSigOps += GetP2SHSigOpCount(tx, inputs) * WITNESS_SCALE_FACTOR;
+ }
+
+ for (unsigned int i = 0; i < tx.vin.size(); i++)
+ {
+ const CTxOut &prevout = inputs.GetOutputFor(tx.vin[i]);
+ nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, i < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[i].scriptWitness : NULL, flags);
+ }
+ return nSigOps;
+}
@@ -1029,8 +1055,8 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vin-empty");
if (tx.vout.empty())
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");
- // Size limits
- if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
+ // Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
+ if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_BASE_SIZE)
return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");
// Check for negative or overflow output values
@@ -1119,6 +1145,11 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
return state.DoS(0, false, REJECT_NONSTANDARD, "premature-version2-tx");
}
+ // Reject transactions with witness before segregated witness activates (override with -prematurewitness)
+ if (!GetBoolArg("-prematurewitness",false) && !tx.wit.IsNull() && !IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus())) {
+ return state.DoS(0, false, REJECT_NONSTANDARD, "no-witness-yet", true);
+ }
+
// Only accept nLockTime-using transactions that can be mined in the next
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
@@ -1231,8 +1262,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
if (fRequireStandard && !AreInputsStandard(tx, view))
return state.Invalid(false, REJECT_NONSTANDARD, "bad-txns-nonstandard-inputs");
- unsigned int nSigOps = GetLegacySigOpCount(tx);
- nSigOps += GetP2SHSigOpCount(tx, view);
+ int64_t nSigOpsCost = GetTransactionSigOpCost(tx, view, STANDARD_SCRIPT_VERIFY_FLAGS);
CAmount nValueOut = tx.GetValueOut();
CAmount nFees = nValueIn-nValueOut;
@@ -1255,7 +1285,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
}
}
- CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbase, nSigOps, lp);
+ CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbase, nSigOpsCost, lp);
unsigned int nSize = entry.GetTxSize();
// Check that the transaction doesn't have an excessive number of
@@ -1263,9 +1293,9 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
// itself can contain sigops MAX_STANDARD_TX_SIGOPS is less than
// MAX_BLOCK_SIGOPS; we still consider this an invalid rather than
// merely non-standard transaction.
- if ((nSigOps > MAX_STANDARD_TX_SIGOPS) || (nBytesPerSigOp && nSigOps > nSize / nBytesPerSigOp))
+ if ((nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST) || (nBytesPerSigOp && nSigOpsCost > nSize * WITNESS_SCALE_FACTOR / nBytesPerSigOp))
return state.DoS(0, false, REJECT_NONSTANDARD, "bad-txns-too-many-sigops", false,
- strprintf("%d", nSigOps));
+ strprintf("%d", nSigOpsCost));
CAmount mempoolRejectFee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(nSize);
if (mempoolRejectFee > 0 && nModifiedFees < mempoolRejectFee) {
@@ -1457,10 +1487,24 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
}
}
+ unsigned int scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS;
+ if (!Params().RequireStandard()) {
+ scriptVerifyFlags = GetArg("-promiscuousmempoolflags", scriptVerifyFlags);
+ }
+
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
- if (!CheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true))
- return false; // state filled in by CheckInputs
+ if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true)) {
+ // SCRIPT_VERIFY_CLEANSTACK requires SCRIPT_VERIFY_WITNESS, so we
+ // need to turn both off, and compare against just turning off CLEANSTACK
+ // to see if the failure is specifically due to witness validation.
+ if (CheckInputs(tx, state, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true) &&
+ !CheckInputs(tx, state, view, true, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true)) {
+ // Only the witness is wrong, so the transaction itself may be fine.
+ state.SetCorruptionPossible();
+ }
+ return false;
+ }
// Check again against just the consensus-critical mandatory script
// verification flags, in case of bugs in the standard flags that cause
@@ -1867,7 +1911,8 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight)
bool CScriptCheck::operator()() {
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
- if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, cacheStore), &error)) {
+ const CScriptWitness *witness = (nIn < ptxTo->wit.vtxinwit.size()) ? &ptxTo->wit.vtxinwit[nIn].scriptWitness : NULL;
+ if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore), &error)) {
return false;
}
return true;
@@ -2405,6 +2450,11 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE;
}
+ // Start enforcing WITNESS rules using versionbits logic.
+ if (IsWitnessEnabled(pindex->pprev, chainparams.GetConsensus())) {
+ flags |= SCRIPT_VERIFY_WITNESS;
+ }
+
int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1;
LogPrint("bench", " - Fork checks: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeForks * 0.000001);
@@ -2416,7 +2466,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
std::vector<int> prevheights;
CAmount nFees = 0;
int nInputs = 0;
- unsigned int nSigOps = 0;
+ int64_t nSigOpsCost = 0;
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
std::vector<std::pair<uint256, CDiskTxPos> > vPos;
vPos.reserve(block.vtx.size());
@@ -2426,10 +2476,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
const CTransaction &tx = block.vtx[i];
nInputs += tx.vin.size();
- nSigOps += GetLegacySigOpCount(tx);
- if (nSigOps > MAX_BLOCK_SIGOPS)
- return state.DoS(100, error("ConnectBlock(): too many sigops"),
- REJECT_INVALID, "bad-blk-sigops");
if (!tx.IsCoinBase())
{
@@ -2460,18 +2506,19 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return state.DoS(100, error("%s: contains a non-BIP68-final transaction", __func__),
REJECT_INVALID, "bad-txns-nonfinal");
}
+ }
- if (fStrictPayToScriptHash)
- {
- // Add in sigops done by pay-to-script-hash inputs;
- // this is to prevent a "rogue miner" from creating
- // an incredibly-expensive-to-validate block.
- nSigOps += GetP2SHSigOpCount(tx, view);
- if (nSigOps > MAX_BLOCK_SIGOPS)
- return state.DoS(100, error("ConnectBlock(): too many sigops"),
- REJECT_INVALID, "bad-blk-sigops");
- }
+ // GetTransactionSigOpCost counts 3 types of sigops:
+ // * legacy (always)
+ // * p2sh (when P2SH enabled in flags and excludes coinbase)
+ // * witness (when witness enabled in flags and excludes coinbase)
+ nSigOpsCost += GetTransactionSigOpCost(tx, view, flags);
+ if (nSigOpsCost > MAX_BLOCK_SIGOPS_COST)
+ return state.DoS(100, error("ConnectBlock(): too many sigops"),
+ REJECT_INVALID, "bad-blk-sigops");
+ if (!tx.IsCoinBase())
+ {
nFees += view.GetValueIn(tx)-tx.GetValueOut();
std::vector<CScriptCheck> vChecks;
@@ -2742,7 +2789,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) {
}
/** Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and manually re-limit mempool size after this, with cs_main held. */
-bool static DisconnectTip(CValidationState& state, const CChainParams& chainparams)
+bool static DisconnectTip(CValidationState& state, const CChainParams& chainparams, bool fBare = false)
{
CBlockIndex *pindexDelete = chainActive.Tip();
assert(pindexDelete);
@@ -2762,24 +2809,28 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
// Write the chain state to disk, if necessary.
if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
return false;
- // Resurrect mempool transactions from the disconnected block.
- std::vector<uint256> vHashUpdate;
- BOOST_FOREACH(const CTransaction &tx, block.vtx) {
- // ignore validation errors in resurrected transactions
- list<CTransaction> removed;
- CValidationState stateDummy;
- if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, true)) {
- mempool.removeRecursive(tx, removed);
- } else if (mempool.exists(tx.GetHash())) {
- vHashUpdate.push_back(tx.GetHash());
- }
- }
- // AcceptToMemoryPool/addUnchecked all assume that new mempool entries have
- // no in-mempool children, which is generally not true when adding
- // previously-confirmed transactions back to the mempool.
- // UpdateTransactionsFromBlock finds descendants of any transactions in this
- // block that were added back and cleans up the mempool state.
- mempool.UpdateTransactionsFromBlock(vHashUpdate);
+
+ if (!fBare) {
+ // Resurrect mempool transactions from the disconnected block.
+ std::vector<uint256> vHashUpdate;
+ BOOST_FOREACH(const CTransaction &tx, block.vtx) {
+ // ignore validation errors in resurrected transactions
+ list<CTransaction> removed;
+ CValidationState stateDummy;
+ if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, true)) {
+ mempool.removeRecursive(tx, removed);
+ } else if (mempool.exists(tx.GetHash())) {
+ vHashUpdate.push_back(tx.GetHash());
+ }
+ }
+ // AcceptToMemoryPool/addUnchecked all assume that new mempool entries have
+ // no in-mempool children, which is generally not true when adding
+ // previously-confirmed transactions back to the mempool.
+ // UpdateTransactionsFromBlock finds descendants of any transactions in this
+ // block that were added back and cleans up the mempool state.
+ mempool.UpdateTransactionsFromBlock(vHashUpdate);
+ }
+
// Update chainActive and related variables.
UpdateTip(pindexDelete->pprev, chainparams);
// Let wallets know transactions went from 1-confirmed to
@@ -3231,6 +3282,9 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
pindexNew->nDataPos = pos.nPos;
pindexNew->nUndoPos = 0;
pindexNew->nStatus |= BLOCK_HAVE_DATA;
+ if (IsWitnessEnabled(pindexNew->pprev, Params().GetConsensus())) {
+ pindexNew->nStatus |= BLOCK_OPT_WITNESS;
+ }
pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
setDirtyBlockIndex.insert(pindexNew);
@@ -3394,9 +3448,11 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
// All potential-corruption validation must be done before we do any
// transaction validation, as otherwise we may mark the header as invalid
// because we receive the wrong transactions for it.
+ // Note that witness malleability is checked in ContextualCheckBlock, so no
+ // checks that use witness data may be performed here.
// Size limits
- if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
+ if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_BASE_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_BASE_SIZE)
return state.DoS(100, false, REJECT_INVALID, "bad-blk-length", false, "size limits failed");
// First transaction must be coinbase, the rest must not be
@@ -3417,7 +3473,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
{
nSigOps += GetLegacySigOpCount(tx);
}
- if (nSigOps > MAX_BLOCK_SIGOPS)
+ if (nSigOps * WITNESS_SCALE_FACTOR > MAX_BLOCK_SIGOPS_COST)
return state.DoS(100, false, REJECT_INVALID, "bad-blk-sigops", false, "out-of-bounds SigOpCount");
if (fCheckPOW && fCheckMerkleRoot)
@@ -3440,6 +3496,71 @@ static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidati
return true;
}
+bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params)
+{
+ LOCK(cs_main);
+ return (VersionBitsState(pindexPrev, params, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == THRESHOLD_ACTIVE);
+}
+
+// Compute at which vout of the block's coinbase transaction the witness
+// commitment occurs, or -1 if not found.
+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) {
+ commitpos = o;
+ }
+ }
+ return commitpos;
+}
+
+void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams)
+{
+ 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;
+ }
+}
+
+std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams)
+{
+ std::vector<unsigned char> commitment;
+ int commitpos = GetWitnessCommitmentIndex(block);
+ bool fHaveWitness = false;
+ for (size_t t = 1; t < block.vtx.size(); t++) {
+ if (!block.vtx[t].wit.IsNull()) {
+ fHaveWitness = true;
+ break;
+ }
+ }
+ std::vector<unsigned char> ret(32, 0x00);
+ if (fHaveWitness && IsWitnessEnabled(pindexPrev, consensusParams)) {
+ if (commitpos == -1) {
+ uint256 witnessroot = BlockWitnessMerkleRoot(block, NULL);
+ CHash256().Write(witnessroot.begin(), 32).Write(&ret[0], 32).Finalize(witnessroot.begin());
+ CTxOut out;
+ out.nValue = 0;
+ out.scriptPubKey.resize(38);
+ out.scriptPubKey[0] = OP_RETURN;
+ out.scriptPubKey[1] = 0x24;
+ out.scriptPubKey[2] = 0xaa;
+ out.scriptPubKey[3] = 0x21;
+ out.scriptPubKey[4] = 0xa9;
+ 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();
+ }
+ }
+ UpdateUncommittedBlockStructures(block, pindexPrev, consensusParams);
+ return commitment;
+}
+
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex * const pindexPrev, int64_t nAdjustedTime)
{
// Check proof of work
@@ -3496,6 +3617,53 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
}
}
+ // Validation for witness commitments.
+ // * We compute the witness hash (which is the hash including witnesses) of all the block's transactions, except the
+ // coinbase (where 0x0000....0000 is used instead).
+ // * The coinbase scriptWitness is a stack of a single 32-byte vector, containing a witness nonce (unconstrained).
+ // * We build a merkle tree with all those witness hashes as leaves (similar to the hashMerkleRoot in the block header).
+ // * There must be at least one output whose scriptPubKey is a single 36-byte push, the first 4 bytes of which are
+ // {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness nonce). In case there are
+ // multiple, the last one is used.
+ bool fHaveWitness = false;
+ if (IsWitnessEnabled(pindexPrev, consensusParams)) {
+ int commitpos = GetWitnessCommitmentIndex(block);
+ if (commitpos != -1) {
+ bool malleated = false;
+ uint256 hashWitness = BlockWitnessMerkleRoot(block, &malleated);
+ // 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) {
+ return state.DoS(100, error("%s : invalid witness nonce size", __func__), REJECT_INVALID, "bad-witness-nonce-size", true);
+ }
+ 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, error("%s : witness merkle commitment mismatch", __func__), REJECT_INVALID, "bad-witness-merkle-match", true);
+ }
+ fHaveWitness = true;
+ }
+ }
+
+ // 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()) {
+ return state.DoS(100, error("%s : unexpected witness data found", __func__), REJECT_INVALID, "unexpected-witness", true);
+ }
+ }
+ }
+
+ // After the coinbase witness nonce and commitment are verified,
+ // we can check if the block cost passes (before we've checked the
+ // coinbase witness, it would be possible for the cost to be too
+ // large by filling up the coinbase witness, which doesn't change
+ // the block hash, so we couldn't mark the block as permanently
+ // failed).
+ if (GetBlockCost(block) > MAX_BLOCK_COST) {
+ return state.DoS(100, error("ContextualCheckBlock(): cost limit failed"), REJECT_INVALID, "bad-blk-cost");
+ }
+
return true;
}
@@ -4065,6 +4233,90 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
return true;
}
+bool RewindBlockIndex(const CChainParams& params)
+{
+ LOCK(cs_main);
+
+ int nHeight = 1;
+ while (nHeight <= chainActive.Height()) {
+ if (IsWitnessEnabled(chainActive[nHeight - 1], params.GetConsensus()) && !(chainActive[nHeight]->nStatus & BLOCK_OPT_WITNESS)) {
+ break;
+ }
+ nHeight++;
+ }
+
+ // nHeight is now the height of the first insufficiently-validated block, or tipheight + 1
+ CValidationState state;
+ CBlockIndex* pindex = chainActive.Tip();
+ while (chainActive.Height() >= nHeight) {
+ if (fPruneMode && !(chainActive.Tip()->nStatus & BLOCK_HAVE_DATA)) {
+ // If pruning, don't try rewinding past the HAVE_DATA point;
+ // since older blocks can't be served anyway, there's
+ // no need to walk further, and trying to DisconnectTip()
+ // will fail (and require a needless reindex/redownload
+ // of the blockchain).
+ break;
+ }
+ if (!DisconnectTip(state, params, true)) {
+ return error("RewindBlockIndex: unable to disconnect block at height %i", pindex->nHeight);
+ }
+ // Occasionally flush state to disk.
+ if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC))
+ return false;
+ }
+
+ // Reduce validity flag and have-data flags.
+ // We do this after actual disconnecting, otherwise we'll end up writing the lack of data
+ // to disk before writing the chainstate, resulting in a failure to continue if interrupted.
+ for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); it++) {
+ CBlockIndex* pindexIter = it->second;
+
+ // Note: If we encounter an insufficiently validated block that
+ // is on chainActive, it must be because we are a pruning node, and
+ // this block or some successor doesn't HAVE_DATA, so we were unable to
+ // rewind all the way. Blocks remaining on chainActive at this point
+ // must not have their validity reduced.
+ if (IsWitnessEnabled(pindexIter->pprev, params.GetConsensus()) && !(pindexIter->nStatus & BLOCK_OPT_WITNESS) && !chainActive.Contains(pindexIter)) {
+ // Reduce validity
+ pindexIter->nStatus = std::min<unsigned int>(pindexIter->nStatus & BLOCK_VALID_MASK, BLOCK_VALID_TREE) | (pindexIter->nStatus & ~BLOCK_VALID_MASK);
+ // Remove have-data flags.
+ pindexIter->nStatus &= ~(BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO);
+ // Remove storage location.
+ pindexIter->nFile = 0;
+ pindexIter->nDataPos = 0;
+ pindexIter->nUndoPos = 0;
+ // Remove various other things
+ pindexIter->nTx = 0;
+ pindexIter->nChainTx = 0;
+ pindexIter->nSequenceId = 0;
+ // Make sure it gets written.
+ setDirtyBlockIndex.insert(pindexIter);
+ // Update indexes
+ setBlockIndexCandidates.erase(pindexIter);
+ std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> ret = mapBlocksUnlinked.equal_range(pindexIter->pprev);
+ while (ret.first != ret.second) {
+ if (ret.first->second == pindexIter) {
+ mapBlocksUnlinked.erase(ret.first++);
+ } else {
+ ++ret.first;
+ }
+ }
+ } else if (pindexIter->IsValid(BLOCK_VALID_TRANSACTIONS) && pindexIter->nChainTx) {
+ setBlockIndexCandidates.insert(pindexIter);
+ }
+ }
+
+ PruneBlockIndexCandidates();
+
+ CheckBlockIndex(params.GetConsensus());
+
+ if (!FlushStateToDisk(state, FLUSH_STATE_ALWAYS)) {
+ return false;
+ }
+
+ return true;
+}
+
void UnloadBlockIndex()
{
LOCK(cs_main);
@@ -4159,7 +4411,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB
int nLoaded = 0;
try {
// This takes over fileIn and calls fclose() on it in the CBufferedFile destructor
- CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION);
+ CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SERIALIZED_SIZE, MAX_BLOCK_SERIALIZED_SIZE+8, SER_DISK, CLIENT_VERSION);
uint64_t nRewind = blkdat.GetPos();
while (!blkdat.eof()) {
boost::this_thread::interruption_point();
@@ -4178,7 +4430,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB
continue;
// read size
blkdat >> nSize;
- if (nSize < 80 || nSize > MAX_BLOCK_SIZE)
+ if (nSize < 80 || nSize > MAX_BLOCK_SERIALIZED_SIZE)
continue;
} catch (const std::exception&) {
// no valid block header found; don't complain
@@ -4508,6 +4760,7 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
switch (inv.type)
{
case MSG_TX:
+ case MSG_WITNESS_TX:
{
assert(recentRejects);
if (chainActive.Tip()->GetBlockHash() != hashRecentRejectsChainTip)
@@ -4528,6 +4781,7 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
pcoinsTip->HaveCoinsInCache(inv.hash);
}
case MSG_BLOCK:
+ case MSG_WITNESS_BLOCK:
return mapBlockIndex.count(inv.hash);
}
// Don't know what it is, just say we already got one
@@ -4552,7 +4806,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
boost::this_thread::interruption_point();
it++;
- if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK)
+ if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK)
{
bool send = false;
BlockMap::iterator mi = mapBlockIndex.find(inv.hash);
@@ -4593,6 +4847,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
if (!ReadBlockFromDisk(block, (*mi).second, consensusParams))
assert(!"cannot load block from disk");
if (inv.type == MSG_BLOCK)
+ pfrom->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, block);
+ else if (inv.type == MSG_WITNESS_BLOCK)
pfrom->PushMessage(NetMsgType::BLOCK, block);
else if (inv.type == MSG_FILTERED_BLOCK)
{
@@ -4609,7 +4865,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)
- pfrom->PushMessage(NetMsgType::TX, block.vtx[pair.first]);
+ pfrom->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, block.vtx[pair.first]);
}
// else
// no response
@@ -4622,9 +4878,9 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// instead we respond with the full, non-compact block.
if (mi->second->nHeight >= chainActive.Height() - 10) {
CBlockHeaderAndShortTxIDs cmpctblock(block);
- pfrom->PushMessage(NetMsgType::CMPCTBLOCK, cmpctblock);
+ pfrom->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::CMPCTBLOCK, cmpctblock);
} else
- pfrom->PushMessage(NetMsgType::BLOCK, block);
+ pfrom->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, block);
}
// Trigger the peer node to send a getblocks request for the next batch of inventory
@@ -4640,20 +4896,20 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
}
}
- else if (inv.type == MSG_TX)
+ else if (inv.type == MSG_TX || inv.type == MSG_WITNESS_TX)
{
// Send stream from relay memory
bool push = false;
auto mi = mapRelay.find(inv.hash);
if (mi != mapRelay.end()) {
- pfrom->PushMessage(NetMsgType::TX, *mi->second);
+ pfrom->PushMessageWithFlag(inv.type == MSG_TX ? SERIALIZE_TRANSACTION_NO_WITNESS : 0, NetMsgType::TX, *mi->second);
push = true;
} else if (pfrom->timeLastMempoolReq) {
auto txinfo = mempool.info(inv.hash);
// To protect privacy, do not answer getdata using the mempool when
// that TX couldn't have been INVed in reply to a MEMPOOL request.
if (txinfo.tx && txinfo.nTime <= pfrom->timeLastMempoolReq) {
- pfrom->PushMessage(NetMsgType::TX, *txinfo.tx);
+ pfrom->PushMessageWithFlag(inv.type == MSG_TX ? SERIALIZE_TRANSACTION_NO_WITNESS : 0, NetMsgType::TX, *txinfo.tx);
push = true;
}
}
@@ -4665,7 +4921,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// Track requests for our stuff.
GetMainSignals().Inventory(inv.hash);
- if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK)
+ if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK)
break;
}
}
@@ -4684,6 +4940,14 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
}
+uint32_t GetFetchFlags(CNode* pfrom, CBlockIndex* pprev, const Consensus::Params& chainparams) {
+ uint32_t nFetchFlags = 0;
+ if (IsWitnessEnabled(pprev, chainparams) && State(pfrom->GetId())->fHaveWitness) {
+ nFetchFlags |= MSG_WITNESS_FLAG;
+ }
+ return nFetchFlags;
+}
+
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams)
{
LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id);
@@ -4790,6 +5054,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->fClient = !(pfrom->nServices & NODE_NETWORK);
+ if((pfrom->nServices & NODE_WITNESS))
+ {
+ LOCK(cs_main);
+ State(pfrom->GetId())->fHaveWitness = true;
+ }
+
// Potentially mark this peer as a preferred download peer.
{
LOCK(cs_main);
@@ -4991,17 +5261,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
LOCK(cs_main);
+ uint32_t nFetchFlags = GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus());
+
std::vector<CInv> vToFetch;
for (unsigned int nInv = 0; nInv < vInv.size(); nInv++)
{
- const CInv &inv = vInv[nInv];
+ CInv &inv = vInv[nInv];
boost::this_thread::interruption_point();
bool fAlreadyHave = AlreadyHave(inv);
LogPrint("net", "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id);
+ if (inv.type == MSG_TX) {
+ inv.type |= nFetchFlags;
+ }
+
if (inv.type == MSG_BLOCK) {
UpdateBlockAvailability(pfrom->GetId(), inv.hash);
if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) {
@@ -5016,8 +5292,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash);
CNodeState *nodestate = State(pfrom->GetId());
if (CanDirectFetch(chainparams.GetConsensus()) &&
- nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
- if (nodestate->fProvidesHeaderAndIDs)
+ nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER &&
+ (!IsWitnessEnabled(chainActive.Tip(), chainparams.GetConsensus()) || State(pfrom->GetId())->fHaveWitness)) {
+ inv.type |= nFetchFlags;
+ if (nodestate->fProvidesHeaderAndIDs && !(nLocalServices & NODE_WITNESS))
vToFetch.push_back(CInv(MSG_CMPCT_BLOCK, inv.hash));
else
vToFetch.push_back(inv);
@@ -5146,7 +5424,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
resp.txn[i] = block.vtx[req.indexes[i]];
}
- pfrom->PushMessage(NetMsgType::BLOCKTXN, resp);
+ pfrom->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCKTXN, resp);
}
@@ -5273,7 +5551,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
else if (!fMissingInputs2)
{
int nDos = 0;
- if (stateDummy.IsInvalid(nDos) && nDos > 0)
+ if (stateDummy.IsInvalid(nDos) && nDos > 0 && (!state.CorruptionPossible() || State(fromPeer)->fHaveWitness))
{
// Punish peer that gave us an invalid orphan tx
Misbehaving(fromPeer, nDos);
@@ -5284,8 +5562,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Probably non-standard or insufficient fee/priority
LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString());
vEraseQueue.push_back(orphanHash);
- assert(recentRejects);
- recentRejects->insert(orphanHash);
+ if (!stateDummy.CorruptionPossible()) {
+ assert(recentRejects);
+ recentRejects->insert(orphanHash);
+ }
}
mempool.check(pcoinsTip);
}
@@ -5320,8 +5600,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
LogPrint("mempool", "not keeping orphan with rejected parents %s\n",tx.GetHash().ToString());
}
} else {
- assert(recentRejects);
- recentRejects->insert(tx.GetHash());
+ if (!state.CorruptionPossible()) {
+ assert(recentRejects);
+ recentRejects->insert(tx.GetHash());
+ }
if (pfrom->fWhitelisted && GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) {
// Always relay transactions received from whitelisted peers, even
@@ -5350,8 +5632,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (state.GetRejectCode() < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P
pfrom->PushMessage(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
- if (nDoS > 0)
+ if (nDoS > 0 && (!state.CorruptionPossible() || State(pfrom->id)->fHaveWitness)) {
+ // When a non-witness-supporting peer gives us a transaction that would
+ // be accepted if witness validation was off, we can't blame them for it.
Misbehaving(pfrom->GetId(), nDoS);
+ }
}
FlushStateToDisk(state, FLUSH_STATE_PERIODIC);
}
@@ -5595,7 +5880,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Calculate all the blocks we'd need to switch to pindexLast, up to a limit.
while (pindexWalk && !chainActive.Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) &&
- !mapBlocksInFlight.count(pindexWalk->GetBlockHash())) {
+ !mapBlocksInFlight.count(pindexWalk->GetBlockHash()) &&
+ (!IsWitnessEnabled(pindexWalk->pprev, chainparams.GetConsensus()) || State(pfrom->GetId())->fHaveWitness)) {
// We don't have this block, and it's not yet in flight.
vToFetch.push_back(pindexWalk);
}
@@ -5617,7 +5903,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Can't download any more from this peer
break;
}
- vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash()));
+ uint32_t nFetchFlags = GetFetchFlags(pfrom, pindex->pprev, chainparams.GetConsensus());
+ vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
MarkBlockAsInFlight(pfrom->GetId(), pindex->GetBlockHash(), chainparams.GetConsensus(), pindex);
LogPrint("net", "Requesting block %s from peer=%d\n",
pindex->GetBlockHash().ToString(), pfrom->id);
@@ -5627,7 +5914,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pindexLast->GetBlockHash().ToString(), pindexLast->nHeight);
}
if (vGetData.size() > 0) {
- if (nodestate->fProvidesHeaderAndIDs && vGetData.size() == 1 && mapBlocksInFlight.size() == 1 && pindexLast->pprev->IsValid(BLOCK_VALID_CHAIN)) {
+ if (nodestate->fProvidesHeaderAndIDs && vGetData.size() == 1 && mapBlocksInFlight.size() == 1 && pindexLast->pprev->IsValid(BLOCK_VALID_CHAIN) && !(nLocalServices & NODE_WITNESS)) {
// We seem to be rather well-synced, so it appears pfrom was the first to provide us
// with this block! Let's get them to announce using compact blocks in the future.
MaybeSetPeerAsAnnouncingHeaderAndIDs(nodestate, pfrom);
@@ -6463,10 +6750,13 @@ bool SendMessages(CNode* pto)
NodeId staller = -1;
FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller);
BOOST_FOREACH(CBlockIndex *pindex, vToDownload) {
- vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash()));
- MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex);
- LogPrint("net", "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(),
- pindex->nHeight, pto->id);
+ if (State(pto->GetId())->fHaveWitness || !IsWitnessEnabled(pindex->pprev, consensusParams)) {
+ uint32_t nFetchFlags = GetFetchFlags(pto, pindex->pprev, consensusParams);
+ vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
+ MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex);
+ LogPrint("net", "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(),
+ pindex->nHeight, pto->id);
+ }
}
if (state.nBlocksInFlight == 0 && staller != -1) {
if (State(staller)->nStallingSince == 0) {
diff --git a/src/main.h b/src/main.h
index f004a29bb1..2ffe5770dc 100644
--- a/src/main.h
+++ b/src/main.h
@@ -152,6 +152,7 @@ typedef boost::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
extern BlockMap mapBlockIndex;
extern uint64_t nLastBlockTx;
extern uint64_t nLastBlockSize;
+extern uint64_t nLastBlockCost;
extern const std::string strMessageMagic;
extern CWaitableCriticalSection csBestBlock;
extern CConditionVariable cvBlockChange;
@@ -332,6 +333,14 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx);
*/
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs);
+/**
+ * Compute total signature operation cost of a transaction.
+ * @param[in] tx Transaction for which we are computing the cost
+ * @param[in] inputs Map of previous transactions that have outputs we're spending
+ * @param[out] flags Script verification flags
+ * @return Total signature operation cost of tx
+ */
+int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags);
/**
* Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
@@ -394,6 +403,7 @@ class CScriptCheck
{
private:
CScript scriptPubKey;
+ CAmount amount;
const CTransaction *ptxTo;
unsigned int nIn;
unsigned int nFlags;
@@ -401,9 +411,9 @@ private:
ScriptError error;
public:
- CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
+ CScriptCheck(): amount(0), ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) :
- scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
+ scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), amount(txFromIn.vout[txToIn.vin[nInIn].prevout.n].nValue),
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) { }
bool operator()();
@@ -411,6 +421,7 @@ public:
void swap(CScriptCheck &check) {
scriptPubKey.swap(check.scriptPubKey);
std::swap(ptxTo, check.ptxTo);
+ std::swap(amount, check.amount);
std::swap(nIn, check.nIn);
std::swap(nFlags, check.nFlags);
std::swap(cacheStore, check.cacheStore);
@@ -453,6 +464,18 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */
bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
+/** Check whether witness commitments are required for block. */
+bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params);
+
+/** When there are blocks in the active chain with missing data, rewind the chainstate and remove them from the block index */
+bool RewindBlockIndex(const CChainParams& params);
+
+/** Update uncommitted block structures (currently: only the witness nonce). This is safe for submitted blocks. */
+void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams);
+
+/** Produce the necessary coinbase commitment for a block (modifies the hash, don't call for mined blocks). */
+std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams);
+
/** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */
class CVerifyDB {
public:
diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
index dca4973cc4..31332526a9 100644
--- a/src/merkleblock.cpp
+++ b/src/merkleblock.cpp
@@ -155,7 +155,7 @@ uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch, std::ve
if (nTransactions == 0)
return uint256();
// check for excessively high numbers of transactions
- if (nTransactions > MAX_BLOCK_SIZE / 60) // 60 is the lower bound for the size of a serialized CTransaction
+ if (nTransactions > MAX_BLOCK_BASE_SIZE / 60) // 60 is the lower bound for the size of a serialized CTransaction
return uint256();
// there can never be more hashes provided than one for every txid
if (vHash.size() > nTransactions)
diff --git a/src/miner.cpp b/src/miner.cpp
index 989ad11a26..cfc2dae56e 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -45,6 +45,7 @@ using namespace std;
uint64_t nLastBlockTx = 0;
uint64_t nLastBlockSize = 0;
+uint64_t nLastBlockCost = 0;
class ScoreCompare
{
@@ -75,15 +76,36 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam
BlockAssembler::BlockAssembler(const CChainParams& _chainparams)
: chainparams(_chainparams)
{
- // Largest block you're willing to create:
- nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
- // Limit to between 1K and MAX_BLOCK_SIZE-1K for sanity:
- nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
+ // Block resource limits
+ // If neither -blockmaxsize or -blockmaxcost is given, limit to DEFAULT_BLOCK_MAX_*
+ // If only one is given, only restrict the specified resource.
+ // If both are given, restrict both.
+ nBlockMaxCost = DEFAULT_BLOCK_MAX_COST;
+ nBlockMaxSize = DEFAULT_BLOCK_MAX_SIZE;
+ bool fCostSet = false;
+ if (mapArgs.count("-blockmaxcost")) {
+ nBlockMaxCost = GetArg("-blockmaxcost", DEFAULT_BLOCK_MAX_COST);
+ nBlockMaxSize = MAX_BLOCK_SERIALIZED_SIZE;
+ fCostSet = true;
+ }
+ if (mapArgs.count("-blockmaxsize")) {
+ nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
+ if (!fCostSet) {
+ nBlockMaxCost = nBlockMaxSize * WITNESS_SCALE_FACTOR;
+ }
+ }
+ // Limit cost to between 4K and MAX_BLOCK_COST-4K for sanity:
+ nBlockMaxCost = std::max((unsigned int)4000, std::min((unsigned int)(MAX_BLOCK_COST-4000), nBlockMaxCost));
+ // Limit size to between 1K and MAX_BLOCK_SERIALIZED_SIZE-1K for sanity:
+ nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SERIALIZED_SIZE-1000), nBlockMaxSize));
// Minimum block size you want to create; block will be filled with free transactions
// until there are no more or the block reaches this size:
nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
+
+ // Whether we need to account for byte usage (in addition to cost usage)
+ fNeedSizeAccounting = (nBlockMaxSize < MAX_BLOCK_SERIALIZED_SIZE-1000) || (nBlockMinSize > 0);
}
void BlockAssembler::resetBlock()
@@ -92,7 +114,9 @@ void BlockAssembler::resetBlock()
// Reserve space for coinbase tx
nBlockSize = 1000;
- nBlockSigOps = 100;
+ nBlockCost = 4000;
+ nBlockSigOpsCost = 400;
+ fIncludeWitness = false;
// These counters do not include coinbase tx
nBlockTx = 0;
@@ -115,7 +139,7 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
// Add dummy coinbase tx as first transaction
pblock->vtx.push_back(CTransaction());
pblocktemplate->vTxFees.push_back(-1); // updated at end
- pblocktemplate->vTxSigOps.push_back(-1); // updated at end
+ pblocktemplate->vTxSigOpsCost.push_back(-1); // updated at end
LOCK2(cs_main, mempool.cs);
CBlockIndex* pindexPrev = chainActive.Tip();
@@ -134,12 +158,27 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
? nMedianTimePast
: pblock->GetBlockTime();
+ // Decide whether to include witness transactions
+ // This is only needed in case the witness softfork activation is reverted
+ // (which would require a very deep reorganization) or when
+ // -promiscuousmempoolflags is used.
+ // TODO: replace this with a call to main to assess validity of a mempool
+ // transaction (which in most cases can be a no-op).
+ fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus());
+
addPriorityTxs();
- addPackageTxs();
+ if (fNeedSizeAccounting) {
+ // addPackageTxs (the CPFP-based algorithm) cannot deal with size based
+ // accounting, so fall back to the old algorithm.
+ addScoreTxs();
+ } else {
+ addPackageTxs();
+ }
nLastBlockTx = nBlockTx;
nLastBlockSize = nBlockSize;
- LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOps);
+ nLastBlockCost = nBlockCost;
+ LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOpsCost);
// Create coinbase transaction.
CMutableTransaction coinbaseTx;
@@ -150,6 +189,7 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus());
coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0;
pblock->vtx[0] = coinbaseTx;
+ pblocktemplate->vchCoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, chainparams.GetConsensus());
pblocktemplate->vTxFees[0] = -nFees;
// Fill in header
@@ -157,7 +197,7 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus());
pblock->nNonce = 0;
- pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
+ pblocktemplate->vTxSigOpsCost[0] = GetLegacySigOpCount(pblock->vtx[0]);
CValidationState state;
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
@@ -191,11 +231,12 @@ void BlockAssembler::onlyUnconfirmed(CTxMemPool::setEntries& testSet)
}
}
-bool BlockAssembler::TestPackage(uint64_t packageSize, unsigned int packageSigOps)
+bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost)
{
- if (nBlockSize + packageSize >= nBlockMaxSize)
+ // TODO: switch to cost-based accounting for packages instead of vsize-based accounting.
+ if (nBlockCost + WITNESS_SCALE_FACTOR * packageSize >= nBlockMaxCost)
return false;
- if (nBlockSigOps + packageSigOps >= MAX_BLOCK_SIGOPS)
+ if (nBlockSigOpsCost + packageSigOpsCost >= MAX_BLOCK_SIGOPS_COST)
return false;
return true;
}
@@ -213,26 +254,39 @@ bool BlockAssembler::TestPackageFinality(const CTxMemPool::setEntries& package)
bool BlockAssembler::TestForBlock(CTxMemPool::txiter iter)
{
- if (nBlockSize + iter->GetTxSize() >= nBlockMaxSize) {
+ if (nBlockCost + iter->GetTxCost() >= nBlockMaxCost) {
// If the block is so close to full that no more txs will fit
// or if we've tried more than 50 times to fill remaining space
// then flag that the block is finished
- if (nBlockSize > nBlockMaxSize - 100 || lastFewTxs > 50) {
+ if (nBlockCost > nBlockMaxCost - 400 || lastFewTxs > 50) {
blockFinished = true;
return false;
}
- // Once we're within 1000 bytes of a full block, only look at 50 more txs
+ // Once we're within 4000 cost of a full block, only look at 50 more txs
// to try to fill the remaining space.
- if (nBlockSize > nBlockMaxSize - 1000) {
+ if (nBlockCost > nBlockMaxCost - 4000) {
lastFewTxs++;
}
return false;
}
- if (nBlockSigOps + iter->GetSigOpCount() >= MAX_BLOCK_SIGOPS) {
+ if (fNeedSizeAccounting) {
+ if (nBlockSize + ::GetSerializeSize(iter->GetTx(), SER_NETWORK, PROTOCOL_VERSION) >= nBlockMaxSize) {
+ if (nBlockSize > nBlockMaxSize - 100 || lastFewTxs > 50) {
+ blockFinished = true;
+ return false;
+ }
+ if (nBlockSize > nBlockMaxSize - 1000) {
+ lastFewTxs++;
+ }
+ return false;
+ }
+ }
+
+ if (nBlockSigOpsCost + iter->GetSigOpCost() >= MAX_BLOCK_SIGOPS_COST) {
// If the block has room for no more sig ops then
// flag that the block is finished
- if (nBlockSigOps > MAX_BLOCK_SIGOPS - 2) {
+ if (nBlockSigOpsCost > MAX_BLOCK_SIGOPS_COST - 8) {
blockFinished = true;
return false;
}
@@ -254,10 +308,13 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter)
{
pblock->vtx.push_back(iter->GetTx());
pblocktemplate->vTxFees.push_back(iter->GetFee());
- pblocktemplate->vTxSigOps.push_back(iter->GetSigOpCount());
- nBlockSize += iter->GetTxSize();
+ pblocktemplate->vTxSigOpsCost.push_back(iter->GetSigOpCost());
+ if (fNeedSizeAccounting) {
+ nBlockSize += ::GetSerializeSize(iter->GetTx(), SER_NETWORK, PROTOCOL_VERSION);
+ }
+ nBlockCost += iter->GetTxCost();
++nBlockTx;
- nBlockSigOps += iter->GetSigOpCount();
+ nBlockSigOpsCost += iter->GetSigOpCost();
nFees += iter->GetFee();
inBlock.insert(iter);
@@ -299,6 +356,10 @@ void BlockAssembler::addScoreTxs()
continue;
}
+ // cannot accept witness transactions into a non-witness block
+ if (!fIncludeWitness && !iter->GetTx().wit.IsNull())
+ continue;
+
// If tx is dependent on other mempool txs which haven't yet been included
// then put it in the waitSet
if (isStillDependent(iter)) {
@@ -344,7 +405,7 @@ void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alread
CTxMemPoolModifiedEntry modEntry(desc);
modEntry.nSizeWithAncestors -= it->GetTxSize();
modEntry.nModFeesWithAncestors -= it->GetModifiedFee();
- modEntry.nSigOpCountWithAncestors -= it->GetSigOpCount();
+ modEntry.nSigOpCostWithAncestors -= it->GetSigOpCost();
mapModifiedTx.insert(modEntry);
} else {
mapModifiedTx.modify(mit, update_for_parent_inclusion(it));
@@ -446,19 +507,19 @@ void BlockAssembler::addPackageTxs()
uint64_t packageSize = iter->GetSizeWithAncestors();
CAmount packageFees = iter->GetModFeesWithAncestors();
- unsigned int packageSigOps = iter->GetSigOpCountWithAncestors();
+ int64_t packageSigOpsCost = iter->GetSigOpCostWithAncestors();
if (fUsingModified) {
packageSize = modit->nSizeWithAncestors;
packageFees = modit->nModFeesWithAncestors;
- packageSigOps = modit->nSigOpCountWithAncestors;
+ packageSigOpsCost = modit->nSigOpCostWithAncestors;
}
- if (packageFees < ::minRelayTxFee.GetFee(packageSize) && nBlockSize >= nBlockMinSize) {
+ if (packageFees < ::minRelayTxFee.GetFee(packageSize)) {
// Everything else we might consider has a lower fee rate
return;
}
- if (!TestPackage(packageSize, packageSigOps)) {
+ if (!TestPackage(packageSize, packageSigOpsCost)) {
if (fUsingModified) {
// Since we always look at the best entry in mapModifiedTx,
// we must erase failed entries so that we can consider the
@@ -512,6 +573,8 @@ void BlockAssembler::addPriorityTxs()
return;
}
+ fNeedSizeAccounting = true;
+
// This vector will be sorted into a priority queue:
vector<TxCoinAgePriority> vecPriority;
TxCoinAgePriorityCompare pricomparer;
@@ -543,6 +606,10 @@ void BlockAssembler::addPriorityTxs()
continue;
}
+ // cannot accept witness transactions into a non-witness block
+ if (!fIncludeWitness && !iter->GetTx().wit.IsNull())
+ continue;
+
// If tx is dependent on other mempool txs which haven't yet been included
// then put it in the waitSet
if (isStillDependent(iter)) {
diff --git a/src/miner.h b/src/miner.h
index a9fea85304..b303a8fa3c 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -28,7 +28,8 @@ struct CBlockTemplate
{
CBlock block;
std::vector<CAmount> vTxFees;
- std::vector<int64_t> vTxSigOps;
+ std::vector<int64_t> vTxSigOpsCost;
+ std::vector<unsigned char> vchCoinbaseCommitment;
};
// Container for tracking updates to ancestor feerate as we include (parent)
@@ -39,13 +40,13 @@ struct CTxMemPoolModifiedEntry {
iter = entry;
nSizeWithAncestors = entry->GetSizeWithAncestors();
nModFeesWithAncestors = entry->GetModFeesWithAncestors();
- nSigOpCountWithAncestors = entry->GetSigOpCountWithAncestors();
+ nSigOpCostWithAncestors = entry->GetSigOpCostWithAncestors();
}
CTxMemPool::txiter iter;
uint64_t nSizeWithAncestors;
CAmount nModFeesWithAncestors;
- unsigned int nSigOpCountWithAncestors;
+ int64_t nSigOpCostWithAncestors;
};
/** Comparator for CTxMemPool::txiter objects.
@@ -123,7 +124,7 @@ struct update_for_parent_inclusion
{
e.nModFeesWithAncestors -= iter->GetFee();
e.nSizeWithAncestors -= iter->GetTxSize();
- e.nSigOpCountWithAncestors -= iter->GetSigOpCount();
+ e.nSigOpCostWithAncestors -= iter->GetSigOpCost();
}
CTxMemPool::txiter iter;
@@ -139,12 +140,15 @@ private:
CBlock* pblock;
// Configuration parameters for the block size
- unsigned int nBlockMaxSize, nBlockMinSize;
+ bool fIncludeWitness;
+ unsigned int nBlockMaxCost, nBlockMaxSize, nBlockMinSize;
+ bool fNeedSizeAccounting;
// Information on the current status of the block
+ uint64_t nBlockCost;
uint64_t nBlockSize;
uint64_t nBlockTx;
- unsigned int nBlockSigOps;
+ uint64_t nBlockSigOpsCost;
CAmount nFees;
CTxMemPool::setEntries inBlock;
@@ -187,7 +191,7 @@ private:
/** Remove confirmed (inBlock) entries from given set */
void onlyUnconfirmed(CTxMemPool::setEntries& testSet);
/** Test if a new package would "fit" in the block */
- bool TestPackage(uint64_t packageSize, unsigned int packageSigOps);
+ bool TestPackage(uint64_t packageSize, int64_t packageSigOpsCost);
/** Test if a set of transactions are all final */
bool TestPackageFinality(const CTxMemPool::setEntries& package);
/** Return true if given transaction from mapTx has already been evaluated,
diff --git a/src/net.cpp b/src/net.cpp
index 336163a896..4cbc43e4d8 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -72,7 +72,7 @@ namespace {
const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*";
/** Services this node implementation cares about */
-static const ServiceFlags nRelevantServices = NODE_NETWORK;
+ServiceFlags nRelevantServices = NODE_NETWORK;
//
// Global state variables
@@ -1676,6 +1676,10 @@ void ThreadOpenConnections()
if (nANow - addr.nLastTry < 600 && nTries < 30)
continue;
+ // only consider nodes missing relevant services after 40 failed attemps
+ if ((addr.nServices & nRelevantServices) != nRelevantServices && nTries < 40)
+ continue;
+
// do not allow non-default ports, unless after 50 invalid addresses selected already
if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
continue;
@@ -2178,7 +2182,7 @@ void CNode::RecordBytesSent(uint64_t bytes)
void CNode::SetMaxOutboundTarget(uint64_t limit)
{
LOCK(cs_totalBytesSent);
- uint64_t recommendedMinimum = (nMaxOutboundTimeframe / 600) * MAX_BLOCK_SIZE;
+ uint64_t recommendedMinimum = (nMaxOutboundTimeframe / 600) * MAX_BLOCK_SERIALIZED_SIZE;
nMaxOutboundLimit = limit;
if (limit > 0 && limit < recommendedMinimum)
@@ -2233,7 +2237,7 @@ bool CNode::OutboundTargetReached(bool historicalBlockServingLimit)
{
// keep a large enough buffer to at least relay each block once
uint64_t timeLeftInCycle = GetMaxOutboundTimeLeftInCycle();
- uint64_t buffer = timeLeftInCycle / 600 * MAX_BLOCK_SIZE;
+ uint64_t buffer = timeLeftInCycle / 600 * MAX_BLOCK_SERIALIZED_SIZE;
if (buffer >= nMaxOutboundLimit || nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer)
return true;
}
diff --git a/src/net.h b/src/net.h
index aa9b2c11a3..41315fc9b9 100644
--- a/src/net.h
+++ b/src/net.h
@@ -45,8 +45,8 @@ static const int TIMEOUT_INTERVAL = 20 * 60;
static const unsigned int MAX_INV_SZ = 50000;
/** The maximum number of new addresses to accumulate before announcing. */
static const unsigned int MAX_ADDR_TO_SEND = 1000;
-/** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */
-static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 2 * 1024 * 1024;
+/** Maximum length of incoming protocol messages (no message over 4 MB is currently acceptable). */
+static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 4 * 1000 * 1000;
/** Maximum length of strSubVer in `version` message */
static const unsigned int MAX_SUBVERSION_LENGTH = 256;
/** -listen default */
@@ -156,6 +156,7 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL);
extern bool fDiscover;
extern bool fListen;
extern ServiceFlags nLocalServices;
+extern ServiceFlags nRelevantServices;
extern bool fRelayTxes;
extern uint64_t nLocalHostNonce;
extern CAddrMan addrman;
@@ -598,6 +599,23 @@ public:
}
}
+ /** Send a message containing a1, serialized with flag flag. */
+ template<typename T1>
+ void PushMessageWithFlag(int flag, const char* pszCommand, const T1& a1)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ WithOrVersion(&ssSend, flag) << a1;
+ EndMessage(pszCommand);
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
template<typename T1, typename T2>
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2)
{
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index d1a15451dc..f2148bfe10 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -64,8 +64,8 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
// 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.
- unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
- if (sz >= MAX_STANDARD_TX_SIZE) {
+ unsigned int sz = GetTransactionCost(tx);
+ if (sz >= MAX_STANDARD_TX_COST) {
reason = "tx-size";
return false;
}
@@ -137,7 +137,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
{
std::vector<std::vector<unsigned char> > stack;
// convert the scriptSig into a stack, so we can inspect the redeemScript
- if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), 0))
+ if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SIGVERSION_BASE))
return false;
if (stack.empty())
return false;
@@ -150,3 +150,13 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
return true;
}
+
+int64_t GetVirtualTransactionSize(int64_t nCost)
+{
+ return (nCost + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
+}
+
+int64_t GetVirtualTransactionSize(const CTransaction& tx)
+{
+ return GetVirtualTransactionSize(GetTransactionCost(tx));
+}
diff --git a/src/policy/policy.h b/src/policy/policy.h
index 4f9354e36f..fefb562ff9 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -19,12 +19,14 @@ static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000;
static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0;
/** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/
static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 0;
+/** Default for -blockmaxcost, which control the range of block costs the mining code will create **/
+static const unsigned int DEFAULT_BLOCK_MAX_COST = 3000000;
/** The maximum size for transactions we're willing to relay/mine */
-static const unsigned int MAX_STANDARD_TX_SIZE = 100000;
+static const unsigned int MAX_STANDARD_TX_COST = 400000;
/** Maximum number of signature check operations in an IsStandard() P2SH script */
static const unsigned int MAX_P2SH_SIGOPS = 15;
/** The maximum number of sigops we're willing to relay/mine in a single tx */
-static const unsigned int MAX_STANDARD_TX_SIGOPS = MAX_BLOCK_SIGOPS/5;
+static const unsigned int MAX_STANDARD_TX_SIGOPS_COST = MAX_BLOCK_SIGOPS_COST/5;
/** Default for -maxmempool, maximum megabytes of mempool memory usage */
static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;
/**
@@ -41,7 +43,9 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY
SCRIPT_VERIFY_CLEANSTACK |
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY |
- SCRIPT_VERIFY_LOW_S;
+ SCRIPT_VERIFY_LOW_S |
+ SCRIPT_VERIFY_WITNESS |
+ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM;
/** For convenience, standard but not mandatory verify flags. */
static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS;
@@ -63,4 +67,8 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason);
*/
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
+/** Compute the virtual transaction size (cost reinterpreted as bytes). */
+int64_t GetVirtualTransactionSize(int64_t nCost);
+int64_t GetVirtualTransactionSize(const CTransaction& tx);
+
#endif // BITCOIN_POLICY_POLICY_H
diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp
index 6fb33230a5..df900388f2 100644
--- a/src/primitives/block.cpp
+++ b/src/primitives/block.cpp
@@ -31,3 +31,12 @@ std::string CBlock::ToString() const
}
return s.str();
}
+
+int64_t GetBlockCost(const CBlock& block)
+{
+ // This implements the cost = (stripped_size * 4) + witness_size formula,
+ // using only serialization with and without witness data. As witness_size
+ // is equal to total_size - stripped_size, this formula is identical to:
+ // cost = (stripped_size * 3) + total_size.
+ return ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION);
+}
diff --git a/src/primitives/block.h b/src/primitives/block.h
index 42276b2bc2..e2a309e63d 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -38,7 +38,6 @@ public:
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(this->nVersion);
- nVersion = this->nVersion;
READWRITE(hashPrevBlock);
READWRITE(hashMerkleRoot);
READWRITE(nTime);
@@ -120,7 +119,6 @@ public:
std::string ToString() const;
};
-
/** Describes a place in the block chain to another node such that if the
* other node doesn't have the same branch, it can find a recent common trunk.
* The further back it is, the further before the fork it may be.
@@ -156,4 +154,7 @@ struct CBlockLocator
}
};
+/** Compute the consensus-critical block cost (see BIP 141). */
+int64_t GetBlockCost(const CBlock& tx);
+
#endif // BITCOIN_PRIMITIVES_BLOCK_H
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index 947f2e6a73..7f10409c05 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -60,21 +60,26 @@ std::string CTxOut::ToString() const
}
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {}
-CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {}
+CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), wit(tx.wit), nLockTime(tx.nLockTime) {}
uint256 CMutableTransaction::GetHash() const
{
- return SerializeHash(*this);
+ return SerializeHash(*this, SER_GETHASH, SERIALIZE_TRANSACTION_NO_WITNESS);
}
void CTransaction::UpdateHash() const
{
- *const_cast<uint256*>(&hash) = SerializeHash(*this);
+ *const_cast<uint256*>(&hash) = SerializeHash(*this, SER_GETHASH, SERIALIZE_TRANSACTION_NO_WITNESS);
+}
+
+uint256 CTransaction::GetWitnessHash() const
+{
+ return SerializeHash(*this, SER_GETHASH, 0);
}
CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { }
-CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {
+CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), wit(tx.wit), nLockTime(tx.nLockTime) {
UpdateHash();
}
@@ -82,6 +87,7 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) {
*const_cast<int*>(&nVersion) = tx.nVersion;
*const_cast<std::vector<CTxIn>*>(&vin) = tx.vin;
*const_cast<std::vector<CTxOut>*>(&vout) = tx.vout;
+ *const_cast<CTxWitness*>(&wit) = tx.wit;
*const_cast<unsigned int*>(&nLockTime) = tx.nLockTime;
*const_cast<uint256*>(&hash) = tx.hash;
return *this;
@@ -115,7 +121,7 @@ unsigned int CTransaction::CalculateModifiedSize(unsigned int nTxSize) const
// Providing any more cleanup incentive than making additional inputs free would
// risk encouraging people to create junk outputs to redeem later.
if (nTxSize == 0)
- nTxSize = ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION);
+ nTxSize = (GetTransactionCost(*this) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
for (std::vector<CTxIn>::const_iterator it(vin.begin()); it != vin.end(); ++it)
{
unsigned int offset = 41U + std::min(110U, (unsigned int)it->scriptSig.size());
@@ -136,7 +142,14 @@ std::string CTransaction::ToString() const
nLockTime);
for (unsigned int i = 0; i < vin.size(); i++)
str += " " + vin[i].ToString() + "\n";
+ for (unsigned int i = 0; i < wit.vtxinwit.size(); i++)
+ str += " " + wit.vtxinwit[i].scriptWitness.ToString() + "\n";
for (unsigned int i = 0; i < vout.size(); i++)
str += " " + vout[i].ToString() + "\n";
return str;
}
+
+int64_t GetTransactionCost(const CTransaction& tx)
+{
+ return ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR -1) + ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
+}
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 149816406a..e87ad90f0d 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -11,6 +11,10 @@
#include "serialize.h"
#include "uint256.h"
+static const int SERIALIZE_TRANSACTION_NO_WITNESS = 0x40000000;
+
+static const int WITNESS_SCALE_FACTOR = 4;
+
/** An outpoint - a combination of a transaction hash and an index n into its vout */
class COutPoint
{
@@ -164,15 +168,30 @@ public:
// which has units satoshis-per-kilobyte.
// If you'd pay more than 1/3 in fees
// to spend something, then we consider it dust.
- // A typical spendable txout is 34 bytes big, and will
+ // A typical spendable non-segwit txout is 34 bytes big, and will
// need a CTxIn of at least 148 bytes to spend:
// so dust is a spendable txout less than
- // 546*minRelayTxFee/1000 (in satoshis)
+ // 546*minRelayTxFee/1000 (in satoshis).
+ // A typical spendable segwit txout is 31 bytes big, and will
+ // need a CTxIn of at least 67 bytes to spend:
+ // so dust is a spendable txout less than
+ // 294*minRelayTxFee/1000 (in satoshis).
if (scriptPubKey.IsUnspendable())
return 0;
- size_t nSize = GetSerializeSize(SER_DISK,0)+148u;
- return 3*minRelayTxFee.GetFee(nSize);
+ size_t nSize = GetSerializeSize(SER_DISK, 0);
+ int witnessversion = 0;
+ std::vector<unsigned char> witnessprogram;
+
+ if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
+ // sum the sizes of the parts of a transaction input
+ // with 75% segwit discount applied to the script size.
+ nSize += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4);
+ } else {
+ nSize += (32 + 4 + 1 + 107 + 4); // the 148 mentioned above
+ }
+
+ return 3 * minRelayTxFee.GetFee(nSize);
}
bool IsDust(const CFeeRate &minRelayTxFee) const
@@ -194,8 +213,137 @@ public:
std::string ToString() const;
};
+class CTxinWitness
+{
+public:
+ CScriptWitness scriptWitness;
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
+ {
+ READWRITE(scriptWitness.stack);
+ }
+
+ bool IsNull() const { return scriptWitness.IsNull(); }
+
+ CTxinWitness() { }
+};
+
+class CTxWitness
+{
+public:
+ /** In case vtxinwit is missing, all entries are treated as if they were empty CTxInWitnesses */
+ std::vector<CTxinWitness> vtxinwit;
+
+ ADD_SERIALIZE_METHODS;
+
+ bool IsEmpty() const { return vtxinwit.empty(); }
+
+ bool IsNull() const
+ {
+ for (size_t n = 0; n < vtxinwit.size(); n++) {
+ if (!vtxinwit[n].IsNull()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void SetNull()
+ {
+ vtxinwit.clear();
+ }
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
+ {
+ for (size_t n = 0; n < vtxinwit.size(); n++) {
+ READWRITE(vtxinwit[n]);
+ }
+ if (IsNull()) {
+ /* It's illegal to encode a witness when all vtxinwit entries are empty. */
+ throw std::ios_base::failure("Superfluous witness record");
+ }
+ }
+};
+
struct CMutableTransaction;
+/**
+ * Basic transaction serialization format:
+ * - int32_t nVersion
+ * - std::vector<CTxIn> vin
+ * - std::vector<CTxOut> vout
+ * - uint32_t nLockTime
+ *
+ * Extended transaction serialization format:
+ * - int32_t nVersion
+ * - unsigned char dummy = 0x00
+ * - unsigned char flags (!= 0)
+ * - std::vector<CTxIn> vin
+ * - std::vector<CTxOut> vout
+ * - if (flags & 1):
+ * - CTxWitness wit;
+ * - uint32_t nLockTime
+ */
+template<typename Stream, typename Operation, typename TxType>
+inline void SerializeTransaction(TxType& tx, Stream& s, Operation ser_action, int nType, int nVersion) {
+ READWRITE(*const_cast<int32_t*>(&tx.nVersion));
+ unsigned char flags = 0;
+ if (ser_action.ForRead()) {
+ const_cast<std::vector<CTxIn>*>(&tx.vin)->clear();
+ const_cast<std::vector<CTxOut>*>(&tx.vout)->clear();
+ const_cast<CTxWitness*>(&tx.wit)->SetNull();
+ /* Try to read the vin. In case the dummy is there, this will be read as an empty vector. */
+ READWRITE(*const_cast<std::vector<CTxIn>*>(&tx.vin));
+ if (tx.vin.size() == 0 && !(nVersion & SERIALIZE_TRANSACTION_NO_WITNESS)) {
+ /* We read a dummy or an empty vin. */
+ READWRITE(flags);
+ if (flags != 0) {
+ READWRITE(*const_cast<std::vector<CTxIn>*>(&tx.vin));
+ READWRITE(*const_cast<std::vector<CTxOut>*>(&tx.vout));
+ }
+ } else {
+ /* We read a non-empty vin. Assume a normal vout follows. */
+ READWRITE(*const_cast<std::vector<CTxOut>*>(&tx.vout));
+ }
+ if ((flags & 1) && !(nVersion & SERIALIZE_TRANSACTION_NO_WITNESS)) {
+ /* The witness flag is present, and we support witnesses. */
+ flags ^= 1;
+ const_cast<CTxWitness*>(&tx.wit)->vtxinwit.resize(tx.vin.size());
+ READWRITE(tx.wit);
+ }
+ if (flags) {
+ /* Unknown flag in the serialization */
+ throw std::ios_base::failure("Unknown transaction optional data");
+ }
+ } else {
+ // Consistency check
+ assert(tx.wit.vtxinwit.size() <= tx.vin.size());
+ if (!(nVersion & SERIALIZE_TRANSACTION_NO_WITNESS)) {
+ /* Check whether witnesses need to be serialized. */
+ if (!tx.wit.IsNull()) {
+ flags |= 1;
+ }
+ }
+ if (flags) {
+ /* Use extended format in case witnesses are to be serialized. */
+ std::vector<CTxIn> vinDummy;
+ READWRITE(vinDummy);
+ READWRITE(flags);
+ }
+ READWRITE(*const_cast<std::vector<CTxIn>*>(&tx.vin));
+ READWRITE(*const_cast<std::vector<CTxOut>*>(&tx.vout));
+ if (flags & 1) {
+ const_cast<CTxWitness*>(&tx.wit)->vtxinwit.resize(tx.vin.size());
+ READWRITE(tx.wit);
+ }
+ }
+ READWRITE(*const_cast<uint32_t*>(&tx.nLockTime));
+}
+
/** The basic transaction that is broadcasted on the network and contained in
* blocks. A transaction can contain multiple inputs and outputs.
*/
@@ -204,7 +352,6 @@ class CTransaction
private:
/** Memory only. */
const uint256 hash;
- void UpdateHash() const;
public:
// Default transaction version.
@@ -224,6 +371,7 @@ public:
const int32_t nVersion;
const std::vector<CTxIn> vin;
const std::vector<CTxOut> vout;
+ CTxWitness wit; // Not const: can change without invalidating the txid cache
const uint32_t nLockTime;
/** Construct a CTransaction that qualifies as IsNull() */
@@ -238,13 +386,10 @@ public:
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- READWRITE(*const_cast<int32_t*>(&this->nVersion));
- nVersion = this->nVersion;
- READWRITE(*const_cast<std::vector<CTxIn>*>(&vin));
- READWRITE(*const_cast<std::vector<CTxOut>*>(&vout));
- READWRITE(*const_cast<uint32_t*>(&nLockTime));
- if (ser_action.ForRead())
+ SerializeTransaction(*this, s, ser_action, nType, nVersion);
+ if (ser_action.ForRead()) {
UpdateHash();
+ }
}
bool IsNull() const {
@@ -255,6 +400,9 @@ public:
return hash;
}
+ // Compute a hash that includes both transaction and witness data
+ uint256 GetWitnessHash() const;
+
// Return sum of txouts.
CAmount GetValueOut() const;
// GetValueIn() is a method on CCoinsViewCache, because
@@ -282,6 +430,8 @@ public:
}
std::string ToString() const;
+
+ void UpdateHash() const;
};
/** A mutable version of CTransaction. */
@@ -290,6 +440,7 @@ struct CMutableTransaction
int32_t nVersion;
std::vector<CTxIn> vin;
std::vector<CTxOut> vout;
+ CTxWitness wit;
uint32_t nLockTime;
CMutableTransaction();
@@ -299,11 +450,7 @@ struct CMutableTransaction
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- READWRITE(this->nVersion);
- nVersion = this->nVersion;
- READWRITE(vin);
- READWRITE(vout);
- READWRITE(nLockTime);
+ SerializeTransaction(*this, s, ser_action, nType, nVersion);
}
/** Compute the hash of this CMutableTransaction. This is computed on the
@@ -312,4 +459,7 @@ struct CMutableTransaction
uint256 GetHash() const;
};
+/** Compute the cost of a transaction, as defined by BIP 141 */
+int64_t GetTransactionCost(const CTransaction &tx);
+
#endif // BITCOIN_PRIMITIVES_TRANSACTION_H
diff --git a/src/protocol.cpp b/src/protocol.cpp
index 2f90fb764c..247c6c2120 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -41,15 +41,6 @@ const char *GETBLOCKTXN="getblocktxn";
const char *BLOCKTXN="blocktxn";
};
-static const char* ppszTypeName[] =
-{
- "ERROR", // Should never occur
- NetMsgType::TX,
- NetMsgType::BLOCK,
- "filtered block", // Should never occur
- "compact block" // Should never occur
-};
-
/** All known message types. Keep this in the same order as the list of
* messages above and in protocol.h.
*/
@@ -166,37 +157,26 @@ CInv::CInv(int typeIn, const uint256& hashIn)
hash = hashIn;
}
-CInv::CInv(const std::string& strType, const uint256& hashIn)
-{
- unsigned int i;
- for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
- {
- if (strType == ppszTypeName[i])
- {
- type = i;
- break;
- }
- }
- if (i == ARRAYLEN(ppszTypeName))
- throw std::out_of_range(strprintf("CInv::CInv(string, uint256): unknown type '%s'", strType));
- hash = hashIn;
-}
-
bool operator<(const CInv& a, const CInv& b)
{
return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
}
-bool CInv::IsKnownType() const
+std::string CInv::GetCommand() const
{
- return (type >= 1 && type < (int)ARRAYLEN(ppszTypeName));
-}
-
-const char* CInv::GetCommand() const
-{
- if (!IsKnownType())
+ std::string cmd;
+ if (type & MSG_WITNESS_FLAG)
+ cmd.append("witness-");
+ int masked = type & MSG_TYPE_MASK;
+ switch (masked)
+ {
+ case MSG_TX: return cmd.append(NetMsgType::TX);
+ case MSG_BLOCK: return cmd.append(NetMsgType::BLOCK);
+ case MSG_FILTERED_BLOCK: return cmd.append(NetMsgType::MERKLEBLOCK);
+ case MSG_CMPCT_BLOCK: return cmd.append(NetMsgType::CMPCTBLOCK);
+ default:
throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
- return ppszTypeName[type];
+ }
}
std::string CInv::ToString() const
diff --git a/src/protocol.h b/src/protocol.h
index a72813e959..15f27e2d2f 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -264,6 +264,9 @@ enum ServiceFlags : uint64_t {
// Bitcoin Core nodes used to support this by default, without advertising this bit,
// but no longer do as of protocol version 70011 (= NO_BLOOM_VERSION)
NODE_BLOOM = (1 << 2),
+ // Indicates that a node can be asked for blocks and transactions including
+ // witness data.
+ NODE_WITNESS = (1 << 3),
// Bits 24-31 are reserved for temporary experiments. Just pick a bit that
// isn't getting used, or one not being used much, and notify the
@@ -309,13 +312,29 @@ public:
unsigned int nTime;
};
+/** getdata message types */
+const uint32_t MSG_WITNESS_FLAG = 1 << 30;
+const uint32_t MSG_TYPE_MASK = 0xffffffff >> 2;
+enum GetDataMsg
+{
+ UNDEFINED = 0,
+ MSG_TX,
+ MSG_BLOCK,
+ MSG_TYPE_MAX = MSG_BLOCK,
+ // The following can only occur in getdata. Invs always use TX or BLOCK.
+ MSG_FILTERED_BLOCK,
+ MSG_CMPCT_BLOCK,
+ MSG_WITNESS_BLOCK = MSG_BLOCK | MSG_WITNESS_FLAG,
+ MSG_WITNESS_TX = MSG_TX | MSG_WITNESS_FLAG,
+ MSG_FILTERED_WITNESS_BLOCK = MSG_FILTERED_BLOCK | MSG_WITNESS_FLAG,
+};
+
/** inv message data */
class CInv
{
public:
CInv();
CInv(int typeIn, const uint256& hashIn);
- CInv(const std::string& strType, const uint256& hashIn);
ADD_SERIALIZE_METHODS;
@@ -328,8 +347,7 @@ public:
friend bool operator<(const CInv& a, const CInv& b);
- bool IsKnownType() const;
- const char* GetCommand() const;
+ std::string GetCommand() const;
std::string ToString() const;
// TODO: make private (improves encapsulation)
@@ -338,13 +356,4 @@ public:
uint256 hash;
};
-enum {
- MSG_TX = 1,
- MSG_BLOCK,
- // Nodes may always request a MSG_FILTERED_BLOCK/MSG_CMPCT_BLOCK in a getdata, however,
- // MSG_FILTERED_BLOCK/MSG_CMPCT_BLOCK should not appear in any invs except as a part of getdata.
- MSG_FILTERED_BLOCK,
- MSG_CMPCT_BLOCK,
-};
-
#endif // BITCOIN_PROTOCOL_H
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index f909499952..837f8ba6c1 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -485,6 +485,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
unsigned int nQuantity = 0;
int nQuantityUncompressed = 0;
bool fAllowFree = false;
+ bool fWitness = false;
std::vector<COutPoint> vCoinControl;
std::vector<COutput> vOutputs;
@@ -513,7 +514,14 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
// Bytes
CTxDestination address;
- if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
+ int witnessversion = 0;
+ std::vector<unsigned char> witnessprogram;
+ if (out.tx->vout[out.i].scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram))
+ {
+ nBytesInputs += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4);
+ fWitness = true;
+ }
+ else if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
{
CPubKey pubkey;
CKeyID *keyid = boost::get<CKeyID>(&address);
@@ -534,6 +542,14 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
{
// Bytes
nBytes = nBytesInputs + ((CoinControlDialog::payAmounts.size() > 0 ? CoinControlDialog::payAmounts.size() + 1 : 2) * 34) + 10; // always assume +1 output for change here
+ if (fWitness)
+ {
+ // there is some fudging in these numbers related to the actual virtual transaction size calculation that will keep this estimate from being exact.
+ // usually, the result will be an overestimate within a couple of satoshis so that the confirmation dialog ends up displaying a slightly smaller fee.
+ // also, the witness stack size value value is a variable sized integer. usually, the number of stack items will be well under the single byte var int limit.
+ nBytes += 2; // account for the serialized marker and flag bytes
+ nBytes += nQuantity; // account for the witness byte that holds the number of stack items for each input.
+ }
// Priority
double mempoolEstimatePriority = mempool.estimateSmartPriority(nTxConfirmTarget);
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index ff4320b36a..4327de9b0c 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -909,6 +909,9 @@ QString formatServicesStr(quint64 mask)
case NODE_BLOOM:
strList.append("BLOOM");
break;
+ case NODE_WITNESS:
+ strList.append("WITNESS");
+ break;
default:
strList.append(QString("%1[%2]").arg("UNKNOWN").arg(check));
}
diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp
index 8c970ee8aa..ffadf89cc8 100644
--- a/src/qt/walletmodeltransaction.cpp
+++ b/src/qt/walletmodeltransaction.cpp
@@ -4,6 +4,7 @@
#include "walletmodeltransaction.h"
+#include "policy/policy.h"
#include "wallet/wallet.h"
WalletModelTransaction::WalletModelTransaction(const QList<SendCoinsRecipient> &recipients) :
@@ -33,7 +34,7 @@ CWalletTx *WalletModelTransaction::getTransaction()
unsigned int WalletModelTransaction::getTransactionSize()
{
- return (!walletTransaction ? 0 : (::GetSerializeSize(*(CTransaction*)walletTransaction, SER_NETWORK, PROTOCOL_VERSION)));
+ return (!walletTransaction ? 0 : ::GetVirtualTransactionSize(*walletTransaction));
}
CAmount WalletModelTransaction::getTransactionFee()
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 1bb365d36c..43ba4edd78 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -99,7 +99,9 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
if (chainActive.Contains(blockindex))
confirmations = chainActive.Height() - blockindex->nHeight + 1;
result.push_back(Pair("confirmations", confirmations));
+ result.push_back(Pair("strippedsize", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS)));
result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
+ result.push_back(Pair("cost", (int)::GetBlockCost(block)));
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", block.nVersion));
result.push_back(Pair("versionHex", strprintf("%08x", block.nVersion)));
@@ -558,6 +560,8 @@ UniValue getblock(const UniValue& params, bool fHelp)
" \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
" \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
" \"size\" : n, (numeric) The block size\n"
+ " \"strippedsize\" : n, (numeric) The block size excluding witness data\n"
+ " \"cost\" : n (numeric) The block cost\n"
" \"height\" : n, (numeric) The block height or index\n"
" \"version\" : n, (numeric) The block version\n"
" \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
@@ -930,6 +934,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
bip9_softforks.push_back(Pair("csv", BIP9SoftForkDesc(consensusParams, Consensus::DEPLOYMENT_CSV)));
+ bip9_softforks.push_back(Pair("segwit", BIP9SoftForkDesc(consensusParams, Consensus::DEPLOYMENT_SEGWIT)));
obj.push_back(Pair("softforks", softforks));
obj.push_back(Pair("bip9_softforks", bip9_softforks));
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 94eeea91f3..4c4e599781 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -224,6 +224,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp)
"{\n"
" \"blocks\": nnn, (numeric) The current block\n"
" \"currentblocksize\": nnn, (numeric) The last block size\n"
+ " \"currentblockcost\": nnn, (numeric) The last block cost\n"
" \"currentblocktx\": nnn, (numeric) The last block transaction\n"
" \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
" \"errors\": \"...\" (string) Current errors\n"
@@ -242,6 +243,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp)
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
+ obj.push_back(Pair("currentblockcost", (uint64_t)nLastBlockCost));
obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
@@ -348,13 +350,15 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
" \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n"
" {\n"
" \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
- " \"hash\" : \"xxxx\", (string) hash/id encoded in little-endian hexadecimal\n"
+ " \"txid\" : \"xxxx\", (string) transaction id encoded in little-endian hexadecimal\n"
+ " \"hash\" : \"xxxx\", (string) hash encoded in little-endian hexadecimal (including witness data)\n"
" \"depends\" : [ (array) array of numbers \n"
" n (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n"
" ,...\n"
" ],\n"
" \"fee\": n, (numeric) difference in value between transaction inputs and outputs (in Satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n"
- " \"sigops\" : n, (numeric) total number of SigOps, as counted for purposes of block limits; if key is not present, sigop count is unknown and clients MUST NOT assume there aren't any\n"
+ " \"sigops\" : n, (numeric) total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero\n"
+ " \"cost\" : n, (numeric) total transaction size cost, as counted for purposes of block limits\n"
" \"required\" : true|false (boolean) if provided and true, this transaction must be in the final block\n"
" }\n"
" ,...\n"
@@ -371,8 +375,9 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
" ,...\n"
" ],\n"
" \"noncerange\" : \"00000000ffffffff\", (string) A range of valid nonces\n"
- " \"sigoplimit\" : n, (numeric) limit of sigops in blocks\n"
+ " \"sigoplimit\" : n, (numeric) cost limit of sigops in blocks\n"
" \"sizelimit\" : n, (numeric) limit of block size\n"
+ " \"costlimit\" : n, (numeric) limit of block cost\n"
" \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
" \"bits\" : \"xxx\", (string) compressed target of next block\n"
" \"height\" : n (numeric) The height of the next block\n"
@@ -546,7 +551,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
UniValue transactions(UniValue::VARR);
map<uint256, int64_t> setTxIndex;
int i = 0;
- BOOST_FOREACH (const CTransaction& tx, pblock->vtx) {
+ BOOST_FOREACH (CTransaction& tx, pblock->vtx) {
uint256 txHash = tx.GetHash();
setTxIndex[txHash] = i++;
@@ -556,8 +561,8 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
UniValue entry(UniValue::VOBJ);
entry.push_back(Pair("data", EncodeHexTx(tx)));
-
- entry.push_back(Pair("hash", txHash.GetHex()));
+ entry.push_back(Pair("txid", txHash.GetHex()));
+ entry.push_back(Pair("hash", tx.GetWitnessHash().GetHex()));
UniValue deps(UniValue::VARR);
BOOST_FOREACH (const CTxIn &in, tx.vin)
@@ -569,7 +574,8 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
int index_in_template = i - 1;
entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
- entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template]));
+ entry.push_back(Pair("sigops", pblocktemplate->vTxSigOpsCost[index_in_template]));
+ entry.push_back(Pair("cost", GetTransactionCost(tx)));
transactions.push_back(entry);
}
@@ -651,11 +657,15 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
result.push_back(Pair("mutable", aMutable));
result.push_back(Pair("noncerange", "00000000ffffffff"));
- result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS));
- result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE));
+ result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS_COST));
+ result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SERIALIZED_SIZE));
+ result.push_back(Pair("costlimit", (int64_t)MAX_BLOCK_COST));
result.push_back(Pair("curtime", pblock->GetBlockTime()));
result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));
+ if (!pblocktemplate->vchCoinbaseCommitment.empty()) {
+ result.push_back(Pair("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end())));
+ }
return result;
}
@@ -719,6 +729,14 @@ UniValue submitblock(const UniValue& params, bool fHelp)
}
}
+ {
+ LOCK(cs_main);
+ BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
+ if (mi != mapBlockIndex.end()) {
+ UpdateUncommittedBlockStructures(block, mi->second, Params().GetConsensus());
+ }
+ }
+
CValidationState state;
submitblock_StateCatcher sc(block.GetHash());
RegisterValidationInterface(&sc);
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 09f5185781..f2a29416e6 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -312,6 +312,43 @@ UniValue createmultisig(const UniValue& params, bool fHelp)
return result;
}
+UniValue createwitnessaddress(const UniValue& params, bool fHelp)
+{
+ if (fHelp || params.size() < 1 || params.size() > 1)
+ {
+ string msg = "createwitnessaddress \"script\"\n"
+ "\nCreates a witness address for a particular script.\n"
+ "It returns a json object with the address and witness script.\n"
+
+ "\nArguments:\n"
+ "1. \"script\" (string, required) A hex encoded script\n"
+
+ "\nResult:\n"
+ "{\n"
+ " \"address\":\"multisigaddress\", (string) The value of the new address (P2SH of witness script).\n"
+ " \"witnessScript\":\"script\" (string) The string value of the hex-encoded witness script.\n"
+ "}\n"
+ ;
+ throw runtime_error(msg);
+ }
+
+ if (!IsHex(params[0].get_str())) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Script must be hex-encoded");
+ }
+
+ std::vector<unsigned char> code = ParseHex(params[0].get_str());
+ CScript script(code.begin(), code.end());
+ CScript witscript = GetScriptForWitness(script);
+ CScriptID witscriptid(witscript);
+ CBitcoinAddress address(witscriptid);
+
+ UniValue result(UniValue::VOBJ);
+ result.push_back(Pair("address", address.ToString()));
+ result.push_back(Pair("witnessScript", HexStr(witscript.begin(), witscript.end())));
+
+ return result;
+}
+
UniValue verifymessage(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 3)
@@ -445,6 +482,7 @@ static const CRPCCommand commands[] =
{ "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */
{ "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */
{ "util", "createmultisig", &createmultisig, true },
+ { "util", "createwitnessaddress", &createwitnessaddress, true },
{ "util", "verifymessage", &verifymessage, true },
{ "util", "signmessagewithprivkey", &signmessagewithprivkey, true },
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 9723e394d6..3270cd384f 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -62,11 +62,15 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fInclud
void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
{
entry.push_back(Pair("txid", tx.GetHash().GetHex()));
+ entry.push_back(Pair("hash", tx.GetWitnessHash().GetHex()));
entry.push_back(Pair("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)));
+ entry.push_back(Pair("vsize", (int)::GetVirtualTransactionSize(tx)));
entry.push_back(Pair("version", tx.nVersion));
entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
+
UniValue vin(UniValue::VARR);
- BOOST_FOREACH(const CTxIn& txin, tx.vin) {
+ for (unsigned int i = 0; i < tx.vin.size(); i++) {
+ const CTxIn& txin = tx.vin[i];
UniValue in(UniValue::VOBJ);
if (tx.IsCoinBase())
in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
@@ -78,6 +82,17 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
in.push_back(Pair("scriptSig", o));
}
+ if (!tx.wit.IsNull()) {
+ if (!tx.wit.vtxinwit[i].IsNull()) {
+ UniValue txinwitness(UniValue::VARR);
+ for (unsigned int j = 0; j < tx.wit.vtxinwit[i].scriptWitness.stack.size(); j++) {
+ std::vector<unsigned char> item = tx.wit.vtxinwit[i].scriptWitness.stack[j];
+ txinwitness.push_back(HexStr(item.begin(), item.end()));
+ }
+ in.push_back(Pair("txinwitness", txinwitness));
+ }
+
+ }
in.push_back(Pair("sequence", (int64_t)txin.nSequence));
vin.push_back(in);
}
@@ -134,7 +149,9 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp)
"{\n"
" \"hex\" : \"data\", (string) The serialized, hex-encoded data for 'txid'\n"
" \"txid\" : \"id\", (string) The transaction id (same as provided)\n"
- " \"size\" : n, (numeric) The transaction size\n"
+ " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n"
+ " \"size\" : n, (numeric) The serialized transaction size\n"
+ " \"vsize\" : n, (numeric) The virtual transaction size (differs from size for witness transactions)\n"
" \"version\" : n, (numeric) The version\n"
" \"locktime\" : ttt, (numeric) The lock time\n"
" \"vin\" : [ (array of json objects)\n"
@@ -146,6 +163,7 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp)
" \"hex\": \"hex\" (string) hex\n"
" },\n"
" \"sequence\": n (numeric) The script sequence number\n"
+ " \"txinwitness\": [\"hex\", ...] (array of string) hex-encoded witness data (if any)\n"
" }\n"
" ,...\n"
" ],\n"
@@ -276,7 +294,7 @@ UniValue gettxoutproof(const UniValue& params, bool fHelp)
if (ntxFound != setTxids.size())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "(Not all) transactions not found in specified block");
- CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION);
+ CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
CMerkleBlock mb(block, setTxids);
ssMB << mb;
std::string strHex = HexStr(ssMB.begin(), ssMB.end());
@@ -296,7 +314,7 @@ UniValue verifytxoutproof(const UniValue& params, bool fHelp)
"[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof is invalid\n"
);
- CDataStream ssMB(ParseHexV(params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION);
+ CDataStream ssMB(ParseHexV(params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
CMerkleBlock merkleBlock;
ssMB >> merkleBlock;
@@ -443,7 +461,9 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp)
"\nResult:\n"
"{\n"
" \"txid\" : \"id\", (string) The transaction id\n"
+ " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n"
" \"size\" : n, (numeric) The transaction size\n"
+ " \"vsize\" : n, (numeric) The virtual transaction size (differs from size for witness transactions)\n"
" \"version\" : n, (numeric) The version\n"
" \"locktime\" : ttt, (numeric) The lock time\n"
" \"vin\" : [ (array of json objects)\n"
@@ -454,6 +474,7 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp)
" \"asm\": \"asm\", (string) asm\n"
" \"hex\": \"hex\" (string) hex\n"
" },\n"
+ " \"txinwitness\": [\"hex\", ...] (array of string) hex-encoded witness data (if any)\n"
" \"sequence\": n (numeric) The script sequence number\n"
" }\n"
" ,...\n"
@@ -487,7 +508,7 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp)
CTransaction tx;
- if (!DecodeHexTx(tx, params[0].get_str()))
+ if (!DecodeHexTx(tx, params[0].get_str(), true))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
UniValue result(UniValue::VOBJ);
@@ -571,7 +592,8 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
" \"txid\":\"id\", (string, required) The transaction id\n"
" \"vout\":n, (numeric, required) The output number\n"
" \"scriptPubKey\": \"hex\", (string, required) script key\n"
- " \"redeemScript\": \"hex\" (string, required for P2SH) redeem script\n"
+ " \"redeemScript\": \"hex\", (string, required for P2SH or P2WSH) redeem script\n"
+ " \"amount\": value (numeric, required) The amount spent\n"
" }\n"
" ,...\n"
" ]\n"
@@ -714,12 +736,15 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
if ((unsigned int)nOut >= coins->vout.size())
coins->vout.resize(nOut+1);
coins->vout[nOut].scriptPubKey = scriptPubKey;
- coins->vout[nOut].nValue = 0; // we don't know the actual output value
+ coins->vout[nOut].nValue = 0;
+ if (prevOut.exists("amount")) {
+ coins->vout[nOut].nValue = AmountFromValue(find_value(prevOut, "amount"));
+ }
}
// if redeemScript given and not using the local wallet (private keys
// given), add redeemScript to the tempKeystore so it can be signed:
- if (fGivenKeys && scriptPubKey.IsPayToScriptHash()) {
+ if (fGivenKeys && (scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash())) {
RPCTypeCheckObj(prevOut,
{
{"txid", UniValueType(UniValue::VSTR)},
@@ -778,18 +803,22 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
continue;
}
const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
+ const CAmount& amount = coins->vout[txin.prevout.n].nValue;
- txin.scriptSig.clear();
+ SignatureData sigdata;
// Only sign SIGHASH_SINGLE if there's a corresponding output:
if (!fHashSingle || (i < mergedTx.vout.size()))
- SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
+ ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata);
// ... and merge in other signatures:
BOOST_FOREACH(const CMutableTransaction& txv, txVariants) {
- txin.scriptSig = CombineSignatures(prevPubKey, txConst, i, txin.scriptSig, txv.vin[i].scriptSig);
+ sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(txv, i));
}
+
+ UpdateTransaction(mergedTx, i, sigdata);
+
ScriptError serror = SCRIPT_ERR_OK;
- if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i), &serror)) {
+ if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
}
}
diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp
index 47ad1d0807..62fd9031f8 100644
--- a/src/script/bitcoinconsensus.cpp
+++ b/src/script/bitcoinconsensus.cpp
@@ -69,7 +69,7 @@ struct ECCryptoClosure
ECCryptoClosure instance_of_eccryptoclosure;
}
-int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen,
+static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, CAmount amount,
const unsigned char *txTo , unsigned int txToLen,
unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err)
{
@@ -82,15 +82,36 @@ int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned i
if (tx.GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION) != txToLen)
return set_error(err, bitcoinconsensus_ERR_TX_SIZE_MISMATCH);
- // Regardless of the verification result, the tx did not error.
- set_error(err, bitcoinconsensus_ERR_OK);
+ // Regardless of the verification result, the tx did not error.
+ set_error(err, bitcoinconsensus_ERR_OK);
- return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), flags, TransactionSignatureChecker(&tx, nIn), NULL);
+ return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, amount), NULL);
} catch (const std::exception&) {
return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing
}
}
+int bitcoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
+ const unsigned char *txTo , unsigned int txToLen,
+ unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err)
+{
+ CAmount am(amount);
+ return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, nIn, flags, err);
+}
+
+
+int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen,
+ const unsigned char *txTo , unsigned int txToLen,
+ unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err)
+{
+ if (flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS) {
+ return set_error(err, bitcoinconsensus_ERR_AMOUNT_REQUIRED);
+ }
+
+ CAmount am(0);
+ return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, nIn, flags, err);
+}
+
unsigned int bitcoinconsensus_version()
{
// Just use the API version for now
diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h
index 5b8c33c6bf..6f868d0d6d 100644
--- a/src/script/bitcoinconsensus.h
+++ b/src/script/bitcoinconsensus.h
@@ -6,6 +6,8 @@
#ifndef BITCOIN_BITCOINCONSENSUS_H
#define BITCOIN_BITCOINCONSENSUS_H
+#include <stdint.h>
+
#if defined(BUILD_BITCOIN_INTERNAL) && defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#if defined(_WIN32)
@@ -31,7 +33,7 @@
extern "C" {
#endif
-#define BITCOINCONSENSUS_API_VER 0
+#define BITCOINCONSENSUS_API_VER 1
typedef enum bitcoinconsensus_error_t
{
@@ -39,6 +41,7 @@ typedef enum bitcoinconsensus_error_t
bitcoinconsensus_ERR_TX_INDEX,
bitcoinconsensus_ERR_TX_SIZE_MISMATCH,
bitcoinconsensus_ERR_TX_DESERIALIZE,
+ bitcoinconsensus_ERR_AMOUNT_REQUIRED,
} bitcoinconsensus_error;
/** Script verification flags */
@@ -48,6 +51,7 @@ enum
bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts
bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG = (1U << 2), // enforce strict DER (BIP66) compliance
bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), // enable CHECKLOCKTIMEVERIFY (BIP65)
+ bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS = (1U << 11), // enable WITNESS (BIP141)
};
/// Returns 1 if the input nIn of the serialized transaction pointed to by
@@ -55,6 +59,10 @@ enum
/// the additional constraints specified by flags.
/// If not NULL, err will contain an error/success code for the operation
EXPORT_SYMBOL int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen,
+ const unsigned char *txTo , unsigned int txToLen,
+ unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err);
+
+EXPORT_SYMBOL int bitcoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
const unsigned char *txTo , unsigned int txToLen,
unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err);
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index fd4a5674cf..bc027e9f0c 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -229,7 +229,7 @@ bool static CheckMinimalPush(const valtype& data, opcodetype opcode) {
return true;
}
-bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
+bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
{
static const CScriptNum bnZero(0);
static const CScriptNum bnOne(1);
@@ -869,13 +869,15 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
CScript scriptCode(pbegincodehash, pend);
// Drop the signature, since there's no way for a signature to sign itself
- scriptCode.FindAndDelete(CScript(vchSig));
+ if (sigversion == SIGVERSION_BASE) {
+ scriptCode.FindAndDelete(CScript(vchSig));
+ }
if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) {
//serror is set
return false;
}
- bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode);
+ bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion);
popstack(stack);
popstack(stack);
@@ -925,7 +927,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
for (int k = 0; k < nSigsCount; k++)
{
valtype& vchSig = stacktop(-isig-k);
- scriptCode.FindAndDelete(CScript(vchSig));
+ if (sigversion == SIGVERSION_BASE) {
+ scriptCode.FindAndDelete(CScript(vchSig));
+ }
}
bool fSuccess = true;
@@ -943,7 +947,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
}
// Check signature
- bool fOk = checker.CheckSig(vchSig, vchPubKey, scriptCode);
+ bool fOk = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion);
if (fOk) {
isig++;
@@ -1106,8 +1110,64 @@ public:
} // anon namespace
-uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
+uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion)
{
+ if (sigversion == SIGVERSION_WITNESS_V0) {
+ uint256 hashPrevouts;
+ uint256 hashSequence;
+ uint256 hashOutputs;
+
+ if (!(nHashType & SIGHASH_ANYONECANPAY)) {
+ CHashWriter ss(SER_GETHASH, 0);
+ for (unsigned int n = 0; n < txTo.vin.size(); n++) {
+ ss << txTo.vin[n].prevout;
+ }
+ hashPrevouts = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
+ }
+
+ if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
+ CHashWriter ss(SER_GETHASH, 0);
+ for (unsigned int n = 0; n < txTo.vin.size(); n++) {
+ ss << txTo.vin[n].nSequence;
+ }
+ hashSequence = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
+ }
+
+ if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
+ CHashWriter ss(SER_GETHASH, 0);
+ for (unsigned int n = 0; n < txTo.vout.size(); n++) {
+ ss << txTo.vout[n];
+ }
+ hashOutputs = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
+ } else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
+ CHashWriter ss(SER_GETHASH, 0);
+ ss << txTo.vout[nIn];
+ hashOutputs = ss.GetHash();
+ }
+
+ CHashWriter ss(SER_GETHASH, 0);
+ // Version
+ ss << txTo.nVersion;
+ // Input prevouts/nSequence (none/all, depending on flags)
+ ss << hashPrevouts;
+ ss << hashSequence;
+ // The input being signed (replacing the scriptSig with scriptCode + amount)
+ // The prevout may already be contained in hashPrevout, and the nSequence
+ // may already be contain in hashSequence.
+ ss << txTo.vin[nIn].prevout;
+ ss << static_cast<const CScriptBase&>(scriptCode);
+ ss << amount;
+ ss << txTo.vin[nIn].nSequence;
+ // Outputs (none/one/all, depending on flags)
+ ss << hashOutputs;
+ // Locktime
+ ss << txTo.nLockTime;
+ // Sighash type
+ ss << nHashType;
+
+ return ss.GetHash();
+ }
+
static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
if (nIn >= txTo.vin.size()) {
// nIn out of range
@@ -1136,7 +1196,7 @@ bool TransactionSignatureChecker::VerifySignature(const std::vector<unsigned cha
return pubkey.Verify(sighash, vchSig);
}
-bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
+bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
{
CPubKey pubkey(vchPubKey);
if (!pubkey.IsValid())
@@ -1149,7 +1209,7 @@ bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn
int nHashType = vchSig.back();
vchSig.pop_back();
- uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
+ uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion);
if (!VerifySignature(vchSig, pubkey, sighash))
return false;
@@ -1239,8 +1299,67 @@ bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) con
return true;
}
-bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
+static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const std::vector<unsigned char>& program, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
{
+ vector<vector<unsigned char> > stack;
+ CScript scriptPubKey;
+
+ if (witversion == 0) {
+ if (program.size() == 32) {
+ // Version 0 segregated witness program: SHA256(CScript) inside the program, CScript + inputs in witness
+ if (witness.stack.size() == 0) {
+ return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY);
+ }
+ scriptPubKey = CScript(witness.stack.back().begin(), witness.stack.back().end());
+ stack = std::vector<std::vector<unsigned char> >(witness.stack.begin(), witness.stack.end() - 1);
+ uint256 hashScriptPubKey;
+ CSHA256().Write(&scriptPubKey[0], scriptPubKey.size()).Finalize(hashScriptPubKey.begin());
+ if (memcmp(hashScriptPubKey.begin(), &program[0], 32)) {
+ return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
+ }
+ } else if (program.size() == 20) {
+ // Special case for pay-to-pubkeyhash; signature + pubkey in witness
+ if (witness.stack.size() != 2) {
+ return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH); // 2 items in witness
+ }
+ scriptPubKey << OP_DUP << OP_HASH160 << program << OP_EQUALVERIFY << OP_CHECKSIG;
+ stack = witness.stack;
+ } else {
+ return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH);
+ }
+ } else if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
+ return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM);
+ } else {
+ // Higher version witness scripts return true for future softfork compatibility
+ return set_success(serror);
+ }
+
+ // Disallow stack item size > MAX_SCRIPT_ELEMENT_SIZE in witness stack
+ for (unsigned int i = 0; i < stack.size(); i++) {
+ if (stack.at(i).size() > MAX_SCRIPT_ELEMENT_SIZE)
+ return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
+ }
+
+ if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_WITNESS_V0, serror)) {
+ return false;
+ }
+
+ // Scripts inside witness implicitly require cleanstack behaviour
+ if (stack.size() != 1)
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ if (!CastToBool(stack.back()))
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ return true;
+}
+
+bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
+{
+ static const CScriptWitness emptyWitness;
+ if (witness == NULL) {
+ witness = &emptyWitness;
+ }
+ bool hadWitness = false;
+
set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
if ((flags & SCRIPT_VERIFY_SIGPUSHONLY) != 0 && !scriptSig.IsPushOnly()) {
@@ -1248,12 +1367,12 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
}
vector<vector<unsigned char> > stack, stackCopy;
- if (!EvalScript(stack, scriptSig, flags, checker, serror))
+ if (!EvalScript(stack, scriptSig, flags, checker, SIGVERSION_BASE, serror))
// serror is set
return false;
if (flags & SCRIPT_VERIFY_P2SH)
stackCopy = stack;
- if (!EvalScript(stack, scriptPubKey, flags, checker, serror))
+ if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_BASE, serror))
// serror is set
return false;
if (stack.empty())
@@ -1261,6 +1380,25 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
if (CastToBool(stack.back()) == false)
return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ // Bare witness programs
+ int witnessversion;
+ std::vector<unsigned char> witnessprogram;
+ if (flags & SCRIPT_VERIFY_WITNESS) {
+ if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
+ hadWitness = true;
+ if (scriptSig.size() != 0) {
+ // The scriptSig must be _exactly_ CScript(), otherwise we reintroduce malleability.
+ return set_error(serror, SCRIPT_ERR_WITNESS_MALLEATED);
+ }
+ if (!VerifyWitnessProgram(*witness, witnessversion, witnessprogram, flags, checker, serror)) {
+ return false;
+ }
+ // Bypass the cleanstack check at the end. The actual stack is obviously not clean
+ // for witness programs.
+ stack.resize(1);
+ }
+ }
+
// Additional validation for spend-to-script-hash transactions:
if ((flags & SCRIPT_VERIFY_P2SH) && scriptPubKey.IsPayToScriptHash())
{
@@ -1280,26 +1418,102 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
popstack(stack);
- if (!EvalScript(stack, pubKey2, flags, checker, serror))
+ if (!EvalScript(stack, pubKey2, flags, checker, SIGVERSION_BASE, serror))
// serror is set
return false;
if (stack.empty())
return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
if (!CastToBool(stack.back()))
return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+
+ // P2SH witness program
+ if (flags & SCRIPT_VERIFY_WITNESS) {
+ if (pubKey2.IsWitnessProgram(witnessversion, witnessprogram)) {
+ hadWitness = true;
+ if (scriptSig != CScript() << std::vector<unsigned char>(pubKey2.begin(), pubKey2.end())) {
+ // The scriptSig must be _exactly_ a single push of the redeemScript. Otherwise we
+ // reintroduce malleability.
+ return set_error(serror, SCRIPT_ERR_WITNESS_MALLEATED_P2SH);
+ }
+ if (!VerifyWitnessProgram(*witness, witnessversion, witnessprogram, flags, checker, serror)) {
+ return false;
+ }
+ // Bypass the cleanstack check at the end. The actual stack is obviously not clean
+ // for witness programs.
+ stack.resize(1);
+ }
+ }
}
// The CLEANSTACK check is only performed after potential P2SH evaluation,
// as the non-P2SH evaluation of a P2SH script will obviously not result in
- // a clean stack (the P2SH inputs remain).
+ // a clean stack (the P2SH inputs remain). The same holds for witness evaluation.
if ((flags & SCRIPT_VERIFY_CLEANSTACK) != 0) {
// Disallow CLEANSTACK without P2SH, as otherwise a switch CLEANSTACK->P2SH+CLEANSTACK
// would be possible, which is not a softfork (and P2SH should be one).
assert((flags & SCRIPT_VERIFY_P2SH) != 0);
+ assert((flags & SCRIPT_VERIFY_WITNESS) != 0);
if (stack.size() != 1) {
return set_error(serror, SCRIPT_ERR_CLEANSTACK);
}
}
+ if (flags & SCRIPT_VERIFY_WITNESS) {
+ // We can't check for correct unexpected witness data if P2SH was off, so require
+ // that WITNESS implies P2SH. Otherwise, going from WITNESS->P2SH+WITNESS would be
+ // possible, which is not a softfork.
+ assert((flags & SCRIPT_VERIFY_P2SH) != 0);
+ if (!hadWitness && !witness->IsNull()) {
+ return set_error(serror, SCRIPT_ERR_WITNESS_UNEXPECTED);
+ }
+ }
+
return set_success(serror);
}
+
+size_t static WitnessSigOps(int witversion, const std::vector<unsigned char>& witprogram, const CScriptWitness& witness, int flags)
+{
+ if (witversion == 0) {
+ if (witprogram.size() == 20)
+ return 1;
+
+ if (witprogram.size() == 32 && witness.stack.size() > 0) {
+ CScript subscript(witness.stack.back().begin(), witness.stack.back().end());
+ return subscript.GetSigOpCount(true);
+ }
+ }
+
+ // Future flags may be implemented here.
+ return 0;
+}
+
+size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags)
+{
+ static const CScriptWitness witnessEmpty;
+
+ if ((flags & SCRIPT_VERIFY_WITNESS) == 0) {
+ return 0;
+ }
+ assert((flags & SCRIPT_VERIFY_P2SH) != 0);
+
+ int witnessversion;
+ std::vector<unsigned char> witnessprogram;
+ if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
+ return WitnessSigOps(witnessversion, witnessprogram, witness ? *witness : witnessEmpty, flags);
+ }
+
+ if (scriptPubKey.IsPayToScriptHash() && scriptSig.IsPushOnly()) {
+ CScript::const_iterator pc = scriptSig.begin();
+ vector<unsigned char> data;
+ while (pc < scriptSig.end()) {
+ opcodetype opcode;
+ scriptSig.GetOp(pc, opcode, data);
+ }
+ CScript subscript(data.begin(), data.end());
+ if (subscript.IsWitnessProgram(witnessversion, witnessprogram)) {
+ return WitnessSigOps(witnessversion, witnessprogram, witness ? *witness : witnessEmpty, flags);
+ }
+ }
+
+ return 0;
+}
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index e5cb7290f2..bd2f211663 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -74,7 +74,7 @@ enum
// "At least one stack element must remain, and when interpreted as a boolean, it must be true" to
// "Exactly one stack element must remain, and when interpreted as a boolean, it must be true".
// (softfork safe, BIP62 rule 6)
- // Note: CLEANSTACK should never be used without P2SH.
+ // Note: CLEANSTACK should never be used without P2SH or WITNESS.
SCRIPT_VERIFY_CLEANSTACK = (1U << 8),
// Verify CHECKLOCKTIMEVERIFY
@@ -86,16 +86,30 @@ enum
//
// See BIP112 for details
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1U << 10),
+
+ // Support segregated witness
+ //
+ SCRIPT_VERIFY_WITNESS = (1U << 11),
+
+ // Making v1-v16 witness program non-standard
+ //
+ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM = (1U << 12),
};
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror);
-uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
+enum SigVersion
+{
+ SIGVERSION_BASE = 0,
+ SIGVERSION_WITNESS_V0 = 1,
+};
+
+uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion);
class BaseSignatureChecker
{
public:
- virtual bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
+ virtual bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
{
return false;
}
@@ -118,13 +132,14 @@ class TransactionSignatureChecker : public BaseSignatureChecker
private:
const CTransaction* txTo;
unsigned int nIn;
+ const CAmount amount;
protected:
virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
public:
- TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {}
- bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const;
+ TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn) {}
+ bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const;
bool CheckLockTime(const CScriptNum& nLockTime) const;
bool CheckSequence(const CScriptNum& nSequence) const;
};
@@ -135,10 +150,12 @@ private:
const CTransaction txTo;
public:
- MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn) : TransactionSignatureChecker(&txTo, nInIn), txTo(*txToIn) {}
+ MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : TransactionSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {}
};
-bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL);
-bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL);
+bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = NULL);
+bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror = NULL);
+
+size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags);
#endif // BITCOIN_SCRIPT_INTERPRETER_H
diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp
index 535c56b57a..0bf180341e 100644
--- a/src/script/ismine.cpp
+++ b/src/script/ismine.cpp
@@ -57,6 +57,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
return ISMINE_SPENDABLE;
break;
case TX_PUBKEYHASH:
+ case TX_WITNESS_V0_KEYHASH:
keyID = CKeyID(uint160(vSolutions[0]));
if (keystore.HaveKey(keyID))
return ISMINE_SPENDABLE;
@@ -72,6 +73,20 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
}
break;
}
+ case TX_WITNESS_V0_SCRIPTHASH:
+ {
+ uint160 hash;
+ CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(hash.begin());
+ CScriptID scriptID = CScriptID(hash);
+ CScript subscript;
+ if (keystore.GetCScript(scriptID, subscript)) {
+ isminetype ret = IsMine(keystore, subscript);
+ if (ret == ISMINE_SPENDABLE)
+ return ret;
+ }
+ break;
+ }
+
case TX_MULTISIG:
{
// Only consider transactions "mine" if we own ALL the
@@ -88,8 +103,8 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
if (keystore.HaveWatchOnly(scriptPubKey)) {
// TODO: This could be optimized some by doing some work after the above solver
- CScript scriptSig;
- return ProduceSignature(DummySignatureCreator(&keystore), scriptPubKey, scriptSig) ? ISMINE_WATCH_SOLVABLE : ISMINE_WATCH_UNSOLVABLE;
+ SignatureData sigs;
+ return ProduceSignature(DummySignatureCreator(&keystore), scriptPubKey, sigs) ? ISMINE_WATCH_SOLVABLE : ISMINE_WATCH_UNSOLVABLE;
}
return ISMINE_NO;
}
diff --git a/src/script/script.cpp b/src/script/script.cpp
index 9f2809e593..da551c23ee 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -210,6 +210,32 @@ bool CScript::IsPayToScriptHash() const
(*this)[22] == OP_EQUAL);
}
+bool CScript::IsPayToWitnessScriptHash() const
+{
+ // Extra-fast test for pay-to-witness-script-hash CScripts:
+ return (this->size() == 34 &&
+ (*this)[0] == OP_0 &&
+ (*this)[1] == 0x20);
+}
+
+// A witness program is any valid CScript that consists of a 1-byte push opcode
+// followed by a data push between 2 and 40 bytes.
+bool CScript::IsWitnessProgram(int& version, std::vector<unsigned char>& program) const
+{
+ if (this->size() < 4 || this->size() > 42) {
+ return false;
+ }
+ if ((*this)[0] != OP_0 && ((*this)[0] < OP_1 || (*this)[0] > OP_16)) {
+ return false;
+ }
+ if ((size_t)((*this)[1] + 2) == this->size()) {
+ version = DecodeOP_N((opcodetype)(*this)[0]);
+ program = std::vector<unsigned char>(this->begin() + 2, this->end());
+ return true;
+ }
+ return false;
+}
+
bool CScript::IsPushOnly(const_iterator pc) const
{
while (pc < end())
@@ -231,3 +257,15 @@ bool CScript::IsPushOnly() const
{
return this->IsPushOnly(begin());
}
+
+std::string CScriptWitness::ToString() const
+{
+ std::string ret = "CScriptWitness(";
+ for (unsigned int i = 0; i < stack.size(); i++) {
+ if (i) {
+ ret += ", ";
+ }
+ ret += HexStr(stack[i]);
+ }
+ return ret + ")";
+}
diff --git a/src/script/script.h b/src/script/script.h
index a2941ce901..71af3754bc 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -621,6 +621,8 @@ public:
unsigned int GetSigOpCount(const CScript& scriptSig) const;
bool IsPayToScriptHash() const;
+ bool IsPayToWitnessScriptHash() const;
+ bool IsWitnessProgram(int& version, std::vector<unsigned char>& program) const;
/** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */
bool IsPushOnly(const_iterator pc) const;
@@ -643,6 +645,20 @@ public:
}
};
+struct CScriptWitness
+{
+ // Note that this encodes the data elements being pushed, rather than
+ // encoding them as a CScript that pushes them.
+ std::vector<std::vector<unsigned char> > stack;
+
+ // Some compilers complain without a default constructor
+ CScriptWitness() { }
+
+ bool IsNull() const { return stack.empty(); }
+
+ std::string ToString() const;
+};
+
class CReserveScript
{
public:
diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp
index f1aa1fb408..cef807edcf 100644
--- a/src/script/script_error.cpp
+++ b/src/script/script_error.cpp
@@ -65,8 +65,22 @@ const char* ScriptErrorString(const ScriptError serror)
return "Dummy CHECKMULTISIG argument must be zero";
case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS:
return "NOPx reserved for soft-fork upgrades";
+ case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM:
+ return "Witness version reserved for soft-fork upgrades";
case SCRIPT_ERR_PUBKEYTYPE:
return "Public key is neither compressed or uncompressed";
+ case SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH:
+ return "Witness program has incorrect length";
+ case SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY:
+ return "Witness program was passed an empty witness";
+ case SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH:
+ return "Witness program hash mismatch";
+ case SCRIPT_ERR_WITNESS_MALLEATED:
+ return "Witness requires empty scriptSig";
+ case SCRIPT_ERR_WITNESS_MALLEATED_P2SH:
+ return "Witness requires only-redeemscript scriptSig";
+ case SCRIPT_ERR_WITNESS_UNEXPECTED:
+ return "Witness provided for non-witness script";
case SCRIPT_ERR_UNKNOWN_ERROR:
case SCRIPT_ERR_ERROR_COUNT:
default: break;
diff --git a/src/script/script_error.h b/src/script/script_error.h
index 26df33932f..09dc6945ad 100644
--- a/src/script/script_error.h
+++ b/src/script/script_error.h
@@ -51,6 +51,15 @@ typedef enum ScriptError_t
/* softfork safeness */
SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS,
+ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM,
+
+ /* segregated witness */
+ SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH,
+ SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY,
+ SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH,
+ SCRIPT_ERR_WITNESS_MALLEATED,
+ SCRIPT_ERR_WITNESS_MALLEATED_P2SH,
+ SCRIPT_ERR_WITNESS_UNEXPECTED,
SCRIPT_ERR_ERROR_COUNT
} ScriptError;
diff --git a/src/script/sigcache.h b/src/script/sigcache.h
index be1df09c2a..050bf8cc42 100644
--- a/src/script/sigcache.h
+++ b/src/script/sigcache.h
@@ -22,7 +22,7 @@ private:
bool store;
public:
- CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, bool storeIn=true) : TransactionSignatureChecker(txToIn, nInIn), store(storeIn) {}
+ CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn) : TransactionSignatureChecker(txToIn, nInIn, amount), store(storeIn) {}
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
};
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 2f4111f786..87f38d9c72 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -18,31 +18,31 @@ using namespace std;
typedef std::vector<unsigned char> valtype;
-TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), checker(txTo, nIn) {}
+TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
-bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode) const
+bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const
{
CKey key;
if (!keystore->GetKey(address, key))
return false;
- uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
+ uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion);
if (!key.Sign(hash, vchSig))
return false;
vchSig.push_back((unsigned char)nHashType);
return true;
}
-static bool Sign1(const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, CScript& scriptSigRet)
+static bool Sign1(const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, SigVersion sigversion)
{
vector<unsigned char> vchSig;
- if (!creator.CreateSig(vchSig, address, scriptCode))
+ if (!creator.CreateSig(vchSig, address, scriptCode, sigversion))
return false;
- scriptSigRet << vchSig;
+ ret.push_back(vchSig);
return true;
}
-static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, CScript& scriptSigRet)
+static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, SigVersion sigversion)
{
int nSigned = 0;
int nRequired = multisigdata.front()[0];
@@ -50,7 +50,7 @@ static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreato
{
const valtype& pubkey = multisigdata[i];
CKeyID keyID = CPubKey(pubkey).GetID();
- if (Sign1(keyID, creator, scriptCode, scriptSigRet))
+ if (Sign1(keyID, creator, scriptCode, ret, sigversion))
++nSigned;
}
return nSigned==nRequired;
@@ -63,9 +63,11 @@ static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreato
* Returns false if scriptPubKey could not be completely satisfied.
*/
static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptPubKey,
- CScript& scriptSigRet, txnouttype& whichTypeRet)
+ std::vector<valtype>& ret, txnouttype& whichTypeRet, SigVersion sigversion)
{
- scriptSigRet.clear();
+ CScript scriptRet;
+ uint160 h160;
+ ret.clear();
vector<valtype> vSolutions;
if (!Solver(scriptPubKey, whichTypeRet, vSolutions))
@@ -79,62 +81,142 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
return false;
case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID();
- return Sign1(keyID, creator, scriptPubKey, scriptSigRet);
+ return Sign1(keyID, creator, scriptPubKey, ret, sigversion);
case TX_PUBKEYHASH:
keyID = CKeyID(uint160(vSolutions[0]));
- if (!Sign1(keyID, creator, scriptPubKey, scriptSigRet))
+ if (!Sign1(keyID, creator, scriptPubKey, ret, sigversion))
return false;
else
{
CPubKey vch;
creator.KeyStore().GetPubKey(keyID, vch);
- scriptSigRet << ToByteVector(vch);
+ ret.push_back(ToByteVector(vch));
}
return true;
case TX_SCRIPTHASH:
- return creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptSigRet);
+ if (creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptRet)) {
+ ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
+ return true;
+ }
+ return false;
case TX_MULTISIG:
- scriptSigRet << OP_0; // workaround CHECKMULTISIG bug
- return (SignN(vSolutions, creator, scriptPubKey, scriptSigRet));
+ ret.push_back(valtype()); // workaround CHECKMULTISIG bug
+ return (SignN(vSolutions, creator, scriptPubKey, ret, sigversion));
+
+ case TX_WITNESS_V0_KEYHASH:
+ ret.push_back(vSolutions[0]);
+ return true;
+
+ case TX_WITNESS_V0_SCRIPTHASH:
+ CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160.begin());
+ if (creator.KeyStore().GetCScript(h160, scriptRet)) {
+ ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
+ return true;
+ }
+ return false;
+
+ default:
+ return false;
}
- return false;
}
-bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, CScript& scriptSig)
+static CScript PushAll(const vector<valtype>& values)
{
+ CScript result;
+ BOOST_FOREACH(const valtype& v, values) {
+ if (v.size() == 0) {
+ result << OP_0;
+ } else if (v.size() == 1 && v[0] >= 1 && v[0] <= 16) {
+ result << CScript::EncodeOP_N(v[0]);
+ } else {
+ result << v;
+ }
+ }
+ return result;
+}
+
+bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata)
+{
+ CScript script = fromPubKey;
+ bool solved = true;
+ std::vector<valtype> result;
txnouttype whichType;
- if (!SignStep(creator, fromPubKey, scriptSig, whichType))
- return false;
+ solved = SignStep(creator, script, result, whichType, SIGVERSION_BASE);
+ bool P2SH = false;
+ CScript subscript;
+ sigdata.scriptWitness.stack.clear();
- if (whichType == TX_SCRIPTHASH)
+ if (solved && whichType == TX_SCRIPTHASH)
{
- // Solver returns the subscript that need to be evaluated;
+ // Solver returns the subscript that needs to be evaluated;
// the final scriptSig is the signatures from that
// and then the serialized subscript:
- CScript subscript = scriptSig;
+ script = subscript = CScript(result[0].begin(), result[0].end());
+ solved = solved && SignStep(creator, script, result, whichType, SIGVERSION_BASE) && whichType != TX_SCRIPTHASH;
+ P2SH = true;
+ }
+ if (solved && whichType == TX_WITNESS_V0_KEYHASH)
+ {
+ CScript witnessscript;
+ witnessscript << OP_DUP << OP_HASH160 << ToByteVector(result[0]) << OP_EQUALVERIFY << OP_CHECKSIG;
txnouttype subType;
- bool fSolved =
- SignStep(creator, subscript, scriptSig, subType) && subType != TX_SCRIPTHASH;
- // Append serialized subscript whether or not it is completely signed:
- scriptSig << valtype(subscript.begin(), subscript.end());
- if (!fSolved) return false;
+ solved = solved && SignStep(creator, witnessscript, result, subType, SIGVERSION_WITNESS_V0);
+ sigdata.scriptWitness.stack = result;
+ result.clear();
+ }
+ else if (solved && whichType == TX_WITNESS_V0_SCRIPTHASH)
+ {
+ CScript witnessscript(result[0].begin(), result[0].end());
+ txnouttype subType;
+ solved = solved && SignStep(creator, witnessscript, result, subType, SIGVERSION_WITNESS_V0) && subType != TX_SCRIPTHASH && subType != TX_WITNESS_V0_SCRIPTHASH && subType != TX_WITNESS_V0_KEYHASH;
+ result.push_back(std::vector<unsigned char>(witnessscript.begin(), witnessscript.end()));
+ sigdata.scriptWitness.stack = result;
+ result.clear();
}
+ if (P2SH) {
+ result.push_back(std::vector<unsigned char>(subscript.begin(), subscript.end()));
+ }
+ sigdata.scriptSig = PushAll(result);
+
// Test solution
- return VerifyScript(scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker());
+ return solved && VerifyScript(sigdata.scriptSig, fromPubKey, &sigdata.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker());
+}
+
+SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn)
+{
+ SignatureData data;
+ assert(tx.vin.size() > nIn);
+ data.scriptSig = tx.vin[nIn].scriptSig;
+ if (tx.wit.vtxinwit.size() > nIn) {
+ data.scriptWitness = tx.wit.vtxinwit[nIn].scriptWitness;
+ }
+ return data;
+}
+
+void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const SignatureData& data)
+{
+ assert(tx.vin.size() > nIn);
+ tx.vin[nIn].scriptSig = data.scriptSig;
+ if (!data.scriptWitness.IsNull() || tx.wit.vtxinwit.size() > nIn) {
+ tx.wit.vtxinwit.resize(tx.vin.size());
+ tx.wit.vtxinwit[nIn].scriptWitness = data.scriptWitness;
+ }
}
-bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
+bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType)
{
assert(nIn < txTo.vin.size());
- CTxIn& txin = txTo.vin[nIn];
CTransaction txToConst(txTo);
- TransactionSignatureCreator creator(&keystore, &txToConst, nIn, nHashType);
+ TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount, nHashType);
- return ProduceSignature(creator, fromPubKey, txin.scriptSig);
+ SignatureData sigdata;
+ bool ret = ProduceSignature(creator, fromPubKey, sigdata);
+ UpdateTransaction(txTo, nIn, sigdata);
+ return ret;
}
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
@@ -144,20 +226,12 @@ bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutab
assert(txin.prevout.n < txFrom.vout.size());
const CTxOut& txout = txFrom.vout[txin.prevout.n];
- return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, nHashType);
-}
-
-static CScript PushAll(const vector<valtype>& values)
-{
- CScript result;
- BOOST_FOREACH(const valtype& v, values)
- result << v;
- return result;
+ return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType);
}
-static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
+static vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
const vector<valtype>& vSolutions,
- const vector<valtype>& sigs1, const vector<valtype>& sigs2)
+ const vector<valtype>& sigs1, const vector<valtype>& sigs2, SigVersion sigversion)
{
// Combine all the signatures we've got:
set<valtype> allsigs;
@@ -185,7 +259,7 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureC
if (sigs.count(pubkey))
continue; // Already got a sig for this pubkey
- if (checker.CheckSig(sig, pubkey, scriptPubKey))
+ if (checker.CheckSig(sig, pubkey, scriptPubKey, sigversion))
{
sigs[pubkey] = sig;
break;
@@ -194,87 +268,126 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureC
}
// Now build a merged CScript:
unsigned int nSigsHave = 0;
- CScript result; result << OP_0; // pop-one-too-many workaround
+ std::vector<valtype> result; result.push_back(valtype()); // pop-one-too-many workaround
for (unsigned int i = 0; i < nPubKeys && nSigsHave < nSigsRequired; i++)
{
if (sigs.count(vSolutions[i+1]))
{
- result << sigs[vSolutions[i+1]];
+ result.push_back(sigs[vSolutions[i+1]]);
++nSigsHave;
}
}
// Fill any missing with OP_0:
for (unsigned int i = nSigsHave; i < nSigsRequired; i++)
- result << OP_0;
+ result.push_back(valtype());
return result;
}
-static CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
+namespace
+{
+struct Stacks
+{
+ std::vector<valtype> script;
+ std::vector<valtype> witness;
+
+ Stacks() {}
+ explicit Stacks(const std::vector<valtype>& scriptSigStack_) : script(scriptSigStack_), witness() {}
+ explicit Stacks(const SignatureData& data) : witness(data.scriptWitness.stack) {
+ EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE);
+ }
+
+ SignatureData Output() const {
+ SignatureData result;
+ result.scriptSig = PushAll(script);
+ result.scriptWitness.stack = witness;
+ return result;
+ }
+};
+}
+
+static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
const txnouttype txType, const vector<valtype>& vSolutions,
- vector<valtype>& sigs1, vector<valtype>& sigs2)
+ Stacks sigs1, Stacks sigs2, SigVersion sigversion)
{
switch (txType)
{
case TX_NONSTANDARD:
case TX_NULL_DATA:
// Don't know anything about this, assume bigger one is correct:
- if (sigs1.size() >= sigs2.size())
- return PushAll(sigs1);
- return PushAll(sigs2);
+ if (sigs1.script.size() >= sigs2.script.size())
+ return sigs1;
+ return sigs2;
case TX_PUBKEY:
case TX_PUBKEYHASH:
// Signatures are bigger than placeholders or empty scripts:
- if (sigs1.empty() || sigs1[0].empty())
- return PushAll(sigs2);
- return PushAll(sigs1);
+ if (sigs1.script.empty() || sigs1.script[0].empty())
+ return sigs2;
+ return sigs1;
+ case TX_WITNESS_V0_KEYHASH:
+ // Signatures are bigger than placeholders or empty scripts:
+ if (sigs1.witness.empty() || sigs1.witness[0].empty())
+ return sigs2;
+ return sigs1;
case TX_SCRIPTHASH:
- if (sigs1.empty() || sigs1.back().empty())
- return PushAll(sigs2);
- else if (sigs2.empty() || sigs2.back().empty())
- return PushAll(sigs1);
+ if (sigs1.script.empty() || sigs1.script.back().empty())
+ return sigs2;
+ else if (sigs2.script.empty() || sigs2.script.back().empty())
+ return sigs1;
else
{
// Recur to combine:
- valtype spk = sigs1.back();
+ valtype spk = sigs1.script.back();
CScript pubKey2(spk.begin(), spk.end());
txnouttype txType2;
vector<vector<unsigned char> > vSolutions2;
Solver(pubKey2, txType2, vSolutions2);
- sigs1.pop_back();
- sigs2.pop_back();
- CScript result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2);
- result << spk;
+ sigs1.script.pop_back();
+ sigs2.script.pop_back();
+ Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, sigversion);
+ result.script.push_back(spk);
return result;
}
case TX_MULTISIG:
- return CombineMultisig(scriptPubKey, checker, vSolutions, sigs1, sigs2);
+ return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions, sigs1.script, sigs2.script, sigversion));
+ case TX_WITNESS_V0_SCRIPTHASH:
+ if (sigs1.witness.empty() || sigs1.witness.back().empty())
+ return sigs2;
+ else if (sigs2.witness.empty() || sigs2.witness.back().empty())
+ return sigs1;
+ else
+ {
+ // Recur to combine:
+ CScript pubKey2(sigs1.witness.back().begin(), sigs1.witness.back().end());
+ txnouttype txType2;
+ vector<valtype> vSolutions2;
+ Solver(pubKey2, txType2, vSolutions2);
+ sigs1.witness.pop_back();
+ sigs1.script = sigs1.witness;
+ sigs1.witness.clear();
+ sigs2.witness.pop_back();
+ sigs2.script = sigs2.witness;
+ sigs2.witness.clear();
+ Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, SIGVERSION_WITNESS_V0);
+ result.witness = result.script;
+ result.script.clear();
+ result.witness.push_back(valtype(pubKey2.begin(), pubKey2.end()));
+ return result;
+ }
+ default:
+ return Stacks();
}
-
- return CScript();
}
-CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
- const CScript& scriptSig1, const CScript& scriptSig2)
-{
- TransactionSignatureChecker checker(&txTo, nIn);
- return CombineSignatures(scriptPubKey, checker, scriptSig1, scriptSig2);
-}
-
-CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
- const CScript& scriptSig1, const CScript& scriptSig2)
+SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
+ const SignatureData& scriptSig1, const SignatureData& scriptSig2)
{
txnouttype txType;
vector<vector<unsigned char> > vSolutions;
Solver(scriptPubKey, txType, vSolutions);
- vector<valtype> stack1;
- EvalScript(stack1, scriptSig1, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker());
- vector<valtype> stack2;
- EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker());
-
- return CombineSignatures(scriptPubKey, checker, txType, vSolutions, stack1, stack2);
+ return CombineSignatures(scriptPubKey, checker, txType, vSolutions, Stacks(scriptSig1), Stacks(scriptSig2), SIGVERSION_BASE).Output();
}
namespace {
@@ -284,7 +397,7 @@ class DummySignatureChecker : public BaseSignatureChecker
public:
DummySignatureChecker() {}
- bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
+ bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
{
return true;
}
@@ -297,7 +410,7 @@ const BaseSignatureChecker& DummySignatureCreator::Checker() const
return dummyChecker;
}
-bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode) const
+bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const
{
// Create a dummy signature that is a valid DER-encoding
vchSig.assign(72, '\000');
diff --git a/src/script/sign.h b/src/script/sign.h
index 47a9cde7f4..6404b4523e 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -27,7 +27,7 @@ public:
virtual const BaseSignatureChecker& Checker() const =0;
/** Create a singular (non-script) signature. */
- virtual bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode) const =0;
+ virtual bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const =0;
};
/** A signature creator for transactions. */
@@ -35,12 +35,20 @@ class TransactionSignatureCreator : public BaseSignatureCreator {
const CTransaction* txTo;
unsigned int nIn;
int nHashType;
+ CAmount amount;
const TransactionSignatureChecker checker;
public:
- TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn=SIGHASH_ALL);
+ TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL);
const BaseSignatureChecker& Checker() const { return checker; }
- bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode) const;
+ bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const;
+};
+
+class MutableTransactionSignatureCreator : public TransactionSignatureCreator {
+ CTransaction tx;
+
+public:
+ MutableTransactionSignatureCreator(const CKeyStore* keystoreIn, const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount, int nHashTypeIn) : TransactionSignatureCreator(keystoreIn, &tx, nInIn, amount, nHashTypeIn), tx(*txToIn) {}
};
/** A signature creator that just produces 72-byte empty signatyres. */
@@ -48,20 +56,29 @@ class DummySignatureCreator : public BaseSignatureCreator {
public:
DummySignatureCreator(const CKeyStore* keystoreIn) : BaseSignatureCreator(keystoreIn) {}
const BaseSignatureChecker& Checker() const;
- bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode) const;
+ bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const;
+};
+
+struct SignatureData {
+ CScript scriptSig;
+ CScriptWitness scriptWitness;
+
+ SignatureData() {}
+ explicit SignatureData(const CScript& script) : scriptSig(script) {}
};
/** Produce a script signature using a generic signature creator. */
-bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& scriptPubKey, CScript& scriptSig);
+bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& scriptPubKey, SignatureData& sigdata);
/** Produce a script signature for a transaction. */
-bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
-bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
+bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType);
+bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType);
/** Combine two script signatures using a generic signature checker, intelligently, possibly with OP_0 placeholders. */
-CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const CScript& scriptSig1, const CScript& scriptSig2);
+SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const SignatureData& scriptSig1, const SignatureData& scriptSig2);
-/** Combine two script signatures on transactions. */
-CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CScript& scriptSig1, const CScript& scriptSig2);
+/** Extract signature data from a transaction, and insert it. */
+SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn);
+void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const SignatureData& data);
#endif // BITCOIN_SCRIPT_SIGN_H
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index 67b6af327a..bb178f49fe 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -31,6 +31,8 @@ const char* GetTxnOutputType(txnouttype t)
case TX_SCRIPTHASH: return "scripthash";
case TX_MULTISIG: return "multisig";
case TX_NULL_DATA: return "nulldata";
+ case TX_WITNESS_V0_KEYHASH: return "witness_v0_keyhash";
+ case TX_WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
}
return NULL;
}
@@ -66,6 +68,22 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
return true;
}
+ int witnessversion;
+ std::vector<unsigned char> witnessprogram;
+ if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
+ if (witnessversion == 0 && witnessprogram.size() == 20) {
+ typeRet = TX_WITNESS_V0_KEYHASH;
+ vSolutionsRet.push_back(witnessprogram);
+ return true;
+ }
+ if (witnessversion == 0 && witnessprogram.size() == 32) {
+ typeRet = TX_WITNESS_V0_SCRIPTHASH;
+ vSolutionsRet.push_back(witnessprogram);
+ return true;
+ }
+ return false;
+ }
+
// Provably prunable, data-carrying output
//
// So long as script passes the IsUnspendable() test and all but the first
@@ -282,3 +300,26 @@ CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
return script;
}
+
+CScript GetScriptForWitness(const CScript& redeemscript)
+{
+ CScript ret;
+
+ txnouttype typ;
+ std::vector<std::vector<unsigned char> > vSolutions;
+ if (Solver(redeemscript, typ, vSolutions)) {
+ if (typ == TX_PUBKEY) {
+ unsigned char h160[20];
+ CHash160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160);
+ ret << OP_0 << std::vector<unsigned char>(&h160[0], &h160[20]);
+ return ret;
+ } else if (typ == TX_PUBKEYHASH) {
+ ret << OP_0 << vSolutions[0];
+ return ret;
+ }
+ }
+ uint256 hash;
+ CSHA256().Write(&redeemscript[0], redeemscript.size()).Finalize(hash.begin());
+ ret << OP_0 << ToByteVector(hash);
+ return ret;
+}
diff --git a/src/script/standard.h b/src/script/standard.h
index f348da8e19..72aaea0b7b 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -51,6 +51,8 @@ enum txnouttype
TX_SCRIPTHASH,
TX_MULTISIG,
TX_NULL_DATA,
+ TX_WITNESS_V0_SCRIPTHASH,
+ TX_WITNESS_V0_KEYHASH,
};
class CNoDestination {
@@ -77,5 +79,6 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::
CScript GetScriptForDestination(const CTxDestination& dest);
CScript GetScriptForRawPubKey(const CPubKey& pubkey);
CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys);
+CScript GetScriptForWitness(const CScript& redeemscript);
#endif // BITCOIN_SCRIPT_STANDARD_H
diff --git a/src/streams.h b/src/streams.h
index ed14f3f412..7132364eb1 100644
--- a/src/streams.h
+++ b/src/streams.h
@@ -22,6 +22,39 @@
#include <utility>
#include <vector>
+template<typename Stream>
+class OverrideStream
+{
+ Stream* stream;
+public:
+ const int nType;
+ const int nVersion;
+
+ OverrideStream(Stream* stream_, int nType_, int nVersion_) : stream(stream_), nType(nType_), nVersion(nVersion_) {}
+
+ template<typename T>
+ OverrideStream<Stream>& operator<<(const T& obj)
+ {
+ // Serialize to this stream
+ ::Serialize(*this->stream, obj, nType, nVersion);
+ return (*this);
+ }
+
+ template<typename T>
+ OverrideStream<Stream>& operator>>(T& obj)
+ {
+ // Unserialize from this stream
+ ::Unserialize(*this->stream, obj, nType, nVersion);
+ return (*this);
+ }
+};
+
+template<typename S>
+OverrideStream<S> WithOrVersion(S* s, int nVersionFlag)
+{
+ return OverrideStream<S>(s, s->GetType(), s->GetVersion() | nVersionFlag);
+}
+
/** Double ended buffer combining vector and stream-like interfaces.
*
* >> and << read and write unformatted data using the above serialization templates.
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index 93f7ae09da..a8c5f95ace 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
tx.vout.resize(1);
tx.vout[0].nValue = 1*CENT;
tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
- SignSignature(keystore, txPrev, tx, 0);
+ SignSignature(keystore, txPrev, tx, 0, SIGHASH_ALL);
AddOrphanTx(tx, i);
}
@@ -168,7 +168,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
tx.vin[j].prevout.n = j;
tx.vin[j].prevout.hash = txPrev.GetHash();
}
- SignSignature(keystore, txPrev, tx, 0);
+ SignSignature(keystore, txPrev, tx, 0, SIGHASH_ALL);
// Re-use same signature for other inputs
// (they don't have to be valid for this test)
for (unsigned int j = 1; j < tx.vin.size(); j++)
diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json
index 0bdac182e0..9b81e0c77d 100644
--- a/src/test/data/script_tests.json
+++ b/src/test/data/script_tests.json
@@ -1,5 +1,5 @@
[
-["Format is: [scriptSig, scriptPubKey, flags, expected_scripterror, ... comments]"],
+["Format is: [[wit..., amount]?, scriptSig, scriptPubKey, flags, expected_scripterror, ... comments]"],
["It is evaluated as if there was a crediting coinbase transaction with two 0"],
["pushes as scriptSig, and one output of 0 satoshi and given scriptPubKey,"],
["followed by a spending transaction which spends this output as only input (and"],
@@ -1253,6 +1253,12 @@
["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length S is incorrectly encoded for DERSIG"],
["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Negative S is incorrectly encoded for DERSIG"],
+["Some basic segwit checks"],
+[["00", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "P2SH,WITNESS", "EVAL_FALSE", "Invalid witness script"],
+[["51", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "P2SH,WITNESS", "WITNESS_PROGRAM_MISMATCH", "Witness script hash mismatch"],
+[["00", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "", "OK", "Invalid witness script without WITNESS"],
+[["51", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "", "OK", "Witness script hash mismatch without WITNESS"],
+
["Automatically generated test cases"],
[
"0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
@@ -1828,6 +1834,289 @@
"OK",
"P2SH with CLEANSTACK"
],
+[
+ [
+ "304402200d461c140cfdfcf36b94961db57ae8c18d1cb80e9d95a9e47ac22470c1bf125502201c8dc1cbfef6a3ef90acbbb992ca22fe9466ee6f9d4898eda277a7ac3ab4b25101",
+ "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "P2SH,WITNESS",
+ "OK",
+ "Basic P2WSH"
+],
+[
+ [
+ "304402201e7216e5ccb3b61d46946ec6cc7e8c4e0117d13ac2fd4b152197e4805191c74202203e9903e33e84d9ee1dd13fb057afb7ccfb47006c23f6a067185efbc9dd780fc501",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000001
+ ],
+ "",
+ "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5",
+ "P2SH,WITNESS",
+ "OK",
+ "Basic P2WPKH"
+],
+[
+ [
+ "3044022066e02c19a513049d49349cf5311a1b012b7c4fae023795a18ab1d91c23496c22022025e216342c8e07ce8ef51e8daee88f84306a9de66236cab230bb63067ded1ad301",
+ "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ 0.00000001
+ ],
+ "0x22 0x0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "HASH160 0x14 0xf386c2ba255cc56d20cfa6ea8b062f8b59945518 EQUAL",
+ "P2SH,WITNESS",
+ "OK",
+ "Basic P2SH(P2WSH)"
+],
+[
+ [
+ "304402200929d11561cd958460371200f82e9cae64c727a495715a31828e27a7ad57b36d0220361732ced04a6f97351ecca21a56d0b8cd4932c1da1f8f569a2b68e5e48aed7801",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000001
+ ],
+ "0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5",
+ "HASH160 0x14 0x17743beb429c55c942d2ec703b98c4d57c2df5c6 EQUAL",
+ "P2SH,WITNESS",
+ "OK",
+ "Basic P2SH(P2WPKH)"
+],
+[
+ [
+ "304402202589f0512cb2408fb08ed9bd24f85eb3059744d9e4f2262d0b7f1338cff6e8b902206c0978f449693e0578c71bc543b11079fd0baae700ee5e9a6bee94db490af9fc01",
+ "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac",
+ 0.00000000
+ ],
+ "",
+ "0 0x20 0xac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2WSH with the wrong key"
+],
+[
+ [
+ "304402206ef7fdb2986325d37c6eb1a8bb24aeb46dede112ed8fc76c7d7500b9b83c0d3d02201edc2322c794fe2d6b0bd73ed319e714aa9b86d8891961530d5c9b7156b60d4e01",
+ "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf",
+ 0.00000000
+ ],
+ "",
+ "0 0x14 0x7cf9c846cd4882efec4bf07e44ebdad495c94f4b",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2WPKH with the wrong key"
+],
+[
+ [
+ "30440220069ea3581afaf8187f63feee1fd2bd1f9c0dc71ea7d6e8a8b07ee2ebcf824bf402201a4fdef4c532eae59223be1eda6a397fc835142d4ddc6c74f4aa85b766a5c16f01",
+ "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac",
+ 0.00000000
+ ],
+ "0x22 0x0020ac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610",
+ "HASH160 0x14 0x61039a003883787c0d6ebc66d97fdabe8e31449d EQUAL",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2SH(P2WSH) with the wrong key"
+],
+[
+ [
+ "304402204209e49457c2358f80d0256bc24535b8754c14d08840fc4be762d6f5a0aed80b02202eaf7d8fc8d62f60c67adcd99295528d0e491ae93c195cec5a67e7a09532a88001",
+ "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf",
+ 0.00000000
+ ],
+ "0x16 0x00147cf9c846cd4882efec4bf07e44ebdad495c94f4b",
+ "HASH160 0x14 0x4e0c2aed91315303fc6a1dc4c7bc21c88f75402e EQUAL",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2SH(P2WPKH) with the wrong key"
+],
+[
+ [
+ "304402202589f0512cb2408fb08ed9bd24f85eb3059744d9e4f2262d0b7f1338cff6e8b902206c0978f449693e0578c71bc543b11079fd0baae700ee5e9a6bee94db490af9fc01",
+ "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac",
+ 0.00000000
+ ],
+ "",
+ "0 0x20 0xac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610",
+ "P2SH",
+ "OK",
+ "Basic P2WSH with the wrong key but no WITNESS"
+],
+[
+ [
+ "304402206ef7fdb2986325d37c6eb1a8bb24aeb46dede112ed8fc76c7d7500b9b83c0d3d02201edc2322c794fe2d6b0bd73ed319e714aa9b86d8891961530d5c9b7156b60d4e01",
+ "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf",
+ 0.00000000
+ ],
+ "",
+ "0 0x14 0x7cf9c846cd4882efec4bf07e44ebdad495c94f4b",
+ "P2SH",
+ "OK",
+ "Basic P2WPKH with the wrong key but no WITNESS"
+],
+[
+ [
+ "30440220069ea3581afaf8187f63feee1fd2bd1f9c0dc71ea7d6e8a8b07ee2ebcf824bf402201a4fdef4c532eae59223be1eda6a397fc835142d4ddc6c74f4aa85b766a5c16f01",
+ "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac",
+ 0.00000000
+ ],
+ "0x22 0x0020ac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610",
+ "HASH160 0x14 0x61039a003883787c0d6ebc66d97fdabe8e31449d EQUAL",
+ "P2SH",
+ "OK",
+ "Basic P2SH(P2WSH) with the wrong key but no WITNESS"
+],
+[
+ [
+ "304402204209e49457c2358f80d0256bc24535b8754c14d08840fc4be762d6f5a0aed80b02202eaf7d8fc8d62f60c67adcd99295528d0e491ae93c195cec5a67e7a09532a88001",
+ "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf",
+ 0.00000000
+ ],
+ "0x16 0x00147cf9c846cd4882efec4bf07e44ebdad495c94f4b",
+ "HASH160 0x14 0x4e0c2aed91315303fc6a1dc4c7bc21c88f75402e EQUAL",
+ "P2SH",
+ "OK",
+ "Basic P2SH(P2WPKH) with the wrong key but no WITNESS"
+],
+[
+ [
+ "3044022066faa86e74e8b30e82691b985b373de4f9e26dc144ec399c4f066aa59308e7c202204712b86f28c32503faa051dbeabff2c238ece861abc36c5e0b40b1139ca222f001",
+ "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ 0.00000000
+ ],
+ "",
+ "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2WSH with wrong value"
+],
+[
+ [
+ "304402203b3389b87448d7dfdb5e82fb854fcf92d7925f9938ea5444e36abef02c3d6a9602202410bc3265049abb07fd2e252c65ab7034d95c9d5acccabe9fadbdc63a52712601",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000000
+ ],
+ "",
+ "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2WPKH with wrong value"
+],
+[
+ [
+ "3044022000a30c4cfc10e4387be528613575434826ad3c15587475e0df8ce3b1746aa210022008149265e4f8e9dafe1f3ea50d90cb425e9e40ea7ebdd383069a7cfa2b77004701",
+ "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ 0.00000000
+ ],
+ "0x22 0x0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "HASH160 0x14 0xf386c2ba255cc56d20cfa6ea8b062f8b59945518 EQUAL",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2SH(P2WSH) with wrong value"
+],
+[
+ [
+ "304402204fc3a2cd61a47913f2a5f9107d0ad4a504c7b31ee2d6b3b2f38c2b10ee031e940220055d58b7c3c281aaa381d8f486ac0f3e361939acfd568046cb6a311cdfa974cf01",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000000
+ ],
+ "0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5",
+ "HASH160 0x14 0x17743beb429c55c942d2ec703b98c4d57c2df5c6 EQUAL",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2SH(P2WPKH) with wrong value"
+],
+[
+ [
+ "304402205ae57ae0534c05ca9981c8a6cdf353b505eaacb7375f96681a2d1a4ba6f02f84022056248e68643b7d8ce7c7d128c9f1f348bcab8be15d094ad5cadd24251a28df8001",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000000
+ ],
+ "",
+ "1 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5",
+ "DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM,P2SH,WITNESS",
+ "DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM",
+ "P2WPKH with future witness version"
+],
+[
+ [
+ "3044022064100ca0e2a33332136775a86cd83d0230e58b9aebb889c5ac952abff79a46ef02205f1bf900e022039ad3091bdaf27ac2aef3eae9ed9f190d821d3e508405b9513101",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000000
+ ],
+ "",
+ "0 0x1f 0xb34b78da162751647974d5cb7410aa428ad339dbf7d1e16e833f68a0cbf1c3",
+ "P2SH,WITNESS",
+ "WITNESS_PROGRAM_WRONG_LENGTH",
+ "P2WPKH with wrong witness program length"
+],
+[
+ "",
+ "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "P2SH,WITNESS",
+ "WITNESS_PROGRAM_WITNESS_EMPTY",
+ "P2WSH with empty witness"
+],
+[
+ [
+ "3044022039105b995a5f448639a997a5c90fda06f50b49df30c3bdb6663217bf79323db002206fecd54269dec569fcc517178880eb58bb40f381a282bb75766ff3637d5f4b4301",
+ "400479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ 0.00000000
+ ],
+ "",
+ "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "P2SH,WITNESS",
+ "WITNESS_PROGRAM_MISMATCH",
+ "P2WSH with witness program mismatch"
+],
+[
+ [
+ "304402201a96950593cb0af32d080b0f193517f4559241a8ebd1e95e414533ad64a3f423022047f4f6d3095c23235bdff3aeff480d0529c027a3f093cb265b7cbf148553b85101",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ "",
+ 0.00000000
+ ],
+ "",
+ "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5",
+ "P2SH,WITNESS",
+ "WITNESS_PROGRAM_MISMATCH",
+ "P2WPKH with witness program mismatch"
+],
+[
+ [
+ "304402201a96950593cb0af32d080b0f193517f4559241a8ebd1e95e414533ad64a3f423022047f4f6d3095c23235bdff3aeff480d0529c027a3f093cb265b7cbf148553b85101",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000000
+ ],
+ "11",
+ "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5",
+ "P2SH,WITNESS",
+ "WITNESS_MALLEATED",
+ "P2WPKH with non-empty scriptSig"
+],
+[
+ [
+ "304402204209e49457c2358f80d0256bc24535b8754c14d08840fc4be762d6f5a0aed80b02202eaf7d8fc8d62f60c67adcd99295528d0e491ae93c195cec5a67e7a09532a88001",
+ "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf",
+ 0.00000000
+ ],
+ "11 0x16 0x00147cf9c846cd4882efec4bf07e44ebdad495c94f4b",
+ "HASH160 0x14 0x4e0c2aed91315303fc6a1dc4c7bc21c88f75402e EQUAL",
+ "P2SH,WITNESS",
+ "WITNESS_MALLEATED_P2SH",
+ "P2SH(P2WPKH) with superfluous push in scriptSig"
+],
+[
+ [
+ "",
+ 0.00000000
+ ],
+ "0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
+ "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+ "P2SH,WITNESS",
+ "WITNESS_UNEXPECTED",
+ "P2PK with witness"
+],
["CHECKSEQUENCEVERIFY tests"],
["", "NOP3", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"],
diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json
index 2d7d9b9585..05502a83f7 100644
--- a/src/test/data/tx_invalid.json
+++ b/src/test/data/tx_invalid.json
@@ -30,10 +30,6 @@
"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", "P2SH"],
["Tests for CheckTransaction()"],
-["No inputs"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]],
-"0100000000010000000000000000015100000000", "P2SH"],
-
["No outputs"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x05ab9e14d983742513f0f451e105ffb4198d1dd4 EQUAL"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022100f16703104aab4e4088317c862daec83440242411b039d14280e03dd33b487ab802201318a7be236672c5c56083eb7a5a195bc57a40af7923ff8545016cd3b571e2a601232103c40e5d339df3f30bf753e7e04450ae4ef76c9e45587d1d993bdc4cd06f0651c7acffffffff0000000000", "P2SH"],
@@ -255,5 +251,68 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+["Unknown witness program version (with DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x60 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623ffffffffff1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
+
+["Unknown length for witness program v0"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x15 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3fff", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff04b60300000000000001519e070000000000000151860b0000000000000100960000000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash Single|AnyoneCanPay (same index output value changed)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e80300000000000001516c070000000000000151b80b0000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash None|AnyoneCanPay (input sequence changed)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff000100000000000000000000000000000000000000000000000000000000000001000000000100000000010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash All|AnyoneCanPay (third output value changed)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151540b00000000000001510002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with a push of 521 bytes"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x33198a9bfef674ebddb9ffaa52928017b8472791e54c609cb95f278ac6b1e349", 1000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015102fd0902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002755100000000", "P2SH,WITNESS"],
+
+["Witness with unknown version which push false on the stack should be invalid (even without DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x02 0x0000", 2000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015101010100000000", "P2SH,WITNESS"],
+
+["Witness program should leave clean stack"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x2f04a3aa051f1f60d695f6c44c0c3d383973dfd446ace8962664a76bb10e31a8", 2000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01000000000000000001510102515100000000", "P2SH,WITNESS"],
+
+["Witness v0 with a push of 2 bytes"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x02 0x0001", 2000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015101040002000100000000", "P2SH,WITNESS"],
+
+["Unknown witness version with non empty scriptSig"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x02 0x0001", 2000]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000000151ffffffff010000000000000000015100000000", "P2SH,WITNESS"],
+
+["Non witness Single|AnyoneCanPay hash input's position (permutation)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1001]],
+"010000000200010000000000000000000000000000000000000000000000000000000000000100000049483045022100acb96cfdbda6dc94b489fd06f2d720983b5f350e31ba906cdbd800773e80b21c02200d74ea5bdf114212b4bbe9ed82c36d2e369e302dff57cb60d01c428f0bd3daab83ffffffff0001000000000000000000000000000000000000000000000000000000000000000000004847304402202a0b4b1294d70540235ae033d78e64b4897ec859c7b6f1b2b1d8a02e1d46006702201445e756d2254b0f1dfda9ab8e1e1bc26df9668077403204f32d16a49a36eb6983ffffffff02e9030000000000000151e803000000000000015100000000", "P2SH,WITNESS"],
+
+["P2WSH with a redeem representing a witness scriptPubKey should fail"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x34b6c399093e06cf9f0f7f660a1abcfe78fcf7b576f43993208edd9518a0ae9b", 1000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0001045102010100000000", "P2SH,WITNESS"],
+
+["33 bytes push should be considered a witness scriptPubKey"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x21 0xff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbff", 1000]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
+
["Make diffs cleaner by leaving a comment here without comma at the end"]
]
diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json
index 717ad19549..c9fe4e313a 100644
--- a/src/test/data/tx_valid.json
+++ b/src/test/data/tx_valid.json
@@ -317,5 +317,175 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7c17aff532f22beb54069942f9bf567a66133eaf EQUAL"]],
"0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+["Valid P2WPKH (Private key of segwit tests is L5AQtV2HDm4xGsseLokK2VAT2EtYKcTm3c7HwqnJBFt9LdaQULsM)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100cfb07164b36ba64c1b1e8c7720a56ad64d96f6ef332d3d37f9cb3c96477dc44502200a464cd7a9cf94cd70f66ce4f4f0625ef650052c7afcfe29d7d7e01830ff91ed012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"],
+
+["Valid P2WSH"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0xff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3db", 1000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000", "P2SH,WITNESS"],
+
+["Valid P2SH(P2WPKH)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xfe9c7dacc9fcfbf7e3b7d5ad06aa2b28c5a7b7e3 EQUAL", 1000]],
+"01000000000101000100000000000000000000000000000000000000000000000000000000000000000000171600144c9c3dfac4207d5d8cb89df5722cb3d712385e3fffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100cfb07164b36ba64c1b1e8c7720a56ad64d96f6ef332d3d37f9cb3c96477dc44502200a464cd7a9cf94cd70f66ce4f4f0625ef650052c7afcfe29d7d7e01830ff91ed012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"],
+
+["Valid P2SH(P2WSH)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x2135ab4f0981830311e35600eebc7376dce3a914 EQUAL", 1000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000023220020ff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000", "P2SH,WITNESS"],
+
+["Witness with SigHash Single|AnyoneCanPay"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100],
+["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]],
+"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff05540b0000000000000151d0070000000000000151840300000000000001513c0f00000000000001512c010000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71000000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash Single|AnyoneCanPay (same signature as previous)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash Single"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff0484030000000000000151d0070000000000000151540b0000000000000151c800000000000000015100024730440220699e6b0cfe015b64ca3283e6551440a34f901ba62dd4c72fe1cb815afb2e6761022021cc5e84db498b1479de14efda49093219441adc6c543e5534979605e273d80b032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash Single (same signature as previous)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b000000000000015100024730440220699e6b0cfe015b64ca3283e6551440a34f901ba62dd4c72fe1cb815afb2e6761022021cc5e84db498b1479de14efda49093219441adc6c543e5534979605e273d80b032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash None|AnyoneCanPay"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100],
+["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]],
+"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff04b60300000000000001519e070000000000000151860b00000000000001009600000000000000015100000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash None|AnyoneCanPay (same signature as previous)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash None"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff04b60300000000000001519e070000000000000151860b0000000000000100960000000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash None (same signature as previous)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash None (same signature, only sequences changed)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"01000000000103000100000000000000000000000000000000000000000000000000000000000000000000000200000000010000000000000000000000000000000000000000000000000000000000000100000000ffffffff000100000000000000000000000000000000000000000000000000000000000002000000000200000003e8030000000000000151d0070000000000000151b80b00000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash All|AnyoneCanPay"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100],
+["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]],
+"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash All|AnyoneCanPay (same signature as previous)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Unknown witness program version (without DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x60 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623ffffffffff1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with a push of 520 bytes"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x33198a9bfef674ebddb9ffaa52928017b8472791e54c609cb95f278ac6b1e349", 1000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015102fd08020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002755100000000", "P2SH,WITNESS"],
+
+["Transaction mixing all SigHash, segwit and normal inputs"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1002],
+["0000000000000000000000000000000000000000000000000000000000000100", 3, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1003],
+["0000000000000000000000000000000000000000000000000000000000000100", 4, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1004],
+["0000000000000000000000000000000000000000000000000000000000000100", 5, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1005],
+["0000000000000000000000000000000000000000000000000000000000000100", 6, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1006],
+["0000000000000000000000000000000000000000000000000000000000000100", 7, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1007],
+["0000000000000000000000000000000000000000000000000000000000000100", 8, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1008],
+["0000000000000000000000000000000000000000000000000000000000000100", 9, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1009],
+["0000000000000000000000000000000000000000000000000000000000000100", 10, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1010],
+["0000000000000000000000000000000000000000000000000000000000000100", 11, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1011]],
+"0100000000010c00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff0001000000000000000000000000000000000000000000000000000000000000020000006a473044022026c2e65b33fcd03b2a3b0f25030f0244bd23cc45ae4dec0f48ae62255b1998a00220463aa3982b718d593a6b9e0044513fd67a5009c2fdccc59992cffc2b167889f4012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000030000006a4730440220008bd8382911218dcb4c9f2e75bf5c5c3635f2f2df49b36994fde85b0be21a1a02205a539ef10fb4c778b522c1be852352ea06c67ab74200977c722b0bc68972575a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000040000006b483045022100d9436c32ff065127d71e1a20e319e4fe0a103ba0272743dbd8580be4659ab5d302203fd62571ee1fe790b182d078ecfd092a509eac112bea558d122974ef9cc012c7012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000050000006a47304402200e2c149b114ec546015c13b2b464bbcb0cdc5872e6775787527af6cbc4830b6c02207e9396c6979fb15a9a2b96ca08a633866eaf20dc0ff3c03e512c1d5a1654f148012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000060000006b483045022100b20e70d897dc15420bccb5e0d3e208d27bdd676af109abbd3f88dbdb7721e6d6022005836e663173fbdfe069f54cde3c2decd3d0ea84378092a5d9d85ec8642e8a41012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff00010000000000000000000000000000000000000000000000000000000000000700000000ffffffff00010000000000000000000000000000000000000000000000000000000000000800000000ffffffff00010000000000000000000000000000000000000000000000000000000000000900000000ffffffff00010000000000000000000000000000000000000000000000000000000000000a00000000ffffffff00010000000000000000000000000000000000000000000000000000000000000b0000006a47304402206639c6e05e3b9d2675a7f3876286bdf7584fe2bbd15e0ce52dd4e02c0092cdc60220757d60b0a61fc95ada79d23746744c72bac1545a75ff6c2c7cdb6ae04e7e9592012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0ce8030000000000000151e9030000000000000151ea030000000000000151eb030000000000000151ec030000000000000151ed030000000000000151ee030000000000000151ef030000000000000151f0030000000000000151f1030000000000000151f2030000000000000151f30300000000000001510248304502210082219a54f61bf126bfc3fa068c6e33831222d1d7138c6faa9d33ca87fd4202d6022063f9902519624254d7c2c8ea7ba2d66ae975e4e229ae38043973ec707d5d4a83012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7102473044022017fb58502475848c1b09f162cb1688d0920ff7f142bed0ef904da2ccc88b168f02201798afa61850c65e77889cbcd648a5703b487895517c88f85cdd18b021ee246a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000000247304402202830b7926e488da75782c81a54cd281720890d1af064629ebf2e31bf9f5435f30220089afaa8b455bbeb7d9b9c3fe1ed37d07685ade8455c76472cda424d93e4074a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7102473044022026326fcdae9207b596c2b05921dbac11d81040c4d40378513670f19d9f4af893022034ecd7a282c0163b89aaa62c22ec202cef4736c58cd251649bad0d8139bcbf55012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71024730440220214978daeb2f38cd426ee6e2f44131a33d6b191af1c216247f1dd7d74c16d84a02205fdc05529b0bc0c430b4d5987264d9d075351c4f4484c16e91662e90a72aab24012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710247304402204a6e9f199dc9672cf2ff8094aaa784363be1eb62b679f7ff2df361124f1dca3302205eeb11f70fab5355c9c8ad1a0700ea355d315e334822fa182227e9815308ee8f012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Unknown version witness program with empty witness"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS"],
+
+["Witness SIGHASH_SINGLE with output out of bound"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x20 0x4d6c2a32c87821d68fc016fca70797abdb80df6cd84651d40a9300c6bad79e62", 1000]],
+"0100000000010200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff01d00700000000000001510003483045022100e078de4e96a0e05dcdc0a414124dd8475782b5f3f0ed3f607919e9a5eeeb22bf02201de309b3a3109adb3de8074b3610d4cf454c49b61247a2779a0bcbf31c889333032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc711976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac00000000", "P2SH,WITNESS"],
+
+["1 byte push should not be considered a witness scriptPubKey"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x01 0x01", 1000]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
+
+["41 bytes push should not be considered a witness scriptPubKey"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x29 0xff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbff0000000000000000", 1000]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
+
+["The witness version must use OP_1 to OP_16 only"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x01 0x10 0x02 0x0001", 1000]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
+
+["The witness program push must be canonical"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x4c02 0x0001", 1000]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
+
+["Witness Single|AnyoneCanPay does not hash input's position"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001]],
+"0100000000010200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff02e8030000000000000151e90300000000000001510247304402206d59682663faab5e4cb733c562e22cdae59294895929ec38d7c016621ff90da0022063ef0af5f970afe8a45ea836e3509b8847ed39463253106ac17d19c437d3d56b832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710248304502210085001a820bfcbc9f9de0298af714493f8a37b3b354bfd21a7097c3e009f2018c022050a8b4dbc8155d4d04da2f5cdd575dcf8dd0108de8bec759bd897ea01ecb3af7832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"],
+
+["Witness Single|AnyoneCanPay does not hash input's position (permutation)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001]],
+"0100000000010200010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff02e9030000000000000151e80300000000000001510248304502210085001a820bfcbc9f9de0298af714493f8a37b3b354bfd21a7097c3e009f2018c022050a8b4dbc8155d4d04da2f5cdd575dcf8dd0108de8bec759bd897ea01ecb3af7832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710247304402206d59682663faab5e4cb733c562e22cdae59294895929ec38d7c016621ff90da0022063ef0af5f970afe8a45ea836e3509b8847ed39463253106ac17d19c437d3d56b832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"],
+
+["Non witness Single|AnyoneCanPay hash input's position"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1001]],
+"01000000020001000000000000000000000000000000000000000000000000000000000000000000004847304402202a0b4b1294d70540235ae033d78e64b4897ec859c7b6f1b2b1d8a02e1d46006702201445e756d2254b0f1dfda9ab8e1e1bc26df9668077403204f32d16a49a36eb6983ffffffff00010000000000000000000000000000000000000000000000000000000000000100000049483045022100acb96cfdbda6dc94b489fd06f2d720983b5f350e31ba906cdbd800773e80b21c02200d74ea5bdf114212b4bbe9ed82c36d2e369e302dff57cb60d01c428f0bd3daab83ffffffff02e8030000000000000151e903000000000000015100000000", "P2SH,WITNESS"],
+
+["BIP143 examples: details and private keys are available in BIP143"],
+["BIP143 example: P2WSH with OP_CODESEPARATOR and out-of-range SIGHASH_SINGLE."],
+[[["6eb316926b1c5d567cd6f5e6a84fec606fc53d7b474526d1fff3948020c93dfe", 0, "0x21 0x036d5c20fa14fb2f635474c1dc4ef5909d4568e5569b79fc94d3448486e14685f8 CHECKSIG", 156250000],
+["f825690aee1b3dc247da796cacb12687a5e802429fd291cfd63e010f02cf1508", 0, "0x00 0x20 0x5d1b56b63d714eebe542309525f484b7e9d6f686b3781b6f61ef925d66d6f6a0", 4900000000]],
+"01000000000102fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e000000004847304402200af4e47c9b9629dbecc21f73af989bdaa911f7e6f6c2e9394588a3aa68f81e9902204f3fcf6ade7e5abb1295b6774c8e0abd94ae62217367096bc02ee5e435b67da201ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac000347304402200de66acf4527789bfda55fc5459e214fa6083f936b430a762c629656216805ac0220396f550692cd347171cbc1ef1f51e15282e837bb2b30860dc77c8f78bc8501e503473044022027dc95ad6b740fe5129e7e62a75dd00f291a2aeb1200b84b09d9e3789406b6c002201a9ecd315dd6a0e632ab20bbb98948bc0c6fb204f2c286963bb48517a7058e27034721026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac00000000", "P2SH,WITNESS"],
+
+["BIP143 example: P2WSH with unexecuted OP_CODESEPARATOR and SINGLE|ANYONECANPAY"],
+[[["01c0cf7fba650638e55eb91261b183251fbb466f90dff17f10086817c542b5e9", 0, "0x00 0x20 0xba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d", 16777215],
+["1b2a9a426ba603ba357ce7773cb5805cb9c7c2b386d100d1fc9263513188e680", 0, "0x00 0x20 0xd9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537", 16777215]],
+"01000000000102e9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff80e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffff0280969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac80969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS"],
+
+["BIP143 example: Same as the previous example with input-output paris swapped"],
+[[["1b2a9a426ba603ba357ce7773cb5805cb9c7c2b386d100d1fc9263513188e680", 0, "0x00 0x20 0xd9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537", 16777215],
+["01c0cf7fba650638e55eb91261b183251fbb466f90dff17f10086817c542b5e9", 0, "0x00 0x20 0xba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d", 16777215]],
+"0100000000010280e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffffe9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff0280969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac80969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS"],
+
+["BIP143 example: P2SH-P2WSH 6-of-6 multisig signed with 6 different SIGHASH types"],
+[[["6eb98797a21c6c10aa74edf29d618be109f48a8e94c694f3701e08ca69186436", 1, "HASH160 0x14 0x9993a429037b5d912407a71c252019287b8d27a5 EQUAL", 987654321]],
+"0100000000010136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000023220020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac080047304402206ac44d672dac41f9b00e28f4df20c52eeb087207e8d758d76d92c6fab3b73e2b0220367750dbbe19290069cba53d096f44530e4f98acaa594810388cf7409a1870ce01473044022068c7946a43232757cbdf9176f009a928e1cd9a1a8c212f15c1e11ac9f2925d9002205b75f937ff2f9f3c1246e547e54f62e027f64eefa2695578cc6432cdabce271502473044022059ebf56d98010a932cf8ecfec54c48e6139ed6adb0728c09cbe1e4fa0915302e022007cd986c8fa870ff5d2b3a89139c9fe7e499259875357e20fcbb15571c76795403483045022100fbefd94bd0a488d50b79102b5dad4ab6ced30c4069f1eaa69a4b5a763414067e02203156c6a5c9cf88f91265f5a942e96213afae16d83321c8b31bb342142a14d16381483045022100a5263ea0553ba89221984bd7f0b13613db16e7a70c549a86de0cc0444141a407022005c360ef0ae5a5d4f9f2f87a56c1546cc8268cab08c73501d6b3be2e1e1a8a08824730440220525406a1482936d5a21888260dc165497a90a15669636d8edca6b9fe490d309c022032af0c646a34a44d1f4576bf6a4a74b67940f8faa84c7df9abe12a01a11e2b4783cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae00000000", "P2SH,WITNESS"],
+
["Make diffs cleaner by leaving a comment here without comma at the end"]
]
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index c8b43df26c..033a50f94f 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -2,6 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "policy/policy.h"
#include "txmempool.h"
#include "util.h"
@@ -336,7 +337,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx2.vout[0].nValue = 2 * COIN;
pool.addUnchecked(tx2.GetHash(), entry.Fee(20000LL).Priority(9.0).FromTx(tx2));
- uint64_t tx2Size = ::GetSerializeSize(tx2, SER_NETWORK, PROTOCOL_VERSION);
+ uint64_t tx2Size = GetVirtualTransactionSize(tx2);
/* lowest fee */
CMutableTransaction tx3 = CMutableTransaction();
@@ -384,7 +385,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
tx6.vout.resize(1);
tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx6.vout[0].nValue = 20 * COIN;
- uint64_t tx6Size = ::GetSerializeSize(tx6, SER_NETWORK, PROTOCOL_VERSION);
+ uint64_t tx6Size = GetVirtualTransactionSize(tx6);
pool.addUnchecked(tx6.GetHash(), entry.Fee(0LL).FromTx(tx6));
BOOST_CHECK_EQUAL(pool.size(), 6);
@@ -398,7 +399,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
tx7.vout.resize(1);
tx7.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx7.vout[0].nValue = 10 * COIN;
- uint64_t tx7Size = ::GetSerializeSize(tx7, SER_NETWORK, PROTOCOL_VERSION);
+ uint64_t tx7Size = GetVirtualTransactionSize(tx7);
/* set the fee to just below tx2's feerate when including ancestor */
CAmount fee = (20000/tx2Size)*(tx7Size + tx6Size) - 1;
@@ -467,12 +468,12 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
BOOST_CHECK(pool.exists(tx2.GetHash()));
BOOST_CHECK(pool.exists(tx3.GetHash()));
- pool.TrimToSize(::GetSerializeSize(CTransaction(tx1), SER_NETWORK, PROTOCOL_VERSION)); // mempool is limited to tx1's size in memory usage, so nothing fits
+ pool.TrimToSize(GetVirtualTransactionSize(tx1)); // mempool is limited to tx1's size in memory usage, so nothing fits
BOOST_CHECK(!pool.exists(tx1.GetHash()));
BOOST_CHECK(!pool.exists(tx2.GetHash()));
BOOST_CHECK(!pool.exists(tx3.GetHash()));
- CFeeRate maxFeeRateRemoved(25000, ::GetSerializeSize(CTransaction(tx3), SER_NETWORK, PROTOCOL_VERSION) + ::GetSerializeSize(CTransaction(tx2), SER_NETWORK, PROTOCOL_VERSION));
+ CFeeRate maxFeeRateRemoved(25000, GetVirtualTransactionSize(tx3) + GetVirtualTransactionSize(tx2));
BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000);
CMutableTransaction tx4 = CMutableTransaction();
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index ca8d6d2e05..fd581db52e 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -181,6 +181,9 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey,
// NOTE: These tests rely on CreateNewBlock doing its own self-validation!
BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
{
+ // Disable size accounting (CPFP does not support it)
+ mapArgs["-blockmaxsize"] = strprintf("%u", MAX_BLOCK_SERIALIZED_SIZE);
+
const CChainParams& chainparams = Params(CBaseChainParams::MAIN);
CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
CBlockTemplate *pblocktemplate;
@@ -264,7 +267,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
hash = tx.GetHash();
bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase
// If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes
- mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOps(20).FromTx(tx));
+ mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx));
tx.vin[0].prevout.hash = hash;
}
BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey));
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index d48a68ba54..581b0cee1e 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -26,7 +26,7 @@ BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
CScript
sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction, int whichIn)
{
- uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL);
+ uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, SIGVERSION_BASE);
CScript result;
result << OP_0; // CHECKMULTISIG bug workaround
@@ -46,6 +46,7 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
ScriptError err;
CKey key[4];
+ CAmount amount = 0;
for (int i = 0; i < 4; i++)
key[i].MakeNewKey(true);
@@ -81,20 +82,20 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
keys.assign(1,key[0]);
keys.push_back(key[1]);
s = sign_multisig(a_and_b, keys, txTo[0], 0);
- BOOST_CHECK(VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err));
+ BOOST_CHECK(VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
for (int i = 0; i < 4; i++)
{
keys.assign(1,key[i]);
s = sign_multisig(a_and_b, keys, txTo[0], 0);
- BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 1: %d", i));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 1: %d", i));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
keys.assign(1,key[1]);
keys.push_back(key[i]);
s = sign_multisig(a_and_b, keys, txTo[0], 0);
- BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 2: %d", i));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 2: %d", i));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
}
@@ -105,18 +106,18 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
s = sign_multisig(a_or_b, keys, txTo[1], 0);
if (i == 0 || i == 1)
{
- BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i));
+ BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
else
{
- BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
}
}
s.clear();
s << OP_0 << OP_1;
- BOOST_CHECK(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err));
+ BOOST_CHECK(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
@@ -128,12 +129,12 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
s = sign_multisig(escrow, keys, txTo[2], 0);
if (i < j && i < 3 && j < 3)
{
- BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 1: %d %d", i, j));
+ BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 1: %d %d", i, j));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
else
{
- BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 2: %d %d", i, j));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 2: %d %d", i, j));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
}
}
@@ -302,7 +303,7 @@ BOOST_AUTO_TEST_CASE(multisig_Sign)
for (int i = 0; i < 3; i++)
{
- BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
+ BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
}
}
diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp
index 2b00e6f567..5c902387f1 100644
--- a/src/test/policyestimator_tests.cpp
+++ b/src/test/policyestimator_tests.cpp
@@ -2,6 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "policy/policy.h"
#include "policy/fees.h"
#include "txmempool.h"
#include "uint256.h"
@@ -50,7 +51,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
tx.vin[0].scriptSig = garbage;
tx.vout.resize(1);
tx.vout[0].nValue=0LL;
- CFeeRate baseRate(basefee, ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION));
+ CFeeRate baseRate(basefee, GetVirtualTransactionSize(tx));
// Create a fake block
std::vector<CTransaction> block;
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index d10284fe94..5224b57ca4 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -2,6 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "core_io.h"
#include "key.h"
#include "keystore.h"
#include "main.h"
@@ -42,7 +43,7 @@ Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, Scri
txTo.vin[0].scriptSig = scriptSig;
txTo.vout[0].nValue = 1;
- return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, 0), &err);
+ return VerifyScript(scriptSig, scriptPubKey, NULL, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, 0, txFrom.vout[0].nValue), &err);
}
@@ -102,7 +103,7 @@ BOOST_AUTO_TEST_CASE(sign)
}
for (int i = 0; i < 8; i++)
{
- BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
+ BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
}
// All of the above should be OK, and the txTos have valid signatures
// Check to make sure signature verification fails if we use the wrong ScriptSig:
@@ -197,7 +198,7 @@ BOOST_AUTO_TEST_CASE(set)
}
for (int i = 0; i < 4; i++)
{
- BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
+ BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason), strprintf("txTo[%d].IsStandard", i));
}
}
@@ -326,9 +327,9 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txTo.vin[i].prevout.n = i;
txTo.vin[i].prevout.hash = txFrom.GetHash();
}
- BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0));
- BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1));
- BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2));
+ BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL));
+ BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1, SIGHASH_ALL));
+ BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2, SIGHASH_ALL));
// SignSignature doesn't know how to sign these. We're
// not testing validating signatures, so just create
// dummy signatures that DO include the correct P2SH scripts:
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 39089f103d..5a9aaf9bc0 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -13,6 +13,7 @@
#include "util.h"
#include "utilstrencodings.h"
#include "test/test_bitcoin.h"
+#include "rpc/server.h"
#if defined(HAVE_CONSENSUS_LIB)
#include "script/bitcoinconsensus.h"
@@ -88,7 +89,14 @@ static ScriptErrorDesc script_errors[]={
{SCRIPT_ERR_SIG_NULLDUMMY, "SIG_NULLDUMMY"},
{SCRIPT_ERR_PUBKEYTYPE, "PUBKEYTYPE"},
{SCRIPT_ERR_CLEANSTACK, "CLEANSTACK"},
- {SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, "DISCOURAGE_UPGRADABLE_NOPS"}
+ {SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, "DISCOURAGE_UPGRADABLE_NOPS"},
+ {SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM, "DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"},
+ {SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH, "WITNESS_PROGRAM_WRONG_LENGTH"},
+ {SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY, "WITNESS_PROGRAM_WITNESS_EMPTY"},
+ {SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH, "WITNESS_PROGRAM_MISMATCH"},
+ {SCRIPT_ERR_WITNESS_MALLEATED, "WITNESS_MALLEATED"},
+ {SCRIPT_ERR_WITNESS_MALLEATED_P2SH, "WITNESS_MALLEATED_P2SH"},
+ {SCRIPT_ERR_WITNESS_UNEXPECTED, "WITNESS_UNEXPECTED"},
};
const char *FormatScriptError(ScriptError_t err)
@@ -111,7 +119,7 @@ ScriptError_t ParseScriptError(const std::string &name)
BOOST_FIXTURE_TEST_SUITE(script_tests, BasicTestingSetup)
-CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey)
+CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue = 0)
{
CMutableTransaction txCredit;
txCredit.nVersion = 1;
@@ -122,40 +130,52 @@ CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey)
txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0);
txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
txCredit.vout[0].scriptPubKey = scriptPubKey;
- txCredit.vout[0].nValue = 0;
+ txCredit.vout[0].nValue = nValue;
return txCredit;
}
-CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMutableTransaction& txCredit)
+CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CMutableTransaction& txCredit)
{
CMutableTransaction txSpend;
txSpend.nVersion = 1;
txSpend.nLockTime = 0;
txSpend.vin.resize(1);
txSpend.vout.resize(1);
+ txSpend.wit.vtxinwit.resize(1);
+ txSpend.wit.vtxinwit[0].scriptWitness = scriptWitness;
txSpend.vin[0].prevout.hash = txCredit.GetHash();
txSpend.vin[0].prevout.n = 0;
txSpend.vin[0].scriptSig = scriptSig;
txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
txSpend.vout[0].scriptPubKey = CScript();
- txSpend.vout[0].nValue = 0;
+ txSpend.vout[0].nValue = txCredit.vout[0].nValue;
return txSpend;
}
-void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, const std::string& message, int scriptError)
+void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& scriptWitness, int flags, const std::string& message, int scriptError, CAmount nValue = 0)
{
bool expect = (scriptError == SCRIPT_ERR_OK);
+ if (flags & SCRIPT_VERIFY_CLEANSTACK) {
+ flags |= SCRIPT_VERIFY_P2SH;
+ flags |= SCRIPT_VERIFY_WITNESS;
+ }
ScriptError err;
- CMutableTransaction tx = BuildSpendingTransaction(scriptSig, BuildCreditingTransaction(scriptPubKey));
+ CMutableTransaction txCredit = BuildCreditingTransaction(scriptPubKey, nValue);
+ CMutableTransaction tx = BuildSpendingTransaction(scriptSig, scriptWitness, txCredit);
CMutableTransaction tx2 = tx;
- BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, MutableTransactionSignatureChecker(&tx, 0), &err) == expect, message);
+ BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message);
BOOST_CHECK_MESSAGE(err == scriptError, std::string(FormatScriptError(err)) + " where " + std::string(FormatScriptError((ScriptError_t)scriptError)) + " expected: " + message);
#if defined(HAVE_CONSENSUS_LIB)
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << tx2;
- BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script(begin_ptr(scriptPubKey), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect,message);
+ if (flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS) {
+ BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(begin_ptr(scriptPubKey), scriptPubKey.size(), txCredit.vout[0].nValue, (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect, message);
+ } else {
+ BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(begin_ptr(scriptPubKey), scriptPubKey.size(), 0, (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect, message);
+ BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script(begin_ptr(scriptPubKey), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect,message);
+ }
#endif
}
@@ -234,11 +254,22 @@ struct KeyData
}
};
+enum WitnessMode {
+ WITNESS_NONE,
+ WITNESS_PKH,
+ WITNESS_SH
+};
class TestBuilder
{
private:
- CScript scriptPubKey;
+ //! Actually executed script
+ CScript script;
+ //! The P2SH redeemscript
+ CScript redeemscript;
+ //! The Witness embedded script
+ CScript witscript;
+ CScriptWitness scriptWitness;
CTransaction creditTx;
CMutableTransaction spendTx;
bool havePush;
@@ -246,6 +277,7 @@ private:
std::string comment;
int flags;
int scriptError;
+ CAmount nValue;
void DoPush()
{
@@ -263,14 +295,26 @@ private:
}
public:
- TestBuilder(const CScript& redeemScript, const std::string& comment_, int flags_, bool P2SH = false) : scriptPubKey(redeemScript), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK)
+ TestBuilder(const CScript& script_, const std::string& comment_, int flags_, bool P2SH = false, WitnessMode wm = WITNESS_NONE, int witnessversion = 0, CAmount nValue_ = 0) : script(script_), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK), nValue(nValue_)
{
+ CScript scriptPubKey = script;
+ if (wm == WITNESS_PKH) {
+ uint160 hash;
+ CHash160().Write(&script[1], script.size() - 1).Finalize(hash.begin());
+ script = CScript() << OP_DUP << OP_HASH160 << ToByteVector(hash) << OP_EQUALVERIFY << OP_CHECKSIG;
+ scriptPubKey = CScript() << witnessversion << ToByteVector(hash);
+ } else if (wm == WITNESS_SH) {
+ witscript = scriptPubKey;
+ uint256 hash;
+ CSHA256().Write(&witscript[0], witscript.size()).Finalize(hash.begin());
+ scriptPubKey = CScript() << witnessversion << ToByteVector(hash);
+ }
if (P2SH) {
- creditTx = BuildCreditingTransaction(CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL);
- } else {
- creditTx = BuildCreditingTransaction(redeemScript);
+ redeemscript = scriptPubKey;
+ scriptPubKey = CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemscript)) << OP_EQUAL;
}
- spendTx = BuildSpendingTransaction(CScript(), creditTx);
+ creditTx = BuildCreditingTransaction(scriptPubKey, nValue);
+ spendTx = BuildSpendingTransaction(CScript(), CScriptWitness(), creditTx);
}
TestBuilder& ScriptError(ScriptError_t err)
@@ -299,9 +343,14 @@ public:
return *this;
}
- TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32)
+ TestBuilder& Push(const CScript& script) {
+ DoPush(std::vector<unsigned char>(script.begin(), script.end()));
+ return *this;
+ }
+
+ TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_BASE, CAmount amount = 0)
{
- uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType);
+ uint256 hash = SignatureHash(script, spendTx, 0, nHashType, amount, sigversion);
std::vector<unsigned char> vchSig, r, s;
uint32_t iter = 0;
do {
@@ -317,6 +366,13 @@ public:
return *this;
}
+ TestBuilder& PushWitSig(const CKey& key, CAmount amount = -1, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_WITNESS_V0)
+ {
+ if (amount == -1)
+ amount = nValue;
+ return PushSig(key, nHashType, lenR, lenS, sigversion, amount).AsWit();
+ }
+
TestBuilder& Push(const CPubKey& pubkey)
{
DoPush(std::vector<unsigned char>(pubkey.begin(), pubkey.end()));
@@ -325,10 +381,16 @@ public:
TestBuilder& PushRedeem()
{
- DoPush(std::vector<unsigned char>(scriptPubKey.begin(), scriptPubKey.end()));
+ DoPush(std::vector<unsigned char>(redeemscript.begin(), redeemscript.end()));
return *this;
}
+ TestBuilder& PushWitRedeem()
+ {
+ DoPush(std::vector<unsigned char>(witscript.begin(), witscript.end()));
+ return AsWit();
+ }
+
TestBuilder& EditPush(unsigned int pos, const std::string& hexin, const std::string& hexout)
{
assert(havePush);
@@ -353,15 +415,31 @@ public:
{
TestBuilder copy = *this; // Make a copy so we can rollback the push.
DoPush();
- DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, flags, comment, scriptError);
+ DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, scriptWitness, flags, comment, scriptError, nValue);
*this = copy;
return *this;
}
+ TestBuilder& AsWit()
+ {
+ assert(havePush);
+ scriptWitness.stack.push_back(push);
+ havePush = false;
+ return *this;
+ }
+
UniValue GetJSON()
{
DoPush();
UniValue array(UniValue::VARR);
+ if (!scriptWitness.stack.empty()) {
+ UniValue wit(UniValue::VARR);
+ for (unsigned i = 0; i < scriptWitness.stack.size(); i++) {
+ wit.push_back(HexStr(scriptWitness.stack[i]));
+ }
+ wit.push_back(ValueFromAmount(nValue));
+ array.push_back(wit);
+ }
array.push_back(FormatScript(spendTx.vin[0].scriptSig));
array.push_back(FormatScript(creditTx.vout[0].scriptPubKey));
array.push_back(FormatScriptFlags(flags));
@@ -660,6 +738,90 @@ BOOST_AUTO_TEST_CASE(script_build)
"P2SH with CLEANSTACK", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true
).PushSig(keys.key0).PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "Basic P2WSH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH,
+ 0, 1).PushWitSig(keys.key0).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "Basic P2WPKH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH,
+ 0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "Basic P2SH(P2WSH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH,
+ 0, 1).PushWitSig(keys.key0).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "Basic P2SH(P2WPKH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH,
+ 0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
+ "Basic P2WSH with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH
+ ).PushWitSig(keys.key0).PushWitRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
+ "Basic P2WPKH with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH
+ ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
+ "Basic P2SH(P2WSH) with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH
+ ).PushWitSig(keys.key0).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
+ "Basic P2SH(P2WPKH) with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH
+ ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
+ "Basic P2WSH with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, false, WITNESS_SH
+ ).PushWitSig(keys.key0).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
+ "Basic P2WPKH with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, false, WITNESS_PKH
+ ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
+ "Basic P2SH(P2WSH) with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, true, WITNESS_SH
+ ).PushWitSig(keys.key0).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
+ "Basic P2SH(P2WPKH) with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, true, WITNESS_PKH
+ ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "Basic P2WSH with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH,
+ 0, 0).PushWitSig(keys.key0, 1).PushWitRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "Basic P2WPKH with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH,
+ 0, 0).PushWitSig(keys.key0, 1).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "Basic P2SH(P2WSH) with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH,
+ 0, 0).PushWitSig(keys.key0, 1).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "Basic P2SH(P2WPKH) with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH,
+ 0, 0).PushWitSig(keys.key0, 1).Push(keys.pubkey0).AsWit().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "P2WPKH with future witness version", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH |
+ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM, false, WITNESS_PKH, 1
+ ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM));
+ {
+ CScript witscript = CScript() << ToByteVector(keys.pubkey0);
+ uint256 hash;
+ CSHA256().Write(&witscript[0], witscript.size()).Finalize(hash.begin());
+ vector<unsigned char> hashBytes = ToByteVector(hash);
+ hashBytes.pop_back();
+ tests.push_back(TestBuilder(CScript() << OP_0 << hashBytes,
+ "P2WPKH with wrong witness program length", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false
+ ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH));
+ }
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2WSH with empty witness", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH
+ ).ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY));
+ {
+ CScript witscript = CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG;
+ tests.push_back(TestBuilder(witscript,
+ "P2WSH with witness program mismatch", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH
+ ).PushWitSig(keys.key0).Push(witscript).DamagePush(0).AsWit().ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH));
+ }
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "P2WPKH with witness program mismatch", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH
+ ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().Push("0").AsWit().ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "P2WPKH with non-empty scriptSig", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH
+ ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().Num(11).ScriptError(SCRIPT_ERR_WITNESS_MALLEATED));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
+ "P2SH(P2WPKH) with superfluous push in scriptSig", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH
+ ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().Num(11).PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_MALLEATED_P2SH));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2PK with witness", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH
+ ).PushSig(keys.key0).Push("0").AsWit().ScriptError(SCRIPT_ERR_WITNESS_UNEXPECTED));
std::set<std::string> tests_set;
@@ -696,29 +858,42 @@ BOOST_AUTO_TEST_CASE(script_json_test)
{
// Read tests from test/data/script_tests.json
// Format is an array of arrays
- // Inner arrays are [ "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ]
+ // Inner arrays are [ ["wit"..., nValue]?, "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ]
// ... where scriptSig and scriptPubKey are stringified
// scripts.
+ // If a witness is given, then the last value in the array should be the
+ // amount (nValue) to use in the crediting tx
UniValue tests = read_json(std::string(json_tests::script_tests, json_tests::script_tests + sizeof(json_tests::script_tests)));
for (unsigned int idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
string strTest = test.write();
- if (test.size() < 4) // Allow size > 3; extra stuff ignored (useful for comments)
+ CScriptWitness witness;
+ CAmount nValue = 0;
+ unsigned int pos = 0;
+ if (test.size() > 0 && test[pos].isArray()) {
+ unsigned int i=0;
+ for (i = 0; i < test[pos].size()-1; i++) {
+ witness.stack.push_back(ParseHex(test[pos][i].get_str()));
+ }
+ nValue = AmountFromValue(test[pos][i]);
+ pos++;
+ }
+ if (test.size() < 4 + pos) // Allow size > 3; extra stuff ignored (useful for comments)
{
if (test.size() != 1) {
BOOST_ERROR("Bad test: " << strTest);
}
continue;
}
- string scriptSigString = test[0].get_str();
+ string scriptSigString = test[pos++].get_str();
CScript scriptSig = ParseScript(scriptSigString);
- string scriptPubKeyString = test[1].get_str();
+ string scriptPubKeyString = test[pos++].get_str();
CScript scriptPubKey = ParseScript(scriptPubKeyString);
- unsigned int scriptflags = ParseScriptFlags(test[2].get_str());
- int scriptError = ParseScriptError(test[3].get_str());
+ unsigned int scriptflags = ParseScriptFlags(test[pos++].get_str());
+ int scriptError = ParseScriptError(test[pos++].get_str());
- DoTest(scriptPubKey, scriptSig, scriptflags, strTest, scriptError);
+ DoTest(scriptPubKey, scriptSig, witness, scriptflags, strTest, scriptError, nValue);
}
}
@@ -733,21 +908,21 @@ BOOST_AUTO_TEST_CASE(script_PushData)
ScriptError err;
vector<vector<unsigned char> > directStack;
- BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
+ BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
vector<vector<unsigned char> > pushdata1Stack;
- BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
+ BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
BOOST_CHECK(pushdata1Stack == directStack);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
vector<vector<unsigned char> > pushdata2Stack;
- BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
+ BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
BOOST_CHECK(pushdata2Stack == directStack);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
vector<vector<unsigned char> > pushdata4Stack;
- BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
+ BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
BOOST_CHECK(pushdata4Stack == directStack);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
@@ -755,7 +930,7 @@ BOOST_AUTO_TEST_CASE(script_PushData)
CScript
sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction)
{
- uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL);
+ uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
CScript result;
//
@@ -796,21 +971,21 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
scriptPubKey12 << OP_1 << ToByteVector(key1.GetPubKey()) << ToByteVector(key2.GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
CMutableTransaction txFrom12 = BuildCreditingTransaction(scriptPubKey12);
- CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12);
+ CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom12);
CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12);
- BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err));
+ BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
txTo12.vout[0].nValue = 2;
- BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err));
+ BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12);
- BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err));
+ BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12);
- BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err));
+ BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
}
@@ -827,65 +1002,66 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
scriptPubKey23 << OP_2 << ToByteVector(key1.GetPubKey()) << ToByteVector(key2.GetPubKey()) << ToByteVector(key3.GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
CMutableTransaction txFrom23 = BuildCreditingTransaction(scriptPubKey23);
- CMutableTransaction txTo23 = BuildSpendingTransaction(CScript(), txFrom23);
+ CMutableTransaction txTo23 = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom23);
std::vector<CKey> keys;
keys.push_back(key1); keys.push_back(key2);
CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
+ BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key1); keys.push_back(key3);
CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
+ BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key2); keys.push_back(key3);
CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
+ BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key2); keys.push_back(key2); // Can't re-use sig
CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
+ BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order
CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
+ BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order
CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
+ BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys
CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
+ BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys
CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
+ BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear(); // Must have signatures
CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err));
+ BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
}
BOOST_AUTO_TEST_CASE(script_combineSigs)
{
// Test the CombineSignatures function
+ CAmount amount = 0;
CBasicKeyStore keystore;
vector<CKey> keys;
vector<CPubKey> pubkeys;
@@ -899,66 +1075,66 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
}
CMutableTransaction txFrom = BuildCreditingTransaction(GetScriptForDestination(keys[0].GetPubKey().GetID()));
- CMutableTransaction txTo = BuildSpendingTransaction(CScript(), txFrom);
+ CMutableTransaction txTo = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom);
CScript& scriptPubKey = txFrom.vout[0].scriptPubKey;
CScript& scriptSig = txTo.vin[0].scriptSig;
- CScript empty;
- CScript combined = CombineSignatures(scriptPubKey, txTo, 0, empty, empty);
- BOOST_CHECK(combined.empty());
+ SignatureData empty;
+ SignatureData combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, empty);
+ BOOST_CHECK(combined.scriptSig.empty());
// Single signature case:
- SignSignature(keystore, txFrom, txTo, 0); // changes scriptSig
- combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
- BOOST_CHECK(combined == scriptSig);
- combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig);
- BOOST_CHECK(combined == scriptSig);
+ SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); // changes scriptSig
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty);
+ BOOST_CHECK(combined.scriptSig == scriptSig);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig));
+ BOOST_CHECK(combined.scriptSig == scriptSig);
CScript scriptSigCopy = scriptSig;
// Signing again will give a different, valid signature:
- SignSignature(keystore, txFrom, txTo, 0);
- combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig);
- BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig);
+ SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig));
+ BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig);
// P2SH, single-signature case:
CScript pkSingle; pkSingle << ToByteVector(keys[0].GetPubKey()) << OP_CHECKSIG;
keystore.AddCScript(pkSingle);
scriptPubKey = GetScriptForDestination(CScriptID(pkSingle));
- SignSignature(keystore, txFrom, txTo, 0);
- combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
- BOOST_CHECK(combined == scriptSig);
- combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig);
- BOOST_CHECK(combined == scriptSig);
+ SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty);
+ BOOST_CHECK(combined.scriptSig == scriptSig);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig));
+ BOOST_CHECK(combined.scriptSig == scriptSig);
scriptSigCopy = scriptSig;
- SignSignature(keystore, txFrom, txTo, 0);
- combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig);
- BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig);
+ SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig));
+ BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig);
// dummy scriptSigCopy with placeholder, should always choose non-placeholder:
- scriptSigCopy = CScript() << OP_0 << vector<unsigned char>(pkSingle.begin(), pkSingle.end());
- combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig);
- BOOST_CHECK(combined == scriptSig);
- combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, scriptSigCopy);
- BOOST_CHECK(combined == scriptSig);
+ scriptSigCopy = CScript() << OP_0 << std::vector<unsigned char>(pkSingle.begin(), pkSingle.end());
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig));
+ BOOST_CHECK(combined.scriptSig == scriptSig);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), SignatureData(scriptSigCopy));
+ BOOST_CHECK(combined.scriptSig == scriptSig);
// Hardest case: Multisig 2-of-3
scriptPubKey = GetScriptForMultisig(2, pubkeys);
keystore.AddCScript(scriptPubKey);
- SignSignature(keystore, txFrom, txTo, 0);
- combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
- BOOST_CHECK(combined == scriptSig);
- combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig);
- BOOST_CHECK(combined == scriptSig);
+ SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty);
+ BOOST_CHECK(combined.scriptSig == scriptSig);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig));
+ BOOST_CHECK(combined.scriptSig == scriptSig);
// A couple of partially-signed versions:
vector<unsigned char> sig1;
- uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL);
+ uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
BOOST_CHECK(keys[0].Sign(hash1, sig1));
sig1.push_back(SIGHASH_ALL);
vector<unsigned char> sig2;
- uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE);
+ uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE, 0, SIGVERSION_BASE);
BOOST_CHECK(keys[1].Sign(hash2, sig2));
sig2.push_back(SIGHASH_NONE);
vector<unsigned char> sig3;
- uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE);
+ uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE, 0, SIGVERSION_BASE);
BOOST_CHECK(keys[2].Sign(hash3, sig3));
sig3.push_back(SIGHASH_SINGLE);
@@ -974,22 +1150,22 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
CScript complete13 = CScript() << OP_0 << sig1 << sig3;
CScript complete23 = CScript() << OP_0 << sig2 << sig3;
- combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial1b);
- BOOST_CHECK(combined == partial1a);
- combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial2a);
- BOOST_CHECK(combined == complete12);
- combined = CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial1a);
- BOOST_CHECK(combined == complete12);
- combined = CombineSignatures(scriptPubKey, txTo, 0, partial1b, partial2b);
- BOOST_CHECK(combined == complete12);
- combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial1b);
- BOOST_CHECK(combined == complete13);
- combined = CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial3a);
- BOOST_CHECK(combined == complete23);
- combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial2b);
- BOOST_CHECK(combined == complete23);
- combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial3a);
- BOOST_CHECK(combined == partial3c);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial1b));
+ BOOST_CHECK(combined.scriptSig == partial1a);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial2a));
+ BOOST_CHECK(combined.scriptSig == complete12);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial1a));
+ BOOST_CHECK(combined.scriptSig == complete12);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1b), SignatureData(partial2b));
+ BOOST_CHECK(combined.scriptSig == complete12);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial1b));
+ BOOST_CHECK(combined.scriptSig == complete13);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial3a));
+ BOOST_CHECK(combined.scriptSig == complete23);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial2b));
+ BOOST_CHECK(combined.scriptSig == complete23);
+ combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial3a));
+ BOOST_CHECK(combined.scriptSig == partial3c);
}
BOOST_AUTO_TEST_CASE(script_standard_push)
@@ -999,7 +1175,7 @@ BOOST_AUTO_TEST_CASE(script_standard_push)
CScript script;
script << i;
BOOST_CHECK_MESSAGE(script.IsPushOnly(), "Number " << i << " is not pure push.");
- BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Number " << i << " push is not minimal data.");
+ BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, NULL, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Number " << i << " push is not minimal data.");
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
@@ -1008,7 +1184,7 @@ BOOST_AUTO_TEST_CASE(script_standard_push)
CScript script;
script << data;
BOOST_CHECK_MESSAGE(script.IsPushOnly(), "Length " << i << " is not pure push.");
- BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Length " << i << " push is not minimal data.");
+ BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, NULL, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Length " << i << " push is not minimal data.");
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
}
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index e43b2ff6c4..4a48347b70 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -82,7 +82,7 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un
}
// Serialize and hash
- CHashWriter ss(SER_GETHASH, 0);
+ CHashWriter ss(SER_GETHASH, SERIALIZE_TRANSACTION_NO_WITNESS);
ss << txTmp << nHashType;
return ss.GetHash();
}
@@ -143,7 +143,7 @@ BOOST_AUTO_TEST_CASE(sighash_test)
uint256 sh, sho;
sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType);
- sh = SignatureHash(scriptCode, txTo, nIn, nHashType);
+ sh = SignatureHash(scriptCode, txTo, nIn, nHashType, 0, SIGVERSION_BASE);
#if defined(PRINT_SIGHASH_JSON)
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << txTo;
@@ -209,7 +209,7 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
continue;
}
- sh = SignatureHash(scriptCode, tx, nIn, nHashType);
+ sh = SignatureHash(scriptCode, tx, nIn, nHashType, 0, SIGVERSION_BASE);
BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest);
}
}
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
index a207fd9216..8dea388332 100644
--- a/src/test/sigopcount_tests.cpp
+++ b/src/test/sigopcount_tests.cpp
@@ -2,6 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "main.h"
#include "pubkey.h"
#include "key.h"
#include "script/script.h"
@@ -64,4 +65,180 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount)
BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig2), 3U);
}
+/**
+ * Verifies script execution of the zeroth scriptPubKey of tx output and
+ * zeroth scriptSig and witness of tx input.
+ */
+ScriptError VerifyWithFlag(const CTransaction& output, const CMutableTransaction& input, int flags)
+{
+ ScriptError error;
+ CTransaction inputi(input);
+ bool ret = VerifyScript(inputi.vin[0].scriptSig, output.vout[0].scriptPubKey, inputi.wit.vtxinwit.size() > 0 ? &inputi.wit.vtxinwit[0].scriptWitness : NULL, flags, TransactionSignatureChecker(&inputi, 0, output.vout[0].nValue), &error);
+ BOOST_CHECK((ret == true) == (error == SCRIPT_ERR_OK));
+
+ return error;
+}
+
+/**
+ * Builds a creationTx from scriptPubKey and a spendingTx from scriptSig
+ * and witness such that spendingTx spends output zero of creationTx.
+ * Also inserts creationTx's output into the coins view.
+ */
+void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CMutableTransaction& creationTx, const CScript& scriptPubKey, const CScript& scriptSig, const CTxinWitness& witness)
+{
+ creationTx.nVersion = 1;
+ creationTx.vin.resize(1);
+ creationTx.vin[0].prevout.SetNull();
+ creationTx.vin[0].scriptSig = CScript();
+ creationTx.wit.vtxinwit.resize(1);
+ creationTx.vout.resize(1);
+ creationTx.vout[0].nValue = 1;
+ creationTx.vout[0].scriptPubKey = scriptPubKey;
+
+ spendingTx.nVersion = 1;
+ spendingTx.vin.resize(1);
+ spendingTx.vin[0].prevout.hash = creationTx.GetHash();
+ spendingTx.vin[0].prevout.n = 0;
+ spendingTx.vin[0].scriptSig = scriptSig;
+ spendingTx.wit.vtxinwit.resize(1);
+ spendingTx.wit.vtxinwit[0] = witness;
+ spendingTx.vout.resize(1);
+ spendingTx.vout[0].nValue = 1;
+ spendingTx.vout[0].scriptPubKey = CScript();
+
+ coins.ModifyCoins(creationTx.GetHash())->FromTx(creationTx, 0);
+}
+
+BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
+{
+ // Transaction creates outputs
+ CMutableTransaction creationTx;
+ // Transaction that spends outputs and whose
+ // sig op cost is going to be tested
+ CMutableTransaction spendingTx;
+
+ // Create utxo set
+ CCoinsView coinsDummy;
+ CCoinsViewCache coins(&coinsDummy);
+ // Create key
+ CKey key;
+ key.MakeNewKey(true);
+ CPubKey pubkey = key.GetPubKey();
+ // Default flags
+ int flags = SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH;
+
+ // Multisig script (legacy counting)
+ {
+ CScript scriptPubKey = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY;
+ // Do not use a valid signature to avoid using wallet operations.
+ CScript scriptSig = CScript() << OP_0 << OP_0;
+
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CTxinWitness());
+ // Legacy counting only includes signature operations in scriptSigs and scriptPubKeys
+ // of a transaction and does not take the actual executed sig operations into account.
+ // spendingTx in itself does not contain a signature operation.
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 0);
+ // creationTx contains two signature operations in its scriptPubKey, but legacy counting
+ // is not accurate.
+ assert(GetTransactionSigOpCost(CTransaction(creationTx), coins, flags) == MAX_PUBKEYS_PER_MULTISIG * WITNESS_SCALE_FACTOR);
+ // Sanity check: script verification fails because of an invalid signature.
+ assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
+ }
+
+ // Multisig nested in P2SH
+ {
+ CScript redeemScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY;
+ CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
+ CScript scriptSig = CScript() << OP_0 << OP_0 << ToByteVector(redeemScript);
+
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CTxinWitness());
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2 * WITNESS_SCALE_FACTOR);
+ assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
+ }
+
+ // P2WPKH witness program
+ {
+ CScript p2pk = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
+ CScript scriptPubKey = GetScriptForWitness(p2pk);
+ CScript scriptSig = CScript();
+ CTxinWitness witness;
+ CScriptWitness scriptWitness;
+ scriptWitness.stack.push_back(vector<unsigned char>(0));
+ scriptWitness.stack.push_back(vector<unsigned char>(0));
+ witness.scriptWitness = scriptWitness;
+
+
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness);
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 1);
+ // No signature operations if we don't verify the witness.
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags & ~SCRIPT_VERIFY_WITNESS) == 0);
+ assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_EQUALVERIFY);
+
+ // The sig op cost for witness version != 0 is zero.
+ assert(scriptPubKey[0] == 0x00);
+ scriptPubKey[0] = 0x51;
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness);
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 0);
+ scriptPubKey[0] = 0x00;
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness);
+
+ // The witness of a coinbase transaction is not taken into account.
+ spendingTx.vin[0].prevout.SetNull();
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 0);
+ }
+
+ // P2WPKH nested in P2SH
+ {
+ CScript p2pk = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
+ CScript scriptSig = GetScriptForWitness(p2pk);
+ CScript scriptPubKey = GetScriptForDestination(CScriptID(scriptSig));
+ scriptSig = CScript() << ToByteVector(scriptSig);
+ CTxinWitness witness;
+ CScriptWitness scriptWitness;
+ scriptWitness.stack.push_back(vector<unsigned char>(0));
+ scriptWitness.stack.push_back(vector<unsigned char>(0));
+ witness.scriptWitness = scriptWitness;
+
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness);
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 1);
+ assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_EQUALVERIFY);
+ }
+
+ // P2WSH witness program
+ {
+ CScript witnessScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY;
+ CScript scriptPubKey = GetScriptForWitness(witnessScript);
+ CScript scriptSig = CScript();
+ CTxinWitness witness;
+ CScriptWitness scriptWitness;
+ scriptWitness.stack.push_back(vector<unsigned char>(0));
+ scriptWitness.stack.push_back(vector<unsigned char>(0));
+ scriptWitness.stack.push_back(vector<unsigned char>(witnessScript.begin(), witnessScript.end()));
+ witness.scriptWitness = scriptWitness;
+
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness);
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2);
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags & ~SCRIPT_VERIFY_WITNESS) == 0);
+ assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
+ }
+
+ // P2WSH nested in P2SH
+ {
+ CScript witnessScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY;
+ CScript redeemScript = GetScriptForWitness(witnessScript);
+ CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
+ CScript scriptSig = CScript() << ToByteVector(redeemScript);
+ CTxinWitness witness;
+ CScriptWitness scriptWitness;
+ scriptWitness.stack.push_back(vector<unsigned char>(0));
+ scriptWitness.stack.push_back(vector<unsigned char>(0));
+ scriptWitness.stack.push_back(vector<unsigned char>(witnessScript.begin(), witnessScript.end()));
+ witness.scriptWitness = scriptWitness;
+
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness);
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2);
+ assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 1f3b198800..856f9b8423 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -136,7 +136,7 @@ CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(CTransaction &txn, CTxMemPool *po
CAmount inChainValue = hasNoDependencies ? txn.GetValueOut() : 0;
return CTxMemPoolEntry(txn, nFee, nTime, dPriority, nHeight,
- hasNoDependencies, inChainValue, spendsCoinbase, sigOpCount, lp);
+ hasNoDependencies, inChainValue, spendsCoinbase, sigOpCost, lp);
}
void Shutdown(void* parg)
diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h
index 78b87e7109..bc0d2fe316 100644
--- a/src/test/test_bitcoin.h
+++ b/src/test/test_bitcoin.h
@@ -70,12 +70,12 @@ struct TestMemPoolEntryHelper
unsigned int nHeight;
bool hadNoDependencies;
bool spendsCoinbase;
- unsigned int sigOpCount;
+ unsigned int sigOpCost;
LockPoints lp;
TestMemPoolEntryHelper() :
nFee(0), nTime(0), dPriority(0.0), nHeight(1),
- hadNoDependencies(false), spendsCoinbase(false), sigOpCount(1) { }
+ hadNoDependencies(false), spendsCoinbase(false), sigOpCost(4) { }
CTxMemPoolEntry FromTx(CMutableTransaction &tx, CTxMemPool *pool = NULL);
CTxMemPoolEntry FromTx(CTransaction &tx, CTxMemPool *pool = NULL);
@@ -87,6 +87,6 @@ struct TestMemPoolEntryHelper
TestMemPoolEntryHelper &Height(unsigned int _height) { nHeight = _height; return *this; }
TestMemPoolEntryHelper &HadNoDependencies(bool _hnd) { hadNoDependencies = _hnd; return *this; }
TestMemPoolEntryHelper &SpendsCoinbase(bool _flag) { spendsCoinbase = _flag; return *this; }
- TestMemPoolEntryHelper &SigOps(unsigned int _sigops) { sigOpCount = _sigops; return *this; }
+ TestMemPoolEntryHelper &SigOpsCost(unsigned int _sigopsCost) { sigOpCost = _sigopsCost; return *this; }
};
#endif
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index d9195bf345..fd4f174b40 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -14,7 +14,9 @@
#include "main.h" // For CheckTransaction
#include "policy/policy.h"
#include "script/script.h"
+#include "script/sign.h"
#include "script/script_error.h"
+#include "script/standard.h"
#include "utilstrencodings.h"
#include <map>
@@ -25,11 +27,14 @@
#include <boost/assign/list_of.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/assign/list_of.hpp>
+#include <boost/foreach.hpp>
#include <univalue.h>
using namespace std;
+typedef vector<unsigned char> valtype;
+
// In script_tests.cpp
extern UniValue read_json(const std::string& jsondata);
@@ -45,7 +50,9 @@ static std::map<string, unsigned int> mapFlagNames = boost::assign::map_list_of
(string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
(string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK)
(string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)
- (string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY);
+ (string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)
+ (string("WITNESS"), (unsigned int)SCRIPT_VERIFY_WITNESS)
+ (string("DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM);
unsigned int ParseScriptFlags(string strFlags)
{
@@ -108,6 +115,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
}
map<COutPoint, CScript> mapprevOutScriptPubKeys;
+ map<COutPoint, int64_t> mapprevOutValues;
UniValue inputs = test[0].get_array();
bool fValid = true;
for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) {
@@ -118,13 +126,17 @@ BOOST_AUTO_TEST_CASE(tx_valid)
break;
}
UniValue vinput = input.get_array();
- if (vinput.size() != 3)
+ if (vinput.size() < 3 || vinput.size() > 4)
{
fValid = false;
break;
}
-
- mapprevOutScriptPubKeys[COutPoint(uint256S(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str());
+ COutPoint outpoint(uint256S(vinput[0].get_str()), vinput[1].get_int());
+ mapprevOutScriptPubKeys[outpoint] = ParseScript(vinput[2].get_str());
+ if (vinput.size() >= 4)
+ {
+ mapprevOutValues[outpoint] = vinput[3].get_int64();
+ }
}
if (!fValid)
{
@@ -149,9 +161,14 @@ BOOST_AUTO_TEST_CASE(tx_valid)
break;
}
+ CAmount amount = 0;
+ if (mapprevOutValues.count(tx.vin[i].prevout)) {
+ amount = mapprevOutValues[tx.vin[i].prevout];
+ }
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
+ const CScriptWitness *witness = (i < tx.wit.vtxinwit.size()) ? &tx.wit.vtxinwit[i].scriptWitness : NULL;
BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
- verify_flags, TransactionSignatureChecker(&tx, i), &err),
+ witness, verify_flags, TransactionSignatureChecker(&tx, i, amount), &err),
strTest);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
@@ -183,6 +200,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
}
map<COutPoint, CScript> mapprevOutScriptPubKeys;
+ map<COutPoint, int64_t> mapprevOutValues;
UniValue inputs = test[0].get_array();
bool fValid = true;
for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) {
@@ -193,13 +211,17 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
break;
}
UniValue vinput = input.get_array();
- if (vinput.size() != 3)
+ if (vinput.size() < 3 || vinput.size() > 4)
{
fValid = false;
break;
}
-
- mapprevOutScriptPubKeys[COutPoint(uint256S(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str());
+ COutPoint outpoint(uint256S(vinput[0].get_str()), vinput[1].get_int());
+ mapprevOutScriptPubKeys[outpoint] = ParseScript(vinput[2].get_str());
+ if (vinput.size() >= 4)
+ {
+ mapprevOutValues[outpoint] = vinput[3].get_int64();
+ }
}
if (!fValid)
{
@@ -208,7 +230,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
}
string transaction = test[1].get_str();
- CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
+ CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION );
CTransaction tx;
stream >> tx;
@@ -224,8 +246,13 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
}
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
+ CAmount amount = 0;
+ if (mapprevOutValues.count(tx.vin[i].prevout)) {
+ amount = mapprevOutValues[tx.vin[i].prevout];
+ }
+ const CScriptWitness *witness = (i < tx.wit.vtxinwit.size()) ? &tx.wit.vtxinwit[i].scriptWitness : NULL;
fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
- verify_flags, TransactionSignatureChecker(&tx, i), &err);
+ witness, verify_flags, TransactionSignatureChecker(&tx, i, amount), &err);
}
BOOST_CHECK_MESSAGE(!fValid, strTest);
BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err));
@@ -313,6 +340,277 @@ BOOST_AUTO_TEST_CASE(test_Get)
BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50+21+22)*CENT);
}
+void CreateCreditAndSpend(const CKeyStore& keystore, const CScript& outscript, CTransaction& output, CMutableTransaction& input, bool success = true)
+{
+ CMutableTransaction outputm;
+ outputm.nVersion = 1;
+ outputm.vin.resize(1);
+ outputm.vin[0].prevout.SetNull();
+ outputm.vin[0].scriptSig = CScript();
+ outputm.wit.vtxinwit.resize(1);
+ outputm.vout.resize(1);
+ outputm.vout[0].nValue = 1;
+ outputm.vout[0].scriptPubKey = outscript;
+ CDataStream ssout(SER_NETWORK, PROTOCOL_VERSION);
+ ssout << outputm;
+ ssout >> output;
+ assert(output.vin.size() == 1);
+ assert(output.vin[0] == outputm.vin[0]);
+ assert(output.vout.size() == 1);
+ assert(output.vout[0] == outputm.vout[0]);
+ assert(output.wit.vtxinwit.size() == 0);
+
+ CMutableTransaction inputm;
+ inputm.nVersion = 1;
+ inputm.vin.resize(1);
+ inputm.vin[0].prevout.hash = output.GetHash();
+ inputm.vin[0].prevout.n = 0;
+ inputm.wit.vtxinwit.resize(1);
+ inputm.vout.resize(1);
+ inputm.vout[0].nValue = 1;
+ inputm.vout[0].scriptPubKey = CScript();
+ bool ret = SignSignature(keystore, output, inputm, 0, SIGHASH_ALL);
+ assert(ret == success);
+ CDataStream ssin(SER_NETWORK, PROTOCOL_VERSION);
+ ssin << inputm;
+ ssin >> input;
+ assert(input.vin.size() == 1);
+ assert(input.vin[0] == inputm.vin[0]);
+ assert(input.vout.size() == 1);
+ assert(input.vout[0] == inputm.vout[0]);
+ if (inputm.wit.IsNull()) {
+ assert(input.wit.IsNull());
+ } else {
+ assert(!input.wit.IsNull());
+ assert(input.wit.vtxinwit.size() == 1);
+ assert(input.wit.vtxinwit[0].scriptWitness.stack == inputm.wit.vtxinwit[0].scriptWitness.stack);
+ }
+}
+
+void CheckWithFlag(const CTransaction& output, const CMutableTransaction& input, int flags, bool success)
+{
+ ScriptError error;
+ CTransaction inputi(input);
+ bool ret = VerifyScript(inputi.vin[0].scriptSig, output.vout[0].scriptPubKey, inputi.wit.vtxinwit.size() > 0 ? &inputi.wit.vtxinwit[0].scriptWitness : NULL, flags, TransactionSignatureChecker(&inputi, 0, output.vout[0].nValue), &error);
+ assert(ret == success);
+}
+
+static CScript PushAll(const vector<valtype>& values)
+{
+ CScript result;
+ BOOST_FOREACH(const valtype& v, values) {
+ if (v.size() == 0) {
+ result << OP_0;
+ } else if (v.size() == 1 && v[0] >= 1 && v[0] <= 16) {
+ result << CScript::EncodeOP_N(v[0]);
+ } else {
+ result << v;
+ }
+ }
+ return result;
+}
+
+void ReplaceRedeemScript(CScript& script, const CScript& redeemScript)
+{
+ vector<valtype> stack;
+ EvalScript(stack, script, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE);
+ assert(stack.size() > 0);
+ stack.back() = std::vector<unsigned char>(redeemScript.begin(), redeemScript.end());
+ script = PushAll(stack);
+}
+
+BOOST_AUTO_TEST_CASE(test_witness)
+{
+ CBasicKeyStore keystore, keystore2;
+ CKey key1, key2, key3, key1L, key2L;
+ CPubKey pubkey1, pubkey2, pubkey3, pubkey1L, pubkey2L;
+ key1.MakeNewKey(true);
+ key2.MakeNewKey(true);
+ key3.MakeNewKey(true);
+ key1L.MakeNewKey(false);
+ key2L.MakeNewKey(false);
+ pubkey1 = key1.GetPubKey();
+ pubkey2 = key2.GetPubKey();
+ pubkey3 = key3.GetPubKey();
+ pubkey1L = key1L.GetPubKey();
+ pubkey2L = key2L.GetPubKey();
+ keystore.AddKeyPubKey(key1, pubkey1);
+ keystore.AddKeyPubKey(key2, pubkey2);
+ keystore.AddKeyPubKey(key1L, pubkey1L);
+ keystore.AddKeyPubKey(key2L, pubkey2L);
+ CScript scriptPubkey1, scriptPubkey2, scriptPubkey1L, scriptPubkey2L, scriptMulti;
+ scriptPubkey1 << ToByteVector(pubkey1) << OP_CHECKSIG;
+ scriptPubkey2 << ToByteVector(pubkey2) << OP_CHECKSIG;
+ scriptPubkey1L << ToByteVector(pubkey1L) << OP_CHECKSIG;
+ scriptPubkey2L << ToByteVector(pubkey2L) << OP_CHECKSIG;
+ std::vector<CPubKey> oneandthree;
+ oneandthree.push_back(pubkey1);
+ oneandthree.push_back(pubkey3);
+ scriptMulti = GetScriptForMultisig(2, oneandthree);
+ keystore.AddCScript(scriptPubkey1);
+ keystore.AddCScript(scriptPubkey2);
+ keystore.AddCScript(scriptPubkey1L);
+ keystore.AddCScript(scriptPubkey2L);
+ keystore.AddCScript(scriptMulti);
+ keystore.AddCScript(GetScriptForWitness(scriptPubkey1));
+ keystore.AddCScript(GetScriptForWitness(scriptPubkey2));
+ keystore.AddCScript(GetScriptForWitness(scriptPubkey1L));
+ keystore.AddCScript(GetScriptForWitness(scriptPubkey2L));
+ keystore.AddCScript(GetScriptForWitness(scriptMulti));
+ keystore2.AddCScript(scriptMulti);
+ keystore2.AddCScript(GetScriptForWitness(scriptMulti));
+ keystore2.AddKeyPubKey(key3, pubkey3);
+
+ CTransaction output1, output2;
+ CMutableTransaction input1, input2;
+ SignatureData sigdata;
+
+ // Normal pay-to-compressed-pubkey.
+ CreateCreditAndSpend(keystore, scriptPubkey1, output1, input1);
+ CreateCreditAndSpend(keystore, scriptPubkey2, output2, input2);
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+ CheckWithFlag(output1, input2, 0, false);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+
+ // P2SH pay-to-compressed-pubkey.
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey1)), output1, input1);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey2)), output2, input2);
+ ReplaceRedeemScript(input2.vin[0].scriptSig, scriptPubkey1);
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+ CheckWithFlag(output1, input2, 0, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+
+ // Witness pay-to-compressed-pubkey (v0).
+ CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey1), output1, input1);
+ CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey2), output2, input2);
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+ CheckWithFlag(output1, input2, 0, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+
+ // P2SH witness pay-to-compressed-pubkey (v0).
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1))), output1, input1);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2))), output2, input2);
+ ReplaceRedeemScript(input2.vin[0].scriptSig, GetScriptForWitness(scriptPubkey1));
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+ CheckWithFlag(output1, input2, 0, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+
+ // Normal pay-to-uncompressed-pubkey.
+ CreateCreditAndSpend(keystore, scriptPubkey1L, output1, input1);
+ CreateCreditAndSpend(keystore, scriptPubkey2L, output2, input2);
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+ CheckWithFlag(output1, input2, 0, false);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+
+ // P2SH pay-to-uncompressed-pubkey.
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey1L)), output1, input1);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey2L)), output2, input2);
+ ReplaceRedeemScript(input2.vin[0].scriptSig, scriptPubkey1L);
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+ CheckWithFlag(output1, input2, 0, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+
+ // Witness pay-to-uncompressed-pubkey (v1).
+ CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey1L), output1, input1);
+ CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey2L), output2, input2);
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+ CheckWithFlag(output1, input2, 0, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+
+ // P2SH witness pay-to-uncompressed-pubkey (v1).
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1L))), output1, input1);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2L))), output2, input2);
+ ReplaceRedeemScript(input2.vin[0].scriptSig, GetScriptForWitness(scriptPubkey1L));
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+ CheckWithFlag(output1, input2, 0, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+
+ // Normal 2-of-2 multisig
+ CreateCreditAndSpend(keystore, scriptMulti, output1, input1, false);
+ CheckWithFlag(output1, input1, 0, false);
+ CreateCreditAndSpend(keystore2, scriptMulti, output2, input2, false);
+ CheckWithFlag(output2, input2, 0, false);
+ BOOST_CHECK(output1 == output2);
+ UpdateTransaction(input1, 0, CombineSignatures(output1.vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1.vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+
+ // P2SH 2-of-2 multisig
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptMulti)), output1, input1, false);
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, false);
+ CreateCreditAndSpend(keystore2, GetScriptForDestination(CScriptID(scriptMulti)), output2, input2, false);
+ CheckWithFlag(output2, input2, 0, true);
+ CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, false);
+ BOOST_CHECK(output1 == output2);
+ UpdateTransaction(input1, 0, CombineSignatures(output1.vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1.vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+
+ // Witness 2-of-2 multisig
+ CreateCreditAndSpend(keystore, GetScriptForWitness(scriptMulti), output1, input1, false);
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
+ CreateCreditAndSpend(keystore2, GetScriptForWitness(scriptMulti), output2, input2, false);
+ CheckWithFlag(output2, input2, 0, true);
+ CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
+ BOOST_CHECK(output1 == output2);
+ UpdateTransaction(input1, 0, CombineSignatures(output1.vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1.vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+
+ // P2SH witness 2-of-2 multisig
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptMulti))), output1, input1, false);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
+ CreateCreditAndSpend(keystore2, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptMulti))), output2, input2, false);
+ CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
+ BOOST_CHECK(output1 == output2);
+ UpdateTransaction(input1, 0, CombineSignatures(output1.vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1.vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+}
+
BOOST_AUTO_TEST_CASE(test_IsStandard)
{
LOCK(cs_main);
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index c29e30792a..76e4e7a4be 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -48,7 +48,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
// Sign:
std::vector<unsigned char> vchSig;
- uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL);
+ uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
vchSig.push_back((unsigned char)SIGHASH_ALL);
spends[i].vin[0].scriptSig << vchSig;
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index ead28546de..a48a6d9465 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -9,6 +9,7 @@
#include "consensus/consensus.h"
#include "consensus/validation.h"
#include "main.h"
+#include "policy/policy.h"
#include "policy/fees.h"
#include "streams.h"
#include "timedata.h"
@@ -22,17 +23,17 @@ using namespace std;
CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
int64_t _nTime, double _entryPriority, unsigned int _entryHeight,
bool poolHasNoInputsOf, CAmount _inChainInputValue,
- bool _spendsCoinbase, unsigned int _sigOps, LockPoints lp):
+ bool _spendsCoinbase, int64_t _sigOpsCost, LockPoints lp):
tx(std::make_shared<CTransaction>(_tx)), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), entryHeight(_entryHeight),
hadNoDependencies(poolHasNoInputsOf), inChainInputValue(_inChainInputValue),
- spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOps), lockPoints(lp)
+ spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp)
{
- nTxSize = ::GetSerializeSize(_tx, SER_NETWORK, PROTOCOL_VERSION);
- nModSize = _tx.CalculateModifiedSize(nTxSize);
+ nTxCost = GetTransactionCost(_tx);
+ nModSize = _tx.CalculateModifiedSize(GetTxSize());
nUsageSize = RecursiveDynamicUsage(*tx) + memusage::DynamicUsage(tx);
nCountWithDescendants = 1;
- nSizeWithDescendants = nTxSize;
+ nSizeWithDescendants = GetTxSize();
nModFeesWithDescendants = nFee;
CAmount nValueIn = _tx.GetValueOut()+nFee;
assert(inChainInputValue <= nValueIn);
@@ -40,9 +41,9 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
feeDelta = 0;
nCountWithAncestors = 1;
- nSizeWithAncestors = nTxSize;
+ nSizeWithAncestors = GetTxSize();
nModFeesWithAncestors = nFee;
- nSigOpCountWithAncestors = sigOpCount;
+ nSigOpCostWithAncestors = sigOpCost;
}
CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other)
@@ -72,6 +73,11 @@ void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp)
lockPoints = lp;
}
+size_t CTxMemPoolEntry::GetTxSize() const
+{
+ return GetVirtualTransactionSize(nTxCost);
+}
+
// Update the given tx for any in-mempool descendants.
// Assumes that setMemPoolChildren is correct for the given tx and all
// descendants.
@@ -111,7 +117,7 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan
modifyCount++;
cachedDescendants[updateIt].insert(cit);
// Update ancestor state for each descendant
- mapTx.modify(cit, update_ancestor_state(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCount()));
+ mapTx.modify(cit, update_ancestor_state(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCost()));
}
}
mapTx.modify(updateIt, update_descendant_state(modifySize, modifyFee, modifyCount));
@@ -247,13 +253,13 @@ void CTxMemPool::UpdateEntryForAncestors(txiter it, const setEntries &setAncesto
int64_t updateCount = setAncestors.size();
int64_t updateSize = 0;
CAmount updateFee = 0;
- int updateSigOps = 0;
+ int64_t updateSigOpsCost = 0;
BOOST_FOREACH(txiter ancestorIt, setAncestors) {
updateSize += ancestorIt->GetTxSize();
updateFee += ancestorIt->GetModifiedFee();
- updateSigOps += ancestorIt->GetSigOpCount();
+ updateSigOpsCost += ancestorIt->GetSigOpCost();
}
- mapTx.modify(it, update_ancestor_state(updateSize, updateFee, updateCount, updateSigOps));
+ mapTx.modify(it, update_ancestor_state(updateSize, updateFee, updateCount, updateSigOpsCost));
}
void CTxMemPool::UpdateChildrenForRemoval(txiter it)
@@ -282,7 +288,7 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, b
setDescendants.erase(removeIt); // don't update state for self
int64_t modifySize = -((int64_t)removeIt->GetTxSize());
CAmount modifyFee = -removeIt->GetModifiedFee();
- int modifySigOps = -removeIt->GetSigOpCount();
+ int modifySigOps = -removeIt->GetSigOpCost();
BOOST_FOREACH(txiter dit, setDescendants) {
mapTx.modify(dit, update_ancestor_state(modifySize, modifyFee, -1, modifySigOps));
}
@@ -338,8 +344,8 @@ void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee,
nModFeesWithAncestors += modifyFee;
nCountWithAncestors += modifyCount;
assert(int64_t(nCountWithAncestors) > 0);
- nSigOpCountWithAncestors += modifySigOps;
- assert(int(nSigOpCountWithAncestors) >= 0);
+ nSigOpCostWithAncestors += modifySigOps;
+ assert(int(nSigOpCostWithAncestors) >= 0);
}
CTxMemPool::CTxMemPool(const CFeeRate& _minReasonableRelayFee) :
@@ -666,7 +672,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
bool fDependsWait = false;
setEntries setParentCheck;
int64_t parentSizes = 0;
- unsigned int parentSigOpCount = 0;
+ int64_t parentSigOpCost = 0;
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
// Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
@@ -676,7 +682,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
fDependsWait = true;
if (setParentCheck.insert(it2).second) {
parentSizes += it2->GetTxSize();
- parentSigOpCount += it2->GetSigOpCount();
+ parentSigOpCost += it2->GetSigOpCost();
}
} else {
const CCoins* coins = pcoins->AccessCoins(txin.prevout.hash);
@@ -698,17 +704,17 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
uint64_t nCountCheck = setAncestors.size() + 1;
uint64_t nSizeCheck = it->GetTxSize();
CAmount nFeesCheck = it->GetModifiedFee();
- unsigned int nSigOpCheck = it->GetSigOpCount();
+ int64_t nSigOpCheck = it->GetSigOpCost();
BOOST_FOREACH(txiter ancestorIt, setAncestors) {
nSizeCheck += ancestorIt->GetTxSize();
nFeesCheck += ancestorIt->GetModifiedFee();
- nSigOpCheck += ancestorIt->GetSigOpCount();
+ nSigOpCheck += ancestorIt->GetSigOpCost();
}
assert(it->GetCountWithAncestors() == nCountCheck);
assert(it->GetSizeWithAncestors() == nSizeCheck);
- assert(it->GetSigOpCountWithAncestors() == nSigOpCheck);
+ assert(it->GetSigOpCostWithAncestors() == nSigOpCheck);
assert(it->GetModFeesWithAncestors() == nFeesCheck);
// Check children against mapNextTx
diff --git a/src/txmempool.h b/src/txmempool.h
index d6d0d72ff5..e5a500e19d 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -78,7 +78,7 @@ class CTxMemPoolEntry
private:
std::shared_ptr<const CTransaction> tx;
CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups
- size_t nTxSize; //!< ... and avoid recomputing tx size
+ size_t nTxCost; //!< ... and avoid recomputing tx cost (also used for GetTxSize())
size_t nModSize; //!< ... and modified size for priority
size_t nUsageSize; //!< ... and total memory usage
int64_t nTime; //!< Local time when entering the mempool
@@ -87,7 +87,7 @@ private:
bool hadNoDependencies; //!< Not dependent on any other txs when it entered the mempool
CAmount inChainInputValue; //!< Sum of all txin values that are already in blockchain
bool spendsCoinbase; //!< keep track of transactions that spend a coinbase
- unsigned int sigOpCount; //!< Legacy sig ops plus P2SH sig op count
+ int64_t sigOpCost; //!< Total sigop cost
int64_t feeDelta; //!< Used for determining the priority of the transaction for mining in a block
LockPoints lockPoints; //!< Track the height and time at which tx was final
@@ -104,13 +104,13 @@ private:
uint64_t nCountWithAncestors;
uint64_t nSizeWithAncestors;
CAmount nModFeesWithAncestors;
- unsigned int nSigOpCountWithAncestors;
+ int64_t nSigOpCostWithAncestors;
public:
CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
int64_t _nTime, double _entryPriority, unsigned int _entryHeight,
bool poolHasNoInputsOf, CAmount _inChainInputValue, bool spendsCoinbase,
- unsigned int nSigOps, LockPoints lp);
+ int64_t nSigOpsCost, LockPoints lp);
CTxMemPoolEntry(const CTxMemPoolEntry& other);
const CTransaction& GetTx() const { return *this->tx; }
@@ -121,11 +121,12 @@ public:
*/
double GetPriority(unsigned int currentHeight) const;
const CAmount& GetFee() const { return nFee; }
- size_t GetTxSize() const { return nTxSize; }
+ size_t GetTxSize() const;
+ size_t GetTxCost() const { return nTxCost; }
int64_t GetTime() const { return nTime; }
unsigned int GetHeight() const { return entryHeight; }
bool WasClearAtEntry() const { return hadNoDependencies; }
- unsigned int GetSigOpCount() const { return sigOpCount; }
+ int64_t GetSigOpCost() const { return sigOpCost; }
int64_t GetModifiedFee() const { return nFee + feeDelta; }
size_t DynamicMemoryUsage() const { return nUsageSize; }
const LockPoints& GetLockPoints() const { return lockPoints; }
@@ -149,7 +150,7 @@ public:
uint64_t GetCountWithAncestors() const { return nCountWithAncestors; }
uint64_t GetSizeWithAncestors() const { return nSizeWithAncestors; }
CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; }
- unsigned int GetSigOpCountWithAncestors() const { return nSigOpCountWithAncestors; }
+ int64_t GetSigOpCostWithAncestors() const { return nSigOpCostWithAncestors; }
mutable size_t vTxHashesIdx; //!< Index in mempool's vTxHashes
};
@@ -172,18 +173,18 @@ struct update_descendant_state
struct update_ancestor_state
{
- update_ancestor_state(int64_t _modifySize, CAmount _modifyFee, int64_t _modifyCount, int _modifySigOps) :
- modifySize(_modifySize), modifyFee(_modifyFee), modifyCount(_modifyCount), modifySigOps(_modifySigOps)
+ update_ancestor_state(int64_t _modifySize, CAmount _modifyFee, int64_t _modifyCount, int64_t _modifySigOpsCost) :
+ modifySize(_modifySize), modifyFee(_modifyFee), modifyCount(_modifyCount), modifySigOpsCost(_modifySigOpsCost)
{}
void operator() (CTxMemPoolEntry &e)
- { e.UpdateAncestorState(modifySize, modifyFee, modifyCount, modifySigOps); }
+ { e.UpdateAncestorState(modifySize, modifyFee, modifyCount, modifySigOpsCost); }
private:
int64_t modifySize;
CAmount modifyFee;
int64_t modifyCount;
- int modifySigOps;
+ int64_t modifySigOpsCost;
};
struct update_fee_delta
diff --git a/src/versionbits.cpp b/src/versionbits.cpp
index 043819c654..bf32ae6627 100644
--- a/src/versionbits.cpp
+++ b/src/versionbits.cpp
@@ -14,6 +14,10 @@ const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION
{
/*.name =*/ "csv",
/*.gbt_force =*/ true,
+ },
+ {
+ /*.name =*/ "segwit",
+ /*.gbt_force =*/ false,
}
};
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 2d4e95911d..8538f880ff 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -1011,6 +1011,85 @@ UniValue addmultisigaddress(const UniValue& params, bool fHelp)
return CBitcoinAddress(innerID).ToString();
}
+class Witnessifier : public boost::static_visitor<bool>
+{
+public:
+ CScriptID result;
+
+ bool operator()(const CNoDestination &dest) const { return false; }
+
+ bool operator()(const CKeyID &keyID) {
+ CPubKey pubkey;
+ if (pwalletMain && pwalletMain->GetPubKey(keyID, pubkey)) {
+ CScript basescript;
+ basescript << ToByteVector(pubkey) << OP_CHECKSIG;
+ CScript witscript = GetScriptForWitness(basescript);
+ pwalletMain->AddCScript(witscript);
+ result = CScriptID(witscript);
+ return true;
+ }
+ return false;
+ }
+
+ bool operator()(const CScriptID &scriptID) {
+ CScript subscript;
+ if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) {
+ int witnessversion;
+ std::vector<unsigned char> witprog;
+ if (subscript.IsWitnessProgram(witnessversion, witprog)) {
+ result = scriptID;
+ return true;
+ }
+ CScript witscript = GetScriptForWitness(subscript);
+ pwalletMain->AddCScript(witscript);
+ result = CScriptID(witscript);
+ return true;
+ }
+ return false;
+ }
+};
+
+UniValue addwitnessaddress(const UniValue& params, bool fHelp)
+{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
+ if (fHelp || params.size() < 1 || params.size() > 1)
+ {
+ string msg = "addwitnessaddress \"address\"\n"
+ "\nAdd a witness address for a script (with pubkey or redeemscript known).\n"
+ "It returns the witness script.\n"
+
+ "\nArguments:\n"
+ "1. \"address\" (string, required) An address known to the wallet\n"
+
+ "\nResult:\n"
+ "\"witnessaddress\", (string) The value of the new address (P2SH of witness script).\n"
+ "}\n"
+ ;
+ throw runtime_error(msg);
+ }
+
+ {
+ LOCK(cs_main);
+ if (!IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus()) && !GetBoolArg("-walletprematurewitness", false)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Segregated witness not enabled on network");
+ }
+ }
+
+ CBitcoinAddress address(params[0].get_str());
+ if (!address.IsValid())
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
+
+ Witnessifier w;
+ CTxDestination dest = address.Get();
+ bool ret = boost::apply_visitor(w, dest);
+ if (!ret) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet");
+ }
+
+ return CBitcoinAddress(w.result).ToString();
+}
struct tallyitem
{
@@ -2451,7 +2530,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
// parse hex string from parameter
CTransaction origTx;
- if (!DecodeHexTx(origTx, params[0].get_str()))
+ if (!DecodeHexTx(origTx, params[0].get_str(), true))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
if (origTx.vout.size() == 0)
@@ -2491,6 +2570,7 @@ static const CRPCCommand commands[] =
{ "hidden", "resendwallettransactions", &resendwallettransactions, true },
{ "wallet", "abandontransaction", &abandontransaction, false },
{ "wallet", "addmultisigaddress", &addmultisigaddress, true },
+ { "wallet", "addwitnessaddress", &addwitnessaddress, true },
{ "wallet", "backupwallet", &backupwallet, true },
{ "wallet", "dumpprivkey", &dumpprivkey, true },
{ "wallet", "dumpwallet", &dumpwallet, true },
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index ba5f92a987..87b85eeb72 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -2334,33 +2334,37 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
{
bool signSuccess;
const CScript& scriptPubKey = coin.first->vout[coin.second].scriptPubKey;
- CScript& scriptSigRes = txNew.vin[nIn].scriptSig;
+ SignatureData sigdata;
if (sign)
- signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, SIGHASH_ALL), scriptPubKey, scriptSigRes);
+ signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, coin.first->vout[coin.second].nValue, SIGHASH_ALL), scriptPubKey, sigdata);
else
- signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, scriptSigRes);
+ signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata);
if (!signSuccess)
{
strFailReason = _("Signing transaction failed");
return false;
+ } else {
+ UpdateTransaction(txNew, nIn, sigdata);
}
+
nIn++;
}
- unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
+ unsigned int nBytes = GetVirtualTransactionSize(txNew);
// Remove scriptSigs if we used dummy signatures for fee calculation
if (!sign) {
BOOST_FOREACH (CTxIn& vin, txNew.vin)
vin.scriptSig = CScript();
+ txNew.wit.SetNull();
}
// Embed the constructed transaction data in wtxNew.
*static_cast<CTransaction*>(&wtxNew) = CTransaction(txNew);
// Limit size
- if (nBytes >= MAX_STANDARD_TX_SIZE)
+ if (GetTransactionCost(txNew) >= MAX_STANDARD_TX_COST)
{
strFailReason = _("Transaction too large");
return false;
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 71b0ff26db..d083722dd2 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -7,6 +7,7 @@
#define BITCOIN_WALLET_WALLETDB_H
#include "amount.h"
+#include "primitives/transaction.h"
#include "wallet/db.h"
#include "key.h"