#17580 refactor: Add ALLOW_LIST flags and enforce usage in CheckArgFlags
| Reviewability | Reviews | Agreement | Size | ||||
|---|---|---|---|---|---|---|---|
| #17580 refactor: Add ALLOW_LIST flags and enforce usage in CheckArgFlags | Review #16545 first | 0 | Strong | 378 + 767 tests | |||
|
|
| |||||
Reviewability: ReadyStalePaused Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs. Size: lines added or modified outside tests, then in tests; greener = smaller. | |||||||
Goal
Adds the ALLOW_LIST flag to ArgsManager options and enforces via CheckArgFlags that list options are retrieved with GetArgs() while non-list options are retrieved with GetArg(). It allows combining ALLOW_STRING and ALLOW_INT with ALLOW_BOOL for arguments that take optional values, and converts callers throughout the codebase that improperly invoked single-value methods on list options. It also fixes inconsistent behavior with empty -blockfilterindex="" arguments so they are consistently rejected as errors.
Problem: Calling single-value getters like GetArg() or IsArgSet() on multi-value list arguments is error-prone: GetArg() returns the last command-line value but the first config value in a list, and IsArgSet() can return true on an empty negated list. Additionally, -blockfilterindex="" exhibited position-dependent behavior, enabling all filters in some configurations while triggering parse errors in others.
Evidence of importance:
- Commit b95db49ce7 explains: 'For example GetArg will return last command line value but first config value in the list, and IsArgSet will return true even if the list is empty if the list was negated.'
- Commit 7bd8fce664 notes: 'Previous behavior was inconsistent: if -blockfilterindex or -blockfilterindex="" arguments were specified they would normally enable all block filter indexes, but could also trigger "Unknown -blockfilterindex value" errors if followed by later -blockfilterindex arguments.'
- PR description notes: 'Followup PRs could use the ALLOW_LIST flags for better documentation and error checking in the future. For example, #17493 builds on this to disallow conflicting config values.'
Scope: Stacked on top of unmerged PR #16545; commits up to 0b435cb8fe belong to that base. Includes a scripted-diff commit (d10df8eee1) adding ALLOW_LIST to arguments retrieved with GetArgs.
Risk of a mistake: medium (other). A mistake in argument flag enforcement or parsing could throw a logic_error during startup or misparse valid node configuration parameters.
Changed since the previous assessment: Rebased on updated base PR #16545; the separate rpcauth parsing fix mentioned in the original description was merged separately in #30401.
Reviewability
Ready · Review #16545 first
Stacked on #16545; the base PR's changes are included in this diff.
Waiting on (from the thread read):
- nothing
Agreement
Strong
substantive support, no open objection (ajtowns)
Thread notes: Converted schema 1 claims by ajtowns from objections to suggestions and added question rc:364559553. Updated ajtowns' stance to support given the Concept ACK and lack of standing objections. / Reclassified ajtowns' claims from objections to suggestions/questions as they do not name costs of merging as-is, added unrecorded question rc:364559553, and updated ajtowns' stance to support.
Objections, suggestions, and questions:
| Reviewer | Type | Harm, request, or question | Status | Must be | Author replied | Quote |
|---|---|---|---|---|---|---|
| ajtowns (member) | suggestion, approach | enforce argument flag checks at compile time rather than runtime | answered · author explained compile-time checks are easier to add once constraints are in place | answered | yes | 2020-01-09: 'shame all these checks are happening at runtime rather than compile time though' Status from: 2020-01-09: ryanofsky: 'Switching enforcement from runtime to compile time after constraints are in already place would be easier by comparison' |
| ajtowns (member) | suggestion, approach | simplify CheckArgFlags to not include ALLOW_ANY types in forbid | fixed · fix pushed · author simplified CheckArgFlags in push | answered | yes | 2020-01-09: 'I don't think it makes sense to ever include any of the `ALLOW_ANY` types in `forbid`' Status from: 2020-01-24: ryanofsky: 'with suggested checkargflags simplification' |
| ajtowns (member) | suggestion, maintenance | restructure the tests instead of using helper functions that tweak flags | answered · author declined to restructure tests in this PR | answered | yes | 2020-01-09: 'I think it might be better to restructure the tests than have these special functions that tweak the flags.' Status from: 2020-01-09: ryanofsky: 'I'm not too inclined to want to restructure the tests, though I'd be happy to review a PR that did.' |
| ajtowns (member) | question, correctness | whether gArgs.IsArgSet("-rpcauth") should be used instead | answered · author explained IsArgSet is broken for negated list arguments | answered | yes | 2020-01-09: '`gArgs.IsArgSet("-rpcauth")` ?' Status from: 2020-01-09: ryanofsky: 'That would do the wrong thing if the argument is negated.' |
Support:
- hebasto (member) (Concept ACK, 2019-11-24): Concept ACK [not substantive]
- promag (contributor) (Concept ACK, 2019-12-22): Concept ACK. [not substantive]
- ajtowns (member) (Concept ACK, 2020-01-09) [read]: Concept ACK, shame all these checks are happening at runtime rather than compile time though
Participants:
- hebasto (member, support, 1 statements 2019-11-24 to 2019-11-24): Concept ACK
- promag (contributor, support, 1 statements 2019-12-22 to 2019-12-22): Concept ACK
- ajtowns (member, support, 4 statements 2020-01-09 to 2020-01-09): Concept ACK; suggested compile-time checks, CheckArgFlags simplification, test restructuring, and asked about IsArgSet
- fanquake (member, neutral, 1 statements 2023-02-08 to 2023-02-08): moved PR to draft because base PR is a draft
Dependencies
Files
849 lines under test/bench/ci.
- src/test/argsman_tests.cpp +648/-66
- src/common/args.cpp +157/-31
- src/common/args.h +162/-18
- src/init.cpp +45/-36
- src/test/getarg_tests.cpp +61/-3
- src/test/fuzz/system.cpp +47/-7
- src/chainparamsbase.cpp +6/-5
- src/init/common.cpp +3/-3
- src/test/logging_tests.cpp +3/-3
- test/lint/check-doc.py +3/-2
- src/common/config.cpp +4/-0
- src/test/util/common.h +4/-0
- src/wallet/init.cpp +1/-1
- test/functional/feature_config_args.py +1/-1
Card
The short text the ranking pass compares across PRs.
Adds the ALLOW_LIST flag to ArgsManager and enforces at runtime that multi-value options are accessed via GetArgs() rather than GetArg(). This eliminates internal developer footguns where single-value accessors return inconsistent or unexpected elements from multi-value lists, and resolves position-dependent handling of empty -blockfilterindex arguments. It unblocks follow-up work in #17493 to reject ambiguous duplicate config settings. The PR is stacked on base PR #16545.
Data
thread read through 2024-12-06 (13 statements), head a79914f0fc
labels: Refactoring · draft
Categories
Utilities (logging, arguments, libraries)
P2 · cleanup
Enforces proper argument fetching patterns across the codebase to prevent error-prone usage of GetArg() on list options and fixes inconsistent parsing for empty options like -blockfilterindex="". It also establishes infrastructure that unblocks follow-up config validation work such as #17493.
Membership: Directly refactors core argument parsing and flag checking in src/common/args.cpp and src/common/args.h.
Factors: security/stability 1, bug 1, performance 0, user value 1, leverage 2