Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rpc: treat univalue type check error as RPC_TYPE_ERROR, not RPC_MISC_ERROR #25737

Merged
merged 2 commits into from
Sep 21, 2022

Conversation

furszy
Copy link
Member

@furszy furszy commented Jul 29, 2022

Same rationale as #26039, tackling another angle of the problem.

Context

We have the same univalue type error checking code spread/duplicated few times:
RPCTypeCheckObj, RPCTypeCheckArgument, UniValue::checkType.

In the first two functions, we are properly returning an RPC_TYPE_ERROR while in UniValue::checkType
we are throwing an std::runtime_error which is caught by the RPC server request handler, who invalidly
treats it as RPC_MISC_ERROR (which is a generic error return code that provides no information to the user).

Proposed Changes

Throw a custom exception from Univalue::checkType (instead of a plain
std::runtime_error) and catch it on the RPC server request handler.

So we properly return RPC_TYPE_ERROR (-3) on every arg type error and
not the general RPC_MISC_ERROR (-1).

This will allow us to remove all the RPCTypeCheckArgument calls. As them are redundant since #25629.

@fanquake
Copy link
Member

In https://cirrus-ci.com/task/5952817063002112 (mempool_accept.py):

 test  2022-07-29T13:45:02.711000Z TestFramework (ERROR): Assertion failed 
                                   Traceback (most recent call last):
                                     File "/tmp/cirrus-ci-build/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/test/functional/test_framework/util.py", line 135, in try_rpc
                                       fun(*args, **kwds)
                                     File "/tmp/cirrus-ci-build/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/test/functional/mempool_accept.py", line 68, in <lambda>
                                       assert_raises_rpc_error(-3, 'JSON value of type string is not of expected type array', lambda: node.testmempoolaccept(rawtxs='ff00baar'))
                                     File "/tmp/cirrus-ci-build/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/test/functional/test_framework/coverage.py", line 49, in __call__
                                       return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs)
                                     File "/tmp/cirrus-ci-build/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/test/functional/test_framework/authproxy.py", line 144, in __call__
                                       raise JSONRPCException(response['error'], status)
                                   test_framework.authproxy.JSONRPCException: Expected type array, got string (-3)
                                   During handling of the above exception, another exception occurred:
                                   Traceback (most recent call last):
                                     File "/tmp/cirrus-ci-build/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/test/functional/test_framework/test_framework.py", line 133, in main
                                       self.run_test()
                                     File "/tmp/cirrus-ci-build/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/test/functional/mempool_accept.py", line 68, in run_test
                                       assert_raises_rpc_error(-3, 'JSON value of type string is not of expected type array', lambda: node.testmempoolaccept(rawtxs='ff00baar'))
                                     File "/tmp/cirrus-ci-build/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/test/functional/test_framework/util.py", line 126, in assert_raises_rpc_error
                                       assert try_rpc(code, message, fun, *args, **kwds), "No exception raised"
                                     File "/tmp/cirrus-ci-build/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/test/functional/test_framework/util.py", line 143, in try_rpc
                                       message, e.error['message']))
                                   AssertionError: Expected substring not found in error message:
                                   substring: 'JSON value of type string is not of expected type array'
                                   error message: 'Expected type array, got string'.

@furszy furszy force-pushed the 2022_rpc_remove_type_check branch from 8a8583d to a3e5674 Compare July 29, 2022 13:50
@furszy
Copy link
Member Author

furszy commented Jul 29, 2022

thx @fanquake, pushed 👍🏼.

Copy link
Member

@jonatack jonatack left a comment

Choose a reason for hiding this comment

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

Would it make sense to first adapt the UniValue error messages so that these remain the same for client software? Otherwise this seems like it would be needlessly changing user space.

@furszy furszy force-pushed the 2022_rpc_remove_type_check branch 2 times, most recently from c2cc1db to 0e5e63c Compare July 29, 2022 17:27
@furszy
Copy link
Member Author

furszy commented Jul 29, 2022

Would it make sense to first adapt the UniValue error messages so that these remain the same for client software? Otherwise this seems like it would be needlessly changing user space.

good point @jonatack. Will move into that direction.

still, the new error introduced in #25629 is much more descriptive, and helpful for the user, than the current one. Might be good to deprecate the old one and move to the new format.

@furszy furszy force-pushed the 2022_rpc_remove_type_check branch 5 times, most recently from 1fbf520 to 53ce3b8 Compare July 29, 2022 20:00
@fanquake
Copy link
Member

good point @jonatack. Will move into that direction.
still, the new error introduced in #25629 is much more descriptive, and helpful for the user, than the current one. Might be good to deprecate the old one and move to the new format.

I really don't think we need to revert these changes (£25629), or have any sort of "deprecation" for the older messages.

@DrahtBot
Copy link
Contributor

DrahtBot commented Jul 29, 2022

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

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #26039 (rpc: Return RPC_TYPE_ERROR, not RPC_MISC_ERROR on type mismatch (1/2) by MarcoFalke)
  • #25429 (refactor: Avoid UniValue copies by MarcoFalke)
  • #23319 (rpc: Return fee and prevout (utxos) to getrawtransaction by dougEfresh)

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.

@furszy
Copy link
Member Author

furszy commented Jul 30, 2022

good point @jonatack. Will move into that direction.
still, the new error introduced in #25629 is much more descriptive, and helpful for the user, than the current one. Might be good to deprecate the old one and move to the new format.

I really don't think we need to revert these changes (£25629), or have any sort of "deprecation" for the older messages.

Thinking about this for a second time, and.. agree. It doesn't make sense to build any client based on a json parsing error.. if the RPC command is expecting an int and receives a string, it will always fail and never execute the command. So the new error description shouldn't affect anyone. Will just drop the first commit.

@furszy furszy force-pushed the 2022_rpc_remove_type_check branch from 53ce3b8 to d48f5d1 Compare July 30, 2022 15:17
@jonatack
Copy link
Member

If we really want to change user space, would it make sense to opt for the most frequently used of the error message formats currently, and the shortest and most straightforward one?

@jonatack
Copy link
Member

(See #24944 (comment) for a list of RPCs.)

@furszy furszy force-pushed the 2022_rpc_remove_type_check branch from d48f5d1 to 133fa8a Compare July 31, 2022 13:27
@furszy
Copy link
Member Author

furszy commented Jul 31, 2022

If we really want to change user space, would it make sense to opt for the most frequently used of the error message formats currently, and the shortest and most straightforward one?

Right now, we are throwing two different errors for the same problematic.

  1. "Expected type {expected], got {type}"
  2. "JSON value of type {type} is not of expected type {expected}"

This PR aims to drop the first one as it is less informative than the second one.

Note: aside from this changes, we still have the first error in RPCTypeCheckObj.

@furszy furszy force-pushed the 2022_rpc_remove_type_check branch from 133fa8a to d54f65c Compare July 31, 2022 13:48
Copy link
Member

@aureleoules aureleoules left a comment

Choose a reason for hiding this comment

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

ACK d54f65c.
Verified that RPCTypeCheckArgument calls are redundant.
+1 for unifying error messages.

src/rpc/util.cpp Outdated Show resolved Hide resolved
@jarolrod
Copy link
Member

concept ack

@@ -605,7 +605,6 @@ static RPCHelpMan gettxspendingprevout()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
RPCTypeCheckArgument(request.params[0], UniValue::VARR);
Copy link
Member

Choose a reason for hiding this comment

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

why is this redundant?

Copy link
Member Author

Choose a reason for hiding this comment

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

oops, great catch. There is another one in coins.cpp. Pushing..

Copy link
Member

Choose a reason for hiding this comment

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

Now you changed the error code from -3 to -1, effectively the opposite of what #26039 is doing

Copy link
Member Author

Choose a reason for hiding this comment

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

true.. general exceptions are -1, while this is a type error.

We could throw a custom exception on the UniValue type check to catch all of them as type errors.

But.. I'm more inclined to close this PR and directly go ahead with moving the type checks responsibility to the request handler (which seems that is what you are doing in #26039).
Haven't checked if there is any restriction there but we do have each arg type on the help info object, so.. we could use that to verify every arg type.

Copy link
Member

Choose a reason for hiding this comment

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

now you are changing the behavior in commit 8bdd192 and then reverting the behavior change in the next commit?

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.

.

@maflcko
Copy link
Member

maflcko commented Sep 13, 2022

I think both can be done independently

sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Sep 13, 2022
2870a97 RPC: unify arg type error message (furszy)

Pull request description:

  Decoupled from bitcoin#25737 per request.

  We are throwing two different error descriptions for the same problematic:

  1) "Expected type {expected], got {type}" --> `RPCTypeCheckArgument()`
  2) "JSON value of type {type} is not of expected type {expected}" --> `UniValue::checkType()`

ACKs for top commit:
  MarcoFalke:
    review ACK 2870a97
  fanquake:
    ACK 2870a97

Tree-SHA512: 9ac863243b6b7687986c0394611b5cad8b35424ec49d82195d536f2a5e64c60327b25f0dc7336189f86fd71122689c7309da49adfa93805d2e345693fa8efa9b
@furszy furszy force-pushed the 2022_rpc_remove_type_check branch 2 times, most recently from 8d56cf9 to 9b63460 Compare September 14, 2022 15:18
@furszy furszy changed the title rpc: remove redundant univalue type checks rpc: custom univalue type exception + remove redundant univalue type checks Sep 14, 2022
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 two nits

src/univalue/include/univalue.h Outdated Show resolved Hide resolved
src/rpc/util.cpp Outdated
}
i++;
}
}

void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected)
Copy link
Member

Choose a reason for hiding this comment

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

not really a fan of removing this, given that this is needed for #26039

Copy link
Member Author

Choose a reason for hiding this comment

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

Left you a comment there, #26039 (comment).
I think that we shouldn't continue having the type error string defined in two different places.

Copy link
Member

Choose a reason for hiding this comment

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

I am removing RPCTypeCheck and you are adding the type error string to RPCTypeCheck. So I don't see how the changes here require removing it or help in any way to reducing it to one place.

Copy link
Member

Choose a reason for hiding this comment

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

Also, unrelated: RPCTypeCheckObj has a third and different type error string?

Copy link
Member Author

@furszy furszy Sep 14, 2022

Choose a reason for hiding this comment

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

I am removing RPCTypeCheck and you are adding the type error string to RPCTypeCheck. So I don't see how the changes here require removing it or help in any way to reducing it to one place.

Yeah, it's not really needed here. I was pointing out that, as you are removing RPCTypeCheck, and I'm removing RPCTypeCheckArgument here, we could also reduce the error string duplication there as well.

But.. I could also implement the changes here too..
So yeah, probably better to leave it up for another PR and done.

Also, unrelated: RPCTypeCheckObj has a third and different type error string?

Yeah, I mentioned it in one of the first comments here #25737 (comment) and then forgot about it.
Could fix it on the follow-up Univalue::checkType unification PR.

@maflcko
Copy link
Member

maflcko commented Sep 14, 2022

Also, the tests fail

@furszy furszy force-pushed the 2022_rpc_remove_type_check branch 2 times, most recently from 5032c39 to 153f465 Compare September 14, 2022 22:05
@maflcko
Copy link
Member

maflcko commented Sep 15, 2022

It would be good to explain the behavior change in the title, not summarize the detailed code changes. If someone was interested in the detailed code changes they could look at them, or you could summarize them in the commit/pull description.

Also, it would help reviewers if you explained for each commit whether it is a refactor or behavior change. This helps to document whether a change was intentional or not.

@furszy
Copy link
Member Author

furszy commented Sep 15, 2022

It would be good to explain the behavior change in the title, not summarize the detailed code changes. If someone was interested in the detailed code changes they could look at them, or you could summarize them in the commit/pull description.

Sure, the lack of scope in the PR description is mainly because this started as a simple redundant code removal (which didn't require much text) and then we realized that for making the cleanup, needed to properly return RPC_TYPE_ERROR instead of RPC_MISC_ERROR in the inner univalue type check.

Also, it would help reviewers if you explained for each commit whether it is a refactor or behavior change. This helps to document whether a change was intentional or not.

Sure.

…ERROR

By throwing a custom exception from `Univalue::checkType` (instead of a plain
std::runtime_error) and catching it on the RPC server request handler.

So we properly return RPC_TYPE_ERROR (-3) on arg type errors and
not the general RPC_MISC_ERROR (-1).
@furszy furszy changed the title rpc: custom univalue type exception + remove redundant univalue type checks rpc: treat univalue type check error as RPC_TYPE_ERROR, not RPC_MISC_ERROR Sep 15, 2022
No-behavior change.

Since bitcoin#25629, we check the univalue type internally.
@furszy
Copy link
Member Author

furszy commented Sep 15, 2022

Updated per feedback.

@fanquake fanquake merged commit b1f44ec into bitcoin:master Sep 21, 2022
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Sep 23, 2022
…_ERROR, not RPC_MISC_ERROR

e68d380 rpc: remove unneeded RPCTypeCheckArgument checks (furszy)
5556663 rpc: treat univalue type check error as RPC_TYPE_ERROR, not RPC_MISC_ERROR (furszy)

Pull request description:

  Same rationale as bitcoin#26039, tackling another angle of the problem.

  #### Context
  We have the same univalue type error checking code spread/duplicated few times:
  `RPCTypeCheckObj`, `RPCTypeCheckArgument`, `UniValue::checkType`.

  In the first two functions, we are properly returning an `RPC_TYPE_ERROR` while in `UniValue::checkType`
  we are throwing an `std::runtime_error` which is caught by the RPC server request handler, who invalidly
  treats it as `RPC_MISC_ERROR` (which is a generic error return code that provides no information to the user).

  #### Proposed Changes

  Throw a custom exception from `Univalue::checkType` (instead of a plain
  `std::runtime_error`) and catch it on the RPC server request handler.

  So we properly return `RPC_TYPE_ERROR` (-3) on every arg type error and
  not the general `RPC_MISC_ERROR` (-1).

  This will allow us to remove all the `RPCTypeCheckArgument` calls. As them are redundant since bitcoin#25629.

Top commit has no ACKs.

Tree-SHA512: 4e4c41851fd4e2b01a2d8b94e71513f9831f810768ebd89684caca4901e87d3677980003949bcce441f9ca607a1b38a5894839b6c492f5947b8bab8cd9423ba6
maflcko pushed a commit to maflcko/bitcoin-core that referenced this pull request Nov 14, 2022
2dede9f Adjust RPCTypeCheckObj error string (Leonardo Araujo)

Pull request description:

  Unifies the JSON type error strings as mentioned in bitcoin#26214. Also refer to bitcoin#25737.

ACKs for top commit:
  furszy:
    ACK 2dede9f

Tree-SHA512: c918889e347ba32cb6d0e33c0de5956c2077dd40c996151e16741b0c4983ff098c60258206ded76ad7bbec4876c780c6abb494a97e4f1e05717d28a59b9167a6
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Nov 14, 2022
2dede9f Adjust RPCTypeCheckObj error string (Leonardo Araujo)

Pull request description:

  Unifies the JSON type error strings as mentioned in bitcoin#26214. Also refer to bitcoin#25737.

ACKs for top commit:
  furszy:
    ACK 2dede9f

Tree-SHA512: c918889e347ba32cb6d0e33c0de5956c2077dd40c996151e16741b0c4983ff098c60258206ded76ad7bbec4876c780c6abb494a97e4f1e05717d28a59b9167a6
@furszy furszy deleted the 2022_rpc_remove_type_check branch May 27, 2023 01:48
@bitcoin bitcoin locked and limited conversation to collaborators May 26, 2024
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.

7 participants