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

refactor: Run type check against RPCArgs (1/2) #26039

Merged
merged 2 commits into from Jan 17, 2023

Conversation

maflcko
Copy link
Member

@maflcko maflcko commented Sep 7, 2022

It seems brittle to require RPCTypeCheck being called inside the code logic. Without compile-time enforcement this will lead to places where it is forgotten and thus to inconsistencies and bugs. Fix this by removing the calls to RPCTypeCheck and doing the check internally.

The changes should be reviewed as refactoring changes. However, if they change behavior, it will be a bugfix. For example the changes here happen to also detect/fix bugs like the one fixed in commit 3b5fb6e.

@DrahtBot
Copy link
Contributor

DrahtBot commented Sep 8, 2022

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
ACK ajtowns
Concept ACK fanquake, luke-jr, w0xlt
Stale ACK furszy

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:

  • #26863 (test: merge banning test from p2p_disconnect_ban to rpc_setban by brunoerg)
  • #26469 (rpc: getblock: implement with block height as input parameter. by russeree)
  • #25943 (rpc: Add a parameter to sendrawtransaction which sets a maximum burned output for OP_RETURN transactions. by davidgumberg)
  • #25939 (rpc: In utxoupdatepsbt also look for the tx in the txindex by ishaanam)
  • #25796 (rpc: add descriptorprocesspsbt rpc by ishaanam)
  • #25429 (refactor: Avoid UniValue copies by MarcoFalke)
  • #25344 (New outputs argument for bumpfee/psbtbumpfee by rodentrabies)
  • #25093 (rpc: Check for omitted, but required parameters by MarcoFalke)
  • #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.

@amovfx
Copy link

amovfx commented Sep 9, 2022

Is this something that I can help out on? I'm looking for another task. I don't know of the etiquette of hoping on a drafted pull request.

Copy link

@amovfx amovfx left a comment

Choose a reason for hiding this comment

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

From what I gather this is a large refactor with the removal of the RPCTypeCheck functions all over the place?

@fanquake
Copy link
Member

Concept ACK

@luke-jr
Copy link
Member

luke-jr commented Sep 10, 2022

Concept ACK, but this feels like it's doing too much additional. It might be nice to have something minimal we can backport?

@maflcko
Copy link
Member Author

maflcko commented Sep 12, 2022

Not sure if we want to backport this, but this should already be minimal. A fragile alternative would be to add RPCTypeCheck to every RPC that is missing it, with no compile-time guarantee that all have been covered.

@w0xlt
Copy link
Contributor

w0xlt commented Sep 13, 2022

Concept ACK.

src/rpc/util.cpp Outdated Show resolved Hide resolved
@luke-jr
Copy link
Member

luke-jr commented Sep 21, 2022

Not sure if we want to backport this, but this should already be minimal. A fragile alternative would be to add RPCTypeCheck to every RPC that is missing it, with no compile-time guarantee that all have been covered.

Shouldn't we be able to just adjust the return code?

@maflcko
Copy link
Member Author

maflcko commented Sep 21, 2022

Yes, see #25737 (rpc: treat univalue type check error as RPC_TYPE_ERROR, not RPC_MISC_ERROR by furszy)

fanquake added a commit that referenced this pull request Sep 21, 2022
… 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 #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.

Top commit has no ACKs.

Tree-SHA512: 4e4c41851fd4e2b01a2d8b94e71513f9831f810768ebd89684caca4901e87d3677980003949bcce441f9ca607a1b38a5894839b6c492f5947b8bab8cd9423ba6
Copy link
Member

@furszy furszy left a comment

Choose a reason for hiding this comment

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

diff ACK faa7522

Copy link
Member

@furszy furszy left a comment

Choose a reason for hiding this comment

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

diff utACK fa35405

@maflcko
Copy link
Member Author

maflcko commented Jan 11, 2023

rebased due to one-line conflict, should be trivial to re-ACK

Copy link
Contributor

@ajtowns ajtowns 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.

@@ -162,7 +162,7 @@ static std::vector<RPCArg> CreateTxDoc()
},
},
},
},
RPCArgOptions{.skip_type_check = true}},
Copy link
Contributor

Choose a reason for hiding this comment

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

Any reason to spell out RPCArgOptions rather than just writing {.skip_type_check = true} on its own?

Copy link
Member Author

Choose a reason for hiding this comment

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

Pretty sure this is needed due to a compiler bug

Copy link
Member Author

Choose a reason for hiding this comment

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

gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0:

/usr/bin/ccache g++ -std=c++17 -DHAVE_CONFIG_H -I. -I../src/config  -fmacro-prefix-map=/bitcoin-core=. -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -DHAVE_BUILD_INFO -DPROVIDE_FUZZ_MAIN_FUNCTION -I. -I./minisketch/include -I./secp256k1/include -I./univalue/include -I./leveldb/include -I/usr/include -DBOOST_MULTI_INDEX_DISABLE_SERIALIZATION -DBOOST_NO_CXX98_FUNCTION_BASE    -pthread   -fdebug-prefix-map=/bitcoin-core=. -fstack-reuse=none -Wstack-protector -fstack-protector-all -fcf-protection=full -fstack-clash-protection -Wall -Wextra -Wformat -Wformat-security -Wvla -Wredundant-decls -Wdate-time -Wduplicated-branches -Wduplicated-cond -Wlogical-op -Woverloaded-virtual -Wsuggest-override -Wimplicit-fallthrough -Wno-unused-parameter -Wno-deprecated-copy     -fno-extended-identifiers -fPIE -g -O2 -MT rpc/libbitcoin_node_a-blockchain.o -MD -MP -MF rpc/.deps/libbitcoin_node_a-blockchain.Tpo -c -o rpc/libbitcoin_node_a-blockchain.o `test -f 'rpc/blockchain.cpp' || echo './'`rpc/blockchain.cpp
rpc/blockchain.cpp: In function 'RPCHelpMan getblock()':
rpc/blockchain.cpp:760:5: error: conversion from '<brace-enclosed initializer list>' to 'RPCArg' is ambiguous
  760 |     };
      |     ^
In file included from ./rpc/server.h:10,
                 from rpc/blockchain.cpp:31:
./rpc/util.h:195:5: note: candidate: 'RPCArg::RPCArg(std::string, RPCArg::Type, RPCArg::Fallback, std::string, std::vector<RPCArg>, RPCArgOptions)'
  195 |     RPCArg(
      |     ^~~~~~
./rpc/util.h:180:5: note: candidate: 'RPCArg::RPCArg(std::string, RPCArg::Type, RPCArg::Fallback, std::string, RPCArgOptions)'
  180 |     RPCArg(
      |     ^~~~~~
In file included from /usr/include/c++/9/vector:67,
                 from ./core_io.h:11,
                 from ./rpc/blockchain.h:9,
                 from rpc/blockchain.cpp:6:
/usr/include/c++/9/bits/stl_vector.h:622:43: note:   initializing argument 1 of 'std::vector<_Tp, _Alloc>::vector(std::initializer_list<_Tp>, const allocator_type&) [with _Tp = RPCArg; _Alloc = std::allocator<RPCArg>; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<RPCArg>]'
  622 |       vector(initializer_list<value_type> __l,
      |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
make[2]: *** [Makefile:10271: rpc/libbitcoin_node_a-blockchain.o] Error 1

@@ -217,6 +211,9 @@ struct RPCArg {

bool IsOptional() const;

/** Check whether the request JSON type matches. */
Copy link
Contributor

Choose a reason for hiding this comment

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

Document that it throws JSONRPCError if there's a mismatch?

Copy link
Member Author

Choose a reason for hiding this comment

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

Reworked in #26929

Comment on lines +855 to +875
{"hash_or_height", RPCArg::Type::NUM, RPCArg::DefaultHint{"the current best block"}, "The block hash or height of the target height (only available with coinstatsindex).",
RPCArgOptions{
.skip_type_check = true,
.type_str = {"", "string or numeric"},
}},
Copy link
Contributor

Choose a reason for hiding this comment

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

Keeping the RPC API simpler seems better than adding too much cleverness/complexity -- you can always convert height to a hash on the client side in advance...

@ajtowns
Copy link
Contributor

ajtowns commented Jan 13, 2023

ACK fa9f6d7

Added some debugging code to verify that the removed RPCTypeCheck calls seem to match what the new logic will enforce.

@ajtowns
Copy link
Contributor

ajtowns commented Jan 13, 2023

Is there a (2/2) somewhere?

@fanquake fanquake merged commit 7799f53 into bitcoin:master Jan 17, 2023
@fanquake
Copy link
Member

Is there a (2/2) somewhere?

@MarcoFalke Address the comments in the 2/2 ?

@maflcko maflcko deleted the 2209-rpc-type-🔤 branch January 17, 2023 12:53
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Jan 17, 2023
@maflcko
Copy link
Member Author

maflcko commented Jan 20, 2023

Is there a (2/2) somewhere?

I haven't written it, because code that isn't written doesn't need to be rebased by me.

I can do a 1.5/2, unless you really want me to write 2/2 now.

@maflcko
Copy link
Member Author

maflcko commented Jan 20, 2023

1.5

Done in #26929

@bitcoin bitcoin locked and limited conversation to collaborators Jan 20, 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.

None yet

10 participants