Changeset View
Changeset View
Standalone View
Standalone View
test/functional/feature_dersig.py
Show First 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | def create_transaction(node, coinbase, to_address, amount): | ||||
rawtx = node.createrawtransaction(inputs, outputs) | rawtx = node.createrawtransaction(inputs, outputs) | ||||
signresult = node.signrawtransactionwithwallet(rawtx) | signresult = node.signrawtransactionwithwallet(rawtx) | ||||
return FromHex(CTransaction(), signresult['hex']) | return FromHex(CTransaction(), signresult['hex']) | ||||
class BIP66Test(BitcoinTestFramework): | class BIP66Test(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.num_nodes = 1 | self.num_nodes = 1 | ||||
self.extra_args = [['-whitelist=127.0.0.1']] | self.extra_args = [['-whitelist=127.0.0.1', '-enablebip61']] | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
def run_test(self): | def run_test(self): | ||||
self.nodes[0].add_p2p_connection(P2PInterface()) | self.nodes[0].add_p2p_connection(P2PInterface()) | ||||
network_thread_start() | network_thread_start() | ||||
# wait_for_verack ensures that the P2P connection is fully up. | # wait_for_verack ensures that the P2P connection is fully up. | ||||
self.nodes[0].p2p.wait_for_verack() | self.nodes[0].p2p.wait_for_verack() | ||||
self.log.info("Mining {} blocks".format(DERSIG_HEIGHT - 1)) | self.log.info("Mining {} blocks".format(DERSIG_HEIGHT - 1)) | ||||
self.coinbase_blocks = self.nodes[0].generate(DERSIG_HEIGHT - 1) | self.coinbase_blocks = self.nodes[0].generate(DERSIG_HEIGHT - 1) | ||||
self.nodeaddress = self.nodes[0].getnewaddress() | self.nodeaddress = self.nodes[0].getnewaddress() | ||||
self.log.info("Test that blocks must now be at least version 3") | self.log.info("Test that blocks must now be at least version 3") | ||||
tip = self.nodes[0].getbestblockhash() | tip = self.nodes[0].getbestblockhash() | ||||
block_time = self.nodes[0].getblockheader(tip)['mediantime'] + 1 | block_time = self.nodes[0].getblockheader(tip)['mediantime'] + 1 | ||||
block = create_block( | block = create_block( | ||||
int(tip, 16), create_coinbase(DERSIG_HEIGHT), block_time) | int(tip, 16), create_coinbase(DERSIG_HEIGHT), block_time) | ||||
block.nVersion = 2 | block.nVersion = 2 | ||||
block.rehash() | block.rehash() | ||||
block.solve() | block.solve() | ||||
with self.nodes[0].assert_debug_log(expected_msgs=['{}, bad-version(0x00000002)'.format(block.hash)]): | |||||
self.nodes[0].p2p.send_and_ping(msg_block(block)) | self.nodes[0].p2p.send_and_ping(msg_block(block)) | ||||
assert_equal(self.nodes[0].getbestblockhash(), tip) | assert_equal(self.nodes[0].getbestblockhash(), tip) | ||||
self.nodes[0].p2p.sync_with_ping() | |||||
wait_until(lambda: "reject" in self.nodes[0].p2p.last_message.keys(), | |||||
lock=mininode_lock) | |||||
with mininode_lock: | |||||
assert_equal( | |||||
self.nodes[0].p2p.last_message["reject"].code, REJECT_OBSOLETE) | |||||
assert_equal( | |||||
self.nodes[0].p2p.last_message["reject"].reason, b'bad-version(0x00000002)') | |||||
assert_equal( | |||||
self.nodes[0].p2p.last_message["reject"].data, block.sha256) | |||||
del self.nodes[0].p2p.last_message["reject"] | |||||
self.log.info( | self.log.info( | ||||
"Test that transactions with non-DER signatures cannot appear in a block") | "Test that transactions with non-DER signatures cannot appear in a block") | ||||
block.nVersion = 3 | block.nVersion = 3 | ||||
spendtx = create_transaction(self.nodes[0], self.coinbase_blocks[1], | spendtx = create_transaction(self.nodes[0], self.coinbase_blocks[1], | ||||
self.nodeaddress, 1.0) | self.nodeaddress, 1.0) | ||||
unDERify(spendtx) | unDERify(spendtx) | ||||
Show All 9 Lines | def run_test(self): | ||||
) | ) | ||||
# Now we verify that a block with this transaction is also invalid. | # Now we verify that a block with this transaction is also invalid. | ||||
block.vtx.append(spendtx) | block.vtx.append(spendtx) | ||||
block.hashMerkleRoot = block.calc_merkle_root() | block.hashMerkleRoot = block.calc_merkle_root() | ||||
block.rehash() | block.rehash() | ||||
block.solve() | block.solve() | ||||
with self.nodes[0].assert_debug_log(expected_msgs=['ConnectBlock {} failed (blk-bad-inputs'.format(block.hash)]): | |||||
self.nodes[0].p2p.send_and_ping(msg_block(block)) | self.nodes[0].p2p.send_and_ping(msg_block(block)) | ||||
assert_equal(self.nodes[0].getbestblockhash(), tip) | assert_equal(self.nodes[0].getbestblockhash(), tip) | ||||
self.nodes[0].p2p.sync_with_ping() | |||||
wait_until(lambda: "reject" in self.nodes[0].p2p.last_message.keys(), | wait_until(lambda: "reject" in self.nodes[0].p2p.last_message.keys(), | ||||
lock=mininode_lock) | lock=mininode_lock) | ||||
with mininode_lock: | 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 self.nodes[0].p2p.last_message["reject"].code in [ | assert self.nodes[0].p2p.last_message["reject"].code in [ | ||||
REJECT_INVALID, REJECT_NONSTANDARD] | REJECT_INVALID, REJECT_NONSTANDARD] | ||||
assert_equal( | assert_equal( | ||||
self.nodes[0].p2p.last_message["reject"].data, block.sha256) | self.nodes[0].p2p.last_message["reject"].data, block.sha256) | ||||
if self.nodes[0].p2p.last_message["reject"].code == REJECT_INVALID: | assert b'blk-bad-inputs' in self.nodes[0].p2p.last_message["reject"].reason | ||||
# Generic rejection when a block is invalid | |||||
assert_equal( | |||||
self.nodes[0].p2p.last_message["reject"].reason, b'blk-bad-inputs') | |||||
else: | |||||
assert b'Non-canonical DER signature' in self.nodes[0].p2p.last_message["reject"].reason | |||||
self.log.info( | self.log.info( | ||||
"Test that a version 3 block with a DERSIG-compliant transaction is accepted") | "Test that a version 3 block with a DERSIG-compliant transaction is accepted") | ||||
block.vtx[1] = create_transaction(self.nodes[0], | block.vtx[1] = create_transaction(self.nodes[0], | ||||
self.coinbase_blocks[1], self.nodeaddress, 1.0) | self.coinbase_blocks[1], self.nodeaddress, 1.0) | ||||
block.hashMerkleRoot = block.calc_merkle_root() | block.hashMerkleRoot = block.calc_merkle_root() | ||||
block.rehash() | block.rehash() | ||||
block.solve() | block.solve() | ||||
self.nodes[0].p2p.send_and_ping(msg_block(block)) | self.nodes[0].p2p.send_and_ping(msg_block(block)) | ||||
assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) | assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
BIP66Test().main() | BIP66Test().main() |