Repository: bitcoin/bitcoin
File: test/functional/data/invalid_txs.py (Python)

Code before:


class TooManySigops(BadTxTemplate):
    reject_reason = "bad-txns-too-many-sigops"
    block_reject_reason = "bad-blk-sigops, out-of-bounds SigOpCount"
    expect_disconnect = False

    def get_tx(self):
        lotsa_checksigs = CScript([OP_CHECKSIG] * (MAX_BLOCK_SIGOPS))
        return create_tx_with_script(
            self.spend_tx, 0,
            output_script=lotsa_checksigs,
            amount=1)

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))
        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
        })

class NonStandardAndInvalid(BadTxTemplate):
    """A non-standard transaction which is also consensus-invalid should return the consensus error."""
    reject_reason = "mandatory-script-verify-flag-failed (OP_RETURN was encountered)"
    expect_disconnect = True
    valid_in_block = False

    def get_tx(self):
        return create_tx_with_script(
            self.spend_tx, 0, script_sig=b'\x00' * 3 + b'\xab\x6a',
            amount=(self.spend_avail // 2))

# Disabled opcode tx templates (CVE-2010-5137)
DisabledOpcodeTemplates = [getDisabledOpcodeTemplate(opcode) for opcode in [
    OP_CAT,
    OP_SUBSTR,
    OP_LEFT,
    OP_RIGHT,
    OP_INVERT,
    OP_AND,

Review comment (suggestion):
Took me a minute to realize this is only the 2nd(?) case where it's valid in block but non-standard-even-with-acceotnonstdtxn set.

Also meta: would be nice if there was a border testing capability, where you could pair it with a tx that would be successful and obviously just-at the limit.

Code after:
    def get_tx(self):
        return create_tx_with_script(
            self.spend_tx, 0, script_sig=b'\x64' * 35,
            amount=(self.spend_avail // 2))


class TooManySigopsPerBlock(BadTxTemplate):
    reject_reason = "bad-txns-too-many-sigops"
    block_reject_reason = "bad-blk-sigops, out-of-bounds SigOpCount"
    expect_disconnect = False

    def get_tx(self):
        lotsa_checksigs = CScript([OP_CHECKSIG] * (MAX_BLOCK_SIGOPS))
        return create_tx_with_script(
            self.spend_tx, 0,
            output_script=lotsa_checksigs,
            amount=1)


class TooManySigopsPerTransaction(BadTxTemplate):
    reject_reason = "bad-txns-too-many-sigops"
    expect_disconnect = False
    valid_in_block = True

    def get_tx(self):
        lotsa_checksigs = CScript([OP_CHECKSIG] * (MAX_STANDARD_TX_SIGOPS + 1))
        return create_tx_with_script(
            self.spend_tx, 0,
            output_script=lotsa_checksigs,
            amount=1)


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))
        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
        })

class NonStandardAndInvalid(BadTxTemplate):