Repository: bitcoin/bitcoin
File: src/psbt.cpp (C++)

Code before:
    }

    return sig_complete ? PSBTError::OK : PSBTError::INCOMPLETE;
}

void RemoveUnnecessaryTransactions(PartiallySignedTransaction& psbtx)
{
    // Figure out if any non_witness_utxos should be dropped
    std::vector<unsigned int> to_drop;
    for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
        const auto& input = psbtx.inputs.at(i);
        int wit_ver;
        std::vector<unsigned char> wit_prog;
        if (input.witness_utxo.IsNull() || !input.witness_utxo.scriptPubKey.IsWitnessProgram(wit_ver, wit_prog)) {
            // There's a non-segwit input, so we cannot drop any non_witness_utxos
            to_drop.clear();
            break;
        }
        if (wit_ver == 0) {
            // Segwit v0, so we cannot drop any non_witness_utxos
            to_drop.clear();
            break;
        }
        // non_witness_utxos cannot be dropped if the sighash type includes SIGHASH_ANYONECANPAY
        // Since callers should have called SignPSBTInput which updates the sighash type in the PSBT, we only
        // need to look at that field. If it is not present, then we can assume SIGHASH_DEFAULT or SIGHASH_ALL.
        if (input.sighash_type != std::nullopt && (*input.sighash_type & 0x80) == SIGHASH_ANYONECANPAY) {
            to_drop.clear();
            break;
        }

        if (input.non_witness_utxo) {
            to_drop.push_back(i);
        }
    }

    // Drop the non_witness_utxos that we can drop
    for (unsigned int i : to_drop) {
        psbtx.inputs.at(i).non_witness_utxo = nullptr;
    }
}

bool FinalizePSBT(PartiallySignedTransaction& psbtx)
{
    // Finalize input signatures -- in case we have partial signatures that add up to a complete
    //   signature, but have not combined them yet (e.g. because the combiner that created this
    //   PartiallySignedTransaction did not understand them), this will combine them into a final
    //   script.
    bool complete = true;
    const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
    for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {

Review comment (suggestion):
Re: https://github.com/bitcoin/bitcoin/pull/31622#discussion_r1933698058

Earlier I thought we should add a test that checks the removal of `non_witness_utxo` in case of segwit v1 inputs only but I see there is one already here `test_utxo_conversion` in `rpc_psbt`. However, it works using `walletprocesspsbt` RPC only. I think this PR can test for the same functionality via `descriptorprocesspsbt` RPC too because it uses a different flow internally. Either of `test_utxo_conversion` or `test_sighash_adding` can be updated for this. 

Code after:

    // If we are not finalizing, set sigdata.complete to false to not set the scriptWitness
    if (!finalize && sigdata.complete) sigdata.complete = false;

    input.FromSignatureData(sigdata);

    // If we have a witness signature, put a witness UTXO.
    if (sigdata.witness) {
        input.witness_utxo = utxo;
        // We can remove the non_witness_utxo if and only if there are no non-segwit or segwit v0
        // inputs in this transaction. Since this requires inspecting the entire transaction, this
        // is something for the caller to deal with (i.e. FillPSBT).
    }

    // Fill in the missing info
    if (out_sigdata) {
        out_sigdata->missing_pubkeys = sigdata.missing_pubkeys;
        out_sigdata->missing_sigs = sigdata.missing_sigs;
        out_sigdata->missing_redeem_script = sigdata.missing_redeem_script;
        out_sigdata->missing_witness_script = sigdata.missing_witness_script;
    }

    return sig_complete ? PSBTError::OK : PSBTError::INCOMPLETE;
}

void RemoveUnnecessaryTransactions(PartiallySignedTransaction& psbtx)
{
    // Figure out if any non_witness_utxos should be dropped
    std::vector<unsigned int> to_drop;
    for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
        const auto& input = psbtx.inputs.at(i);
        int wit_ver;
        std::vector<unsigned char> wit_prog;
        if (input.witness_utxo.IsNull() || !input.witness_utxo.scriptPubKey.IsWitnessProgram(wit_ver, wit_prog)) {
            // There's a non-segwit input, so we cannot drop any non_witness_utxos
            to_drop.clear();
            break;
        }
        if (wit_ver == 0) {
            // Segwit v0, so we cannot drop any non_witness_utxos
            to_drop.clear();
            break;
        }
        // non_witness_utxos cannot be dropped if the sighash type includes SIGHASH_ANYONECANPAY
        // Since callers should have called SignPSBTInput which updates the sighash type in the PSBT, we only
        // need to look at that field. If it is not present, then we can assume SIGHASH_DEFAULT or SIGHASH_ALL.
        if (input.sighash_type != std::nullopt && (*input.sighash_type & 0x80) == SIGHASH_ANYONECANPAY) {
            to_drop.clear();
            break;
        }