Skip to content

Conversation

@ryanofsky
Copy link
Contributor

Just pass arguments that can't be parsed as JSON as string arguments. If the
RPC method isn't expecting a string argument, this will result in more specific
errors from the RPC. And if it allows an argument to be a string as one
possible type (for example the hash_or_height argument to getblockstats),
this avoids the need for bitcoin-cli users to use double JSON quoting+shell
quoting to pass the string.

Just pass arguments that can't be parsed as JSON as string arguments. If the
RPC method isn't expecting a string argument, this will result in more specific
errors from the RPC. And if it allows an argument to be a string as one
possible type (for example the `hash_or_height` argument to `getblockstats`),
this avoids the need for bitcoin-cli users to use double JSON quoting+shell
quoting to pass the string.
@promag
Copy link
Contributor

promag commented Feb 20, 2019

I think this approach is fine, unless there is an use case where the end result would be really bad - which I don't believe there is.

Concept ACK from me.

@maflcko
Copy link
Member

maflcko commented Feb 20, 2019

If this is conceptually ACKed, the now unused ParseNonRFCJSONValue should be removed

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.

Tested ACK 45c743

This is effectively moving the type check from the client to the server (unparsable json will get send as string). I guess this is fine

# type check is moved to server
$ for i in {master,45c743}; do ./src/bitcoin-cli-$i -regtest getrawtransaction ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff True ffff  ; done
error: Error parsing JSON:True

error code: -1
error message:
JSON value is not a boolean as expected


# test conversion
$ for i in {master,45c743}; do ./src/bitcoin-cli-$i -regtest echojson true 1 '"str"' '[1,2]' '{"a":1}'  ; done
[
  true,
  1,
  "str",
  [
    1,
    2
  ],
  {
    "a": 1
  }
]
[
  true,
  1,
  "str",
  [
    1,
    2
  ],
  {
    "a": 1
  }
]

# test no conversion
$ for i in {master,45c743}; do ./src/bitcoin-cli-$i -regtest echo true 1 '"str"' '[1,2]' '{"a":1}'  ; done
[
  "true",
  "1",
  "\"str\"",
  "[1,2]",
  "{\"a\":1}"
]
[
  "true",
  "1",
  "\"str\"",
  "[1,2]",
  "{\"a\":1}"
]

# test conversion with invalid json
$ for i in {master,45c743}; do ./src/bitcoin-cli-$i -regtest echojson True  ; done
error: Error parsing JSON:True
[
  "True"
]


if (!rpcCvtTable.convert(strMethod, idx)) {
UniValue json_value;
if (!rpcCvtTable.convert(strMethod, idx) || !json_value.read(strVal)) {
Copy link
Member

Choose a reason for hiding this comment

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

Seems odd to have two inversions in a condition. Would be easier to write

if convert() and read():
 # push back parsed value
else:
 # push back str

Copy link
Contributor

Choose a reason for hiding this comment

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

Keep diff small? 👼 But agree.

@jgarzik
Copy link
Contributor

jgarzik commented Feb 20, 2019

This is effectively moving the type check from the client to the server (unparsable json will get send as string)

Agree. This matches a common frontend validation pattern:

The server must validate and reject garbage. (1) Thus one option is to lean on the remote server to perform that validation.

However, it is often better UX -- and potentially saves users $$ in bandwidth, and saves server CPU cycles -- to (2) avoid sending data the client can prove, via its own validation, is known garbage data.

Yes, this is double validation; but the 90+% common case is rejected on the client side, remaining efficient by sending no garbage over the network.

@ryanofsky
Copy link
Contributor Author

Will wait for concept acks & nacks before working more on this. To summarize comments so far:

Advantages of this change

  1. More usable bitcoin-cli getblockstats command, no longer requiring double json+shell quoting. Other rpc methods could benefit similarly since nothing about this change is specific to getblockstats.
  2. Potentially improved error reporting. Server side error reporting can be more customized and provide context.
  3. Simplified bitcoin-cli logic. Gets rid of thrown exception.

Disadvantages of this change

  1. Increased latency and bandwidth (in error case only) since errors now handled server side.
  2. Potentially worse error reporting in the future. bitcoin-cli error reporting is bad now, but if it's removed entirely, there's loss of opportunity to improve it in the future.

Potential followups

  1. bitcoin-cli: Eliminate "Error parsing JSON" errors #15448 (comment): logic should be inverted for clarity
  2. bitcoin-cli: Eliminate "Error parsing JSON" errors #15448 (comment): unused ParseNonRFCJSONValue function should be removed
  3. Should have python test for new bitcoin-cli behavior.

@maflcko
Copy link
Member

maflcko commented Feb 20, 2019

I don't think we should be optimizing for bandwidth in the error case, which can only happen when a developer debugs locally.

@practicalswift
Copy link
Contributor

Concept ACK

In this case I think we should optimise for user-friendliness.

@jonasschnelli
Copy link
Contributor

Concept ACK

@laanwj
Copy link
Member

laanwj commented Feb 21, 2019

I'm kind of skeptical about this, to be honest. I prefer strong validation both client and server side, from my experience, lazy "anything goes" validation (in this case "let the server sort them out") has resulted in quite some unexpected disasters. At the least it makes it harder to reason about what things will do, in advance.

@Empact
Copy link
Contributor

Empact commented Mar 7, 2019

Looks like this removed all remaining calls to ParseNonRFCJSONValue, so it can be removed.

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

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

ACK 45c7439, above comment #15448 (comment) looks good.

Should have python test for new bitcoin-cli behavior.

👍

has resulted in quite some unexpected disasters.

@laanwj like what? Preventing disasters and client validation sound like 2 different things and pretty much unrelated. But better safe than sorry? No strong opinion.


if (!rpcCvtTable.convert(strMethod, idx)) {
UniValue json_value;
if (!rpcCvtTable.convert(strMethod, idx) || !json_value.read(strVal)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Keep diff small? 👼 But agree.


if (!rpcCvtTable.convert(strMethod, name)) {
UniValue json_value;
if (!rpcCvtTable.convert(strMethod, name) || !json_value.read(value)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above.

@laanwj
Copy link
Member

laanwj commented Jun 25, 2019

@laanwj like what? Preventing disasters and client validation sound like 2 different things and pretty much unrelated. But better safe than sorry? No strong opinion.

Defense in depth, belt and suspenders, etc.

I mean the underlying issue is that there is an ambiguity, and resolving this ambiguity is here moved from the client to the server, which isn't always better. It's better if both the client and server know what the interpretation of some value is. SQL injection attacks are a well-known problem that is caused by trusting that the server will the right thing when you just pass the value as-is.

@DrahtBot DrahtBot closed this Mar 9, 2020
@DrahtBot DrahtBot reopened this Mar 9, 2020
maflcko pushed a commit that referenced this pull request Apr 20, 2020
7099984 rpc: doc: Fix and extend getblockstats examples (Adam Soltys)

Pull request description:

  This pull fixes the example curl command for `getblockstats` which doesn't work as is because it's missing a comma between the params and has single quotes around the second parameter.

  It also adds an additional example of getting block stats by hash by using a known workaround (#15412) to get bitcoin-cli to treat the hash parameter as JSON instead of a string since there is ongoing deliberation about how or whether to fix the root issue (#15448).

ACKs for top commit:
  theStack:
    ACK 7099984

Tree-SHA512: 84a5b7f449f06fff785bc0afbc1a7dfd55454bc76c52a8945e91556f87f3edfdc5a1780faab8fcfd6c415b734295b7c67d2e04ba7b6cfa91a77758af5dda53ae
ftrader pushed a commit to bitcoin-cash-node/bitcoin-cash-node that referenced this pull request Aug 17, 2020
Just pass arguments that can't be parsed as JSON as string arguments. If the
RPC method isn't expecting a string argument, this will result in more specific
errors from the RPC. And if it allows an argument to be a string as one
possible type (for example the `hash_or_height` argument to `getblockstats`),
this avoids the need for bitcoin-cli users to use double JSON quoting+shell
quoting to pass the string.

This is a port of bitcoin/bitcoin#15448

Includes several adaptations by Andrea Suisani:

- Remove unused ParseNonRFCJSONValue and related unit tests
- Avoid double inversion in the same if condition
- Functional test adaptation

Merge #15488: bitcoin-cli: Eliminate "Error parsing JSON" errors

Test plan:

- On a version without this patch (!446), run `bitcoin-cli getblockstats 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f` (passing the hash value without quotes ), and observe you get the following error message from the command line program:
  `error: Error parsing JSON:000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f`
- On a version with this patch, run the above command and you should get block statistics JSON output instead of the error message.
- Run `test/functional/test_runner.py interface_bitcoin_cli_getblockstats` - it should pass.
@promag
Copy link
Contributor

promag commented Sep 21, 2020

@laanwj this just pretends the client typed "" - it fallbacks the argument to string which seems natural considering this is a command line tool.

@ryanofsky just wrote 4c19cf5 but then I've realised it's pretty much the same as this.

@DrahtBot
Copy link
Contributor

DrahtBot commented Sep 22, 2020

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

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #19949 (cli: Parse and allow hash value by fjahr)

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.

@Sjors Sjors mentioned this pull request Oct 9, 2020
@laanwj
Copy link
Member

laanwj commented Nov 23, 2020

@laanwj this just pretends the client typed "" - it fallbacks the argument to string which seems natural considering this is a command line tool.

That's my problem with it "pretends the client typed". If it is purely a user-facing tool like a GUI it might be different (still, it's often better not to guess at intent). The problem is that tools like this are also used in scripts and such, and they might deal with (partially) untrusted input. I think determinism and predictability is very important in input processing.

PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Dec 28, 2021
7099984 rpc: doc: Fix and extend getblockstats examples (Adam Soltys)

Pull request description:

  This pull fixes the example curl command for `getblockstats` which doesn't work as is because it's missing a comma between the params and has single quotes around the second parameter.

  It also adds an additional example of getting block stats by hash by using a known workaround (bitcoin#15412) to get bitcoin-cli to treat the hash parameter as JSON instead of a string since there is ongoing deliberation about how or whether to fix the root issue (bitcoin#15448).

ACKs for top commit:
  theStack:
    ACK bitcoin@7099984

Tree-SHA512: 84a5b7f449f06fff785bc0afbc1a7dfd55454bc76c52a8945e91556f87f3edfdc5a1780faab8fcfd6c415b734295b7c67d2e04ba7b6cfa91a77758af5dda53ae
@kallewoof
Copy link
Contributor

Concept ACK

@achow101
Copy link
Member

Closing this as it has not had any activity in a while. If you are interested in continuing work on this, please leave a comment so that it can be reopened.

@achow101 achow101 closed this Oct 12, 2022
@bitcoin bitcoin deleted a comment from DrahtBot Oct 13, 2022
@bitcoin bitcoin locked and limited conversation to collaborators Oct 13, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.