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

Code before:
    def get_tx(self):
        tx = CTransaction()
        return tx


# The following check prevents exploit of lack of merkle
# tree depth commitment (CVE-2017-12842)
class SizeTooSmall(BadTxTemplate):
    reject_reason = "tx-size-small"
    valid_in_block = True

    def get_tx(self):
        tx = CTransaction()
        tx.vin.append(self.valid_txin)
        tx.vout.append(CTxOut(0, CScript([OP_RETURN] + ([OP_0] * (MIN_PADDING - 2)))))
        assert len(tx.serialize_without_witness()) == 64
        assert MIN_STANDARD_TX_NONWITNESS_SIZE - 1 == 64
        return tx


class BadInputOutpointIndex(BadTxTemplate):
    # Won't be rejected - nonexistent outpoint index is treated as an orphan since the coins
    # database can't distinguish between spent outpoints and outpoints which never existed.
    reject_reason = None
    # But fails in block
    block_reject_reason = "bad-txns-inputs-missingorspent"

    def get_tx(self):
        num_indices = len(self.spend_tx.vin)
        bad_idx = num_indices + 100

        tx = CTransaction()
        tx.vin.append(CTxIn(COutPoint(self.spend_tx.txid_int, bad_idx), b"", SEQUENCE_FINAL))
        tx.vout.append(CTxOut(0, basic_p2sh))
        return tx


class DuplicateInput(BadTxTemplate):
    reject_reason = 'bad-txns-inputs-duplicate'

    def get_tx(self):
        tx = CTransaction()
        tx.vin.append(self.valid_txin)
        tx.vin.append(self.valid_txin)
        tx.vout.append(CTxOut(1, basic_p2sh))
        return tx


class PrevoutNullInput(BadTxTemplate):
    reject_reason = 'bad-txns-prevout-null'


Review comment (suggestion):
these two lines can be dropped; `expect_disconnect` was removed in #33050 (commit 876dbdfb4702410dfd4037614dc9298a0c09c63e) and `valid_in_block` is set to False by default anyways
```suggestion
```
other than that, lgtm

Code after:
    # "surpufluous witness" check during deserialization
    # rather than the input count check.
    def get_tx(self):
        tx = CTransaction()
        return tx


# The following check prevents exploit of lack of merkle
# tree depth commitment (CVE-2017-12842)
class SizeTooSmall(BadTxTemplate):
    reject_reason = "tx-size-small"
    valid_in_block = True

    def get_tx(self):
        tx = CTransaction()
        tx.vin.append(self.valid_txin)
        tx.vout.append(CTxOut(0, CScript([OP_RETURN] + ([OP_0] * (MIN_PADDING - 2)))))
        assert len(tx.serialize_without_witness()) == 64
        assert MIN_STANDARD_TX_NONWITNESS_SIZE - 1 == 64
        return tx

# reject a transaction that contains a witness
# but doesn't spend a segwit output
class ExtraWitness(BadTxTemplate):
    reject_reason = "tx-size-small"
    block_reject_reason = "block-script-verify-flag-failed (Witness provided for non-witness script)"

    def get_tx(self):
        tx = CTransaction()
        tx.vin.append(self.valid_txin)
        tx.vout.append(CTxOut(0, CScript()))
        tx.wit.vtxinwit = [CTxInWitness()]
        tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])]
        return tx


class BadInputOutpointIndex(BadTxTemplate):
    # Won't be rejected - nonexistent outpoint index is treated as an orphan since the coins
    # database can't distinguish between spent outpoints and outpoints which never existed.
    reject_reason = None
    # But fails in block
    block_reject_reason = "bad-txns-inputs-missingorspent"

    def get_tx(self):
        num_indices = len(self.spend_tx.vin)
        bad_idx = num_indices + 100

        tx = CTransaction()
        tx.vin.append(CTxIn(COutPoint(self.spend_tx.txid_int, bad_idx), b"", SEQUENCE_FINAL))
        tx.vout.append(CTxOut(0, basic_p2sh))
        return tx