[rpc] `gettxout`: array argument for bulk queries #33531

pull w0xlt wants to merge 1 commits into bitcoin:master from w0xlt:multiple_utxos3 changing 8 files +92 −62
  1. w0xlt commented at 12:58 AM on October 3, 2025: contributor

    gettxout supports only a single outpoint per call, requiring multiple RPC round trips to inspect all inputs of a transaction.

    This PR changes gettxout to accept an array of {txid, vout} objects, processing them in a single pass and returning results aligned to the inputs.

    This reduces latency, avoids redundant lookups, and improves throughput for batch use cases (e.g. wallets, indexers, transaction verification).

    For simplicity, the changes are not backward compatible, but this can be adjusted based on review feedback.

  2. [rpc] `gettxout`: allow array argument for bulk queries b361b45707
  3. DrahtBot commented at 12:58 AM on October 3, 2025: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33531.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept NACK luke-jr, stickies-v

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #31449 (coins,refactor: Reduce getblockstats RPC UTXO overhead estimation by l0rinc)
    • #21283 (Implement BIP 370 PSBTv2 by achow101)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  4. luke-jr commented at 10:12 AM on October 3, 2025: member

    Concept NACK, just use JSON-RPC batching

  5. in src/rpc/blockchain.cpp:1210 in b361b45707
    1210 | -    auto hash{Txid::FromUint256(ParseHashV(request.params[0], "txid"))};
    1211 | -    COutPoint out{hash, request.params[1].getInt<uint32_t>()};
    1212 |      bool fMempool = true;
    1213 | -    if (!request.params[2].isNull())
    1214 | -        fMempool = request.params[2].get_bool();
    1215 | +    if (!request.params[1].isNull())
    


    stickies-v commented at 10:18 AM on October 3, 2025:

    This can be cleaned up with the Arg helper, making the code more concise and removing the duplication of the default value definition:

    <details> <summary>git diff on b361b45707</summary>

    diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
    index 63bd172e52..74631a33f6 100644
    --- a/src/rpc/blockchain.cpp
    +++ b/src/rpc/blockchain.cpp
    @@ -1206,9 +1206,7 @@ static RPCHelpMan gettxout()
         Chainstate& active_chainstate = chainman.ActiveChainstate();
         CCoinsViewCache* coins_view = &active_chainstate.CoinsTip();
     
    -    bool fMempool = true;
    -    if (!request.params[1].isNull())
    -        fMempool = request.params[1].get_bool();
    +    const bool include_mempool{self.Arg<bool>("include_mempool")};
     
         UniValue ret(UniValue::VARR);
     
    @@ -1227,7 +1225,7 @@ static RPCHelpMan gettxout()
             UniValue item(UniValue::VOBJ);
     
             std::optional<Coin> coin;
    -        if (fMempool) {
    +        if (include_mempool) {
                 const CTxMemPool& mempool = EnsureMemPool(node);
                 LOCK(mempool.cs);
                 CCoinsViewMemPool view(coins_view, mempool);
    
    

    </details>

  6. in src/rpc/blockchain.cpp:1219 in b361b45707
    1231 | -    if (!coin) return UniValue::VNULL;
    1232 | +    for (const UniValue& outpoint : request.params[0].get_array().getValues()) {
    1233 | +        const UniValue& txidv = outpoint.find_value("txid");
    1234 | +        const UniValue& voutv = outpoint.find_value("vout");
    1235 | +        if (txidv.isNull() || voutv.isNull()) {
    1236 | +            throw JSONRPCError(RPC_INVALID_PARAMETER, "Each element must have txid (string) and vout (number)");
    


    stickies-v commented at 10:35 AM on October 3, 2025:

    gettxspendingprevout also takes an array of txid/vout, perhaps worth carving that out into helper functions and reusing it here? (there might be even more users of this logic, didn't do an exhaustive search)

  7. stickies-v commented at 10:43 AM on October 3, 2025: contributor

    I think this PR needs much better motivation, especially with the breaking changes:

    1. what are the observed performance differences between:
    • master and this PR for non-batch query
    • master and this PR for batch query
    1. has this been a problem / request by any downstream users? If so, would be useful to document here.

    For simplicity, the changes are not backward compatible, but this can be adjusted based on review feedback.

    If the backwards incompatibility is kept, it definitely needs a -deprecatedrpc option, I'd argue for at leas a couple versions since this seems like an often-used RPC. My preference here would be to not make the change breaking, though.

    I suspect the batch query approach is going to be a good enough, in which case I'm at least approach NACK, but if there is a convincing use case to change this I'm happy to be convinced.

  8. w0xlt commented at 1:56 PM on October 3, 2025: contributor

    Thanks for the review and the suggestions @stickies-v . I'll improve the motivation and reopen the PR if needed.

  9. w0xlt closed this on Oct 3, 2025


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-21 00:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me