Skip to content

Conversation

@ryanofsky
Copy link
Contributor

@ryanofsky ryanofsky commented Nov 8, 2024

This PR changes the way settings are registered and retrieved to provide more compile-time safety. Currently settings are registered and retrieved like:

// Register setting
argsman.AddArg("-pid=<file>", strprintf("Specify pid file. Relative paths will be prefixed by a net-specific datadir location. (default: %s)", BITCOIN_PID_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);

// Retrieve setting
args.GetPathArg("-pid", BITCOIN_PID_FILENAME)

But this is not ideal because nothing checks that setting names are spelled correctly, or that default values (BITCOIN_PID_FILENAME) are used consistently in the help string and retrieval sites, or that settings are retrieved with consistent types (bool, int, string, path, or list). This PR addresses these issues by adding setting declarations which allow settings to be registered and retrieved like:

// Declare setting
using PidSetting = common::Setting<
    "-pid=<file>", fs::path, {.legacy = true},
    "Specify pid file. Relative paths will be prefixed by a net-specific datadir location. (default: %s)">
    ::DefaultFn<[] { return BITCOIN_PID_FILENAME; }>;

// Register setting
PidSetting::Register(argsman);

// Retrieve setting
PidSetting::Get(args)

Suggestions for review

All the real changes in this PR are in the last scripted-diff commit:

If you take a few minutes to look at the changes applied in this scripted-diff commit, you'll understand everything this PR is doing. A good place to start looking around in this commit is the generated src/init_settings.h file which declares the settings that get registered in src/init.cpp. Then you can look at the surrounding diffs and see they are just replacing AddArg and GetArg calls.

The other notable commit is second commit, which implements the Setting class:

The other commits do minor things like moving code or updating linters. The python script that implements the scripted diff is a temporary artifact that gets deleted. The python script is complicated because it does things like parsing c++ code to extract help strings, and figuring out the right types to declare settings with so code compiles. But the entire scope of the script is to (1) generate Setting type definitions, (2) add #includes, and (3) replace AddArg() calls with Register() calls and GetArg() calls with Get() calls. So there is not much the script can actually do wrong without triggering build and test failures.


Extensions

This PR only adds the ability to declare individual settings with built-in types. It doesn't provide any new runtime behavior, but a branch in issue #22978 extends the Setting class implemented here to support runtime setting validation, additional types like std::variant, additional conversion options, custom types, custom validation, and groups of settings declared as options structs.

This change is mostly orthogonal to #16545. #16545 only provides runtime type checking while this PR only provides compile-time checking with no new runtime behavior. But this change does allow a nicer way of declaring types in #16545, using c++ types like int instead of flags like ALLOW_INT, orstd::vector<std::string> instead of ALLOW_STRING | ALLOW_LIST.

@DrahtBot
Copy link
Contributor

DrahtBot commented Nov 8, 2024

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

Code Coverage & Benchmarks

For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31260.

Reviews

See the guideline for information on the review process.

Type Reviewers
Concept ACK l0rinc, hodlinator

If your review is incorrectly listed, please copy-paste <!--meta-tag:bot-skip--> into the comment that the bot should ignore.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #bitcoin-core/gui/762 (Update about logo icon (colour) to denote the chain type of the QT instance in About/ Help Message Window/ Dialog by pablomartin4btc)
  • #34038 (logging: API improvements by ajtowns)
  • #34037 (wallet, doc: clarify the coin selection filters that enforce cluster count by glozow)
  • #34004 (Implementation of SwiftSync by rustaceanrob)
  • #33878 (refactor, docs: Embedded ASMap [2/3]: Refactor asmap internals and add documentation by fjahr)
  • #33854 (fix assumevalid is ignored during reindex by Eunovo)
  • #33740 (RFC: bench: Add multi thread benchmarking by fjahr)
  • #33540 (argsman, cli: GNU-style command-line option parsing (allows options after non-option arguments) by pablomartin4btc)
  • #33343 (help: enrich help text for -loadblock by HowHsu)
  • #33324 (blocks: add -reobfuscate-blocks argument to enable (de)obfuscating existing blocks by l0rinc)
  • #33300 (fuzz: compact block harness by Crypt-iQ)
  • #33215 (Fix compatibility with -debuglogfile command-line option by hebasto)
  • #33192 (refactor: unify container presence checks by l0rinc)
  • #33008 (wallet: support bip388 policy with external signer by Sjors)
  • #32636 (Split CWallet::Create() into CreateNew and LoadExisting by davidgumberg)
  • #32427 ((RFC) kernel: Replace leveldb-based BlockTreeDB with flat-file based store by sedited)
  • #32297 (bitcoin-cli: Add -ipcconnect option by ryanofsky)
  • #32138 (wallet, rpc: remove settxfee and paytxfee by polespinasa)
  • #31974 (Drop testnet3 by Sjors)
  • #31723 (node: Add --debug_runs/-waitfordebugger + --debug_cmd by hodlinator)
  • #31425 (RFC: Riscv bare metal CI job by sedited)
  • #30951 (net: option to disallow v1 connection on ipv4 and ipv6 peers by stratospher)
  • #30343 (wallet, logging: Replace WalletLogPrintf() with LogInfo() by ryanofsky)
  • #29415 (Broadcast own transactions only via short-lived Tor or I2P connections by vasild)
  • #29278 (Wallet: Add maxfeerate wallet startup option by ismaelsadeeq)
  • #28802 (ArgsManager: support subcommand-specific options by ajtowns)
  • #28792 (build: Embedded ASMap [3/3]: Build binary dump header file by fjahr)
  • #28463 (p2p: Increase inbound capacity for block-relay only connections by mzumsande)
  • #26988 (cli: rework -addrinfo cli to use addresses which aren’t filtered for quality/recency by stratospher)
  • #24539 (Add a "tx output spender" index by sstone)
  • #19461 (multiprocess: Add bitcoin-gui -ipcconnect option by ryanofsky)
  • #19460 (multiprocess: Add bitcoin-wallet -ipcconnect option by ryanofsky)
  • #17783 (common: Disallow calling IsArgSet() on ALLOW_LIST options by ryanofsky)
  • #17581 (refactor: Remove settings merge reverse precedence code by ryanofsky)
  • #17580 (refactor: Add ALLOW_LIST flags and enforce usage in CheckArgFlags by ryanofsky)
  • #17493 (util: Forbid ambiguous multiple assignments in config file by ryanofsky)
  • #16545 (refactor: Implement missing error checking for ArgsManager flags by ryanofsky)
  • #10102 (Multiprocess bitcoin by ryanofsky)

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.

@ryanofsky ryanofsky marked this pull request as draft November 8, 2024 22:34
@ryanofsky
Copy link
Contributor Author

Current status of this PR is that bitcoind and test_bitcoin binaries work and functional and unit tests pass, but there are compile errors in the other binaries that need to be fixed, and this also needs to be rebased. The PR is complete with all functionality described above implemented, but it probably needs more documentation. I also would like to add more commits replacing last remaining GetArg / GetIntArg / GetBoolArg / GetArgs / IsArgSet / IsArgNegated method uses with Setting::Get and dropping all those methods.

@ryanofsky ryanofsky force-pushed the pr/scripty branch 2 times, most recently from 47e30b4 to d8a4a0a Compare November 13, 2024 00:31
@ryanofsky
Copy link
Contributor Author

ryanofsky commented Nov 13, 2024

Updated 416860f -> 47e30b4 (pr/scripty.1 -> pr/scripty.2, compare) getting the remaining binaries (not just test_bitcoin and bitcoind) to build, simplifying the way optional and default values are used, making many other cleanups and fixes.
Rebased 47e30b4 -> d8a4a0a (pr/scripty.2 -> pr/scripty.3, compare) due to conflicts
Updated d8a4a0a -> ad32a27 (pr/scripty.3 -> pr/scripty.4, compare) with a fix for the feature_logging.py test that got broken by the previous optional/default changes. Also includes cmake changes to fix some CI build errors.
Updated ad32a27 -> 534f971 (pr/scripty.4 -> pr/scripty.5, compare) replacing IsArgSet calls with Setting::Value().isNull() instead of using std::optional and Setting::Get() to avoid changing any behavior since Get() fully parses the setting and can throw exceptions, and to reduce uses of std::optional which complicated code. Also add basic unit tests and make various script improvements.
Rebased 534f971 -> 7e57237 (pr/scripty.5 -> pr/scripty.6, compare) with a number of changes intended to fix CI errors, and with a fix for silent merge conflict with #31174
Rebased 7e57237 -> 1f24346 (pr/scripty.6 -> pr/scripty.7, compare) due to conflict #31287 and many workarounds for various compiler issues in CI and fixes for more linters

@DrahtBot
Copy link
Contributor

🚧 At least one of the CI tasks failed.
Debug: https://github.com/bitcoin/bitcoin/runs/32896439725

Hints

Try to run the tests locally, according to the documentation. However, a CI failure may still
happen due to a number of reasons, for example:

  • Possibly due to a silent merge conflict (the changes in this pull request being
    incompatible with the current code in the target branch). If so, make sure to rebase on the latest
    commit of the target branch.

  • A sanitizer issue, which can only be found by compiling with the sanitizer and running the
    affected test.

  • An intermittent issue.

Leave a comment here, if you need help tracking down a confusing failure.

ryanofsky and others added 10 commits December 12, 2025 05:49
Avoid string concatenation and add missing namespace names so AddArg calls can
be moved to header files in an upcoming scripted-diff.
Move constant declarations referenced in AddArg calls to headers so AddArg
calls be moved to header files in an upcoming scripted-diff.
Drop hidden_args vector so all AddHiddenArgs calls can be replaced in upcoming
scripted diff.
Linter changes to deal with _settings.h headers added in the next commit.

In circular-dependencies.py, prevent _settings.h headers from being included
transitively. Add a new check that makes it an error to include _settings.h
from another header file, rather than a .cpp file. Use this fact to avoid
errors about .cpp files including _settings.h files being circularly dependent
based on each other.

In check-doc.py update test to look for Setting::Get and Setting::Register
instead of GetArg and AddArg.
Add univalue include directory to libraries that need it it because they will
include it indirectly through setting.h files, and add libevent include
directory to libraries that need it because they will include it indirectly
through init_settings.h which includes torcontrol.h which includes
event2/util.h.

The missing cmake library dependencies trigger CI errors that may not happen on
all systems depending in how package include paths are laid out. In particular
the torcontrol / libevent errors only seem to happen on macos with homebrew.

It would probably be good to streamline headers to avoid these dependencies in
the future. It would be good if the torcontrol header did not have a pulic
dependency on libevent or, if it was just split up and the DEFAULT_TOR_CONTROL
and DEFAULT_TOR_CONTROL_PORT constants needed by init_settings.h to a different
file.

Errors look like:

D:\a\bitcoin\bitcoin\src\common\setting.h(10,1): error C1083: Cannot open include file: 'univalue.h': No such file or directory [D:\a\bitcoin\bitcoin\build\src\bitcoin.vcxproj]

In file included from /home/admin/actions-runner/_work/_temp/src/bitcoin.cpp:7:
In file included from /home/admin/actions-runner/_work/_temp/src/bitcoin_settings.h:4:
/home/admin/actions-runner/_work/_temp/src/common/setting.h:10:10: fatal error: 'univalue.h' file not found
   10 | #include <univalue.h>
      |          ^~~~~~~~~~~~
1 error generated.

D:\a\bitcoin\bitcoin\src\txmempool.h(27,1): error C1083: Cannot open include file: 'boost/multi_index/hashed_index.hpp': No such file or directory [D:\a\bitcoin\bitcoin\build\src\bitcoin.vcxproj]

In file included from /home/admin/actions-runner/_work/_temp/src/validation.h:29,
                 from /home/admin/actions-runner/_work/_temp/src/node/chainstatemanager_args.h:9,
                 from /home/admin/actions-runner/_work/_temp/src/init_settings.h:21,
                 from /home/admin/actions-runner/_work/_temp/src/bitcoin.cpp:10:
/home/admin/actions-runner/_work/_temp/src/txmempool.h:27:10: fatal error: boost/multi_index/hashed_index.hpp: No such file or directory
   27 | #include <boost/multi_index/hashed_index.hpp>
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In file included from /Users/runner/work/bitcoin/bitcoin/src/qt/bitcoin.cpp:14:
In file included from /Users/runner/work/bitcoin/bitcoin/src/init_settings.h:30:
/Users/runner/work/bitcoin/bitcoin/src/torcontrol.h:14:10: fatal error: 'event2/util.h' file not found
   14 | #include <event2/util.h>
      |          ^~~~~~~~~~~~~~~
1 error generated.
ninja: build stopped: subcommand failed.

In file included from /Users/runner/work/bitcoin/bitcoin/src/test/util/setup_common.cpp:17:
In file included from /Users/runner/work/bitcoin/bitcoin/src/init_settings.h:30:
/Users/runner/work/bitcoin/bitcoin/src/torcontrol.h:14:10: fatal error: 'event2/util.h' file not found
   14 | #include <event2/util.h>
      |          ^~~~~~~~~~~~~~~
1 error generated.

In file included from /Users/runner/work/bitcoin/bitcoin/src/common/config.cpp:6:
In file included from /Users/runner/work/bitcoin/bitcoin/src/init_settings.h:30:
/Users/runner/work/bitcoin/bitcoin/src/torcontrol.h:14:10: fatal error: 'event2/util.h' file not found
   14 | #include <event2/util.h>
      |          ^~~~~~~~~~~~~~~
1 error generated.

In file included from /Users/runner/work/bitcoin/bitcoin/src/bitcoin.cpp:10:
In file included from /Users/runner/work/bitcoin/bitcoin/src/init_settings.h:30:
/Users/runner/work/bitcoin/bitcoin/src/torcontrol.h:14:10: fatal error: 'event2/util.h' file not found
   14 | #include <event2/util.h>
      |          ^~~~~~~~~~~~~~~
1 error generated.

In file included from /Users/runner/work/bitcoin/bitcoin/src/bitcoind.cpp:15:
In file included from /Users/runner/work/bitcoin/bitcoin/src/init_settings.h:30:
/Users/runner/work/bitcoin/bitcoin/src/torcontrol.h:14:10: fatal error: 'event2/util.h' file not found
   14 | #include <event2/util.h>
      |          ^~~~~~~~~~~~~~~
1 error generated.
…egister / Get calls

Co-authored-by: Hodlinator <172445034+hodlinator@users.noreply.github.com>
…/ Get calls

This commit is a pure refactoring and does not change behavior in any way.

-BEGIN VERIFY SCRIPT-
python contrib/devtools/reg-settings.py
git add -N src/bench/bench_bitcoin_settings.h src/bitcoin_settings.h src/bitcoin-tx_settings.h src/bitcoin-util_settings.h src/bitcoin-wallet_settings.h src/chainparamsbase_settings.h src/common/args_settings.h src/init/common_settings.h src/init_settings.h src/qt/bitcoin_settings.h src/test/argsman_tests_settings.h src/test/logging_tests_settings.h src/wallet/init_settings.h src/dummywallet_settings.h src/qt/test/optiontests_settings.h src/test/getarg_tests_settings.h
git rm contrib/devtools/reg-settings.py
-END VERIFY SCRIPT-
@DrahtBot
Copy link
Contributor

🐙 This pull request conflicts with the target branch and needs rebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants