diff --git a/test/functional/data/invalid_txs.py b/test/functional/data/invalid_txs.py --- a/test/functional/data/invalid_txs.py +++ b/test/functional/data/invalid_txs.py @@ -24,6 +24,18 @@ from test_framework.messages import CTransaction, CTxIn, CTxOut, COutPoint from test_framework import script as sc from test_framework.blocktools import create_tx_with_script +from test_framework.txtools import pad_tx + + +from test_framework.script import ( + CScript, + OP_INVERT, + OP_2MUL, + OP_2DIV, + OP_MUL, + OP_LSHIFT, + OP_RSHIFT +) basic_p2sh = sc.CScript( [sc.OP_HASH160, sc.hash160(sc.CScript([sc.OP_0])), sc.OP_EQUAL]) @@ -183,6 +195,37 @@ amount=(self.spend_avail // 2)) +def getDisabledOpcodeTemplate(opcode): + """ Creates disabled opcode tx template class""" + + def get_tx(self): + tx = CTransaction() + vin = self.valid_txin + vin.scriptSig = CScript([opcode]) + tx.vin.append(vin) + tx.vout.append(CTxOut(1, basic_p2sh)) + pad_tx(tx) + tx.calc_sha256() + return tx + + return type('DisabledOpcode_' + str(opcode), (BadTxTemplate,), { + 'reject_reason': "disabled opcode", + 'expect_disconnect': True, + 'get_tx': get_tx, + 'valid_in_block': True + }) + + +# Disabled opcode tx templates (CVE-2010-5137) +DisabledOpcodeTemplates = [getDisabledOpcodeTemplate(opcode) for opcode in [ + OP_INVERT, + OP_2MUL, + OP_2DIV, + OP_MUL, + OP_LSHIFT, + OP_RSHIFT]] + + def iter_all_templates(): """Iterate through all bad transaction template types.""" return BadTxTemplate.__subclasses__() diff --git a/test/functional/p2p_invalid_block.py b/test/functional/p2p_invalid_block.py --- a/test/functional/p2p_invalid_block.py +++ b/test/functional/p2p_invalid_block.py @@ -17,6 +17,7 @@ create_block, create_coinbase, create_tx_with_script, + make_conform_to_ctor, ) from test_framework.messages import COIN from test_framework.mininode import P2PDataStore @@ -97,15 +98,16 @@ # Check transactions for duplicate inputs (CVE-2018-17144) self.log.info("Test duplicate input block.") - block2_orig.vtx[2].vin.append(block2_orig.vtx[2].vin[0]) - block2.vtx = [block2.vtx[0]] + \ - sorted(block2.vtx[1:], key=lambda tx: tx.get_id()) - block2_orig.vtx[2].rehash() - block2_orig.hashMerkleRoot = block2_orig.calc_merkle_root() - block2_orig.rehash() - block2_orig.solve() + block2_dup = copy.deepcopy(block2_orig) + block2_dup.vtx[2].vin.append(block2_dup.vtx[2].vin[0]) + block2_dup.vtx[2].rehash() + make_conform_to_ctor(block2_dup) + block2_dup.hashMerkleRoot = block2_dup.calc_merkle_root() + block2_dup.rehash() + block2_dup.solve() node.p2p.send_blocks_and_test( - [block2_orig], node, success=False, reject_reason='bad-txns-inputs-duplicate') + [block2_dup], node, success=False, + reject_reason='bad-txns-inputs-duplicate') self.log.info("Test very broken block.") @@ -121,6 +123,38 @@ node.p2p.send_blocks_and_test( [block3], node, success=False, reject_reason='bad-cb-amount') + # Complete testing of CVE-2012-2459 by sending the original block. + # It should be accepted even though it has the same hash as the mutated + # one. + + self.log.info("Test accepting original block after rejecting its" + " mutated version.") + node.p2p.send_blocks_and_test([block2_orig], node, success=True, + timeout=5) + + # Update tip info + height += 1 + block_time += 1 + tip = int(block2_orig.hash, 16) + + # Complete testing of CVE-2018-17144, by checking for the inflation bug. + # Create a block that spends the output of a tx in a previous block. + block4 = create_block(tip, create_coinbase(height), block_time) + tx3 = create_tx_with_script(tx2, 0, script_sig=b'\x51', + amount=50 * COIN) + + # Duplicates input + tx3.vin.append(tx3.vin[0]) + tx3.rehash() + block4.vtx.append(tx3) + make_conform_to_ctor(block4) + block4.hashMerkleRoot = block4.calc_merkle_root() + block4.rehash() + block4.solve() + self.log.info("Test inflation by duplicating input") + node.p2p.send_blocks_and_test([block4], node, success=False, + reject_reason='bad-txns-inputs-duplicate') + if __name__ == '__main__': InvalidBlockRequestTest().main()