These have been accumulating over the past few years.
Each is described in its commit message.
These have been accumulating over the past few years.
Each is described in its commit message.
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31887.
See the guideline for information on the review process.
Type | Reviewers |
---|---|
ACK | pablomartin4btc, hodlinator, l0rinc, ryanofsky |
Concept ACK | yancyribbens |
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.
Reviewers, this pull request conflicts with the following ones:
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.
As the pull title is “CLI cleanups”, just a random comment: It seems odd to treat -getinfo
different than -netinfo
(and everything else). It would be good for consistency to treat them the same:
0diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
1index defe5e4c4e..18bd6b1f91 100644
2--- a/src/bitcoin-cli.cpp
3+++ b/src/bitcoin-cli.cpp
4@@ -1267,7 +1267,7 @@ static int CommandLineRPC(int argc, char *argv[])
5 gArgs.CheckMultipleCLIArgs();
6 std::unique_ptr<BaseRequestHandler> rh;
7 std::string method;
8- if (gArgs.IsArgSet("-getinfo")) {
9+ if (gArgs.GetBoolArg("-getinfo", false)) {
10 rh.reset(new GetinfoRequestHandler());
11 } else if (gArgs.GetBoolArg("-netinfo", false)) {
12 if (!args.empty() && (args.at(0) == "h" || args.at(0) == "help")) {
Unrelated, negation probably does not make sense for any of them, so ArgsManager::DISALLOW_NEGATION
could be set.
But up to you. Feel free to ignore.
re: #31887 (review)
Mostly agree with this suggestion. It would be nice to remove this IsArgSet
call (in a separate commit or PR), because like many other IsArgSet
calls, this one introduces a bug and doesn’t handle negation properly. A common sense interpretation of -nogetinfo
would be to not run the getinfo command instead of running it.
Only part of suggestion above I’d disagree with is the part about also adding the DISALLOW_NEGATION
flag. I think the DISALLOW_NEGATION
flag is useful for non-boolean options accepting string/int/path/list values where not having a value isn’t supported or doesn’t make sense (e.g. -nodatadir
). For other options, it is better IMO to stay consistent and allow negation so code does not fill up with special cases and users do not have to guess which options allow negation and which will trigger errors for no particular reason.
It would be nice to remove this IsArgSet call (in a separate commit or PR)
Looks like that was followed up on already? https://github.com/bitcoin/bitcoin/pull/31896
It seems odd to treat -getinfo different than -netinfo (and everything else). It would be good for consistency to treat them the same
It would be nice to remove this IsArgSet call (in a separate commit or PR), because like #30529 https://github.com/bitcoin/bitcoin/pull/31212 IsArgSet calls, this one introduces a bug and doesn’t handle negation properly. A common sense interpretation of -nogetinfo would be to not run the getinfo command instead of running it.
Thanks, done.
129@@ -130,14 +130,11 @@ static void libevent_log_cb(int severity, const char *msg)
130 // Exception thrown on connection error. This error is used to determine
131 // when to wait if -rpcwait is given.
132 //
133-class CConnectionFailed : public std::runtime_error
134+struct CConnectionFailed : std::runtime_error
class -> class
to struct -> class
.
class
/struct
in the inheritance hierarchy to be a separate issue.
My objection does not come from a knowledge gap in what C++ can and cannot do. It is about sticking to certain conventions.
As I was checking to see if the Core Guidelines had influenced me in the matter I only found weak counter evidence:
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c122-use-abstract-classes-as-interfaces-when-complete-separation-of-interface-and-implementation-is-needed
In the example code class D1
inherits from struct Device
, full of virtual methods.
Thread #31887 (review):
I still read #31887 (review) as what can be done technically, not what should be done (convention). What comes close to indicating convention is the SO-link which shows that some random guy on the internet also prioritizes default visibility over other conventions. His example of taking a struct
from a C library and inheriting from it into a class
is far from convincing to me - it goes against Core Guidelines: “Do not use inheritance when simply having a data member will do.” The way you use inheritance is better than his example in this aspect.
263@@ -267,21 +264,19 @@ static int8_t NetworkStringToId(const std::string& str)
264 return UNKNOWN_NETWORK;
265 }
266
267-/** Class that handles the conversion from a command-line to a JSON-RPC request,
268+/** Handle the conversion from a command-line to a JSON-RPC request,
269 * as well as converting back to a JSON object that can be shown as result.
270 */
271-class BaseRequestHandler
272+struct BaseRequestHandler
class
es for these as they use virtual
functions. Not worth changing just to be able to remove public
IMO.
If I’m understanding the feedback, it comes from the idea of C structs being for POD. My understanding is that in C++, classes and structs are identical except for their default inheritance and member access levels, and for the cases here, structs seem to be the appropriate choice that allows simpler code.
I agree that C++ classes and structs are essentially the same, no confusion there. (C# disallows inheritance for struct
but not class
, Rust doesn’t allow inheritance, period. I know we’re in C++, but still aware of the tendencies).
What contributed to giving me a sense that this project attempts to use struct
/class
as a shorthand for distinct things (like POD/vs non-POD), beyond the code that passed me by so far, was dev-notes.md:
I want to maintain a fairly equal bar for review and 3252f3bab02605129a568112f650ef3cb29703b7 (the topic of this thread) stands out to me as having been shot down instantly if done by a relative newcomer. I’ve benefited from your review guide and am sure you’ve provided and provide much value to the project.
I really hope I can build a reputation for other things than nits. :)
If you insist on keeping structs, maybe hoist up the braces to conform with the dev-notes? Also, you have inconsistent spacing:
struct AddrinfoRequestHandler : BaseRequestHandler
vs
struct GetinfoRequestHandler: BaseRequestHandler
re: #31887 (review)
If you insist on keeping structs, maybe hoist up the braces to conform with the dev-notes?
Not important but do agree it would be good to use recommended style for structs with opening brace on the same line (can just run clang-format
).
Also agree classes make more sense than structs here. Compilers may not care about the difference but they mean different things to developers. Structs usually provide data definitions while classes provide interface definitions, so they have different uses and follow different conventions. In this case, I can see the appeal of dropping some lines of code though so don’t have a strong opinion.
hoist up the braces to conform with the dev-notes? Also…inconsistent spacing
it would be good to use recommended style (can just run
clang-format
)
Good idea, done.
Code reviewed 3252f3bab02605129a568112f650ef3cb29703b7
ACK 9184ec9e8ea6efd4d0d3625a06f223156f940243
Advise dropping 3rd commit, the others seem good.
403@@ -404,7 +404,7 @@ class NetinfoRequestHandler : public BaseRequestHandler
404 return UNKNOWN_NETWORK;
405 }
406 uint8_t m_details_level{0}; //!< Optional user-supplied arg to set dashboard details level
407- bool DetailsRequested() const { return m_details_level > 0 && m_details_level < 5; }
The upper bound check is no longer needed after the merge of PR 21192.
Nit, looks like the bound check is for upper and lower bounds (above zero and bellow 5).
m_details_level
is capped at a maximum value of 4 since https://github.com/bitcoin/bitcoin/pull/21192/files; that line is currently m_details_level = std::min(n, NETINFO_MAX_LEVEL);
cr ACK ccc34a26170ef8c63a6f211eda4464e954873e89
Regarding the 3rd commit:
class
outside CLI
if we want to be consistent (and if we think we won’t require encapsulation for them).*RequestHandler
, are we sure the internal representation of these objects and what they expose won’t change at any time in the future? It looks like it should be ok, but I’m not too sure if at some point we would need to.1251@@ -1252,7 +1252,7 @@ static int CommandLineRPC(int argc, char *argv[])
1252 gArgs.CheckMultipleCLIArgs();
1253 std::unique_ptr<BaseRequestHandler> rh;
1254 std::string method;
1255- if (gArgs.IsArgSet("-getinfo")) {
1256+ if (gArgs.GetBoolArg("-getinfo", false)) {
In commit “cli, refactor: for -getinfo, replace IsArgSet() with GetBoolArg()” (ccc34a26170ef8c63a6f211eda4464e954873e89)
Would be good to drop “refactor” from commit subject since this is a small change in behavior, not a pure refactoring. It could be described as a bugfix: no longer treating -nogetinfo
and -getinfo=0
the same as -getinfo
and -getinfo=1
, instead treating them like getinfo was not specified.
The bounds check is no longer needed after the merge of PR 21192.
and run clang-format on it
for consistency with the other CLI commands (-netinfo, -addrinfo, -generate).
This can be considered a bugfix because IsArgSet() returns whether an arg has
been set even if it has been negated. After this change, we no longer treat
-nogetinfo and -getinfo=0 the same as -getinfo and -getinfo=1, and instead as if
-getinfo was not specified.
Co-authored-by: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz>
Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
254@@ -259,30 +255,25 @@ static void http_error_cb(enum evhttp_request_error err, void *ctx)
255 reply->error = err;
256 }
257
258-/** Class that handles the conversion from a command-line to a JSON-RPC request,
259+static int8_t NetworkStringToId(const std::string& str)
NetworkStringToId()
duplication was introduced in db4d2c282afd46709792aaf2d36ffbfc1745b776. Could add a reference in the commit message if you retouch.
392- }
393- return UNKNOWN_NETWORK;
394- }
395 uint8_t m_details_level{0}; //!< Optional user-supplied arg to set dashboard details level
396- bool DetailsRequested() const { return m_details_level > 0 && m_details_level < 5; }
397+ bool DetailsRequested() const { return m_details_level; }
nit: If you re-touch it might be good to add the missing #
to the commit message (for tooling/consistency). Unless “PR <number>” is also a convention for tooling unbeknownst to me.
0-PR 21192
1+PR [#21192](/bitcoin-bitcoin/21192/)
#
in cases like this, where it isn’t really important to link them here, so that GitHub does not add a notification in that PR every time this branch is (re)pushed.
Code review ACK d423fd9ec83ae323ac29bdc1b677ed8260bd59c4
Good to see -getinfo
negation behavior fixed. I encountered it when exploring args in #16545#pullrequestreview-2316714013 (in the “Expand/collapse lengthy exploration”-section).
Still think the 3rd commit is out of character compared to my brief experience with this project as it is purely stylistic, but at least the formatting was fixed since my previous review.
403@@ -404,7 +404,7 @@ class NetinfoRequestHandler : public BaseRequestHandler
404 return UNKNOWN_NETWORK;
405 }
406 uint8_t m_details_level{0}; //!< Optional user-supplied arg to set dashboard details level
407- bool DetailsRequested() const { return m_details_level > 0 && m_details_level < 5; }
408+ bool DetailsRequested() const { return m_details_level; }
This is better than before, but having a NETINFO_MAX_LEVEL
and a checking the bounded values in methods and having DetailsRequested
, but also checking it manually in https://github.com/bitcoin/bitcoin/blob/master/src/bitcoin-cli.cpp#L499-L501 where we’re checking the raw n
value seems quite hacky.
Seems the code is begging for a bounded type - if we’re cleaning it up, we might as well try an enum here:
0enum class NetinfoDetailLevel : uint8_t {
1 BASIC = 0,
2 PEERS,
3 PEERS_WITH_ADDR,
4 PEERS_WITH_VER,
5 FULL
6};
where we’re checking the raw n value
That is to check user input.
I think the abstraction level here is fine, but happy to review if you propose a further abstraction in a follow-up.
258@@ -259,6 +259,14 @@ static void http_error_cb(enum evhttp_request_error err, void *ctx)
259 reply->error = err;
260 }
261
262+static int8_t NetworkStringToId(const std::string& str)
from the usages it seems we can modernize this in a few more ways:
UNKNOWN_NETWORK
seems to serve as a value-missing proxy - we could use an optional
type insteadconst std::string&
could be modernized to static std::optional<int8_t> NetworkStringToId(std::string_view network)
This would allow us to change the usages to something like:
0if (auto network_id{NetworkStringToId(network_name)}) {
1 ++counts.at(*network_id);
2}
std::optional
wasn’t available when this was added, as the codebase was using C++11 at that time. I think this would be more of a modernization rewrite than a cleanup, but happy to review if you want to propose it.
258@@ -259,6 +259,14 @@ static void http_error_cb(enum evhttp_request_error err, void *ctx)
259 reply->error = err;
260 }
261
262+static int8_t NetworkStringToId(const std::string& str)
263+{
264+ for (size_t i = 0; i < NETWORKS.size(); ++i) {
we’re returning an int8_t
, we might as well iterate over one
0 for (int8_t i{0}; i < NETWORKS.size(); ++i) {
return i
. Doesn’t seem worth it.
int8_t
for an index - unnecessary, should likely be size_t
or int
- not important
278
279 /** Process addrinfo requests */
280-class AddrinfoRequestHandler : public BaseRequestHandler
281-{
282-public:
283+struct AddrinfoRequestHandler : BaseRequestHandler {
I like these cleanups, ans we should go a step further and modernize the code more when touching them. I’m also not a fan of the 3rd commit for the inheritance cases and would prefer seeing the last commit in a separate PR, doesn’t seem like a “refactor:”
Thanks for reviewing. The last commit was added at the request of multiple reviewers, but I’ve removed “refactor” from the pull title. Addressed the other feedback individually and happy to look at any modernization follow-ups you’d like to propose.
I would prefer doing the modernizations here to get rid of more technical debt, but this is already better than before so:
ACK d423fd9ec83ae323ac29bdc1b677ed8260bd59c4