Skip to content

Conversation

achow101
Copy link
Member

There are some RPCs where the argument can be either JSON that needs to be parsed, or a string that we can pass straight through. However, bitcoin-cli would always parse those arguments as JSON which makes for some cumbersome argument passing when using those RPCs. Notably, hash_or_height in getblockstats and gettxoutsetinfo do this, and results in a more cumbersome command of bitcoin-cli getblockstats '"<hash>"'. Otherwise, using a normal invocation of bitcoin-cli getblockstats <hash> results in error: Error parsing JSON. This PR marks those particular options as also being a string so that when bitcoin-cli fails to parse the argument as JSON, it will assume that the argument is a string and pass it straight through.

@DrahtBot
Copy link
Contributor

DrahtBot commented Aug 20, 2025

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

Code Coverage & Benchmarks

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

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK pablomartin4btc, kannapoix, enirox001
Concept ACK nervana21
Approach ACK w0xlt
Stale ACK kevkevinpal

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

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #33192 (refactor: unify container presence checks (without PR conflicts) by l0rinc)
  • #33031 (wallet: Set descriptor cache upgraded flag for migrated wallets by achow101)
  • #32928 (test: add logging to mock external signers by Sjors)
  • #32821 (rpc: Handle -named argument parsing where '=' character is used by zaidmstrr)
  • #32784 (wallet: derivehdkey RPC to get xpub at arbitrary path by Sjors)

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.

@DrahtBot
Copy link
Contributor

🚧 At least one of the CI tasks failed.
Task lint: https://github.com/bitcoin/bitcoin/runs/48530907189
LLM reason (✨ experimental): The CI failure is caused by a linting error detected by ruff due to an unused import in the Python test code.

Hints

Try to run the tests locally, according to the documentation. However, a CI failure may still
happen due to a number of reasons, for example:

  • Possibly due to a silent merge conflict (the changes in this pull request being
    incompatible with the current code in the target branch). If so, make sure to rebase on the latest
    commit of the target branch.

  • A sanitizer issue, which can only be found by compiling with the sanitizer and running the
    affected test.

  • An intermittent issue.

Leave a comment here, if you need help tracking down a confusing failure.

@achow101 achow101 force-pushed the cli-strong-or-json branch from 01039d3 to aabf1f6 Compare August 20, 2025 21:40
@ryanofsky
Copy link
Contributor

Seems like a reasonable change. I wonder if an alternate solution might have the client treat hash_or_height as a string parameter instead of a JSON parameter, and update the server to accept height strings? But I guess that might not be backwards compatible if there are old scripts calling bitcoin-cli with extra quotes around the hash string.

@polespinasa
Copy link
Contributor

polespinasa commented Aug 20, 2025

I wonder if an alternate solution might have the client treat hash_or_height as a string parameter instead of a JSON parameter, and update the server to accept height strings?

Even if there is, there are other use cases taking lists and strings as parameters. See: #32468

Copy link
Contributor

@w0xlt w0xlt left a comment

Choose a reason for hiding this comment

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

Approach ACK

Copy link
Member

@pablomartin4btc pablomartin4btc left a comment

Choose a reason for hiding this comment

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

ACK aabf1f6

This is quite practical, went thru these errors.

Copy link
Member

@luke-jr luke-jr left a comment

Choose a reason for hiding this comment

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

I guess this basically works for the existing params, since a block hash is never valid JSON (which forbids leading zeros), but could be dangerous to use for new parameters that are ambiguous.

With that in mind, it might be worth instead having a new RPCResult::Type::BLOCK_HEIGHT_OR_HASH type to sanity check this. Or at least a warning comment (but I don't know where you'd put it to ensure it's seen).

@@ -32,7 +32,7 @@ def process_mapping(fname):
if line.startswith('};'):
in_rpcs = False
elif '{' in line and '"' in line:
m = re.search(r'{ *("[^"]*"), *([0-9]+) *, *("[^"]*") *},', line)
m = re.search(r'{ *("[^"]*"), *([0-9]+) *, *("[^"]*") *(, \/\*also_string=\*\/true *)?},', line)
Copy link
Member

Choose a reason for hiding this comment

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

Might be a good idea to actually test this is correct?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is here because the test fails without it.

luke-jr pushed a commit to bitcoinknots/bitcoin that referenced this pull request Aug 22, 2025
@achow101
Copy link
Member Author

I guess this basically works for the existing params, since a block hash is never valid JSON (which forbids leading zeros), but could be dangerous to use for new parameters that are ambiguous.

I don't think we have any types where that would be the case. But this is also something that needs to be turned on for a parameter explicitly, so I don't expect this to be problematic.

With that in mind, it might be worth instead having a new RPCResult::Type::BLOCK_HEIGHT_OR_HASH type to sanity check this.

Part of the impetus for this is #32468 where the parameter can be either is a JSON array or a string, so something that is more generic is better.

Or at least a warning comment (but I don't know where you'd put it to ensure it's seen).

I think with it being default off makes that not really necessary.

@nervana21
Copy link
Contributor

nervana21 commented Aug 23, 2025

Concept ACK

@kannapoix
Copy link

kannapoix commented Aug 23, 2025

ACK aabf1f6

nit: It may be a good idea to also update the example command in the help message of getblockstats. Given that this PR eliminates the need for quotes around arguments, it would be good to update the example accordingly by using plain text instead of the quoted format.

HelpExampleCli("getblockstats", R"('"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"' '["minfeerate","avgfeerate"]')") +

@kevkevinpal
Copy link
Contributor

ACK 111938c

This change makes sense. I've definitely run into this issue, and being able to use a regular string is less confusing

I checked that with the change to src/rpc/client.cpp, the old tests using convert_to_json_for_cli still passed.

I was wondering if it makes sense to keep one test using convert_to_json_for_cli to ensure that these parameters can still be used as JSON for backward compatibility.

{ "gettxoutsetinfo", 2, "use_index"},
{ "dumptxoutset", 2, "options" },
{ "dumptxoutset", 2, "rollback" },
{ "dumptxoutset", 2, "rollback", /*also_string=*/true },
Copy link
Contributor

Choose a reason for hiding this comment

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

Will this entry have an effect? In the positional map members, the key ("dumptxoutset", 2) is first set to false. My understanding is that subsequent encounters of the same key are ignored by std::map::emplace. Is this the desired behavior, or should the subsequent value overwrite the first?

{ "dumptxoutset", 2, "options", /*also_string=*/false }, // inserted
{ "dumptxoutset", 2, "rollback", /*also_string=*/true }, // ignored or used to overwrite?

@DrahtBot DrahtBot requested a review from nervana21 August 29, 2025 02:07
Copy link
Contributor

@enirox001 enirox001 left a comment

Choose a reason for hiding this comment

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

ACK aabf1f6 — improves CLI ergonomics for mixed JSON/string RPC params

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.