Skip to content

rpc: replace ELISION references with explicit result fields#34764

Draft
satsfy wants to merge 8 commits intobitcoin:masterfrom
satsfy:fix-rpc-inheritance
Draft

rpc: replace ELISION references with explicit result fields#34764
satsfy wants to merge 8 commits intobitcoin:masterfrom
satsfy:fix-rpc-inheritance

Conversation

@satsfy
Copy link

@satsfy satsfy commented Mar 6, 2026

Seeking concept ACK. Partially addresses #29912. Motivated by #34683, which exports OpenRPC from existing RPCHelpMan metadata. Sample OpenRPC.

Some RPC help definitions currently rely on RPCResult::Type::ELISION entries whose structure is only described in prose. This is concise for human-readable help, but it prevents tools from deriving complete machine-readable result schemas from the metadata.

This PR replaces all non-recursive ELISION-based reuses with shared structured definitions, so the result layout is represented directly in RPCHelpMan metadata instead of only in text.

Affected RPCs:

  • decodepsbt
  • getrawtransaction
  • getblock
  • listsinceblock

The patch also replaces DecodeTxDoc() with TxDoc() plus a TxDocOptions struct, so decoded transaction layouts can be reused without positional booleans and selectively extended with prevout, fee, and hex fields.

As a consequence, bitcoin-cli output for affected RPCs becomes more verbose, since prose summaries like "Same output as verbosity = 1" are replaced by the full field definitions. The actual RPC return values are unchanged. I opened this as a draft because I'd like to discuss whether this tradeoff is acceptable, or whether the help renderer should collapse some sub-structures via manual configuration back into short summaries while keeping the underlying metadata explicit.

This PR doesn't cover getaddressinfo.embedded, which is recursive — runtime output can contain nested embedded objects, and RPCResult has no way to express that today. Happy to discuss approaches here if anyone has thoughts.

Changes:

  • replace DecodeTxDoc() with TxDoc() and TxDocOptions
  • replace ELISION-based reuse in decodepsbt, getrawtransaction, getblock, and listsinceblock
  • factor shared result layouts into TxDoc(), GetBlockFields(), and ListSinceBlockTxFields()
  • mark getblock transaction fee documentation optional where it is conditionally present

@DrahtBot
Copy link
Contributor

DrahtBot commented Mar 6, 2026

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

Reviews

See the guideline for information on the review process.

Type Reviewers
Concept ACK nervana21, Bortlesboat, w0xlt

If your review is incorrectly listed, please copy-paste <!--meta-tag:bot-skip--> into the comment that the bot should ignore.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #34799 (rpc: Run type check on decodepsbt result by maflcko)
  • #34683 (RFC: Support a format description of our JSON-RPC interface by willcl-ark)
  • #34514 (refactor: remove unnecessary std::move for trivially copyable types by l0rinc)
  • #34049 (rpc: Disallow captures in RPCMethodImpl by ajtowns)
  • #31252 (rpc: print P2WSH and P2SH redem Script in (get/decode)rawtransaction by polespinasa)
  • #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.

@nervana21
Copy link
Contributor

Concept ACK

@satsfy satsfy force-pushed the fix-rpc-inheritance branch from 4c7610c to b2e56e3 Compare March 7, 2026 02:30
Copy link

@Bortlesboat Bortlesboat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review ACK

Thorough review of the diff. This is a well-structured elimination of RPCResult::Type::ELISION in favor of explicit documentation:

What it does:

  • Renames DecodeTxDocTxDoc with a new TxDocOptions struct using designated initializers instead of positional booleans — much cleaner API
  • Creates GetBlockFields() to deduplicate the getblock verbosity=1/2/3 help text, parameterized by the tx array result
  • Creates ListSinceBlockTxFields() to share field definitions between transactions and removed arrays in listsinceblock
  • Expands all ELISION placeholders into explicit field documentation

Why this matters: ELISION forced users reading bitcoin-cli help getblock to mentally cross-reference different verbosity levels. Now each level is self-contained, which is especially helpful for verbosity=3 where the prevout fields were previously buried behind two levels of "same as above".

Code observations:

  • TxDocOptions with default-false members + designated initializers is clean C++20 — callers only name what they enable
  • fee_optional controlling the /*optional=*/ param on RPCResult is a nice touch
  • GetBlockFields taking RPCResult tx_result by value + std::move is correct
  • The #include <rpc/rawtransaction_util.h> addition in blockchain.cpp is the right include for the new TxDoc/TxDocOptions dependency

One minor note: the old verbosity=2 getblock ELISION had descriptive text "The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 'tx' result" — this contextual note is lost, but the explicit fields are self-documenting so arguably better.

@willcl-ark
Copy link
Member

Currently this doesn't compile as a few brackets are mis-matched:

diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 920080d3b9e..44baf03aad6 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -793,9 +793,7 @@ static RPCHelpMan getblock()
                         {
                             {RPCResult::Type::ELISION, "", "The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 \"tx\" result"},
                             {RPCResult::Type::NUM, "fee", /*optional=*/true, "The transaction fee in " + CURRENCY_UNIT + ", omitted if block undo data is not available"},
-                        }},
-                    }},
-                }},
+                        }})},
                     RPCResult{"for verbosity = 3",
                 RPCResult::Type::OBJ, "", "",
                 {
@@ -806,7 +804,9 @@ static RPCHelpMan getblock()
                         {
                             {RPCResult::Type::OBJ, "", "",
                                 TxDoc("The transaction id", TxDocOptions{.prevout = true, .fee = true, .fee_optional = true, .hex = true})},
-                        }})},
+                        }},
+                    }},
+                }},
                 },
                 RPCExamples{
                     HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")

I'm not super thrilled about expanding (an already large) help output e.g.

Comparison
❯ bitcoin-cli -regtest help getblock
getblock "blockhash" ( verbosity )

If verbosity is 0, returns a string that is serialized, hex-encoded data for block 'hash'.
If verbosity is 1, returns an Object with information about block <hash>.
If verbosity is 2, returns an Object with information about block <hash> and information about each transaction.
If verbosity is 3, returns an Object with information about block <hash> and information about each transaction, including prevout information for inputs (only for unpruned blocks in the current best chain).

Arguments:
1. blockhash    (string, required) The block hash
2. verbosity    (numeric, optional, default=1) 0 for hex-encoded data, 1 for a JSON object, 2 for JSON object with transaction data, and 3 for JSON object with transaction data including prevout information for inputs

Result (for verbosity = 0):
"hex"    (string) A string that is serialized, hex-encoded data for block 'hash'

Result (for verbosity = 1):
{                                 (json object)
  "hash" : "hex",                 (string) the block hash (same as provided)
  "confirmations" : n,            (numeric) The number of confirmations, or -1 if the block is not on the main chain
  "size" : n,                     (numeric) The block size
  "strippedsize" : n,             (numeric) The block size excluding witness data
  "weight" : n,                   (numeric) The block weight as defined in BIP 141
  "coinbase_tx" : {               (json object) Coinbase transaction metadata
    "version" : n,                (numeric) The coinbase transaction version
    "locktime" : n,               (numeric) The coinbase transaction's locktime (nLockTime)
    "sequence" : n,               (numeric) The coinbase input's sequence number (nSequence)
    "coinbase" : "hex",           (string) The coinbase input's script
    "witness" : "hex"             (string, optional) The coinbase input's first (and only) witness stack element, if present
  },
  "height" : n,                   (numeric) The block height or index
  "version" : n,                  (numeric) The block version
  "versionHex" : "hex",           (string) The block version formatted in hexadecimal
  "merkleroot" : "hex",           (string) The merkle root
  "tx" : [                        (json array) The transaction ids
    "hex",                        (string) The transaction id
    ...
  ],
  "time" : xxx,                   (numeric) The block time expressed in UNIX epoch time
  "mediantime" : xxx,             (numeric) The median block time expressed in UNIX epoch time
  "nonce" : n,                    (numeric) The nonce
  "bits" : "hex",                 (string) nBits: compact representation of the block difficulty target
  "target" : "hex",               (string) The difficulty target
  "difficulty" : n,               (numeric) The difficulty
  "chainwork" : "hex",            (string) Expected number of hashes required to produce the chain up to this block (in hex)
  "nTx" : n,                      (numeric) The number of transactions in the block
  "previousblockhash" : "hex",    (string, optional) The hash of the previous block (if available)
  "nextblockhash" : "hex"         (string, optional) The hash of the next block (if available)
}

Result (for verbosity = 2):
{                   (json object)
  ...,              Same output as verbosity = 1
  "tx" : [          (json array)
    {               (json object)
      ...,          The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 "tx" result
      "fee" : n     (numeric) The transaction fee in BTC, omitted if block undo data is not available
    },
    ...
  ]
}

Result (for verbosity = 3):
{                                        (json object)
  ...,                                   Same output as verbosity = 2
  "tx" : [                               (json array)
    {                                    (json object)
      "vin" : [                          (json array)
        {                                (json object)
          ...,                           The same output as verbosity = 2
          "prevout" : {                  (json object) (Only if undo information is available)
            "generated" : true|false,    (boolean) Coinbase or not
            "height" : n,                (numeric) The height of the prevout
            "value" : n,                 (numeric) The value in BTC
            "scriptPubKey" : {           (json object)
              "asm" : "str",             (string) Disassembly of the output script
              "desc" : "str",            (string) Inferred descriptor for the output
              "hex" : "hex",             (string) The raw output script bytes, hex-encoded
              "address" : "str",         (string, optional) The Bitcoin address (only if a well-defined address exists)
              "type" : "str"             (string) The type (one of: nonstandard, anchor, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_scripthash, witness_v0_keyhash, witness_v1_taproot, witness_unknown)
            }
          }
        },
        ...
      ]
    },
    ...
  ]
}

Examples:
> bitcoin-cli getblock "00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"
> curl --user myusername --data-binary '{"jsonrpc": "2.0", "id": "curltest", "method": "getblock", "params": ["00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"]}' -H 'content-type: application/json' http://127.0.0.1:8332/

goes to

❯ ./build/bin/bitcoin-cli -regtest help getblock
getblock "blockhash" ( verbosity )

If verbosity is 0, returns a string that is serialized, hex-encoded data for block 'hash'.
If verbosity is 1, returns an Object with information about block <hash>.
If verbosity is 2, returns an Object with information about block <hash> and information about each transaction.
If verbosity is 3, returns an Object with information about block <hash> and information about each transaction, including prevout information for inputs (only for unpruned blocks in the current best chain).

Arguments:
1. blockhash    (string, required) The block hash
2. verbosity    (numeric, optional, default=1) 0 for hex-encoded data, 1 for a JSON object, 2 for JSON object with transaction data, and 3 for JSON object with transaction data including prevout information for inputs

Result (for verbosity = 0):
"hex"    (string) A string that is serialized, hex-encoded data for block 'hash'

Result (for verbosity = 1):
{                                 (json object)
  "hash" : "hex",                 (string) the block hash (same as provided)
  "confirmations" : n,            (numeric) The number of confirmations, or -1 if the block is not on the main chain
  "size" : n,                     (numeric) The block size
  "strippedsize" : n,             (numeric) The block size excluding witness data
  "weight" : n,                   (numeric) The block weight as defined in BIP 141
  "coinbase_tx" : {               (json object) Coinbase transaction metadata
    "version" : n,                (numeric) The coinbase transaction version
    "locktime" : n,               (numeric) The coinbase transaction's locktime (nLockTime)
    "sequence" : n,               (numeric) The coinbase input's sequence number (nSequence)
    "coinbase" : "hex",           (string) The coinbase input's script
    "witness" : "hex"             (string, optional) The coinbase input's first (and only) witness stack element, if present
  },
  "height" : n,                   (numeric) The block height or index
  "version" : n,                  (numeric) The block version
  "versionHex" : "hex",           (string) The block version formatted in hexadecimal
  "merkleroot" : "hex",           (string) The merkle root
  "tx" : [                        (json array) The transaction ids
    "hex",                        (string) The transaction id
    ...
  ],
  "time" : xxx,                   (numeric) The block time expressed in UNIX epoch time
  "mediantime" : xxx,             (numeric) The median block time expressed in UNIX epoch time
  "nonce" : n,                    (numeric) The nonce
  "bits" : "hex",                 (string) nBits: compact representation of the block difficulty target
  "target" : "hex",               (string) The difficulty target
  "difficulty" : n,               (numeric) The difficulty
  "chainwork" : "hex",            (string) Expected number of hashes required to produce the chain up to this block (in hex)
  "nTx" : n,                      (numeric) The number of transactions in the block
  "previousblockhash" : "hex",    (string, optional) The hash of the previous block (if available)
  "nextblockhash" : "hex"         (string, optional) The hash of the next block (if available)
}

Result (for verbosity = 2):
{                                 (json object)
  "hash" : "hex",                 (string) the block hash (same as provided)
  "confirmations" : n,            (numeric) The number of confirmations, or -1 if the block is not on the main chain
  "size" : n,                     (numeric) The block size
  "strippedsize" : n,             (numeric) The block size excluding witness data
  "weight" : n,                   (numeric) The block weight as defined in BIP 141
  "coinbase_tx" : {               (json object) Coinbase transaction metadata
    "version" : n,                (numeric) The coinbase transaction version
    "locktime" : n,               (numeric) The coinbase transaction's locktime (nLockTime)
    "sequence" : n,               (numeric) The coinbase input's sequence number (nSequence)
    "coinbase" : "hex",           (string) The coinbase input's script
    "witness" : "hex"             (string, optional) The coinbase input's first (and only) witness stack element, if present
  },
  "height" : n,                   (numeric) The block height or index
  "version" : n,                  (numeric) The block version
  "versionHex" : "hex",           (string) The block version formatted in hexadecimal
  "merkleroot" : "hex",           (string) The merkle root
  "tx" : [                        (json array)
    ...,                          The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 "tx" result
    n,                            (numeric, optional) The transaction fee in BTC, omitted if block undo data is not available
    ...
  ],
  "time" : xxx,                   (numeric) The block time expressed in UNIX epoch time
  "mediantime" : xxx,             (numeric) The median block time expressed in UNIX epoch time
  "nonce" : n,                    (numeric) The nonce
  "bits" : "hex",                 (string) nBits: compact representation of the block difficulty target
  "target" : "hex",               (string) The difficulty target
  "difficulty" : n,               (numeric) The difficulty
  "chainwork" : "hex",            (string) Expected number of hashes required to produce the chain up to this block (in hex)
  "nTx" : n,                      (numeric) The number of transactions in the block
  "previousblockhash" : "hex",    (string, optional) The hash of the previous block (if available)
  "nextblockhash" : "hex"         (string, optional) The hash of the next block (if available)
}

Result (for verbosity = 3):
{                                          (json object)
  ...,                                     Same output as verbosity = 2
  "tx" : [                                 (json array)
    {                                      (json object)
      "" : {                               (json object)
        "txid" : "hex",                    (string) The transaction id
        "hash" : "hex",                    (string) The transaction hash (differs from txid for witness transactions)
        "size" : n,                        (numeric) The serialized transaction size
        "vsize" : n,                       (numeric) The virtual transaction size (differs from size for witness transactions)
        "weight" : n,                      (numeric) The transaction's weight (between vsize*4-3 and vsize*4)
        "version" : n,                     (numeric) The version
        "locktime" : xxx,                  (numeric) The lock time
        "vin" : [                          (json array)
          {                                (json object)
            "coinbase" : "hex",            (string, optional) The coinbase value (only if coinbase transaction)
            "txid" : "hex",                (string, optional) The transaction id (if not coinbase transaction)
            "vout" : n,                    (numeric, optional) The output number (if not coinbase transaction)
            "scriptSig" : {                (json object, optional) The script (if not coinbase transaction)
              "asm" : "str",               (string) Disassembly of the signature script
              "hex" : "hex"                (string) The raw signature script bytes, hex-encoded
            },
            "txinwitness" : [              (json array, optional)
              "hex",                       (string) hex-encoded witness data (if any)
              ...
            ],
            "prevout" : {                  (json object, optional) The previous output, omitted if block undo data is not available
              "generated" : true|false,    (boolean) Coinbase or not
              "height" : n,                (numeric) The height of the prevout
              "value" : n,                 (numeric) The value in BTC
              "scriptPubKey" : {           (json object)
                "asm" : "str",             (string) Disassembly of the output script
                "desc" : "str",            (string) Inferred descriptor for the output
                "hex" : "hex",             (string) The raw output script bytes, hex-encoded
                "address" : "str",         (string, optional) The Bitcoin address (only if a well-defined address exists)
                "type" : "str"             (string) The type (one of: nonstandard, anchor, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_scripthash, witness_v0_keyhash, witness_v1_taproot, witness_unknown)
              }
            },
            "sequence" : n                 (numeric) The script sequence number
          },
          ...
        ],
        "vout" : [                         (json array)
          {                                (json object)
            "value" : n,                   (numeric) The value in BTC
            "n" : n,                       (numeric) index
            "scriptPubKey" : {             (json object)
              "asm" : "str",               (string) Disassembly of the output script
              "desc" : "str",              (string) Inferred descriptor for the output
              "hex" : "hex",               (string) The raw output script bytes, hex-encoded
              "address" : "str",           (string, optional) The Bitcoin address (only if a well-defined address exists)
              "type" : "str"               (string) The type (one of: nonstandard, anchor, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_scripthash, witness_v0_keyhash, witness_v1_taproot, witness_unknown)
            }
          },
          ...
        ],
        "fee" : n,                         (numeric, optional) transaction fee in BTC, omitted if block undo data is not available
        "hex" : "hex"                      (string) The hex-encoded transaction data
      }
    },
    ...
  ]
}

Examples:
> bitcoin-cli getblock "00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"
> curl --user myusername --data-binary '{"jsonrpc": "2.0", "id": "curltest", "method": "getblock", "params": ["00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"]}' -H 'content-type: application/json' http://127.0.0.1:8332/

but, this is certainly one "solution" to ellisions being difficult for a spec parser to read, so it definitely improves on this front. But doing it at the expense of a worse experience for humans reading bitcoin-cli help <cmd>.

I've picked this PR (with the fixup) into #34683 so we can take a look at it all in one place there.

@satsfy satsfy force-pushed the fix-rpc-inheritance branch from b6e6f5d to 15e956a Compare March 10, 2026 15:38
@satsfy
Copy link
Author

satsfy commented Mar 10, 2026

Thanks for the review, will keep supporting the OpenRPC implementation.

In the latest push, I fixed bracket balancing and dropped the fee optionality config since it's always optional (see #34702).

On the help output getting larger for user, I envision a follow-up with the OpenRPC work that:

  • Fully defines all RPCHelpMan results, eliminating ELISIONs
  • Allows configuring what bitcoin-cli help displays to avoid excessive verbosity
  • Improves the type system for codegen use (see this comment).

@satsfy
Copy link
Author

satsfy commented Mar 10, 2026

Note for reviewers: the changes in this PR have been incorporated into #34683. I'll keep this open until it's clear which one will move forward.

@w0xlt
Copy link
Contributor

w0xlt commented Mar 10, 2026

Concept ACK

MarcoFalke added 2 commits March 11, 2026 11:57
Initially only move skip_type_check there.

In the future, more options can be added, without having to touch the
constructors.
This prepares the function to be more flexible, when more options are
passed in the future.
@maflcko
Copy link
Member

maflcko commented Mar 11, 2026

I'd presume it would be possible to return a human readable help text, but use the full structure internally for MatchesType checks. This is required for #34702 (comment) etc ...

I've implemented this in #34799.

If you agree, you may review it and rebase on top of it. I've also re-named the function to TxDoc, so that it is easier for you to rebase.

@willcl-ark
Copy link
Member

Perhaps we could approve CI to run in here please?

MarcoFalke and others added 5 commits March 11, 2026 17:26
For RPCResults, the type may be ELISION, which is confusing and brittle:

* The elision should only affect the help output, not the type.
* The type should be the real type, so that type checks can be run on
  it.

Fix this issue by introducing a new print_elision option and using it
in decodepsbt.

This change will ensure that RPCResult::MatchesType is properly run.
Also, this clarifies the RPC output minimally:

```diff
--- a/decodepsbt
+++ b/decodepsbt
@@ -35,7 +35,7 @@ Result:
   "inputs" : [                             (json array)
     {                                      (json object)
       "non_witness_utxo" : {               (json object, optional) Decoded network transaction for non-witness UTXOs
-        ...
+        ...                                The layout is the same as the output of decoderawtransaction.
       },
       "witness_utxo" : {                   (json object, optional) Transaction output for witness UTXOs
         "amount" : n,                      (numeric) The value in BTC
```
TxDoc() previously only supported wallet field via a bool
in TxDocOptions. Add prevout, fee, and hex boolean fields to
TxDocOptions so callers can opt into each optional section by name:

    TxDoc({.prevout = true, .fee = true})

This avoids positional bool arguments and makes each call site
self-documenting. The internal structure switches from a plain
initializer-list return to Cat() calls so optional result vectors
can be conditionally appended.

Help output is unchanged.
The verbosity=2 result for getrawtransaction contains ELISION prose
both at the top level ("Same output as verbosity = 1") and within
each vin entry. These references are readable for humans but do not
provide structured result metadata.

Replace them with the full result structure using Cat() and TxDoc()
with prevout enabled.
getblock defines four verbosity levels. The verbosity=2 and
verbosity=3 results use ELISION entries to refer to lower verbosity
layouts, even though the only material difference between levels is
the shape of the "tx" field.

Introduce GetBlockFields(RPCResult tx_result) to build the full
block result structure while substituting the appropriate "tx"
definition in the correct position. This avoids ELISION prose and
also avoids the duplicate "tx" field a naive Cat() approach would
produce.

Remove the now-unused getblock_vin helper.
The "removed" array in listsinceblock is described with an ELISION
entry referring to the "transactions" array layout. This is clear in
human-readable help, but it leaves the result structure implicit.

Extract ListSinceBlockTxFields() and use it for both arrays so the
transaction layout is defined once and represented explicitly in
RPCHelpMan metadata.
Copy link
Member

@maflcko maflcko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left some nits

* @param[in] opts Selects which optional fields to include
*
* @return A vector of RPCResult describing the decoded transaction object
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit in e9072d1: I think the comment is a bit long. The function should be pretty self-explanatory and a very brief comment should be sufficient:

/// Explain the UniValue "decoded" transaction object, some fields are adjusted according to the passed @p opts.

* default to false so callers only need to name the ones they enable:
*
* TxDoc({.prevout = true, .hex = true})
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit in e9072d1: Same here. I think this can be removed. Also, "all default to false" may not be accurate, if the type is std::string or std::optional.

Maybe remove or:

/// Options controlling some fields in TxDoc(). Callers only need to name the ones they enable:
///
/// TxDoc({.prevout = true, .hex = true})

(Also changed to the doxygen /// comment format, because the /** is a bit ugly, when the text starts inconsistently and is inconsistently indented)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, in the same commit: It could be easier to review if the commit adding the option also made use of it at the same time. Otherwise, this looks like dead code.

That is, adding prevout option to TxDoc could be done in the commit f225a25, which makes use of it.

The result description for estimaterawfee currently uses ELISION
entries to describe repeated structures for fee horizons and bucket
ranges. This keeps bitcoin-cli help compact, but leaves the full
result layout implicit in RPCHelpMan metadata.

Extract FeeRateBucketDoc() and FeeEstimateHorizonDoc() helpers to
define the shared result structure once and reuse it for the
"short", "medium", and "long" horizons.

Use print_elision on repeated fields so bitcoin-cli help remains
compact while the structured result metadata stays explicit.

No behavior change.
@satsfy satsfy marked this pull request as draft March 12, 2026 20:17
@satsfy
Copy link
Author

satsfy commented Mar 12, 2026

In light of @maflcko’s work in #34799, I’m adjusting this PR so the result structure remains explicit in metadata without worsening the human-readable help output.

I’ve already updated estimaterawfee. After re-checking getaddressinfo.embedded, I think its currently documented shape can also be made explicit here, so I plan to include that as well. I’ll also cover the remaining related case in importdescriptors and clean up the documentation diffs affecting getblock and listsinceblock.

The goal remains the same: make these result layouts fully specified in code while avoiding unnecessary user-visible help churn.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants