diff options
Diffstat (limited to 'test')
30 files changed, 279 insertions, 442 deletions
diff --git a/test/functional/README.md b/test/functional/README.md index 96fe0becce..44efda33d3 100644 --- a/test/functional/README.md +++ b/test/functional/README.md @@ -90,7 +90,7 @@ on nodes 2 and up. - Implement a (generator) function called `get_tests()` which yields `TestInstance`s. Each `TestInstance` consists of: - - a list of `[object, outcome, hash]` entries + - A list of `[object, outcome, hash]` entries * `object` is a `CBlock`, `CTransaction`, or `CBlockHeader`. `CBlock`'s and `CTransaction`'s are tested for acceptance. `CBlockHeader`s can be used so that the test runner can deliver diff --git a/test/functional/bip65-cltv-p2p.py b/test/functional/bip65-cltv-p2p.py index bb83042f35..7e5e4cf682 100755 --- a/test/functional/bip65-cltv-p2p.py +++ b/test/functional/bip65-cltv-p2p.py @@ -4,173 +4,162 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test BIP65 (CHECKLOCKTIMEVERIFY). -Connect to a single node. -Mine 2 (version 3) blocks (save the coinbases for later). -Generate 98 more version 3 blocks, verify the node accepts. -Mine 749 version 4 blocks, verify the node accepts. -Check that the new CLTV rules are not enforced on the 750th version 4 block. -Check that the new CLTV rules are enforced on the 751st version 4 block. -Mine 199 new version blocks. -Mine 1 old-version block. -Mine 1 new version block. -Mine 1 old version block, see that the node rejects. +Test that the CHECKLOCKTIMEVERIFY soft-fork activates at (regtest) block height +1351. """ -from test_framework.test_framework import ComparisonTestFramework +from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -from test_framework.mininode import CTransaction, NetworkThread +from test_framework.mininode import * from test_framework.blocktools import create_coinbase, create_block -from test_framework.comptool import TestInstance, TestManager -from test_framework.script import CScript, OP_1NEGATE, OP_CHECKLOCKTIMEVERIFY, OP_DROP +from test_framework.script import CScript, OP_1NEGATE, OP_CHECKLOCKTIMEVERIFY, OP_DROP, CScriptNum from io import BytesIO -import time + +CLTV_HEIGHT = 1351 + +# Reject codes that we might receive in this test +REJECT_INVALID = 16 +REJECT_OBSOLETE = 17 +REJECT_NONSTANDARD = 64 def cltv_invalidate(tx): '''Modify the signature in vin 0 of the tx to fail CLTV Prepends -1 CLTV DROP in the scriptSig itself. + + TODO: test more ways that transactions using CLTV could be invalid (eg + locktime requirements fail, sequence time requirements fail, etc). ''' tx.vin[0].scriptSig = CScript([OP_1NEGATE, OP_CHECKLOCKTIMEVERIFY, OP_DROP] + list(CScript(tx.vin[0].scriptSig))) - -class BIP65Test(ComparisonTestFramework): +def cltv_validate(node, tx, height): + '''Modify the signature in vin 0 of the tx to pass CLTV + Prepends <height> CLTV DROP in the scriptSig, and sets + the locktime to height''' + tx.vin[0].nSequence = 0 + tx.nLockTime = height + + # Need to re-sign, since nSequence and nLockTime changed + signed_result = node.signrawtransaction(ToHex(tx)) + new_tx = CTransaction() + new_tx.deserialize(BytesIO(hex_str_to_bytes(signed_result['hex']))) + + new_tx.vin[0].scriptSig = CScript([CScriptNum(height), OP_CHECKLOCKTIMEVERIFY, OP_DROP] + + list(CScript(new_tx.vin[0].scriptSig))) + return new_tx + +def create_transaction(node, coinbase, to_address, amount): + from_txid = node.getblock(coinbase)['tx'][0] + inputs = [{ "txid" : from_txid, "vout" : 0}] + outputs = { to_address : amount } + rawtx = node.createrawtransaction(inputs, outputs) + signresult = node.signrawtransaction(rawtx) + tx = CTransaction() + tx.deserialize(BytesIO(hex_str_to_bytes(signresult['hex']))) + return tx + +class BIP65Test(BitcoinTestFramework): def __init__(self): super().__init__() self.num_nodes = 1 - self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=3']] + self.extra_args = [['-promiscuousmempoolflags=1', '-whitelist=127.0.0.1']] + self.setup_clean_chain = True def run_test(self): - test = TestManager(self, self.options.tmpdir) - test.add_all_connections(self.nodes) + node0 = NodeConnCB() + connections = [] + connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node0)) + node0.add_connection(connections[0]) + NetworkThread().start() # Start up network handling in another thread - test.run() - - def create_transaction(self, node, coinbase, to_address, amount): - from_txid = node.getblock(coinbase)['tx'][0] - inputs = [{ "txid" : from_txid, "vout" : 0}] - outputs = { to_address : amount } - rawtx = node.createrawtransaction(inputs, outputs) - signresult = node.signrawtransaction(rawtx) - tx = CTransaction() - f = BytesIO(hex_str_to_bytes(signresult['hex'])) - tx.deserialize(f) - return tx - - def get_tests(self): - - self.coinbase_blocks = self.nodes[0].generate(2) - height = 3 # height of the next block to build - self.tip = int("0x" + self.nodes[0].getbestblockhash(), 0) + + # wait_for_verack ensures that the P2P connection is fully up. + node0.wait_for_verack() + + self.log.info("Mining %d blocks", CLTV_HEIGHT - 2) + self.coinbase_blocks = self.nodes[0].generate(CLTV_HEIGHT - 2) self.nodeaddress = self.nodes[0].getnewaddress() - self.last_block_time = int(time.time()) - - ''' 398 more version 3 blocks ''' - test_blocks = [] - for i in range(398): - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) - block.nVersion = 3 - block.rehash() - block.solve() - test_blocks.append([block, True]) - self.last_block_time += 1 - self.tip = block.sha256 - height += 1 - yield TestInstance(test_blocks, sync_every_block=False) - - ''' Mine 749 version 4 blocks ''' - test_blocks = [] - for i in range(749): - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) - block.nVersion = 4 - block.rehash() - block.solve() - test_blocks.append([block, True]) - self.last_block_time += 1 - self.tip = block.sha256 - height += 1 - yield TestInstance(test_blocks, sync_every_block=False) - - ''' - Check that the new CLTV rules are not enforced in the 750th - version 3 block. - ''' - spendtx = self.create_transaction(self.nodes[0], - self.coinbase_blocks[0], self.nodeaddress, 1.0) + + self.log.info("Test that an invalid-according-to-CLTV transaction can still appear in a block") + + spendtx = create_transaction(self.nodes[0], self.coinbase_blocks[0], + self.nodeaddress, 1.0) cltv_invalidate(spendtx) spendtx.rehash() - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) - block.nVersion = 4 + tip = self.nodes[0].getbestblockhash() + block_time = self.nodes[0].getblockheader(tip)['mediantime'] + 1 + block = create_block(int(tip, 16), create_coinbase(CLTV_HEIGHT - 1), block_time) + block.nVersion = 3 block.vtx.append(spendtx) block.hashMerkleRoot = block.calc_merkle_root() - block.rehash() block.solve() - self.last_block_time += 1 - self.tip = block.sha256 - height += 1 - yield TestInstance([[block, True]]) - - ''' Mine 199 new version blocks on last valid tip ''' - test_blocks = [] - for i in range(199): - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) - block.nVersion = 4 - block.rehash() - block.solve() - test_blocks.append([block, True]) - self.last_block_time += 1 - self.tip = block.sha256 - height += 1 - yield TestInstance(test_blocks, sync_every_block=False) - - ''' Mine 1 old version block ''' - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) + node0.send_and_ping(msg_block(block)) + assert_equal(self.nodes[0].getbestblockhash(), block.hash) + + self.log.info("Test that blocks must now be at least version 4") + tip = block.sha256 + block_time += 1 + block = create_block(tip, create_coinbase(CLTV_HEIGHT), block_time) block.nVersion = 3 - block.rehash() block.solve() - self.last_block_time += 1 - self.tip = block.sha256 - height += 1 - yield TestInstance([[block, True]]) + node0.send_and_ping(msg_block(block)) + assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip) - ''' Mine 1 new version block ''' - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) + assert wait_until(lambda: "reject" in node0.last_message.keys()) + with mininode_lock: + assert_equal(node0.last_message["reject"].code, REJECT_OBSOLETE) + assert_equal(node0.last_message["reject"].reason, b'bad-version(0x00000003)') + assert_equal(node0.last_message["reject"].data, block.sha256) + del node0.last_message["reject"] + + self.log.info("Test that invalid-according-to-cltv transactions cannot appear in a block") block.nVersion = 4 - block.rehash() - block.solve() - self.last_block_time += 1 - self.tip = block.sha256 - height += 1 - yield TestInstance([[block, True]]) - - ''' - Check that the new CLTV rules are enforced in the 951st version 4 - block. - ''' - spendtx = self.create_transaction(self.nodes[0], - self.coinbase_blocks[1], self.nodeaddress, 1.0) + + spendtx = create_transaction(self.nodes[0], self.coinbase_blocks[1], + self.nodeaddress, 1.0) cltv_invalidate(spendtx) spendtx.rehash() - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) - block.nVersion = 4 + # First we show that this tx is valid except for CLTV by getting it + # accepted to the mempool (which we can achieve with + # -promiscuousmempoolflags). + node0.send_and_ping(msg_tx(spendtx)) + assert spendtx.hash in self.nodes[0].getrawmempool() + + # Now we verify that a block with this transaction is invalid. block.vtx.append(spendtx) block.hashMerkleRoot = block.calc_merkle_root() - block.rehash() block.solve() - self.last_block_time += 1 - yield TestInstance([[block, False]]) - ''' Mine 1 old version block, should be invalid ''' - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) - block.nVersion = 3 - block.rehash() + node0.send_and_ping(msg_block(block)) + assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip) + + assert wait_until (lambda: "reject" in node0.last_message.keys()) + with mininode_lock: + assert node0.last_message["reject"].code in [REJECT_INVALID, REJECT_NONSTANDARD] + assert_equal(node0.last_message["reject"].data, block.sha256) + if node0.last_message["reject"].code == REJECT_INVALID: + # Generic rejection when a block is invalid + assert_equal(node0.last_message["reject"].reason, b'block-validation-failed') + else: + assert b'Negative locktime' in node0.last_message["reject"].reason + + self.log.info("Test that a version 4 block with a valid-according-to-CLTV transaction is accepted") + spendtx = cltv_validate(self.nodes[0], spendtx, CLTV_HEIGHT - 1) + spendtx.rehash() + + block.vtx.pop(1) + block.vtx.append(spendtx) + block.hashMerkleRoot = block.calc_merkle_root() block.solve() - self.last_block_time += 1 - yield TestInstance([[block, False]]) + + node0.send_and_ping(msg_block(block)) + assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) + if __name__ == '__main__': BIP65Test().main() diff --git a/test/functional/bip65-cltv.py b/test/functional/bip65-cltv.py deleted file mode 100755 index ddf932c746..0000000000 --- a/test/functional/bip65-cltv.py +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2015-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 CHECKLOCKTIMEVERIFY (BIP65) soft-fork logic.""" - -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * - -class BIP65Test(BitcoinTestFramework): - def __init__(self): - super().__init__() - self.num_nodes = 3 - self.setup_clean_chain = False - self.extra_args = [[], ["-blockversion=3"], ["-blockversion=4"]] - - def setup_network(self): - self.setup_nodes() - connect_nodes(self.nodes[1], 0) - connect_nodes(self.nodes[2], 0) - self.sync_all() - - def run_test(self): - cnt = self.nodes[0].getblockcount() - - # Mine some old-version blocks - self.nodes[1].generate(200) - cnt += 100 - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 100): - raise AssertionError("Failed to mine 100 version=3 blocks") - - # Mine 750 new-version blocks - for i in range(15): - self.nodes[2].generate(50) - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 850): - raise AssertionError("Failed to mine 750 version=4 blocks") - - # TODO: check that new CHECKLOCKTIMEVERIFY rules are not enforced - - # Mine 1 new-version block - self.nodes[2].generate(1) - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 851): - raise AssertionError("Failed to mine a version=4 blocks") - - # TODO: check that new CHECKLOCKTIMEVERIFY rules are enforced - - # Mine 198 new-version blocks - for i in range(2): - self.nodes[2].generate(99) - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 1049): - raise AssertionError("Failed to mine 198 version=4 blocks") - - # Mine 1 old-version block - self.nodes[1].generate(1) - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 1050): - raise AssertionError("Failed to mine a version=3 block after 949 version=4 blocks") - - # Mine 1 new-version blocks - self.nodes[2].generate(1) - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 1051): - raise AssertionError("Failed to mine a version=4 block") - - # Mine 1 old-version blocks. This should fail - assert_raises_jsonrpc(-1,"CreateNewBlock: TestBlockValidity failed: bad-version(0x00000003)", self.nodes[1].generate, 1) - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 1051): - raise AssertionError("Accepted a version=3 block after 950 version=4 blocks") - - # Mine 1 new-version blocks - self.nodes[2].generate(1) - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 1052): - raise AssertionError("Failed to mine a version=4 block") - -if __name__ == '__main__': - BIP65Test().main() diff --git a/test/functional/bipdersig-p2p.py b/test/functional/bipdersig-p2p.py index 31c7ebba90..38a9009544 100755 --- a/test/functional/bipdersig-p2p.py +++ b/test/functional/bipdersig-p2p.py @@ -4,28 +4,24 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test BIP66 (DER SIG). -Connect to a single node. -Mine 2 (version 2) blocks (save the coinbases for later). -Generate 98 more version 2 blocks, verify the node accepts. -Mine 749 version 3 blocks, verify the node accepts. -Check that the new DERSIG rules are not enforced on the 750th version 3 block. -Check that the new DERSIG rules are enforced on the 751st version 3 block. -Mine 199 new version blocks. -Mine 1 old-version block. -Mine 1 new version block. -Mine 1 old version block, see that the node rejects. +Test that the DERSIG soft-fork activates at (regtest) height 1251. """ -from test_framework.test_framework import ComparisonTestFramework +from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -from test_framework.mininode import CTransaction, NetworkThread +from test_framework.mininode import * from test_framework.blocktools import create_coinbase, create_block -from test_framework.comptool import TestInstance, TestManager from test_framework.script import CScript from io import BytesIO -import time -# A canonical signature consists of: +DERSIG_HEIGHT = 1251 + +# Reject codes that we might receive in this test +REJECT_INVALID = 16 +REJECT_OBSOLETE = 17 +REJECT_NONSTANDARD = 64 + +# A canonical signature consists of: # <30> <total len> <02> <len R> <R> <02> <len S> <S> <hashtype> def unDERify(tx): """ @@ -40,143 +36,122 @@ def unDERify(tx): else: newscript.append(i) tx.vin[0].scriptSig = CScript(newscript) - -class BIP66Test(ComparisonTestFramework): + +def create_transaction(node, coinbase, to_address, amount): + from_txid = node.getblock(coinbase)['tx'][0] + inputs = [{ "txid" : from_txid, "vout" : 0}] + outputs = { to_address : amount } + rawtx = node.createrawtransaction(inputs, outputs) + signresult = node.signrawtransaction(rawtx) + tx = CTransaction() + tx.deserialize(BytesIO(hex_str_to_bytes(signresult['hex']))) + return tx + +class BIP66Test(BitcoinTestFramework): def __init__(self): super().__init__() self.num_nodes = 1 + self.extra_args = [['-promiscuousmempoolflags=1', '-whitelist=127.0.0.1']] + self.setup_clean_chain = True def run_test(self): - test = TestManager(self, self.options.tmpdir) - test.add_all_connections(self.nodes) + node0 = NodeConnCB() + connections = [] + connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node0)) + node0.add_connection(connections[0]) NetworkThread().start() # Start up network handling in another thread - test.run() - - def create_transaction(self, node, coinbase, to_address, amount): - from_txid = node.getblock(coinbase)['tx'][0] - inputs = [{ "txid" : from_txid, "vout" : 0}] - outputs = { to_address : amount } - rawtx = node.createrawtransaction(inputs, outputs) - signresult = node.signrawtransaction(rawtx) - tx = CTransaction() - f = BytesIO(hex_str_to_bytes(signresult['hex'])) - tx.deserialize(f) - return tx - - def get_tests(self): - - self.coinbase_blocks = self.nodes[0].generate(2) - height = 3 # height of the next block to build - self.tip = int("0x" + self.nodes[0].getbestblockhash(), 0) + + # wait_for_verack ensures that the P2P connection is fully up. + node0.wait_for_verack() + + self.log.info("Mining %d blocks", DERSIG_HEIGHT - 2) + self.coinbase_blocks = self.nodes[0].generate(DERSIG_HEIGHT - 2) self.nodeaddress = self.nodes[0].getnewaddress() - self.last_block_time = int(time.time()) - - ''' 298 more version 2 blocks ''' - test_blocks = [] - for i in range(298): - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) - block.nVersion = 2 - block.rehash() - block.solve() - test_blocks.append([block, True]) - self.last_block_time += 1 - self.tip = block.sha256 - height += 1 - yield TestInstance(test_blocks, sync_every_block=False) - - ''' Mine 749 version 3 blocks ''' - test_blocks = [] - for i in range(749): - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) - block.nVersion = 3 - block.rehash() - block.solve() - test_blocks.append([block, True]) - self.last_block_time += 1 - self.tip = block.sha256 - height += 1 - yield TestInstance(test_blocks, sync_every_block=False) - - ''' - Check that the new DERSIG rules are not enforced in the 750th - version 3 block. - ''' - spendtx = self.create_transaction(self.nodes[0], - self.coinbase_blocks[0], self.nodeaddress, 1.0) + + self.log.info("Test that a transaction with non-DER signature can still appear in a block") + + spendtx = create_transaction(self.nodes[0], self.coinbase_blocks[0], + self.nodeaddress, 1.0) unDERify(spendtx) spendtx.rehash() - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) - block.nVersion = 3 + tip = self.nodes[0].getbestblockhash() + block_time = self.nodes[0].getblockheader(tip)['mediantime'] + 1 + block = create_block(int(tip, 16), create_coinbase(DERSIG_HEIGHT - 1), block_time) + block.nVersion = 2 block.vtx.append(spendtx) block.hashMerkleRoot = block.calc_merkle_root() block.rehash() block.solve() - self.last_block_time += 1 - self.tip = block.sha256 - height += 1 - yield TestInstance([[block, True]]) - - ''' Mine 199 new version blocks on last valid tip ''' - test_blocks = [] - for i in range(199): - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) - block.nVersion = 3 - block.rehash() - block.solve() - test_blocks.append([block, True]) - self.last_block_time += 1 - self.tip = block.sha256 - height += 1 - yield TestInstance(test_blocks, sync_every_block=False) - - ''' Mine 1 old version block ''' - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) + node0.send_and_ping(msg_block(block)) + assert_equal(self.nodes[0].getbestblockhash(), block.hash) + + self.log.info("Test that blocks must now be at least version 3") + tip = block.sha256 + block_time += 1 + block = create_block(tip, create_coinbase(DERSIG_HEIGHT), block_time) block.nVersion = 2 block.rehash() block.solve() - self.last_block_time += 1 - self.tip = block.sha256 - height += 1 - yield TestInstance([[block, True]]) + node0.send_and_ping(msg_block(block)) + assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip) - ''' Mine 1 new version block ''' - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) + assert wait_until(lambda: "reject" in node0.last_message.keys()) + with mininode_lock: + assert_equal(node0.last_message["reject"].code, REJECT_OBSOLETE) + assert_equal(node0.last_message["reject"].reason, b'bad-version(0x00000002)') + assert_equal(node0.last_message["reject"].data, block.sha256) + del node0.last_message["reject"] + + self.log.info("Test that transactions with non-DER signatures cannot appear in a block") block.nVersion = 3 - block.rehash() - block.solve() - self.last_block_time += 1 - self.tip = block.sha256 - height += 1 - yield TestInstance([[block, True]]) - - ''' - Check that the new DERSIG rules are enforced in the 951st version 3 - block. - ''' - spendtx = self.create_transaction(self.nodes[0], - self.coinbase_blocks[1], self.nodeaddress, 1.0) + + spendtx = create_transaction(self.nodes[0], self.coinbase_blocks[1], + self.nodeaddress, 1.0) unDERify(spendtx) spendtx.rehash() - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) - block.nVersion = 3 + # First we show that this tx is valid except for DERSIG by getting it + # accepted to the mempool (which we can achieve with + # -promiscuousmempoolflags). + node0.send_and_ping(msg_tx(spendtx)) + assert spendtx.hash in self.nodes[0].getrawmempool() + + # Now we verify that a block with this transaction is invalid. block.vtx.append(spendtx) block.hashMerkleRoot = block.calc_merkle_root() block.rehash() block.solve() - self.last_block_time += 1 - yield TestInstance([[block, False]]) - ''' Mine 1 old version block, should be invalid ''' - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) - block.nVersion = 2 + node0.send_and_ping(msg_block(block)) + assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip) + + assert wait_until (lambda: "reject" in node0.last_message.keys()) + with mininode_lock: + # We can receive different reject messages depending on whether + # bitcoind is running with multiple script check threads. If script + # check threads are not in use, then transaction script validation + # happens sequentially, and bitcoind produces more specific reject + # reasons. + assert node0.last_message["reject"].code in [REJECT_INVALID, REJECT_NONSTANDARD] + assert_equal(node0.last_message["reject"].data, block.sha256) + if node0.last_message["reject"].code == REJECT_INVALID: + # Generic rejection when a block is invalid + assert_equal(node0.last_message["reject"].reason, b'block-validation-failed') + else: + assert b'Non-canonical DER signature' in node0.last_message["reject"].reason + + self.log.info("Test that a version 3 block with a DERSIG-compliant transaction is accepted") + block.vtx[1] = create_transaction(self.nodes[0], + self.coinbase_blocks[1], self.nodeaddress, 1.0) + block.hashMerkleRoot = block.calc_merkle_root() block.rehash() block.solve() - self.last_block_time += 1 - yield TestInstance([[block, False]]) + + node0.send_and_ping(msg_block(block)) + assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) if __name__ == '__main__': BIP66Test().main() diff --git a/test/functional/bipdersig.py b/test/functional/bipdersig.py deleted file mode 100755 index 41f88fb664..0000000000 --- a/test/functional/bipdersig.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -"""Test the BIP66 changeover logic.""" - -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * - -class BIP66Test(BitcoinTestFramework): - def __init__(self): - super().__init__() - self.num_nodes = 3 - self.setup_clean_chain = False - self.extra_args = [[], ["-blockversion=2"], ["-blockversion=3"]] - - def setup_network(self): - self.setup_nodes() - connect_nodes(self.nodes[1], 0) - connect_nodes(self.nodes[2], 0) - self.sync_all() - - def run_test(self): - cnt = self.nodes[0].getblockcount() - - # Mine some old-version blocks - self.nodes[1].generate(100) - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 100): - raise AssertionError("Failed to mine 100 version=2 blocks") - - # Mine 750 new-version blocks - for i in range(15): - self.nodes[2].generate(50) - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 850): - raise AssertionError("Failed to mine 750 version=3 blocks") - - # TODO: check that new DERSIG rules are not enforced - - # Mine 1 new-version block - self.nodes[2].generate(1) - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 851): - raise AssertionError("Failed to mine a version=3 blocks") - - # TODO: check that new DERSIG rules are enforced - - # Mine 198 new-version blocks - for i in range(2): - self.nodes[2].generate(99) - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 1049): - raise AssertionError("Failed to mine 198 version=3 blocks") - - # Mine 1 old-version block - self.nodes[1].generate(1) - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 1050): - raise AssertionError("Failed to mine a version=2 block after 949 version=3 blocks") - - # Mine 1 new-version blocks - self.nodes[2].generate(1) - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 1051): - raise AssertionError("Failed to mine a version=3 block") - - # Mine 1 old-version blocks. This should fail - assert_raises_jsonrpc(-1, "CreateNewBlock: TestBlockValidity failed: bad-version(0x00000002)", self.nodes[1].generate, 1) - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 1051): - raise AssertionError("Accepted a version=2 block after 950 version=3 blocks") - - # Mine 1 new-version blocks - self.nodes[2].generate(1) - self.sync_all() - if (self.nodes[0].getblockcount() != cnt + 1052): - raise AssertionError("Failed to mine a version=3 block") - -if __name__ == '__main__': - BIP66Test().main() diff --git a/test/functional/example_test.py b/test/functional/example_test.py index 1ba5f756cd..7709524f23 100755 --- a/test/functional/example_test.py +++ b/test/functional/example_test.py @@ -58,6 +58,10 @@ class BaseNode(NodeConnCB): message.block.calc_sha256() self.block_receive_map[message.block.sha256] += 1 + def on_inv(self, conn, message): + """Override the standard on_inv callback""" + pass + def custom_function(): """Do some custom behaviour @@ -198,10 +202,10 @@ class ExampleTest(BitcoinTestFramework): self.log.info("Wait for node2 reach current tip. Test that it has propogated all the blocks to us") + getdata_request = msg_getdata() for block in blocks: - getdata_request = msg_getdata() getdata_request.inv.append(CInv(2, block)) - node2.send_message(getdata_request) + node2.send_message(getdata_request) # wait_until() will loop until a predicate condition is met. Use it to test properties of the # NodeConnCB objects. diff --git a/test/functional/p2p-leaktests.py b/test/functional/p2p-leaktests.py index 33b57ef33d..5611c876ae 100755 --- a/test/functional/p2p-leaktests.py +++ b/test/functional/p2p-leaktests.py @@ -9,7 +9,10 @@ received a VERACK. This test connects to a node and sends it a few messages, trying to intice it into sending us something it shouldn't. -""" + +Also test that nodes that send unsupported service bits to bitcoind are disconnected +and don't receive a VERACK. Unsupported service bits are currently 1 << 5 and +1 << 7 (until August 1st 2018).""" from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework @@ -98,20 +101,29 @@ class P2PLeakTest(BitcoinTestFramework): no_version_bannode = CNodeNoVersionBan() no_version_idlenode = CNodeNoVersionIdle() no_verack_idlenode = CNodeNoVerackIdle() + unsupported_service_bit5_node = CLazyNode() + unsupported_service_bit7_node = CLazyNode() + self.nodes[0].setmocktime(1501545600) # August 1st 2017 connections = [] connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], no_version_bannode, send_version=False)) connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], no_version_idlenode, send_version=False)) connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], no_verack_idlenode)) + connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], unsupported_service_bit5_node, services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_5)) + connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], unsupported_service_bit7_node, services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_7)) no_version_bannode.add_connection(connections[0]) no_version_idlenode.add_connection(connections[1]) no_verack_idlenode.add_connection(connections[2]) + unsupported_service_bit5_node.add_connection(connections[3]) + unsupported_service_bit7_node.add_connection(connections[4]) NetworkThread().start() # Start up network handling in another thread assert wait_until(lambda: no_version_bannode.ever_connected, timeout=10) assert wait_until(lambda: no_version_idlenode.ever_connected, timeout=10) assert wait_until(lambda: no_verack_idlenode.version_received, timeout=10) + assert wait_until(lambda: unsupported_service_bit5_node.ever_connected, timeout=10) + assert wait_until(lambda: unsupported_service_bit7_node.ever_connected, timeout=10) # Mine a block and make sure that it's not sent to the connected nodes self.nodes[0].generate(1) @@ -122,12 +134,32 @@ class P2PLeakTest(BitcoinTestFramework): #This node should have been banned assert not no_version_bannode.connected + # These nodes should have been disconnected + assert not unsupported_service_bit5_node.connected + assert not unsupported_service_bit7_node.connected + [conn.disconnect_node() for conn in connections] # Make sure no unexpected messages came in assert(no_version_bannode.unexpected_msg == False) assert(no_version_idlenode.unexpected_msg == False) assert(no_verack_idlenode.unexpected_msg == False) + assert not unsupported_service_bit5_node.unexpected_msg + assert not unsupported_service_bit7_node.unexpected_msg + + self.log.info("Service bits 5 and 7 are allowed after August 1st 2018") + self.nodes[0].setmocktime(1533168000) # August 2nd 2018 + + allowed_service_bit5_node = NodeConnCB() + allowed_service_bit7_node = NodeConnCB() + + connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], allowed_service_bit5_node, services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_5)) + connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], allowed_service_bit7_node, services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_7)) + allowed_service_bit5_node.add_connection(connections[5]) + allowed_service_bit7_node.add_connection(connections[6]) + + assert wait_until(lambda: allowed_service_bit5_node.message_count["verack"], timeout=10) + assert wait_until(lambda: allowed_service_bit7_node.message_count["verack"], timeout=10) if __name__ == '__main__': P2PLeakTest().main() diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py index 688347a68f..a4d85501e7 100755 --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -51,6 +51,8 @@ NODE_NETWORK = (1 << 0) NODE_GETUTXO = (1 << 1) NODE_BLOOM = (1 << 2) NODE_WITNESS = (1 << 3) +NODE_UNSUPPORTED_SERVICE_BIT_5 = (1 << 5) +NODE_UNSUPPORTED_SERVICE_BIT_7 = (1 << 7) logger = logging.getLogger("TestFramework.mininode") diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index a043560ea8..dfd3b89895 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -115,6 +115,8 @@ BASE_SCRIPTS= [ 'listsinceblock.py', 'p2p-leaktests.py', 'wallet-encryption.py', + 'bipdersig-p2p.py', + 'bip65-cltv-p2p.py', 'uptime.py', ] @@ -138,10 +140,6 @@ EXTENDED_SCRIPTS = [ 'rpcbind_test.py', # vv Tests less than 30s vv 'assumevalid.py', - 'bip65-cltv.py', - 'bip65-cltv-p2p.py', - 'bipdersig-p2p.py', - 'bipdersig.py', 'example_test.py', 'txn_doublespend.py', 'txn_clone.py --mineblock', diff --git a/test/util/data/tt-delin1-out.json b/test/util/data/tt-delin1-out.json index f6dfbb51cc..0b3235dd4a 100644 --- a/test/util/data/tt-delin1-out.json +++ b/test/util/data/tt-delin1-out.json @@ -189,7 +189,7 @@ ], "vout": [ { - "value": 1.3782, + "value": 1.37820000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", diff --git a/test/util/data/tt-delout1-out.json b/test/util/data/tt-delout1-out.json index 6769ed79ff..5b69d0cd86 100644 --- a/test/util/data/tt-delout1-out.json +++ b/test/util/data/tt-delout1-out.json @@ -198,7 +198,7 @@ ], "vout": [ { - "value": 1.3782, + "value": 1.37820000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", diff --git a/test/util/data/tt-locktime317000-out.json b/test/util/data/tt-locktime317000-out.json index 82b64df075..cf1ebcdf38 100644 --- a/test/util/data/tt-locktime317000-out.json +++ b/test/util/data/tt-locktime317000-out.json @@ -198,7 +198,7 @@ ], "vout": [ { - "value": 1.3782, + "value": 1.37820000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", diff --git a/test/util/data/txcreate1.json b/test/util/data/txcreate1.json index 36741044c9..edb091f946 100644 --- a/test/util/data/txcreate1.json +++ b/test/util/data/txcreate1.json @@ -36,7 +36,7 @@ ], "vout": [ { - "value": 0.18, + "value": 0.18000000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", @@ -49,7 +49,7 @@ } }, { - "value": 4.00, + "value": 4.00000000, "n": 1, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 f2d4db28cad6502226ee484ae24505c2885cb12d OP_EQUALVERIFY OP_CHECKSIG", diff --git a/test/util/data/txcreate2.json b/test/util/data/txcreate2.json index 23fe7ace67..cca00f752b 100644 --- a/test/util/data/txcreate2.json +++ b/test/util/data/txcreate2.json @@ -9,7 +9,7 @@ ], "vout": [ { - "value": 0.00, + "value": 0.00000000, "n": 0, "scriptPubKey": { "asm": "", diff --git a/test/util/data/txcreatedata1.json b/test/util/data/txcreatedata1.json index e65a1859eb..e66a6bb9a5 100644 --- a/test/util/data/txcreatedata1.json +++ b/test/util/data/txcreatedata1.json @@ -18,7 +18,7 @@ ], "vout": [ { - "value": 0.18, + "value": 0.18000000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", @@ -31,7 +31,7 @@ } }, { - "value": 4.00, + "value": 4.00000000, "n": 1, "scriptPubKey": { "asm": "OP_RETURN 54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", diff --git a/test/util/data/txcreatedata2.json b/test/util/data/txcreatedata2.json index 8f1544e1c0..0f8edcafdd 100644 --- a/test/util/data/txcreatedata2.json +++ b/test/util/data/txcreatedata2.json @@ -18,7 +18,7 @@ ], "vout": [ { - "value": 0.18, + "value": 0.18000000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", @@ -31,7 +31,7 @@ } }, { - "value": 0.00, + "value": 0.00000000, "n": 1, "scriptPubKey": { "asm": "OP_RETURN 54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", diff --git a/test/util/data/txcreatedata_seq0.json b/test/util/data/txcreatedata_seq0.json index e52401f418..4b5a7cab4a 100644 --- a/test/util/data/txcreatedata_seq0.json +++ b/test/util/data/txcreatedata_seq0.json @@ -18,7 +18,7 @@ ], "vout": [ { - "value": 0.18, + "value": 0.18000000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", diff --git a/test/util/data/txcreatedata_seq1.json b/test/util/data/txcreatedata_seq1.json index 093ff4a56b..771ff1bb10 100644 --- a/test/util/data/txcreatedata_seq1.json +++ b/test/util/data/txcreatedata_seq1.json @@ -27,7 +27,7 @@ ], "vout": [ { - "value": 0.18, + "value": 0.18000000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", diff --git a/test/util/data/txcreatemultisig1.json b/test/util/data/txcreatemultisig1.json index 0cc530836a..7c814dad83 100644 --- a/test/util/data/txcreatemultisig1.json +++ b/test/util/data/txcreatemultisig1.json @@ -9,7 +9,7 @@ ], "vout": [ { - "value": 1.00, + "value": 1.00000000, "n": 0, "scriptPubKey": { "asm": "2 02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397 021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d 02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485 3 OP_CHECKMULTISIG", diff --git a/test/util/data/txcreatemultisig2.json b/test/util/data/txcreatemultisig2.json index 8ad2ffdc65..7d94ce7396 100644 --- a/test/util/data/txcreatemultisig2.json +++ b/test/util/data/txcreatemultisig2.json @@ -9,7 +9,7 @@ ], "vout": [ { - "value": 1.00, + "value": 1.00000000, "n": 0, "scriptPubKey": { "asm": "OP_HASH160 1c6fbaf46d64221e80cbae182c33ddf81b9294ac OP_EQUAL", diff --git a/test/util/data/txcreatemultisig3.json b/test/util/data/txcreatemultisig3.json index 086bf44b8a..06e093e224 100644 --- a/test/util/data/txcreatemultisig3.json +++ b/test/util/data/txcreatemultisig3.json @@ -9,7 +9,7 @@ ], "vout": [ { - "value": 1.00, + "value": 1.00000000, "n": 0, "scriptPubKey": { "asm": "0 e15a86a23178f433d514dbbce042e87d72662b8b5edcacfd2e37ab7a2d135f05", diff --git a/test/util/data/txcreatemultisig4.json b/test/util/data/txcreatemultisig4.json index d23ccc045e..9a5d2f4a06 100644 --- a/test/util/data/txcreatemultisig4.json +++ b/test/util/data/txcreatemultisig4.json @@ -9,7 +9,7 @@ ], "vout": [ { - "value": 1.00, + "value": 1.00000000, "n": 0, "scriptPubKey": { "asm": "OP_HASH160 6edf12858999f0dae74f9c692e6694ee3621b2ac OP_EQUAL", diff --git a/test/util/data/txcreateoutpubkey1.json b/test/util/data/txcreateoutpubkey1.json index f10aaecf7a..2704ed7673 100644 --- a/test/util/data/txcreateoutpubkey1.json +++ b/test/util/data/txcreateoutpubkey1.json @@ -9,7 +9,7 @@ ], "vout": [ { - "value": 0.00, + "value": 0.00000000, "n": 0, "scriptPubKey": { "asm": "02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397 OP_CHECKSIG", diff --git a/test/util/data/txcreateoutpubkey2.json b/test/util/data/txcreateoutpubkey2.json index 5a473b76c3..5144722230 100644 --- a/test/util/data/txcreateoutpubkey2.json +++ b/test/util/data/txcreateoutpubkey2.json @@ -9,7 +9,7 @@ ], "vout": [ { - "value": 0.00, + "value": 0.00000000, "n": 0, "scriptPubKey": { "asm": "0 a2516e770582864a6a56ed21a102044e388c62e3", diff --git a/test/util/data/txcreateoutpubkey3.json b/test/util/data/txcreateoutpubkey3.json index b8389b8f7e..0a5d489e15 100644 --- a/test/util/data/txcreateoutpubkey3.json +++ b/test/util/data/txcreateoutpubkey3.json @@ -9,7 +9,7 @@ ], "vout": [ { - "value": 0.00, + "value": 0.00000000, "n": 0, "scriptPubKey": { "asm": "OP_HASH160 a5ab14c9804d0d8bf02f1aea4e82780733ad0a83 OP_EQUAL", diff --git a/test/util/data/txcreatescript1.json b/test/util/data/txcreatescript1.json index 823168e9fb..5072452fed 100644 --- a/test/util/data/txcreatescript1.json +++ b/test/util/data/txcreatescript1.json @@ -9,7 +9,7 @@ ], "vout": [ { - "value": 0.00, + "value": 0.00000000, "n": 0, "scriptPubKey": { "asm": "OP_DROP", diff --git a/test/util/data/txcreatescript2.json b/test/util/data/txcreatescript2.json index d4c7e10c78..94b669ffb6 100644 --- a/test/util/data/txcreatescript2.json +++ b/test/util/data/txcreatescript2.json @@ -9,7 +9,7 @@ ], "vout": [ { - "value": 0.00, + "value": 0.00000000, "n": 0, "scriptPubKey": { "asm": "OP_HASH160 71ed53322d470bb96657deb786b94f97dd46fb15 OP_EQUAL", diff --git a/test/util/data/txcreatescript3.json b/test/util/data/txcreatescript3.json index 001e69511f..980da2fb31 100644 --- a/test/util/data/txcreatescript3.json +++ b/test/util/data/txcreatescript3.json @@ -9,7 +9,7 @@ ], "vout": [ { - "value": 0.00, + "value": 0.00000000, "n": 0, "scriptPubKey": { "asm": "0 0bfe935e70c321c7ca3afc75ce0d0ca2f98b5422e008bb31c00c6d7f1f1c0ad6", diff --git a/test/util/data/txcreatescript4.json b/test/util/data/txcreatescript4.json index 20094bcd44..eecdf858b7 100644 --- a/test/util/data/txcreatescript4.json +++ b/test/util/data/txcreatescript4.json @@ -9,7 +9,7 @@ ], "vout": [ { - "value": 0.00, + "value": 0.00000000, "n": 0, "scriptPubKey": { "asm": "OP_HASH160 6a2c482f4985f57e702f325816c90e3723ca81ae OP_EQUAL", diff --git a/test/util/data/txcreatesignv1.json b/test/util/data/txcreatesignv1.json index 519d3ab066..92a3f76a07 100644 --- a/test/util/data/txcreatesignv1.json +++ b/test/util/data/txcreatesignv1.json @@ -18,7 +18,7 @@ ], "vout": [ { - "value": 0.001, + "value": 0.00100000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 5834479edbbe0539b31ffd3a8f8ebadc2165ed01 OP_EQUALVERIFY OP_CHECKSIG", |