Repository: bitcoin/bitcoin
File: src/wallet/rpc/spend.cpp (C++)

Code before:
        if (sffo.isStr()) {
            for (size_t i = 0; i < destinations.size(); ++i) {
                if (sffo.get_str() == destinations.at(i)) {
                    sffo_set.insert(i);
                    break;
                }
            }
        }
        if (sffo.isNum()) {
            int pos = sffo.getInt<int>();
            if (sffo_set.contains(pos))
                throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, duplicated position: %d", pos));
            if (pos < 0)
                throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, negative position: %d", pos));
            if (pos >= int(destinations.size()))
                throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, position too large: %d", pos));
            sffo_set.insert(pos);
        }
    }
    return sffo_set;
}

static UniValue FinishTransaction(const std::shared_ptr<CWallet> pwallet, const UniValue& options, CMutableTransaction& rawTx)
{
    bool can_anti_fee_snipe = !options.exists("locktime");

    for (const CTxIn& tx_in : rawTx.vin) {
        // Checks sequence values consistent with DiscourageFeeSniping
        can_anti_fee_snipe &= (tx_in.nSequence == CTxIn::MAX_SEQUENCE_NONFINAL || tx_in.nSequence == MAX_BIP125_RBF_SEQUENCE);
    }

    if (can_anti_fee_snipe) {
        LOCK(pwallet->cs_wallet);
        FastRandomContext rng_fast;
        DiscourageFeeSniping(rawTx, rng_fast, pwallet->chain(), pwallet->GetLastBlockHash(), pwallet->GetLastBlockHeight());
    }

    // Make a blank psbt
    PartiallySignedTransaction psbtx(rawTx);

    // First fill transaction with our data without signing,
    // so external signers are not asked to sign more than once.
    bool complete;
    pwallet->FillPSBT(psbtx, complete, SIGHASH_DEFAULT, /*sign=*/false, /*bip32derivs=*/true);
    const auto err{pwallet->FillPSBT(psbtx, complete, SIGHASH_DEFAULT, /*sign=*/true, /*bip32derivs=*/false)};
    if (err) {
        throw JSONRPCPSBTError(*err);
    }

    CMutableTransaction mtx;
    complete = FinalizeAndExtractPSBT(psbtx, mtx);

Review comment (suggestion):
Nit: I think this is correct given that booleans in C++ are guaranteed to be true or false, but the bitwise operator did make me do a double take.

I would consider this equivalent and more readable:

```suggestion
        can_anti_fee_snipe = can_anti_fee_snipe && (tx_in.nSequence == CTxIn::MAX_SEQUENCE_NONFINAL || tx_in.nSequence == MAX_BIP125_RBF_SEQUENCE);
```

Code after:
            if (it == destinations.end()) throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter 'subtract fee from output', destination %s not found in tx outputs", sffo.get_str()));
            pos = it - destinations.begin();
        } else if (sffo.isNum()) {
            pos = sffo.getInt<int>();
        } else {
            throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter 'subtract fee from output', invalid value type: %s", uvTypeName(sffo.type())));
        }

        if (sffo_set.contains(pos))
            throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter 'subtract fee from output', duplicated position: %d", pos));
        if (pos < 0)
            throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter 'subtract fee from output', negative position: %d", pos));
        if (pos >= int(destinations.size()))
            throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter 'subtract fee from output', position too large: %d", pos));
        sffo_set.insert(pos);
    }
    return sffo_set;
}

static UniValue FinishTransaction(const std::shared_ptr<CWallet> pwallet, const UniValue& options, CMutableTransaction& rawTx)
{
    bool can_anti_fee_snipe = !options.exists("locktime");

    for (const CTxIn& tx_in : rawTx.vin) {
        // Checks sequence values consistent with DiscourageFeeSniping
        can_anti_fee_snipe = can_anti_fee_snipe && (tx_in.nSequence == CTxIn::MAX_SEQUENCE_NONFINAL || tx_in.nSequence == MAX_BIP125_RBF_SEQUENCE);
    }

    if (can_anti_fee_snipe) {
        LOCK(pwallet->cs_wallet);
        FastRandomContext rng_fast;
        DiscourageFeeSniping(rawTx, rng_fast, pwallet->chain(), pwallet->GetLastBlockHash(), pwallet->GetLastBlockHeight());
    }

    // Make a blank psbt
    PartiallySignedTransaction psbtx(rawTx);

    // First fill transaction with our data without signing,
    // so external signers are not asked to sign more than once.
    bool complete;
    pwallet->FillPSBT(psbtx, complete, std::nullopt, /*sign=*/false, /*bip32derivs=*/true);
    const auto err{pwallet->FillPSBT(psbtx, complete, std::nullopt, /*sign=*/true, /*bip32derivs=*/false)};
    if (err) {
        throw JSONRPCPSBTError(*err);
    }

    CMutableTransaction mtx;
    complete = FinalizeAndExtractPSBT(psbtx, mtx);

    UniValue result(UniValue::VOBJ);