diff --git a/contrib/devtools/reg-settings.py b/contrib/devtools/reg-settings.py deleted file mode 100644 index f8252c6a62ecb..0000000000000 --- a/contrib/devtools/reg-settings.py +++ /dev/null @@ -1,551 +0,0 @@ -import collections -import enum -import os -import re -import subprocess -from dataclasses import dataclass, field -from typing import Literal - -@dataclass -class Call: - file: str - position: int - call_text: str - obj_name: str - arg_name: str - context: str - namespace: str - -class DataType(int, enum.Enum): - STRING_LIST = 1 - STRING = 2 - PATH = 3 - INT = 4 - BOOL = 5 - DISABLED = 6 - -DefaultValue = str | None | Literal[True] - -def from_default_value(default_value: DefaultValue, data_type: DataType) -> str: - if default_value is True: - if data_type == DataType.STRING_LIST: return "std::vector{}" - if data_type == DataType.STRING: return '""' - if data_type == DataType.PATH: return "fs::path{}" - if data_type == DataType.INT: return "0" - if data_type == DataType.BOOL: return "false" - return default_value - -def to_default_value(expr: str, data_type: DataType) -> DefaultValue: - if data_type == DataType.STRING_LIST and expr == "std::vector{}": return True - if data_type == DataType.STRING and expr == '""': return True - if data_type == DataType.PATH and expr == "fs::path{}": return True - if data_type == DataType.INT and expr == "0": return True - if data_type == DataType.BOOL and expr == "false": return True - return expr - -@dataclass -class SettingType: - name: str - primary: bool = False - defaults: set[str | None] = field(default_factory=set) - default_value: DefaultValue = None - -@dataclass -class AddArg: - call: Call - summary: str - help_text: str - help_args: tuple[str, ...] - flags: str - category: str - include_path: str | None = None - data_types: dict[DataType, SettingType] = field(default_factory=dict) - optional: bool = False - extern_args: list[str] = field(default_factory=list) - -@dataclass -class GetArg: - call: Call - function_name: str - data_type: DataType | None - default_value: DefaultValue = None - add: AddArg | None = None - -@dataclass -class Setting: - arg_name: str - adds: list[AddArg] = field(default_factory=list) - gets: list[GetArg] = field(default_factory=list) - -def get_files_with_args(src_dir): - # Run git grep to find files containing AddArg/GetArg/GetIntArg/GetBoolArg/GetArgs - result = subprocess.run( - [ - "git", "grep", "-l", "AddArg(\|GetArg(\|GetIntArg(\|GetBoolArg(\|GetArgs", "--", src_dir - ], - capture_output=True, - text=True - ) - return result.stdout.splitlines() - -def get_file_context(path): - if path in ["src/bitcoin-cli.cpp"]: return "cli" - if path in ["src/bitcoin-tx.cpp"]: return "tx" - if path in ["src/bitcoin-util.cpp"]: return "util" - if path in ["src/bitcoin-wallet.cpp", "src/wallet/wallettool.cpp"]: return "wallet" - if path in ["src/test/argsman_tests.cpp", "src/test/logging_tests.cpp,", "src/test/fuzz/system.cpp", "src/test/getarg_tests.cpp"]: return "test" - if path in ["src/zmq/zmqnotificationinterface.cpp"]: return "test" # FIX - return "main" - -def get_file_namespace(path): - if path.startswith("src/wallet/"): return "wallet" - return "" - -def parse_function_args(arg_str): - args = [] - parens = 0 - quot = False - for pos, c in enumerate(arg_str): - if c == '"': - quot = not quot - if quot: - pass - elif c == "(": - parens += 1 - elif c == ")": - if parens == 0: break - parens -= 1 - elif c == "," and parens == 0: - args.append("") - continue - if not args: args.append("") - args[-1] += c - return pos, args - -def parse_calls(file_path): - adds = [] - gets = [] - context = get_file_context(file_path) - namespace = get_file_namespace(file_path) - with open(file_path, 'r') as f: - content = f.read() - for match in re.finditer(r'\b(\w+)\.AddArg\((")', content): - call_len, (summary, help_text, flags, category) = parse_function_args(content[match.start(2):]) - call = Call( - file=file_path, - position=match.start(), - call_text=content[match.start():match.start(2)+call_len+1], - obj_name=match.group(1), - arg_name=re.match(r'"([^"=(]+).*', summary).group(1), - context=context, - namespace=namespace, - ) - help_text=help_text.strip() - help_args = [] - if m := re.match(r"strprintf\(", help_text): - _, help_args = parse_function_args(help_text[m.end():]) - help_text = help_args[0].strip() - help_args = [a.strip() for a in help_args[1:]] - adds.append(AddArg( - call=call, - summary=summary.strip(), - help_text=help_text, - help_args=tuple(help_args), - flags=flags.strip(), - category=category.strip(), - )) - for match in re.finditer(r'\b([\w.]+)(\.|->)(GetArg|GetPathArg|GetIntArg|GetBoolArg|GetArgs|IsArgSet|IsArgNegated)\((.)', content): - call_len, call_args = parse_function_args(content[match.start(4):]) - obj_name = match.group(1) - if match.group(2) == "->": - obj_name = f"*{obj_name}" - call = Call( - file=file_path, - position=match.start(), - call_text=content[match.start():match.start(4)+call_len+1], - obj_name=obj_name, - arg_name=call_args[0].strip().strip('"'), - context=context, - namespace=namespace, - ) - function_name = match.group(3) - data_type = (DataType.STRING_LIST if function_name == "GetArgs" else - DataType.STRING if function_name == "GetArg" else - DataType.PATH if function_name == "GetPathArg" else - DataType.INT if function_name == "GetIntArg" else - DataType.BOOL if function_name == "GetBoolArg" else - DataType.DISABLED if function_name == "IsArgNegated" else - None) - gets.append(GetArg( - call=call, - function_name=function_name, - data_type=data_type, - default_value=to_default_value(call_args[1].strip(), data_type) if len(call_args) > 1 else - True if function_name == "GetPathArg" else - True if function_name == "GetArgs" else None, - )) - return adds, gets - -def make_setting(settings, call): - name = call.arg_name.lstrip("-") - if name in settings: - setting = settings[name] - else: - setting = settings[name] = Setting(call.arg_name) - return setting - -def flags_to_options(flag_str): - flags = set() - for flag in flag_str.split("|"): - flags.add(flag.strip()) - - def pop(flag): - if flag in flags: - flags.remove(flag) - return True - return False - - options = [".legacy = true"] - if pop("ArgsManager::DEBUG_ONLY"): - options.append(".debug_only = true") - if pop("ArgsManager::NETWORK_ONLY"): - options.append(".network_only = true") - if pop("ArgsManager::SENSITIVE"): - options.append(".sensitive = true") - if pop("ArgsManager::DISALLOW_NEGATION"): - options.append(".disallow_negation = true") - if pop("ArgsManager::DISALLOW_ELISION"): - options.append(".disallow_elision = true") - pop("ArgsManager::ALLOW_ANY") - if flags: - raise Exception("Unknown flags {flags!r}") - return options - -def collect_argument_information(src_dir): - files = get_files_with_args(src_dir) - settings: Dict[str, Setting] = {} - for file in files: - adds, gets = parse_calls(file) - for add in adds: - setting = make_setting(settings, add.call) - setting.adds.append(add) - for get in gets: - setting = make_setting(settings, get.call) - setting.gets.append(get) - - for arg_name, setting in settings.items(): - setting_name = ''.join(word.capitalize() for word in arg_name.split('-')) + "Setting" - counter = collections.Counter() - - for add in setting.adds: - add.include_path = add.call.file.replace(".cpp", "_settings.h") - key = add.call.context, add.call.arg_name - add_setting_name = setting_name - counter[key] += 1 - if counter[key] > 1: add_setting_name += str(counter[key]) - - for get in setting.gets: - if not add.call.context == get.call.context and not add.call.context == "main": - continue - if get.add is None: - get.add = add - if get.data_type is None: - add.optional = True - else: - if get.data_type in add.data_types: - setting_type = add.data_types[get.data_type] - else: - setting_type = add.data_types[get.data_type] = SettingType(add_setting_name) - setting_type.defaults.add(get.default_value) - - if len(add.data_types) == 0: - add.data_types[None] = SettingType(add_setting_name) - - # If same setting is retrieved as different types, add suffixes to distinguish setting names - add.data_types[min(add.data_types.keys())].primary = True - for data_type, setting_type in add.data_types.items(): - if not setting_type.primary: - setting_type.name += ( - "List" if data_type == DataType.STRING_LIST else - "Str" if data_type == DataType.STRING else - "Path" if data_type == DataType.PATH else - "Int" if data_type == DataType.INT else - "Bool" if data_type == DataType.BOOL else - "Disabled" if data_type == DataType.DISABLED else - None - ) - if not (add.optional or None in setting_type.defaults or len(setting_type.defaults) != 1): - default_value = next(iter(setting_type.defaults)) - assert default_value is not None - if default_value is not True: - for pattern, help_arg in HELP_ARGS.items(): - if pattern in default_value and help_arg.extern: - default_value = False - break - if pattern == default_value and help_arg.namespace: - default_value = f"{help_arg.namespace}::{default_value}" - if default_value is not False: - setting_type.default_value = default_value - return settings - -@dataclass -class SettingsHeader: - includes: set[str] = field(default_factory=set) - defs: list[str] = field(default_factory=list) - -def generate_setting_headers(settings): - headers_content = collections.defaultdict(SettingsHeader) - for setting in settings.values(): - for add in setting.adds: - header = headers_content[add.include_path] - help_runtime = False - extern = [] - for pattern, help_arg in HELP_ARGS.items(): - if pattern in add.help_text or any(pattern in a for a in add.help_args): - if help_arg.include_path: - header.includes.add(help_arg.include_path) - help_runtime = help_runtime or help_arg.runtime - if help_arg.extern: - extern.append(pattern) - add.extern_args.append(pattern) - - for data_type, setting_type in sorted(add.data_types.items(), key=lambda p: p[0]): - ctype = ("std::vector" if data_type == DataType.STRING_LIST else - "std::string" if data_type == DataType.STRING else - "fs::path" if data_type == DataType.PATH else - "int64_t" if data_type == DataType.INT else - "bool" if data_type == DataType.BOOL else - "common::Disabled" if data_type == DataType.DISABLED else - "char") - if setting_type.default_value is None: - ctype = f"std::optional<{ctype}>" - help_str = "" - if setting_type.primary: - help_str = f",\n {add.help_text}" - extra = "" - help_args = ', '.join(a for a in add.help_args) - default_arg = from_default_value(setting_type.default_value, data_type) or "" - if setting_type.default_value is True and (not help_args or help_args != default_arg): - default_arg = "" - if default_arg: - default_runtime = False - for pattern, help_arg in HELP_ARGS.items(): - if setting_type.default_value is not True and pattern in setting_type.default_value: - if help_arg.include_path: - header.includes.add(help_arg.include_path) - default_runtime = default_runtime or help_arg.runtime - assert not help_arg.extern - if default_runtime: - extra += f"\n ::DefaultFn<[] {{ return {default_arg}; }}>" - else: - extra += f"\n ::Default<{default_arg}>" - if ((help_args and setting_type.primary) or default_arg) and help_args != default_arg: - if help_runtime or extern: - lambda_args = ", ".join(f"const auto& {a}" for a in ["fmt"] + extern) - extra += f"\n ::HelpFn<[]({lambda_args}) {{ return strprintf(fmt, {help_args}); }}>" - else: - extra += f"\n ::HelpArgs<{help_args}>" - if add.category != "OptionsCategory::OPTIONS": - extra += f"\n ::Category<{add.category}>" - options = flags_to_options(add.flags) - options_str = f"{{{', '.join(options)}}}" if options else "" - setting_definition = f"\nusing {setting_type.name} = common::Setting<\n {add.summary}, {add.help_text if setting_type.primary else 'nullptr'},\n {ctype}, {add.category}{options_str}>{extra};\n" - setting_definition = f"\nusing {setting_type.name} = common::Setting<\n {add.summary}, {ctype}, {options_str}{help_str}>{extra};\n" - header.defs.append(setting_definition) - - for header_file_path, header in headers_content.items(): - if not os.path.exists(header_file_path): - guard = re.sub("^src/", "", header_file_path).replace('/', '_').replace('.', '_').replace('-', '_').upper() - namespace = get_file_namespace(header_file_path) - namespace_str = "" - if namespace: - namespace_str = f"namespace {namespace} {{\n}} // namespace {namespace}\n" - with open(header_file_path, 'w') as f: - f.write(f"#ifndef {guard}\n#define {guard}\n{namespace_str}\n#endif // {guard}\n") - add_to_file( - header_file_path, - [f"#include <{include}>\n" for include in header.includes | {"common/setting.h"}], - ["#include \n", "#include \n"], - header.defs) - -def add_to_file(file_path, local_includes, system_includes=(), defs=()): - with open(file_path, 'r') as f: - lines = f.readlines() - # Identify the include blocks and their positions - local_include_start, local_include_end = None, None - system_include_start, system_include_end = None, None - self_include = f"#include <{file_path.replace('src/', '').replace('.cpp', '.h')}>" - first = last = None - for i, line in enumerate(lines): - #print(f"{i=!r} {line=!r}") - if line.startswith('#include') and "IWYU pragma: keep" not in line and not line.startswith(self_include): - if local_include_start is None: - local_include_start = i - elif system_include_start is None and local_include_end is not None: - system_include_start = i - elif system_include_start is not None and system_include_end is None: - system_include_end = i - elif local_include_start is not None and local_include_end is None: - local_include_end = i - if first is None and not line.startswith("//") and not line.startswith("#ifndef") and not line.startswith("#define") and line != "\n": - first = i - if line != "\n" and not line.startswith("#endif") and not line.startswith("} // namespace "): - last = i + 1 - - lines[last:last] = defs - - if system_includes: - head = [] - tail = [] - if system_include_start is None and system_include_end is None: - system_include_start = system_include_end = min(first, last) - head = ["\n"] - if first < last + 1: tail = ["\n"] - existing_includes = lines[system_include_start:system_include_end] - lines[system_include_start:system_include_end] = head + sorted(set(system_includes) | set(existing_includes)) + tail - - if local_includes: - head = [] - if local_include_start is None and local_include_end is None: - local_include_start = local_include_end = min(first, last) - if lines[local_include_start-1:local_include_start+1] != ["\n", "\n"]: head = ["\n"] - existing_includes = lines[local_include_start:local_include_end] - lines[local_include_start:local_include_end] = head + sorted(set(local_includes) | set(existing_includes)) - - with open(file_path, 'w') as f: - f.writelines(lines) - -def modify_source_files(settings): - includes_to_add = {} - for setting in settings.values(): - for add in setting.adds: - header_file_path = add.include_path - relative_include = os.path.relpath(header_file_path, start="src/").replace(os.sep, '/') - file_path = add.call.file - if file_path not in includes_to_add: - includes_to_add[file_path] = set() - includes_to_add[file_path].add(f"#include <{relative_include}>\n") - with open(file_path, 'r') as f: - content = f.read() - register_args = ", ".join([add.call.obj_name] + add.extern_args) - default_data_type = min(add.data_types.keys()) - new_content = content.replace( - add.call.call_text, - f"{add.data_types[default_data_type].name}::Register({register_args})" - ) - with open(file_path, 'w') as f: - f.write(new_content) - for setting in settings.values(): - for get in setting.gets: - # FIXME handle these by generating synthetic AddArg calls without corresponding Register() - if get.add is None: - #import pprint - #print("*"*80) - #print(f"Bad get call with no corresponding type") - #pprint.pprint(get) - continue - header_file_path = get.add.include_path - relative_include = os.path.relpath(header_file_path, start="src/").replace(os.sep, '/') - file_path = get.call.file - if file_path not in includes_to_add: - includes_to_add[file_path] = set() - includes_to_add[file_path].add(f"#include <{relative_include}>\n") - with open(file_path, 'r') as f: - content = f.read() - setting_type = get.add.data_types[get.data_type or min(get.add.data_types.keys())] - suffix = "" - if get.default_value is not None and not setting_type.default_value: - suffix = f".value_or({from_default_value(get.default_value, get.data_type)})" - prefix = "" - if get.add.call.namespace and get.call.namespace != get.add.call.namespace: - prefix = f"{get.add.call.namespace}::" - new_content = content.replace( - get.call.call_text, - f"{prefix}{setting_type.name}::Get({get.call.obj_name}){suffix}" - ) - with open(file_path, 'w') as f: - f.write(new_content) - # Add necessary includes to files - for file_path, includes in includes_to_add.items(): - add_to_file(file_path, includes) - -@dataclass -class HelpArg: - include_path: str | None = None - runtime: bool = False - extern: bool = False - namespace: str | None = None - -HELP_ARGS = { - "defaultChainParams": HelpArg(extern=True), - "testnetChainParams": HelpArg(extern=True), - "testnet4ChainParams": HelpArg(extern=True), - "signetChainParams": HelpArg(extern=True), - "regtestChainParams": HelpArg(extern=True), - "defaultBaseParams": HelpArg(extern=True), - "testnetBaseParams": HelpArg(extern=True), - "testnet4BaseParams": HelpArg(extern=True), - "signetBaseParams": HelpArg(extern=True), - "regtestBaseParams": HelpArg(extern=True), - "nDefaultDbBatchSize": HelpArg(include_path="txdb.h"), - "DEFAULT_MAX_TRIES": HelpArg(include_path="rpc/mining.h"), - "DEFAULT_COLOR_SETTING": HelpArg(runtime=True), - "DEFAULT_AVOIDPARTIALSPENDS": HelpArg(include_path="wallet/coincontrol.h", runtime=True), - "DatabaseOptions": HelpArg(include_path="wallet/db.h", runtime=True), - "DEFAULT_ADDRESS_TYPE": HelpArg(include_path="wallet/wallet.h"), - #"": HelpArg(include_path="", runtime=True), - #"": HelpArg(include_path="", runtime=True), - #"": HelpArg(include_path="", runtime=True), - "DEFAULT_DEBUGLOGFILE": HelpArg(include_path="logging.h", runtime=True), - "BITCOIN_CONF_FILENAME": HelpArg(include_path="common/args.h", runtime=True), - "BITCOIN_PID_FILENAME": HelpArg(include_path="init.h", runtime=True), - "CURRENCY_UNIT": HelpArg(include_path="policy/feerate.h", runtime=True), - "DEFAULT_ACCEPT_STALE_FEE_ESTIMATES": HelpArg(include_path="policy/fees.h"), - "DEFAULT_ADDRMAN_CONSISTENCY_CHECKS": HelpArg(include_path="addrman.h"), - "DEFAULT_ASMAP_FILENAME": HelpArg(include_path="init.h", runtime=True), - "DEFAULT_BLOCKFILTERINDEX": HelpArg(include_path="index/blockfilterindex.h"), - "DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN": HelpArg(include_path="net_processing.h"), - "DEFAULT_COINSTATSINDEX": HelpArg(include_path="index/coinstatsindex.h"), - "DEFAULT_DAEMON": HelpArg(include_path="init.h"), - "DEFAULT_HTTP_SERVER_TIMEOUT": HelpArg(include_path="httpserver.h"), - "DEFAULT_LISTEN": HelpArg(include_path="net.h"), - "DEFAULT_MAX_MEMPOOL_SIZE_MB": HelpArg(include_path="kernel/mempool_options.h"), - "DEFAULT_MAX_UPLOAD_TARGET": HelpArg(include_path="net.h", runtime=True), - "DEFAULT_MISBEHAVING_BANTIME": HelpArg(include_path="banman.h"), - "DEFAULT_NATPMP": HelpArg(include_path="mapport.h"), - "DEFAULT_PERSIST_MEMPOOL": HelpArg(include_path="node/mempool_persist_args.h", namespace="node"), - "DEFAULT_PRINT_MODIFIED_FEE": HelpArg(include_path="node/miner.h"), - "DEFAULT_STOPATHEIGHT": HelpArg(include_path="node/kernel_notifications.h"), - "DEFAULT_NBLOCKS": HelpArg(runtime=True), - "DEFAULT_TOR_CONTROL": HelpArg(include_path="torcontrol.h", runtime=True), - "DEFAULT_TOR_CONTROL_PORT": HelpArg(include_path="torcontrol.h"), - "DEFAULT_TXINDEX": HelpArg(include_path="index/txindex.h"), - "DEFAULT_VALIDATION_CACHE_BYTES": HelpArg(include_path="script/sigcache.h"), - "DEFAULT_XOR_BLOCKSDIR": HelpArg(include_path="kernel/blockmanager_opts.h"), - "DEFAULT_ZMQ_SNDHWM": HelpArg(include_path="zmq/zmqabstractnotifier.h"), - "LIST_CHAIN_NAMES": HelpArg(include_path="chainparamsbase.h"), - "MAX_SCRIPTCHECK_THREADS": HelpArg(include_path="node/chainstatemanager_args.h"), - "UNIX_EPOCH_TIME": HelpArg(include_path="rpc/util.h"), - "UNIX_EPOCH_TIME": HelpArg(include_path="rpc/util.h", runtime=True), - "FormatMoney(": HelpArg(include_path="util/moneystr.h", runtime=True), - "Join(": HelpArg(include_path="util/string.h", runtime=True), - "ListBlockFilterTypes()": HelpArg(include_path="blockfilter.h", runtime=True), - "LogInstance()": HelpArg(include_path="logging.h", runtime=True), - "PathToString(": HelpArg(include_path="util/fs.h", runtime=True), - "FormatOutputType(": HelpArg(include_path="outputtype.h", runtime=True), - '"regtest only; "': HelpArg(runtime=True), - "BaseParams()": HelpArg(include_path="chainparamsbase.h", runtime=True), - "gArgs": HelpArg(include_path="common/args.h", runtime=True), - "pblock->nVersion": HelpArg(extern=True), - "options.": HelpArg(extern=True), - "mempool_opts.": HelpArg(extern=True), - "mempool_limits.": HelpArg(extern=True), - "nBytesPerSigOp": HelpArg(include_path="policy/settings.h", runtime=True), - "DEFAULT_BLOCKFILTERINDEX": HelpArg(include_path="index/blockfilterindex.h", runtime=True), -} - -if __name__ == "__main__": - src_dir = "src/" - settings = collect_argument_information(src_dir) - generate_setting_headers(settings) - modify_source_files(settings) diff --git a/src/addrdb.cpp b/src/addrdb.cpp index 889f7b3859b14..9d8ffab534f06 100644 --- a/src/addrdb.cpp +++ b/src/addrdb.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -190,7 +191,7 @@ void ReadFromStream(AddrMan& addr, DataStream& ssPeers) util::Result> LoadAddrman(const NetGroupManager& netgroupman, const ArgsManager& args) { - auto check_addrman = std::clamp(args.GetIntArg("-checkaddrman", DEFAULT_ADDRMAN_CONSISTENCY_CHECKS), 0, 1000000); + auto check_addrman = std::clamp(CheckaddrmanSetting::Get(args).value_or(DEFAULT_ADDRMAN_CONSISTENCY_CHECKS), 0, 1000000); bool deterministic = HasTestOption(args, "addrman"); // use a deterministic addrman only for tests auto addrman{std::make_unique(netgroupman, deterministic, /*consistency_check_ratio=*/check_addrman)}; diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp index 555dca7d5982f..7ac750871b226 100644 --- a/src/bench/bench_bitcoin.cpp +++ b/src/bench/bench_bitcoin.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include +#include #include #include #include @@ -28,15 +29,14 @@ static void SetupBenchArgs(ArgsManager& argsman) { SetupHelpOptions(argsman); - argsman.AddArg("-asymptote=", "Test asymptotic growth of the runtime of an algorithm, if supported by the benchmark", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-filter=", strprintf("Regular expression filter to select benchmark by name (default: %s)", DEFAULT_BENCH_FILTER), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-list", "List benchmarks without executing them", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-min-time=", strprintf("Minimum runtime per benchmark, in milliseconds (default: %d)", DEFAULT_MIN_TIME_MS), ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS); - argsman.AddArg("-output-csv=", "Generate CSV file with the most important benchmark results", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-output-json=", "Generate JSON file with all benchmark results", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-sanity-check", "Run benchmarks for only one iteration with no output", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-priority-level=", strprintf("Run benchmarks of one or multiple priority level(s) (%s), default: '%s'", - benchmark::ListPriorities(), DEFAULT_PRIORITY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + AsymptoteSetting::Register(argsman); + FilterSetting::Register(argsman); + ListSetting::Register(argsman); + MinTimeSetting::Register(argsman); + OutputCsvSetting::Register(argsman); + OutputJsonSetting::Register(argsman); + SanityCheckSetting::Register(argsman); + PriorityLevelSetting::Register(argsman); } // parses a comma separated list like "10,20,30,50" @@ -123,14 +123,14 @@ int main(int argc, char** argv) try { benchmark::Args args; - args.asymptote = parseAsymptote(argsman.GetArg("-asymptote", "")); - args.is_list_only = argsman.GetBoolArg("-list", false); - args.min_time = std::chrono::milliseconds(argsman.GetIntArg("-min-time", DEFAULT_MIN_TIME_MS)); - args.output_csv = argsman.GetPathArg("-output-csv"); - args.output_json = argsman.GetPathArg("-output-json"); - args.regex_filter = argsman.GetArg("-filter", DEFAULT_BENCH_FILTER); - args.sanity_check = argsman.GetBoolArg("-sanity-check", false); - args.priority = parsePriorityLevel(argsman.GetArg("-priority-level", DEFAULT_PRIORITY)); + args.asymptote = parseAsymptote(AsymptoteSetting::Get(argsman)); + args.is_list_only = ListSetting::Get(argsman); + args.min_time = std::chrono::milliseconds(MinTimeSetting::Get(argsman)); + args.output_csv = OutputCsvSetting::Get(argsman); + args.output_json = OutputJsonSetting::Get(argsman); + args.regex_filter = FilterSetting::Get(argsman); + args.sanity_check = SanityCheckSetting::Get(argsman); + args.priority = parsePriorityLevel(PriorityLevelSetting::Get(argsman)); benchmark::BenchRunner::RunAll(args); diff --git a/src/bench/bench_bitcoin_settings.h b/src/bench/bench_bitcoin_settings.h new file mode 100644 index 0000000000000..1ba870723f325 --- /dev/null +++ b/src/bench/bench_bitcoin_settings.h @@ -0,0 +1,45 @@ +#ifndef BENCH_BENCH_BITCOIN_SETTINGS_H +#define BENCH_BENCH_BITCOIN_SETTINGS_H + +#include + +#include +#include + +using AsymptoteSetting = common::Setting< + "-asymptote=", std::string, {.legacy = true}, + "Test asymptotic growth of the runtime of an algorithm, if supported by the benchmark">; + +using FilterSetting = common::Setting< + "-filter=", std::string, {.legacy = true}, + "Regular expression filter to select benchmark by name (default: %s)"> + ::Default; + +using ListSetting = common::Setting< + "-list", bool, {.legacy = true}, + "List benchmarks without executing them">; + +using MinTimeSetting = common::Setting< + "-min-time=", int64_t, {.legacy = true, .disallow_negation = true}, + "Minimum runtime per benchmark, in milliseconds (default: %d)"> + ::Default; + +using OutputCsvSetting = common::Setting< + "-output-csv=", fs::path, {.legacy = true}, + "Generate CSV file with the most important benchmark results">; + +using OutputJsonSetting = common::Setting< + "-output-json=", fs::path, {.legacy = true}, + "Generate JSON file with all benchmark results">; + +using SanityCheckSetting = common::Setting< + "-sanity-check", bool, {.legacy = true}, + "Run benchmarks for only one iteration with no output">; + +using PriorityLevelSetting = common::Setting< + "-priority-level=", std::string, {.legacy = true}, + "Run benchmarks of one or multiple priority level(s) (%s), default: '%s'"> + ::Default + ::HelpArgs; + +#endif // BENCH_BENCH_BITCOIN_SETTINGS_H diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index d5181a6182e8a..073b9b35ce61c 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -5,6 +5,7 @@ #include // IWYU pragma: keep +#include #include #include #include @@ -69,34 +70,29 @@ static void SetupCliArgs(ArgsManager& argsman) const auto signetBaseParams = CreateBaseChainParams(ChainType::SIGNET); const auto regtestBaseParams = CreateBaseChainParams(ChainType::REGTEST); - argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-conf=", strprintf("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-datadir=", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-generate", - strprintf("Generate blocks, equivalent to RPC getnewaddress followed by RPC generatetoaddress. Optional positional integer " - "arguments are number of blocks to generate (default: %s) and maximum iterations to try (default: %s), equivalent to " - "RPC generatetoaddress nblocks and maxtries arguments. Example: bitcoin-cli -generate 4 1000", - DEFAULT_NBLOCKS, DEFAULT_MAX_TRIES), - ArgsManager::ALLOW_ANY, OptionsCategory::CLI_COMMANDS); - argsman.AddArg("-addrinfo", "Get the number of addresses known to the node, per network and total, after filtering for quality and recency. The total number of addresses known to the node may be higher.", ArgsManager::ALLOW_ANY, OptionsCategory::CLI_COMMANDS); - argsman.AddArg("-getinfo", "Get general information from the remote server. Note that unlike server-side RPC calls, the output of -getinfo is the result of multiple non-atomic requests. Some entries in the output may represent results from different states (e.g. wallet balance may be as of a different block from the chain state reported)", ArgsManager::ALLOW_ANY, OptionsCategory::CLI_COMMANDS); - argsman.AddArg("-netinfo", strprintf("Get network peer connection information from the remote server. An optional argument from 0 to %d can be passed for different peers listings (default: 0). If a non-zero value is passed, an additional \"outonly\" (or \"o\") argument can be passed to see outbound peers only. Pass \"help\" (or \"h\") for detailed help documentation.", NETINFO_MAX_LEVEL), ArgsManager::ALLOW_ANY, OptionsCategory::CLI_COMMANDS); + VersionSetting::Register(argsman); + ConfSetting::Register(argsman); + DatadirSetting::Register(argsman); + GenerateSetting::Register(argsman); + AddrinfoSetting::Register(argsman); + GetinfoSetting::Register(argsman); + NetinfoSetting::Register(argsman); SetupChainParamsBaseOptions(argsman); - argsman.AddArg("-color=", strprintf("Color setting for CLI output (default: %s). Valid values: always, auto (add color codes when standard output is connected to a terminal and OS is not WIN32), never.", DEFAULT_COLOR_SETTING), ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS); - argsman.AddArg("-named", strprintf("Pass named instead of positional arguments (default: %s)", DEFAULT_NAMED), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-rpcclienttimeout=", strprintf("Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)", DEFAULT_HTTP_CLIENT_TIMEOUT), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-rpcconnect=", strprintf("Send commands to node running on (default: %s)", DEFAULT_RPCCONNECT), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-rpccookiefile=", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-rpcpassword=", "Password for JSON-RPC connections", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-rpcport=", strprintf("Connect to JSON-RPC on (default: %u, testnet: %u, testnet4: %u, signet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), testnet4BaseParams->RPCPort(), signetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::OPTIONS); - argsman.AddArg("-rpcuser=", "Username for JSON-RPC connections", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-rpcwait", "Wait for RPC server to start", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-rpcwaittimeout=", strprintf("Timeout in seconds to wait for the RPC server to start, or 0 for no timeout. (default: %d)", DEFAULT_WAIT_CLIENT_TIMEOUT), ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS); - argsman.AddArg("-rpcwallet=", "Send RPC for non-default wallet on RPC server (needs to exactly match corresponding -wallet option passed to bitcoind). This changes the RPC endpoint used, e.g. http://127.0.0.1:8332/wallet/", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-stdin", "Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases). When combined with -stdinrpcpass, the first line from standard input is used for the RPC password.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-stdinrpcpass", "Read RPC password from standard input as a single line. When combined with -stdin, the first line from standard input is used for the RPC password. When combined with -stdinwalletpassphrase, -stdinrpcpass consumes the first line, and -stdinwalletpassphrase consumes the second.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-stdinwalletpassphrase", "Read wallet passphrase from standard input as a single line. When combined with -stdin, the first line from standard input is used for the wallet passphrase.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + ColorSetting::Register(argsman); + NamedSetting::Register(argsman); + RpcclienttimeoutSetting::Register(argsman); + RpcconnectSetting::Register(argsman); + RpccookiefileSetting::Register(argsman); + RpcpasswordSetting::Register(argsman); + RpcportSetting::Register(argsman, defaultBaseParams, testnetBaseParams, testnet4BaseParams, signetBaseParams, regtestBaseParams); + RpcuserSetting::Register(argsman); + RpcwaitSetting::Register(argsman); + RpcwaittimeoutSetting::Register(argsman); + RpcwalletSetting::Register(argsman); + StdinSetting::Register(argsman); + StdinrpcpassSetting::Register(argsman); + StdinwalletpassphraseSetting::Register(argsman); } /** libevent event log callback */ @@ -134,10 +130,10 @@ static int AppInitRPC(int argc, char* argv[]) tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error); return EXIT_FAILURE; } - if (argc < 2 || HelpRequested(gArgs) || gArgs.IsArgSet("-version")) { + if (argc < 2 || HelpRequested(gArgs) || VersionSetting::Get(gArgs)) { std::string strUsage = CLIENT_NAME " RPC client version " + FormatFullVersion() + "\n"; - if (gArgs.IsArgSet("-version")) { + if (VersionSetting::Get(gArgs)) { strUsage += FormatParagraph(LicenseInfo()); } else { strUsage += "\n" @@ -156,7 +152,7 @@ static int AppInitRPC(int argc, char* argv[]) return EXIT_SUCCESS; } if (!CheckDataDirOption(gArgs)) { - tfm::format(std::cerr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "")); + tfm::format(std::cerr, "Error: Specified data directory \"%s\" does not exist.\n", DatadirSetting::Get(gArgs)); return EXIT_FAILURE; } if (!gArgs.ReadConfigFiles(error, true)) { @@ -756,7 +752,7 @@ class DefaultRequestHandler: public BaseRequestHandler { UniValue PrepareRequest(const std::string& method, const std::vector& args) override { UniValue params; - if(gArgs.GetBoolArg("-named", DEFAULT_NAMED)) { + if(NamedSetting::Get(gArgs)) { params = RPCConvertNamedValues(method, args); } else { params = RPCConvertValues(method, args); @@ -780,7 +776,7 @@ static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, co uint16_t port{BaseParams().RPCPort()}; { uint16_t rpcconnect_port{0}; - const std::string rpcconnect_str = gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT); + const std::string rpcconnect_str = RpcconnectSetting::Get(gArgs); if (!SplitHostPort(rpcconnect_str, rpcconnect_port, host)) { // Uses argument provided as-is // (rather than value parsed) @@ -793,7 +789,7 @@ static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, co } // else, no port was provided in rpcconnect (continue using default one) } - if (std::optional rpcport_arg = gArgs.GetArg("-rpcport")) { + if (std::optional rpcport_arg = RpcportSetting::Get(gArgs)) { // -rpcport was specified const uint16_t rpcport_int{ToIntegral(rpcport_arg.value()).value_or(0)}; if (rpcport_int == 0) { @@ -822,7 +818,7 @@ static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, co // Set connection timeout { - const int timeout = gArgs.GetIntArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT); + const int timeout = RpcclienttimeoutSetting::Get(gArgs); if (timeout > 0) { evhttp_connection_set_timeout(evcon.get(), timeout); } else { @@ -845,13 +841,13 @@ static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, co // Get credentials std::string strRPCUserColonPass; bool failedToGetAuthCookie = false; - if (gArgs.GetArg("-rpcpassword", "") == "") { + if (RpcpasswordSetting::Get(gArgs) == "") { // Try fall back to cookie-based authentication if no password is provided if (!GetAuthCookie(&strRPCUserColonPass)) { failedToGetAuthCookie = true; } } else { - strRPCUserColonPass = gArgs.GetArg("-rpcuser", "") + ":" + gArgs.GetArg("-rpcpassword", ""); + strRPCUserColonPass = RpcuserSetting::Get(gArgs) + ":" + RpcpasswordSetting::Get(gArgs); } struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get()); @@ -934,8 +930,8 @@ static UniValue ConnectAndCallRPC(BaseRequestHandler* rh, const std::string& str { UniValue response(UniValue::VOBJ); // Execute and handle connection failures with -rpcwait. - const bool fWait = gArgs.GetBoolArg("-rpcwait", false); - const int timeout = gArgs.GetIntArg("-rpcwaittimeout", DEFAULT_WAIT_CLIENT_TIMEOUT); + const bool fWait = RpcwaitSetting::Get(gArgs); + const int timeout = RpcwaittimeoutSetting::Get(gArgs); const auto deadline{std::chrono::steady_clock::now() + 1s * timeout}; do { @@ -1054,8 +1050,8 @@ static void ParseGetInfoResult(UniValue& result) } #endif - if (gArgs.IsArgSet("-color")) { - const std::string color{gArgs.GetArg("-color", DEFAULT_COLOR_SETTING)}; + if (ColorSetting::Get(gArgs)) { + const std::string color{ColorSetting::Get(gArgs).value_or(DEFAULT_COLOR_SETTING)}; if (color == "always") { should_colorize = true; } else if (color == "never") { @@ -1167,7 +1163,7 @@ static void ParseGetInfoResult(UniValue& result) static UniValue GetNewAddress() { std::optional wallet_name{}; - if (gArgs.IsArgSet("-rpcwallet")) wallet_name = gArgs.GetArg("-rpcwallet", ""); + if (RpcwalletSetting::Get(gArgs)) wallet_name = RpcwalletSetting::Get(gArgs).value_or(""); DefaultRequestHandler rh; return ConnectAndCallRPC(&rh, "getnewaddress", /* args=*/{}, wallet_name); } @@ -1199,7 +1195,7 @@ static int CommandLineRPC(int argc, char *argv[]) argv++; } std::string rpcPass; - if (gArgs.GetBoolArg("-stdinrpcpass", false)) { + if (StdinrpcpassSetting::Get(gArgs)) { NO_STDIN_ECHO(); if (!StdinReady()) { fputs("RPC password> ", stderr); @@ -1214,7 +1210,7 @@ static int CommandLineRPC(int argc, char *argv[]) gArgs.ForceSetArg("-rpcpassword", rpcPass); } std::vector args = std::vector(&argv[1], &argv[argc]); - if (gArgs.GetBoolArg("-stdinwalletpassphrase", false)) { + if (StdinwalletpassphraseSetting::Get(gArgs)) { NO_STDIN_ECHO(); std::string walletPass; if (args.size() < 1 || args[0].substr(0, 16) != "walletpassphrase") { @@ -1232,7 +1228,7 @@ static int CommandLineRPC(int argc, char *argv[]) } args.insert(args.begin() + 1, walletPass); } - if (gArgs.GetBoolArg("-stdin", false)) { + if (StdinSetting::Get(gArgs)) { // Read one arg per line from stdin and append std::string line; while (std::getline(std::cin, line)) { @@ -1245,15 +1241,15 @@ static int CommandLineRPC(int argc, char *argv[]) gArgs.CheckMultipleCLIArgs(); std::unique_ptr rh; std::string method; - if (gArgs.IsArgSet("-getinfo")) { + if (GetinfoSetting::Get(gArgs)) { rh.reset(new GetinfoRequestHandler()); - } else if (gArgs.GetBoolArg("-netinfo", false)) { + } else if (NetinfoSetting::Get(gArgs)) { if (!args.empty() && (args.at(0) == "h" || args.at(0) == "help")) { tfm::format(std::cout, "%s\n", NetinfoRequestHandler().m_help_doc); return 0; } rh.reset(new NetinfoRequestHandler()); - } else if (gArgs.GetBoolArg("-generate", false)) { + } else if (GenerateSetting::Get(gArgs)) { const UniValue getnewaddress{GetNewAddress()}; const UniValue& error{getnewaddress.find_value("error")}; if (error.isNull()) { @@ -1262,7 +1258,7 @@ static int CommandLineRPC(int argc, char *argv[]) } else { ParseError(error, strPrint, nRet); } - } else if (gArgs.GetBoolArg("-addrinfo", false)) { + } else if (AddrinfoSetting::Get(gArgs)) { rh.reset(new AddrinfoRequestHandler()); } else { rh.reset(new DefaultRequestHandler()); @@ -1275,15 +1271,15 @@ static int CommandLineRPC(int argc, char *argv[]) if (nRet == 0) { // Perform RPC call std::optional wallet_name{}; - if (gArgs.IsArgSet("-rpcwallet")) wallet_name = gArgs.GetArg("-rpcwallet", ""); + if (RpcwalletSetting::Get(gArgs)) wallet_name = RpcwalletSetting::Get(gArgs).value_or(""); const UniValue reply = ConnectAndCallRPC(rh.get(), method, args, wallet_name); // Parse reply UniValue result = reply.find_value("result"); const UniValue& error = reply.find_value("error"); if (error.isNull()) { - if (gArgs.GetBoolArg("-getinfo", false)) { - if (!gArgs.IsArgSet("-rpcwallet")) { + if (GetinfoSetting::Get(gArgs).value_or(false)) { + if (!RpcwalletSetting::Get(gArgs)) { GetWalletBalances(result); // fetch multiwallet balances and append to result } ParseGetInfoResult(result); diff --git a/src/bitcoin-cli_settings.h b/src/bitcoin-cli_settings.h index 883e78cc6a0bc..6fe944668f7b2 100644 --- a/src/bitcoin-cli_settings.h +++ b/src/bitcoin-cli_settings.h @@ -5,6 +5,13 @@ #ifndef BITCOIN_CLI_SETTINGS_H #define BITCOIN_CLI_SETTINGS_H +#include +#include +#include + +#include +#include + static const char DEFAULT_RPCCONNECT[] = "127.0.0.1"; static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900; static constexpr int DEFAULT_WAIT_CLIENT_TIMEOUT = 0; @@ -17,4 +24,103 @@ static const std::string DEFAULT_NBLOCKS = "1"; /** Default -color setting. */ static const std::string DEFAULT_COLOR_SETTING{"auto"}; +using VersionSetting = common::Setting< + "-version", std::optional, {.legacy = true}, + "Print version and exit">; + +using ConfSetting = common::Setting< + "-conf=", std::optional, {.legacy = true}, + "Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)"> + ::HelpFn<[](const auto& fmt) { return strprintf(fmt, BITCOIN_CONF_FILENAME); }>; + +using DatadirSetting = common::Setting< + "-datadir=", std::string, {.legacy = true}, + "Specify data directory">; + +using GenerateSetting = common::Setting< + "-generate", bool, {.legacy = true}, + "Generate blocks, equivalent to RPC getnewaddress followed by RPC generatetoaddress. Optional positional integer " + "arguments are number of blocks to generate (default: %s) and maximum iterations to try (default: %s), equivalent to " + "RPC generatetoaddress nblocks and maxtries arguments. Example: bitcoin-cli -generate 4 1000"> + ::HelpFn<[](const auto& fmt) { return strprintf(fmt, DEFAULT_NBLOCKS, DEFAULT_MAX_TRIES); }> + ::Category; + +using AddrinfoSetting = common::Setting< + "-addrinfo", bool, {.legacy = true}, + "Get the number of addresses known to the node, per network and total, after filtering for quality and recency. The total number of addresses known to the node may be higher."> + ::Category; + +using GetinfoSetting = common::Setting< + "-getinfo", std::optional, {.legacy = true}, + "Get general information from the remote server. Note that unlike server-side RPC calls, the output of -getinfo is the result of multiple non-atomic requests. Some entries in the output may represent results from different states (e.g. wallet balance may be as of a different block from the chain state reported)"> + ::Category; + +using NetinfoSetting = common::Setting< + "-netinfo", bool, {.legacy = true}, + "Get network peer connection information from the remote server. An optional argument from 0 to %d can be passed for different peers listings (default: 0). If a non-zero value is passed, an additional \"outonly\" (or \"o\") argument can be passed to see outbound peers only. Pass \"help\" (or \"h\") for detailed help documentation."> + ::HelpArgs + ::Category; + +using ColorSetting = common::Setting< + "-color=", std::optional, {.legacy = true, .disallow_negation = true}, + "Color setting for CLI output (default: %s). Valid values: always, auto (add color codes when standard output is connected to a terminal and OS is not WIN32), never."> + ::HelpFn<[](const auto& fmt) { return strprintf(fmt, DEFAULT_COLOR_SETTING); }>; + +using NamedSetting = common::Setting< + "-named", bool, {.legacy = true}, + "Pass named instead of positional arguments (default: %s)"> + ::Default; + +using RpcclienttimeoutSetting = common::Setting< + "-rpcclienttimeout=", int64_t, {.legacy = true}, + "Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)"> + ::Default; + +using RpcconnectSetting = common::Setting< + "-rpcconnect=", std::string, {.legacy = true}, + "Send commands to node running on (default: %s)"> + ::Default; + +using RpccookiefileSetting = common::Setting< + "-rpccookiefile=", std::optional, {.legacy = true}, + "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)">; + +using RpcpasswordSetting = common::Setting< + "-rpcpassword=", std::string, {.legacy = true}, + "Password for JSON-RPC connections">; + +using RpcportSetting = common::Setting< + "-rpcport=", std::optional, {.legacy = true, .network_only = true}, + "Connect to JSON-RPC on (default: %u, testnet: %u, testnet4: %u, signet: %u, regtest: %u)"> + ::HelpFn<[](const auto& fmt, const auto& defaultBaseParams, const auto& testnetBaseParams, const auto& testnet4BaseParams, const auto& signetBaseParams, const auto& regtestBaseParams) { return strprintf(fmt, defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), testnet4BaseParams->RPCPort(), signetBaseParams->RPCPort(), regtestBaseParams->RPCPort()); }>; + +using RpcuserSetting = common::Setting< + "-rpcuser=", std::string, {.legacy = true}, + "Username for JSON-RPC connections">; + +using RpcwaitSetting = common::Setting< + "-rpcwait", bool, {.legacy = true}, + "Wait for RPC server to start">; + +using RpcwaittimeoutSetting = common::Setting< + "-rpcwaittimeout=", int64_t, {.legacy = true, .disallow_negation = true}, + "Timeout in seconds to wait for the RPC server to start, or 0 for no timeout. (default: %d)"> + ::Default; + +using RpcwalletSetting = common::Setting< + "-rpcwallet=", std::optional, {.legacy = true}, + "Send RPC for non-default wallet on RPC server (needs to exactly match corresponding -wallet option passed to bitcoind). This changes the RPC endpoint used, e.g. http://127.0.0.1:8332/wallet/">; + +using StdinSetting = common::Setting< + "-stdin", bool, {.legacy = true}, + "Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases). When combined with -stdinrpcpass, the first line from standard input is used for the RPC password.">; + +using StdinrpcpassSetting = common::Setting< + "-stdinrpcpass", bool, {.legacy = true}, + "Read RPC password from standard input as a single line. When combined with -stdin, the first line from standard input is used for the RPC password. When combined with -stdinwalletpassphrase, -stdinrpcpass consumes the first line, and -stdinwalletpassphrase consumes the second.">; + +using StdinwalletpassphraseSetting = common::Setting< + "-stdinwalletpassphrase", bool, {.legacy = true}, + "Read wallet passphrase from standard input as a single line. When combined with -stdin, the first line from standard input is used for the wallet passphrase.">; + #endif // BITCOIN_CLI_SETTINGS_H diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 1aff914792ba2..4e89dd5dbc341 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -4,6 +4,7 @@ #include // IWYU pragma: keep +#include #include #include #include @@ -47,39 +48,27 @@ static void SetupBitcoinTxArgs(ArgsManager &argsman) { SetupHelpOptions(argsman); - argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-create", "Create new, empty TX.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-json", "Select JSON output", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-txid", "Output only the hex-encoded transaction id of the resultant transaction.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + VersionSetting::Register(argsman); + CreateSetting::Register(argsman); + JsonSetting::Register(argsman); + TxidSetting::Register(argsman); SetupChainParamsBaseOptions(argsman); - argsman.AddArg("delin=N", "Delete input N from TX", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS); - argsman.AddArg("delout=N", "Delete output N from TX", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS); - argsman.AddArg("in=TXID:VOUT(:SEQUENCE_NUMBER)", "Add input to TX", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS); - argsman.AddArg("locktime=N", "Set TX lock time to N", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS); - argsman.AddArg("nversion=N", "Set TX version to N", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS); - argsman.AddArg("outaddr=VALUE:ADDRESS", "Add address-based output to TX", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS); - argsman.AddArg("outdata=[VALUE:]DATA", "Add data-based output to TX", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS); - argsman.AddArg("outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]", "Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS. " - "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. " - "Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash.", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS); - argsman.AddArg("outpubkey=VALUE:PUBKEY[:FLAGS]", "Add pay-to-pubkey output to TX. " - "Optionally add the \"W\" flag to produce a pay-to-witness-pubkey-hash output. " - "Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash.", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS); - argsman.AddArg("outscript=VALUE:SCRIPT[:FLAGS]", "Add raw script output to TX. " - "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. " - "Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash.", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS); - argsman.AddArg("replaceable(=N)", "Sets Replace-By-Fee (RBF) opt-in sequence number for input N. " - "If N is not provided, the command attempts to opt-in all available inputs for RBF. " - "If the transaction has no inputs, this option is ignored.", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS); - argsman.AddArg("sign=SIGHASH-FLAGS", "Add zero or more signatures to transaction. " - "This command requires JSON registers:" - "prevtxs=JSON object, " - "privatekeys=JSON object. " - "See signrawtransactionwithkey docs for format of sighash flags, JSON objects.", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS); - - argsman.AddArg("load=NAME:FILENAME", "Load JSON file FILENAME into register NAME", ArgsManager::ALLOW_ANY, OptionsCategory::REGISTER_COMMANDS); - argsman.AddArg("set=NAME:JSON-STRING", "Set register NAME to given JSON-STRING", ArgsManager::ALLOW_ANY, OptionsCategory::REGISTER_COMMANDS); + DelinSetting::Register(argsman); + DeloutSetting::Register(argsman); + InSetting::Register(argsman); + LocktimeSetting::Register(argsman); + NversionSetting::Register(argsman); + OutaddrSetting::Register(argsman); + OutdataSetting::Register(argsman); + OutmultisigSetting::Register(argsman); + OutpubkeySetting::Register(argsman); + OutscriptSetting::Register(argsman); + ReplaceableSetting::Register(argsman); + SignSetting::Register(argsman); + + LoadSetting::Register(argsman); + SetSetting::Register(argsman); } // @@ -103,13 +92,13 @@ static int AppInitRawTx(int argc, char* argv[]) return EXIT_FAILURE; } - fCreateBlank = gArgs.GetBoolArg("-create", false); + fCreateBlank = CreateSetting::Get(gArgs); - if (argc < 2 || HelpRequested(gArgs) || gArgs.IsArgSet("-version")) { + if (argc < 2 || HelpRequested(gArgs) || VersionSetting::Get(gArgs)) { // First part of help message is specific to this utility std::string strUsage = CLIENT_NAME " bitcoin-tx utility version " + FormatFullVersion() + "\n"; - if (gArgs.IsArgSet("-version")) { + if (VersionSetting::Get(gArgs)) { strUsage += FormatParagraph(LicenseInfo()); } else { strUsage += "\n" @@ -770,9 +759,9 @@ static void OutputTxHex(const CTransaction& tx) static void OutputTx(const CTransaction& tx) { - if (gArgs.GetBoolArg("-json", false)) + if (JsonSetting::Get(gArgs)) OutputTxJSON(tx); - else if (gArgs.GetBoolArg("-txid", false)) + else if (TxidSetting::Get(gArgs)) OutputTxHash(tx); else OutputTxHex(tx); diff --git a/src/bitcoin-tx_settings.h b/src/bitcoin-tx_settings.h new file mode 100644 index 0000000000000..b8e1eaee6056d --- /dev/null +++ b/src/bitcoin-tx_settings.h @@ -0,0 +1,107 @@ +#ifndef BITCOIN_TX_SETTINGS_H +#define BITCOIN_TX_SETTINGS_H + +#include + +#include +#include + +using VersionSetting = common::Setting< + "-version", std::optional, {.legacy = true}, + "Print version and exit">; + +using CreateSetting = common::Setting< + "-create", bool, {.legacy = true}, + "Create new, empty TX.">; + +using JsonSetting = common::Setting< + "-json", bool, {.legacy = true}, + "Select JSON output">; + +using TxidSetting = common::Setting< + "-txid", bool, {.legacy = true}, + "Output only the hex-encoded transaction id of the resultant transaction.">; + +using DelinSetting = common::Setting< + "delin=N", std::optional, {.legacy = true}, + "Delete input N from TX"> + ::Category; + +using DeloutSetting = common::Setting< + "delout=N", std::optional, {.legacy = true}, + "Delete output N from TX"> + ::Category; + +using InSetting = common::Setting< + "in=TXID:VOUT(:SEQUENCE_NUMBER)", std::optional, {.legacy = true}, + "Add input to TX"> + ::Category; + +using LocktimeSetting = common::Setting< + "locktime=N", std::optional, {.legacy = true}, + "Set TX lock time to N"> + ::Category; + +using NversionSetting = common::Setting< + "nversion=N", std::optional, {.legacy = true}, + "Set TX version to N"> + ::Category; + +using OutaddrSetting = common::Setting< + "outaddr=VALUE:ADDRESS", std::optional, {.legacy = true}, + "Add address-based output to TX"> + ::Category; + +using OutdataSetting = common::Setting< + "outdata=[VALUE:]DATA", std::optional, {.legacy = true}, + "Add data-based output to TX"> + ::Category; + +using OutmultisigSetting = common::Setting< + "outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]", std::optional, {.legacy = true}, + "Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS. " + "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. " + "Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash."> + ::Category; + +using OutpubkeySetting = common::Setting< + "outpubkey=VALUE:PUBKEY[:FLAGS]", std::optional, {.legacy = true}, + "Add pay-to-pubkey output to TX. " + "Optionally add the \"W\" flag to produce a pay-to-witness-pubkey-hash output. " + "Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash."> + ::Category; + +using OutscriptSetting = common::Setting< + "outscript=VALUE:SCRIPT[:FLAGS]", std::optional, {.legacy = true}, + "Add raw script output to TX. " + "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. " + "Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash."> + ::Category; + +using ReplaceableSetting = common::Setting< + "replaceable(=N)", std::optional, {.legacy = true}, + "Sets Replace-By-Fee (RBF) opt-in sequence number for input N. " + "If N is not provided, the command attempts to opt-in all available inputs for RBF. " + "If the transaction has no inputs, this option is ignored."> + ::Category; + +using SignSetting = common::Setting< + "sign=SIGHASH-FLAGS", std::optional, {.legacy = true}, + "Add zero or more signatures to transaction. " + "This command requires JSON registers:" + "prevtxs=JSON object, " + "privatekeys=JSON object. " + "See signrawtransactionwithkey docs for format of sighash flags, JSON objects."> + ::Category; + +using LoadSetting = common::Setting< + "load=NAME:FILENAME", std::optional, {.legacy = true}, + "Load JSON file FILENAME into register NAME"> + ::Category; + +using SetSetting = common::Setting< + "set=NAME:JSON-STRING", std::optional, {.legacy = true}, + "Set register NAME to given JSON-STRING"> + ::Category; + +#endif // BITCOIN_TX_SETTINGS_H diff --git a/src/bitcoin-util.cpp b/src/bitcoin-util.cpp index 657de544b30a5..9497486241004 100644 --- a/src/bitcoin-util.cpp +++ b/src/bitcoin-util.cpp @@ -5,6 +5,7 @@ #include // IWYU pragma: keep #include +#include #include #include #include @@ -32,7 +33,7 @@ static void SetupBitcoinUtilArgs(ArgsManager &argsman) { SetupHelpOptions(argsman); - argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + VersionSetting::Register(argsman); argsman.AddCommand("grind", "Perform proof of work on hex header string"); @@ -50,11 +51,11 @@ static int AppInitUtil(ArgsManager& args, int argc, char* argv[]) return EXIT_FAILURE; } - if (HelpRequested(args) || args.IsArgSet("-version")) { + if (HelpRequested(args) || VersionSetting::Get(args)) { // First part of help message is specific to this utility std::string strUsage = CLIENT_NAME " bitcoin-util utility version " + FormatFullVersion() + "\n"; - if (args.IsArgSet("-version")) { + if (VersionSetting::Get(args)) { strUsage += FormatParagraph(LicenseInfo()); } else { strUsage += "\n" diff --git a/src/bitcoin-util_settings.h b/src/bitcoin-util_settings.h new file mode 100644 index 0000000000000..71c241023dfb0 --- /dev/null +++ b/src/bitcoin-util_settings.h @@ -0,0 +1,13 @@ +#ifndef BITCOIN_UTIL_SETTINGS_H +#define BITCOIN_UTIL_SETTINGS_H + +#include + +#include +#include + +using VersionSetting = common::Setting< + "-version", std::optional, {.legacy = true}, + "Print version and exit">; + +#endif // BITCOIN_UTIL_SETTINGS_H diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp index c469fbda76b07..90d352d13143f 100644 --- a/src/bitcoin-wallet.cpp +++ b/src/bitcoin-wallet.cpp @@ -4,6 +4,7 @@ #include // IWYU pragma: keep +#include #include #include #include @@ -33,16 +34,16 @@ static void SetupWalletToolArgs(ArgsManager& argsman) SetupHelpOptions(argsman); SetupChainParamsBaseOptions(argsman); - argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-datadir=", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-wallet=", "Specify wallet name", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::OPTIONS); - argsman.AddArg("-dumpfile=", "When used with 'dump', writes out the records to this file. When used with 'createfromdump', loads the records into a new wallet.", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS); - argsman.AddArg("-debug=", "Output debugging information (default: 0).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-descriptors", "Create descriptors wallet. Only for 'create'", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-legacy", "Create legacy wallet. Only for 'create'", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-format=", "The format of the wallet file to create. Either \"bdb\" or \"sqlite\". Only used with 'createfromdump'", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -debug is true, 0 otherwise).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-withinternalbdb", "Use the internal Berkeley DB parser when dumping a Berkeley DB wallet file (default: false)", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); + VersionSetting::Register(argsman); + DatadirSetting::Register(argsman); + WalletSetting::Register(argsman); + DumpfileSetting::Register(argsman); + DebugSetting::Register(argsman); + DescriptorsSetting::Register(argsman); + LegacySetting::Register(argsman); + FormatSetting::Register(argsman); + PrinttoconsoleSetting::Register(argsman); + WithinternalbdbSetting::Register(argsman); argsman.AddCommand("info", "Get wallet info"); argsman.AddCommand("create", "Create new wallet file"); @@ -60,10 +61,10 @@ static std::optional WalletAppInit(ArgsManager& args, int argc, char* argv[ return EXIT_FAILURE; } const bool missing_args{argc < 2}; - if (missing_args || HelpRequested(args) || args.IsArgSet("-version")) { + if (missing_args || HelpRequested(args) || VersionSetting::Get(args)) { std::string strUsage = strprintf("%s bitcoin-wallet version", CLIENT_NAME) + " " + FormatFullVersion() + "\n"; - if (args.IsArgSet("-version")) { + if (VersionSetting::Get(args)) { strUsage += FormatParagraph(LicenseInfo()); } else { strUsage += "\n" @@ -83,10 +84,10 @@ static std::optional WalletAppInit(ArgsManager& args, int argc, char* argv[ } // check for printtoconsole, allow -debug - LogInstance().m_print_to_console = args.GetBoolArg("-printtoconsole", args.GetBoolArg("-debug", false)); + LogInstance().m_print_to_console = args.GetBoolArg("-printtoconsole", DebugSetting::Get(args)); if (!CheckDataDirOption(args)) { - tfm::format(std::cerr, "Error: Specified data directory \"%s\" does not exist.\n", args.GetArg("-datadir", "")); + tfm::format(std::cerr, "Error: Specified data directory \"%s\" does not exist.\n", DatadirSetting::Get(args)); return EXIT_FAILURE; } // Check for chain settings (Params() calls are only valid after this clause) diff --git a/src/bitcoin-wallet_settings.h b/src/bitcoin-wallet_settings.h new file mode 100644 index 0000000000000..8bae31455691e --- /dev/null +++ b/src/bitcoin-wallet_settings.h @@ -0,0 +1,54 @@ +#ifndef BITCOIN_WALLET_SETTINGS_H +#define BITCOIN_WALLET_SETTINGS_H + +#include + +#include +#include + +using VersionSetting = common::Setting< + "-version", std::optional, {.legacy = true}, + "Print version and exit">; + +using DatadirSetting = common::Setting< + "-datadir=", std::string, {.legacy = true}, + "Specify data directory">; + +using WalletSetting = common::Setting< + "-wallet=", std::optional, {.legacy = true, .network_only = true}, + "Specify wallet name">; + +using DumpfileSetting = common::Setting< + "-dumpfile=", std::optional, {.legacy = true, .disallow_negation = true}, + "When used with 'dump', writes out the records to this file. When used with 'createfromdump', loads the records into a new wallet.">; + +using DebugSetting = common::Setting< + "-debug=", bool, {.legacy = true}, + "Output debugging information (default: 0)."> + ::Category; + +using DescriptorsSetting = common::Setting< + "-descriptors", std::optional, {.legacy = true}, + "Create descriptors wallet. Only for 'create'">; + +using LegacySetting = common::Setting< + "-legacy", std::optional, {.legacy = true}, + "Create legacy wallet. Only for 'create'">; + +using FormatSetting = common::Setting< + "-format=", std::optional, {.legacy = true}, + "The format of the wallet file to create. Either \"bdb\" or \"sqlite\". Only used with 'createfromdump'">; + +using PrinttoconsoleSetting = common::Setting< + "-printtoconsole", bool, {.legacy = true}, + "Send trace/debug info to console (default: 1 when no -debug is true, 0 otherwise)."> + ::Default + ::HelpArgs<> + ::Category; + +using WithinternalbdbSetting = common::Setting< + "-withinternalbdb", bool, {.legacy = true}, + "Use the internal Berkeley DB parser when dumping a Berkeley DB wallet file (default: false)"> + ::Category; + +#endif // BITCOIN_WALLET_SETTINGS_H diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index e9d78f2888379..d0be488639afe 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -135,10 +136,10 @@ static bool ParseArgs(NodeContext& node, int argc, char* argv[]) static bool ProcessInitCommands(ArgsManager& args) { // Process help and version before taking care about datadir - if (HelpRequested(args) || args.IsArgSet("-version")) { + if (HelpRequested(args) || VersionSetting::Get(args)) { std::string strUsage = CLIENT_NAME " version " + FormatFullVersion() + "\n"; - if (args.IsArgSet("-version")) { + if (VersionSetting::Get(args)) { strUsage += FormatParagraph(LicenseInfo()); } else { strUsage += "\nUsage: bitcoind [options] Start " CLIENT_NAME "\n" @@ -193,7 +194,7 @@ static bool AppInit(NodeContext& node) return false; } - if (args.GetBoolArg("-daemon", DEFAULT_DAEMON) || args.GetBoolArg("-daemonwait", DEFAULT_DAEMONWAIT)) { + if (DaemonSetting::Get(args).value_or(DEFAULT_DAEMON) || DaemonwaitSetting::Get(args)) { #if HAVE_DECL_FORK tfm::format(std::cout, CLIENT_NAME " starting\n"); @@ -201,7 +202,7 @@ static bool AppInit(NodeContext& node) switch (fork_daemon(1, 0, daemon_ep)) { // don't chdir (1), do close FDs (0) case 0: // Child: continue. // If -daemonwait is not enabled, immediately send a success token the parent. - if (!args.GetBoolArg("-daemonwait", DEFAULT_DAEMONWAIT)) { + if (!DaemonwaitSetting::Get(args)) { daemon_ep.TokenWrite(1); daemon_ep.Close(); } diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 7966b80a2735f..07b328bff5274 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -6,9 +6,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -25,11 +27,11 @@ using util::SplitString; void ReadSigNetArgs(const ArgsManager& args, CChainParams::SigNetOptions& options) { - if (args.IsArgSet("-signetseednode")) { - options.seeds.emplace(args.GetArgs("-signetseednode")); + if (SignetseednodeSetting::Get(args)) { + options.seeds.emplace(SignetseednodeSetting::Get(args).value_or(std::vector{})); } - if (args.IsArgSet("-signetchallenge")) { - const auto signet_challenge = args.GetArgs("-signetchallenge"); + if (SignetchallengeSetting::Get(args)) { + const auto signet_challenge = SignetchallengeSetting::Get(args).value_or(std::vector{}); if (signet_challenge.size() != 1) { throw std::runtime_error("-signetchallenge cannot be multiple values."); } @@ -43,10 +45,10 @@ void ReadSigNetArgs(const ArgsManager& args, CChainParams::SigNetOptions& option void ReadRegTestArgs(const ArgsManager& args, CChainParams::RegTestOptions& options) { - if (auto value = args.GetBoolArg("-fastprune")) options.fastprune = *value; + if (auto value = FastpruneSetting::Get(args)) options.fastprune = *value; if (HasTestOption(args, "bip94")) options.enforce_bip94 = true; - for (const std::string& arg : args.GetArgs("-testactivationheight")) { + for (const std::string& arg : TestactivationheightSetting::Get(args)) { const auto found{arg.find('@')}; if (found == std::string::npos) { throw std::runtime_error(strprintf("Invalid format (%s) for -testactivationheight=name@height.", arg)); @@ -66,9 +68,9 @@ void ReadRegTestArgs(const ArgsManager& args, CChainParams::RegTestOptions& opti } } - if (!args.IsArgSet("-vbparams")) return; + if (!VbparamsSetting::Get(args)) return; - for (const std::string& strDeployment : args.GetArgs("-vbparams")) { + for (const std::string& strDeployment : VbparamsSetting::Get(args).value_or(std::vector{})) { std::vector vDeploymentParams = SplitString(strDeployment, ':'); if (vDeploymentParams.size() < 3 || 4 < vDeploymentParams.size()) { throw std::runtime_error("Version bits parameters malformed, expecting deployment:start:end[:min_activation_height]"); diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index aadd04e509f22..5ebea02c872c9 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -5,6 +5,7 @@ #include +#include #include #include #include @@ -13,16 +14,15 @@ void SetupChainParamsBaseOptions(ArgsManager& argsman) { - argsman.AddArg("-chain=", "Use the chain (default: main). Allowed values: " LIST_CHAIN_NAMES, ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-regtest", "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. " - "This is intended for regression testing tools and app development. Equivalent to -chain=regtest.", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-testactivationheight=name@height.", "Set the activation height of 'name' (segwit, bip34, dersig, cltv, csv). (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-testnet", "Use the testnet3 chain. Equivalent to -chain=test. Support for testnet3 is deprecated and will be removed in an upcoming release. Consider moving to testnet4 now by using -testnet4.", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-testnet4", "Use the testnet4 chain. Equivalent to -chain=testnet4.", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-vbparams=deployment:start:end[:min_activation_height]", "Use given start/end times and min_activation_height for specified version bits deployment (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-signet", "Use the signet chain. Equivalent to -chain=signet. Note that the network is defined by the -signetchallenge parameter", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-signetchallenge", "Blocks must satisfy the given script to be considered valid (only for signet networks; defaults to the global default signet test network challenge)", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-signetseednode", "Specify a seed node for the signet network, in the hostname[:port] format, e.g. sig.net:1234 (may be used multiple times to specify multiple seed nodes; defaults to the global default signet test network seed node(s))", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::CHAINPARAMS); + ChainSetting::Register(argsman); + RegtestSetting::Register(argsman); + TestactivationheightSetting::Register(argsman); + TestnetSetting::Register(argsman); + Testnet4Setting::Register(argsman); + VbparamsSetting::Register(argsman); + SignetSetting::Register(argsman); + SignetchallengeSetting::Register(argsman); + SignetseednodeSetting::Register(argsman); } static std::unique_ptr globalChainBaseParams; diff --git a/src/chainparamsbase_settings.h b/src/chainparamsbase_settings.h new file mode 100644 index 0000000000000..d73d71aca6e8b --- /dev/null +++ b/src/chainparamsbase_settings.h @@ -0,0 +1,56 @@ +#ifndef CHAINPARAMSBASE_SETTINGS_H +#define CHAINPARAMSBASE_SETTINGS_H + +#include +#include + +#include +#include + +using SignetseednodeSetting = common::Setting< + "-signetseednode", std::optional>, {.legacy = true, .disallow_negation = true}, + "Specify a seed node for the signet network, in the hostname[:port] format, e.g. sig.net:1234 (may be used multiple times to specify multiple seed nodes; defaults to the global default signet test network seed node(s))"> + ::Category; + +using SignetchallengeSetting = common::Setting< + "-signetchallenge", std::optional>, {.legacy = true, .disallow_negation = true}, + "Blocks must satisfy the given script to be considered valid (only for signet networks; defaults to the global default signet test network challenge)"> + ::Category; + +using TestactivationheightSetting = common::Setting< + "-testactivationheight=name@height.", std::vector, {.legacy = true, .debug_only = true}, + "Set the activation height of 'name' (segwit, bip34, dersig, cltv, csv). (regtest-only)"> + ::Category; + +using VbparamsSetting = common::Setting< + "-vbparams=deployment:start:end[:min_activation_height]", std::optional>, {.legacy = true, .debug_only = true}, + "Use given start/end times and min_activation_height for specified version bits deployment (regtest-only)"> + ::Category; + +using ChainSetting = common::Setting< + "-chain=", std::optional, {.legacy = true}, + "Use the chain (default: main). Allowed values: " LIST_CHAIN_NAMES> + ::Category; + +using RegtestSetting = common::Setting< + "-regtest", std::optional, {.legacy = true, .debug_only = true}, + "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. " + "This is intended for regression testing tools and app development. Equivalent to -chain=regtest."> + ::Category; + +using TestnetSetting = common::Setting< + "-testnet", std::optional, {.legacy = true}, + "Use the testnet3 chain. Equivalent to -chain=test. Support for testnet3 is deprecated and will be removed in an upcoming release. Consider moving to testnet4 now by using -testnet4."> + ::Category; + +using Testnet4Setting = common::Setting< + "-testnet4", std::optional, {.legacy = true}, + "Use the testnet4 chain. Equivalent to -chain=testnet4."> + ::Category; + +using SignetSetting = common::Setting< + "-signet", std::optional, {.legacy = true}, + "Use the signet chain. Equivalent to -chain=signet. Note that the network is defined by the -signetchallenge parameter"> + ::Category; + +#endif // CHAINPARAMSBASE_SETTINGS_H diff --git a/src/common/args.cpp b/src/common/args.cpp index b7aa582e9a855..667195e6e3203 100644 --- a/src/common/args.cpp +++ b/src/common/args.cpp @@ -6,7 +6,9 @@ #include #include +#include #include +#include #include #include #include @@ -688,12 +690,12 @@ std::string ArgsManager::GetHelpMessage() const bool HelpRequested(const ArgsManager& args) { - return args.IsArgSet("-?") || args.IsArgSet("-h") || args.IsArgSet("-help") || args.IsArgSet("-help-debug"); + return args.IsArgSet("-?") || args.IsArgSet("-h") || HelpSetting::Get(args) || HelpDebugSetting::Get(args); } void SetupHelpOptions(ArgsManager& args) { - args.AddArg("-help", "Print this help message and exit (also -h or -?)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + HelpSetting::Register(args); args.AddHiddenArgs({"-h", "-?"}); } @@ -719,7 +721,7 @@ const std::vector TEST_OPTIONS_DOC{ bool HasTestOption(const ArgsManager& args, const std::string& test_option) { - const auto options = args.GetArgs("-test"); + const auto options = TestSetting::Get(args).value_or(std::vector{}); return std::any_of(options.begin(), options.end(), [test_option](const auto& option) { return option == test_option; }); @@ -759,7 +761,7 @@ fs::path GetDefaultDataDir() bool CheckDataDirOption(const ArgsManager& args) { - const fs::path datadir{args.GetPathArg("-datadir")}; + const fs::path datadir{DatadirSettingPath::Get(args).value_or(fs::path{})}; return datadir.empty() || fs::is_directory(fs::absolute(datadir)); } diff --git a/src/common/args_settings.h b/src/common/args_settings.h new file mode 100644 index 0000000000000..8739483232436 --- /dev/null +++ b/src/common/args_settings.h @@ -0,0 +1,13 @@ +#ifndef COMMON_ARGS_SETTINGS_H +#define COMMON_ARGS_SETTINGS_H + +#include + +#include +#include + +using HelpSetting = common::Setting< + "-help", std::optional, {.legacy = true}, + "Print this help message and exit (also -h or -?)">; + +#endif // COMMON_ARGS_SETTINGS_H diff --git a/src/common/init.cpp b/src/common/init.cpp index 412d73aec7016..130cb2c4ecee3 100644 --- a/src/common/init.cpp +++ b/src/common/init.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -19,7 +20,7 @@ std::optional InitConfig(ArgsManager& args, SettingsAbortFn setting { try { if (!CheckDataDirOption(args)) { - return ConfigError{ConfigStatus::FAILED, strprintf(_("Specified data directory \"%s\" does not exist."), args.GetArg("-datadir", ""))}; + return ConfigError{ConfigStatus::FAILED, strprintf(_("Specified data directory \"%s\" does not exist."), DatadirSetting::Get(args).value_or(""))}; } // Record original datadir and config paths before parsing the config @@ -32,7 +33,7 @@ std::optional InitConfig(ArgsManager& args, SettingsAbortFn setting // parse error, and specifying a datadir= location containing another // bitcoin.conf file just ignores the other file.) const fs::path orig_datadir_path{args.GetDataDirBase()}; - const fs::path orig_config_path{AbsPathForConfigVal(args, args.GetPathArg("-conf", BITCOIN_CONF_FILENAME), /*net_specific=*/false)}; + const fs::path orig_config_path{AbsPathForConfigVal(args, ConfSettingPath::Get(args).value_or(BITCOIN_CONF_FILENAME), /*net_specific=*/false)}; std::string error; if (!args.ReadConfigFiles(error, true)) { @@ -66,7 +67,7 @@ std::optional InitConfig(ArgsManager& args, SettingsAbortFn setting // datadir that is being ignored. const fs::path base_config_path = base_path / BITCOIN_CONF_FILENAME; if (fs::exists(base_config_path) && !fs::equivalent(orig_config_path, base_config_path)) { - const std::string cli_config_path = args.GetArg("-conf", ""); + const std::string cli_config_path = ConfSetting::Get(args).value_or(""); const std::string config_source = cli_config_path.empty() ? strprintf("data directory %s", fs::quoted(fs::PathToString(orig_datadir_path))) : strprintf("command line argument %s", fs::quoted("-conf=" + cli_config_path)); @@ -81,7 +82,7 @@ std::optional InitConfig(ArgsManager& args, SettingsAbortFn setting fs::quoted(BITCOIN_CONF_FILENAME), fs::quoted(fs::PathToString(orig_config_path)), config_source); - if (args.GetBoolArg("-allowignoredconf", false)) { + if (AllowignoredconfSetting::Get(args)) { LogPrintf("Warning: %s\n", error); } else { return ConfigError{ConfigStatus::FAILED, Untranslated(error)}; diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 69dd821dc0442..c214033cc6ffe 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -292,12 +293,12 @@ static bool HTTPReq_JSONRPC(const std::any& context, HTTPRequest* req) static bool InitRPCAuthentication() { - if (gArgs.GetArg("-rpcpassword", "") == "") + if (RpcpasswordSetting::Get(gArgs) == "") { LogInfo("Using random cookie authentication.\n"); std::optional cookie_perms{std::nullopt}; - auto cookie_perms_arg{gArgs.GetArg("-rpccookieperms")}; + auto cookie_perms_arg{RpccookiepermsSetting::Get(gArgs)}; if (cookie_perms_arg) { auto perm_opt = InterpretPermString(*cookie_perms_arg); if (!perm_opt) { @@ -312,12 +313,12 @@ static bool InitRPCAuthentication() } } else { LogPrintf("Config options rpcuser and rpcpassword will soon be deprecated. Locally-run instances may remove rpcuser to use cookie-based auth, or may be replaced with rpcauth. Please see share/rpcauth for rpcauth auth generation.\n"); - strRPCUserColonPass = gArgs.GetArg("-rpcuser", "") + ":" + gArgs.GetArg("-rpcpassword", ""); + strRPCUserColonPass = RpcuserSetting::Get(gArgs) + ":" + RpcpasswordSetting::Get(gArgs); } - if (!gArgs.GetArgs("-rpcauth").empty()) { + if (!RpcauthSetting::Get(gArgs).empty()) { LogInfo("Using rpcauth authentication.\n"); - for (const std::string& rpcauth : gArgs.GetArgs("-rpcauth")) { + for (const std::string& rpcauth : RpcauthSetting::Get(gArgs)) { std::vector fields{SplitString(rpcauth, ':')}; const std::vector salt_hmac{SplitString(fields.back(), '$')}; if (fields.size() == 2 && salt_hmac.size() == 2) { @@ -331,8 +332,8 @@ static bool InitRPCAuthentication() } } - g_rpc_whitelist_default = gArgs.GetBoolArg("-rpcwhitelistdefault", gArgs.IsArgSet("-rpcwhitelist")); - for (const std::string& strRPCWhitelist : gArgs.GetArgs("-rpcwhitelist")) { + g_rpc_whitelist_default = RpcwhitelistdefaultSetting::Get(gArgs); + for (const std::string& strRPCWhitelist : RpcwhitelistSetting::Get(gArgs).value_or(std::vector{})) { auto pos = strRPCWhitelist.find(':'); std::string strUser = strRPCWhitelist.substr(0, pos); bool intersect = g_rpc_whitelist.count(strUser); diff --git a/src/httpserver.cpp b/src/httpserver.cpp index b8772ed852f04..d8c0cfad14c50 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -225,7 +226,7 @@ static bool InitHTTPAllowList() rpc_allow_subnets.clear(); rpc_allow_subnets.emplace_back(LookupHost("127.0.0.1", false).value(), 8); // always allow IPv4 local subnet rpc_allow_subnets.emplace_back(LookupHost("::1", false).value()); // always allow IPv6 localhost - for (const std::string& strAllow : gArgs.GetArgs("-rpcallowip")) { + for (const std::string& strAllow : RpcallowipSetting::Get(gArgs).value_or(std::vector{})) { const CSubNet subnet{LookupSubNet(strAllow)}; if (!subnet.IsValid()) { uiInterface.ThreadSafeMessageBox( @@ -360,21 +361,21 @@ static void ThreadHTTP(struct event_base* base) /** Bind HTTP server to specified addresses */ static bool HTTPBindAddresses(struct evhttp* http) { - uint16_t http_port{static_cast(gArgs.GetIntArg("-rpcport", BaseParams().RPCPort()))}; + uint16_t http_port{static_cast(RpcportSettingInt::Get(gArgs))}; std::vector> endpoints; // Determine what addresses to bind to - if (!(gArgs.IsArgSet("-rpcallowip") && gArgs.IsArgSet("-rpcbind"))) { // Default to loopback if not allowing external IPs + if (!(RpcallowipSetting::Get(gArgs) && RpcbindSetting::Get(gArgs))) { // Default to loopback if not allowing external IPs endpoints.emplace_back("::1", http_port); endpoints.emplace_back("127.0.0.1", http_port); - if (gArgs.IsArgSet("-rpcallowip")) { + if (RpcallowipSetting::Get(gArgs)) { LogPrintf("WARNING: option -rpcallowip was specified without -rpcbind; this doesn't usually make sense\n"); } - if (gArgs.IsArgSet("-rpcbind")) { + if (RpcbindSetting::Get(gArgs)) { LogPrintf("WARNING: option -rpcbind was ignored because -rpcallowip was not specified, refusing to allow everyone to connect\n"); } - } else if (gArgs.IsArgSet("-rpcbind")) { // Specific bind address - for (const std::string& strRPCBind : gArgs.GetArgs("-rpcbind")) { + } else if (RpcbindSetting::Get(gArgs)) { // Specific bind address + for (const std::string& strRPCBind : RpcbindSetting::Get(gArgs).value_or(std::vector{})) { uint16_t port{http_port}; std::string host; if (!SplitHostPort(strRPCBind, port, host)) { @@ -462,7 +463,7 @@ bool InitHTTPServer(const util::SignalInterrupt& interrupt) return false; } - evhttp_set_timeout(http, gArgs.GetIntArg("-rpcservertimeout", DEFAULT_HTTP_SERVER_TIMEOUT)); + evhttp_set_timeout(http, RpcservertimeoutSetting::Get(gArgs)); evhttp_set_max_headers_size(http, MAX_HEADERS_SIZE); evhttp_set_max_body_size(http, MAX_SIZE); evhttp_set_gencb(http, http_request_cb, (void*)&interrupt); @@ -473,7 +474,7 @@ bool InitHTTPServer(const util::SignalInterrupt& interrupt) } LogDebug(BCLog::HTTP, "Initialized HTTP server\n"); - int workQueueDepth = std::max((long)gArgs.GetIntArg("-rpcworkqueue", DEFAULT_HTTP_WORKQUEUE), 1L); + int workQueueDepth = std::max((long)RpcworkqueueSetting::Get(gArgs), 1L); LogDebug(BCLog::HTTP, "creating work queue of depth %d\n", workQueueDepth); g_work_queue = std::make_unique>(workQueueDepth); @@ -496,7 +497,7 @@ static std::vector g_thread_http_workers; void StartHTTPServer() { - int rpcThreads = std::max((long)gArgs.GetIntArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L); + int rpcThreads = std::max((long)RpcthreadsSetting::Get(gArgs), 1L); LogInfo("Starting HTTP server with %d worker threads\n", rpcThreads); g_thread_http = std::thread(ThreadHTTP, eventBase); diff --git a/src/init.cpp b/src/init.cpp index 7569fa4fc6136..067ebfc56e7b0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -7,6 +7,7 @@ #include +#include #include #include @@ -160,7 +161,7 @@ static bool g_generated_pid{false}; static fs::path GetPidFile(const ArgsManager& args) { - return AbsPathForConfigVal(args, args.GetPathArg("-pid", BITCOIN_PID_FILENAME)); + return AbsPathForConfigVal(args, PidSetting::Get(args)); } [[nodiscard]] static bool CreatePidFile(const ArgsManager& args) @@ -239,7 +240,7 @@ bool ShutdownRequested(node::NodeContext& node) static void ShutdownNotify(const ArgsManager& args) { std::vector threads; - for (const auto& cmd : args.GetArgs("-shutdownnotify")) { + for (const auto& cmd : ShutdownnotifySetting::Get(args)) { threads.emplace_back(runCommand, cmd); } for (auto& t : threads) { @@ -431,7 +432,7 @@ static void registerSignalHandler(int signal, void(*handler)(int)) void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc) { SetupHelpOptions(argsman); - argsman.AddArg("-help-debug", "Print help message with debugging options and exit", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); // server-only for now + HelpDebugSetting::Register(argsman); // server-only for now init::AddLoggingArgs(argsman); @@ -452,131 +453,109 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc) // GUI args. These will be overwritten by SetupUIArgs for the GUI "-choosedatadir", "-lang=", "-min", "-resetguisettings", "-splash", "-uiplatform"}; - argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + VersionSetting::Register(argsman); #if HAVE_SYSTEM - argsman.AddArg("-alertnotify=", "Execute command when an alert is raised (%s in cmd is replaced by message)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + AlertnotifySetting::Register(argsman); #endif - argsman.AddArg("-assumevalid=", strprintf("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet3: %s, testnet4: %s, signet: %s)", defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnet4ChainParams->GetConsensus().defaultAssumeValid.GetHex(), signetChainParams->GetConsensus().defaultAssumeValid.GetHex()), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-blocksdir=", "Specify directory to hold blocks subdirectory for *.dat files (default: )", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-blocksxor", - strprintf("Whether an XOR-key applies to blocksdir *.dat files. " - "The created XOR-key will be zeros for an existing blocksdir or when `-blocksxor=0` is " - "set, and random for a freshly initialized blocksdir. " - "(default: %u)", - kernel::DEFAULT_XOR_BLOCKSDIR), - ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-fastprune", "Use smaller block files and lower minimum prune height for testing purposes", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); + AssumevalidSetting::Register(argsman, defaultChainParams, testnetChainParams, testnet4ChainParams, signetChainParams); + BlocksdirSetting::Register(argsman); + BlocksxorSetting::Register(argsman); + FastpruneSetting::Register(argsman); #if HAVE_SYSTEM - argsman.AddArg("-blocknotify=", "Execute command when the best block changes (%s in cmd is replaced by block hash)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + BlocknotifySetting::Register(argsman); #endif - argsman.AddArg("-blockreconstructionextratxn=", strprintf("Extra transactions to keep in memory for compact block reconstructions (default: %u)", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-blocksonly", strprintf("Whether to reject transactions from network peers. Disables automatic broadcast and rebroadcast of transactions, unless the source peer has the 'forcerelay' permission. RPC transactions are not affected. (default: %u)", DEFAULT_BLOCKSONLY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-coinstatsindex", strprintf("Maintain coinstats index used by the gettxoutsetinfo RPC (default: %u)", DEFAULT_COINSTATSINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-conf=", strprintf("Specify path to read-only configuration file. Relative paths will be prefixed by datadir location (only useable from command line, not configuration file) (default: %s)", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-datadir=", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", nDefaultDbBatchSize), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS); - argsman.AddArg("-dbcache=", strprintf("Maximum database cache size MiB (minimum %d, default: %d). Make sure you have enough RAM. In addition, unused memory allocated to the mempool is shared with this cache (see -maxmempool).", nMinDbCache, nDefaultDbCache), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-includeconf=", "Specify additional configuration file, relative to the -datadir path (only useable from configuration file, not command line)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-allowignoredconf", strprintf("For backwards compatibility, treat an unused %s file in the datadir as a warning, not an error.", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-loadblock=", "Imports blocks from external file on startup", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-maxmempool=", strprintf("Keep the transaction memory pool below megabytes (default: %u)", DEFAULT_MAX_MEMPOOL_SIZE_MB), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-maxorphantx=", strprintf("Keep at most unconnectable transactions in memory (default: %u)", DEFAULT_MAX_ORPHAN_TRANSACTIONS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-mempoolexpiry=", strprintf("Do not keep transactions in the mempool longer than hours (default: %u)", DEFAULT_MEMPOOL_EXPIRY_HOURS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-minimumchainwork=", strprintf("Minimum work assumed to exist on a valid chain in hex (default: %s, testnet3: %s, testnet4: %s, signet: %s)", defaultChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnetChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnet4ChainParams->GetConsensus().nMinimumChainWork.GetHex(), signetChainParams->GetConsensus().nMinimumChainWork.GetHex()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS); - argsman.AddArg("-par=", strprintf("Set the number of script verification threads (0 = auto, up to %d, <0 = leave that many cores free, default: %d)", - MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-persistmempool", strprintf("Whether to save the mempool on shutdown and load on restart (default: %u)", node::DEFAULT_PERSIST_MEMPOOL), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-persistmempoolv1", - strprintf("Whether a mempool.dat file created by -persistmempool or the savemempool RPC will be written in the legacy format " - "(version 1) or the current format (version 2). This temporary option will be removed in the future. (default: %u)", - DEFAULT_PERSIST_V1_DAT), - ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-pid=", 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); - argsman.AddArg("-prune=", strprintf("Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex. " - "Warning: Reverting this setting requires re-downloading the entire blockchain. " - "(default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >=%u = automatically prune block files to stay under the specified target size in MiB)", MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-reindex", "If enabled, wipe chain state and block index, and rebuild them from blk*.dat files on disk. Also wipe and rebuild other optional indexes that are active. If an assumeutxo snapshot was loaded, its chainstate will be wiped as well. The snapshot can then be reloaded via RPC.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-reindex-chainstate", "If enabled, wipe chain state, and rebuild it from blk*.dat files on disk. If an assumeutxo snapshot was loaded, its chainstate will be wiped as well. The snapshot can then be reloaded via RPC.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-settings=", strprintf("Specify path to dynamic settings data file. Can be disabled with -nosettings. File is written at runtime and not meant to be edited by users (use %s instead for custom settings). Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME, BITCOIN_SETTINGS_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + BlockreconstructionextratxnSetting::Register(argsman); + BlocksonlySetting::Register(argsman); + CoinstatsindexSetting::Register(argsman); + ConfSetting::Register(argsman); + DatadirSetting::Register(argsman); + DbbatchsizeSetting::Register(argsman); + DbcacheSetting::Register(argsman); + IncludeconfSetting::Register(argsman); + AllowignoredconfSetting::Register(argsman); + LoadblockSetting::Register(argsman); + MaxmempoolSetting::Register(argsman); + MaxorphantxSetting::Register(argsman); + MempoolexpirySetting::Register(argsman); + MinimumchainworkSetting::Register(argsman, defaultChainParams, testnetChainParams, testnet4ChainParams, signetChainParams); + ParSetting::Register(argsman); + PersistmempoolSetting::Register(argsman); + Persistmempoolv1Setting::Register(argsman); + PidSetting::Register(argsman); + PruneSetting::Register(argsman); + ReindexSetting::Register(argsman); + ReindexChainstateSetting::Register(argsman); + SettingsSetting::Register(argsman); #if HAVE_SYSTEM - argsman.AddArg("-startupnotify=", "Execute command on startup.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-shutdownnotify=", "Execute command immediately before beginning shutdown. The need for shutdown may be urgent, so be careful not to delay it long (if the command doesn't require interaction with the server, consider having it fork into the background).", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + StartupnotifySetting::Register(argsman); + ShutdownnotifySetting::Register(argsman); #endif - argsman.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-blockfilterindex=", - strprintf("Maintain an index of compact filters by block (default: %s, values: %s).", DEFAULT_BLOCKFILTERINDEX, ListBlockFilterTypes()) + - " If is not supplied or if = 1, indexes for all known types are enabled.", - ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - - argsman.AddArg("-addnode=", strprintf("Add a node to connect to and attempt to keep the connection open (see the addnode RPC help for more info). This option can be specified multiple times to add multiple nodes; connections are limited to %u at a time and are counted separately from the -maxconnections limit.", MAX_ADDNODE_CONNECTIONS), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION); - argsman.AddArg("-asmap=", strprintf("Specify asn mapping used for bucketing of the peers (default: %s). Relative paths will be prefixed by the net-specific datadir location.", DEFAULT_ASMAP_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-bantime=", strprintf("Default duration (in seconds) of manually configured bans (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-bind=[:][=onion]", strprintf("Bind to given address and always listen on it (default: 0.0.0.0). Use [host]:port notation for IPv6. Append =onion to tag any incoming connections to that address and port as incoming Tor connections (default: 127.0.0.1:%u=onion, testnet3: 127.0.0.1:%u=onion, testnet4: 127.0.0.1:%u=onion, signet: 127.0.0.1:%u=onion, regtest: 127.0.0.1:%u=onion)", defaultBaseParams->OnionServiceTargetPort(), testnetBaseParams->OnionServiceTargetPort(), testnet4BaseParams->OnionServiceTargetPort(), signetBaseParams->OnionServiceTargetPort(), regtestBaseParams->OnionServiceTargetPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION); - argsman.AddArg("-cjdnsreachable", "If set, then this host is configured for CJDNS (connecting to fc00::/8 addresses would lead us to the CJDNS network, see doc/cjdns.md) (default: 0)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-connect=", "Connect only to the specified node; -noconnect disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION); - argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-dnsseed", strprintf("Query for peer addresses via DNS lookup, if low on addresses (default: %u unless -connect used or -maxconnections=0)", DEFAULT_DNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-externalip=", "Specify your own public address", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-fixedseeds", strprintf("Allow fixed seeds if DNS seeds don't provide peers (default: %u)", DEFAULT_FIXEDSEEDS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-forcednsseed", strprintf("Always query for peer addresses via DNS lookup (default: %u)", DEFAULT_FORCEDNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-listen", strprintf("Accept connections from outside (default: %u if no -proxy, -connect or -maxconnections=0)", DEFAULT_LISTEN), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-listenonion", strprintf("Automatically create Tor onion service (default: %d)", DEFAULT_LISTEN_ONION), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-maxconnections=", strprintf("Maintain at most automatic connections to peers (default: %u). This limit does not apply to connections manually added via -addnode or the addnode RPC, which have a separate limit of %u.", DEFAULT_MAX_PEER_CONNECTIONS, MAX_ADDNODE_CONNECTIONS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-maxreceivebuffer=", strprintf("Maximum per-connection receive buffer, *1000 bytes (default: %u)", DEFAULT_MAXRECEIVEBUFFER), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-maxsendbuffer=", strprintf("Maximum per-connection memory usage for the send buffer, *1000 bytes (default: %u)", DEFAULT_MAXSENDBUFFER), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-maxuploadtarget=", strprintf("Tries to keep outbound traffic under the given target per 24h. Limit does not apply to peers with 'download' permission or blocks created within past week. 0 = no limit (default: %s). Optional suffix units [k|K|m|M|g|G|t|T] (default: M). Lowercase is 1000 base while uppercase is 1024 base", DEFAULT_MAX_UPLOAD_TARGET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); + TxindexSetting::Register(argsman); + BlockfilterindexSetting::Register(argsman); + + AddnodeSetting::Register(argsman); + AsmapSetting::Register(argsman); + BantimeSetting::Register(argsman); + BindSetting::Register(argsman, defaultBaseParams, testnetBaseParams, testnet4BaseParams, signetBaseParams, regtestBaseParams); + CjdnsreachableSetting::Register(argsman); + ConnectSetting::Register(argsman); + DiscoverSetting::Register(argsman); + DnsSetting::Register(argsman); + DnsseedSetting::Register(argsman); + ExternalipSetting::Register(argsman); + FixedseedsSetting::Register(argsman); + ForcednsseedSetting::Register(argsman); + ListenSetting::Register(argsman); + ListenonionSetting::Register(argsman); + MaxconnectionsSetting::Register(argsman); + MaxreceivebufferSetting::Register(argsman); + MaxsendbufferSetting::Register(argsman); + MaxuploadtargetSetting::Register(argsman); #ifdef HAVE_SOCKADDR_UN - argsman.AddArg("-onion=", "Use separate SOCKS5 proxy to reach peers via Tor onion services, set -noonion to disable (default: -proxy). May be a local file path prefixed with 'unix:'.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); + OnionSetting::Register(argsman); #else - argsman.AddArg("-onion=", "Use separate SOCKS5 proxy to reach peers via Tor onion services, set -noonion to disable (default: -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); + OnionSetting2::Register(argsman); #endif - argsman.AddArg("-i2psam=", "I2P SAM proxy to reach I2P peers and accept I2P connections (default: none)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-i2pacceptincoming", strprintf("Whether to accept inbound I2P connections (default: %i). Ignored if -i2psam is not set. Listening for inbound I2P connections is done through the SAM proxy, not by binding to a local address and port.", DEFAULT_I2P_ACCEPT_INCOMING), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-onlynet=", strprintf("Make automatic outbound connections only to network (%s). Inbound and manual connections are not affected by this option. It can be specified multiple times to allow multiple networks.", util::Join(GetNetworkNames(), ", ")), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-v2transport", strprintf("Support v2 transport (default: %u)", DEFAULT_V2_TRANSPORT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-peerblockfilters", strprintf("Serve compact block filters to peers per BIP 157 (default: %u)", DEFAULT_PEERBLOCKFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-txreconciliation", strprintf("Enable transaction reconciliations per BIP 330 (default: %d)", DEFAULT_TXRECONCILIATION_ENABLE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION); - argsman.AddArg("-port=", strprintf("Listen for connections on (default: %u, testnet3: %u, testnet4: %u, signet: %u, regtest: %u). Not relevant for I2P (see doc/i2p.md).", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), testnet4ChainParams->GetDefaultPort(), signetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION); + I2psamSetting::Register(argsman); + I2pacceptincomingSetting::Register(argsman); + OnlynetSetting::Register(argsman); + V2transportSetting::Register(argsman); + PeerbloomfiltersSetting::Register(argsman); + PeerblockfiltersSetting::Register(argsman); + TxreconciliationSetting::Register(argsman); + PortSetting::Register(argsman, defaultChainParams, testnetChainParams, testnet4ChainParams, signetChainParams, regtestChainParams); #ifdef HAVE_SOCKADDR_UN - argsman.AddArg("-proxy=", "Connect through SOCKS5 proxy, set -noproxy to disable (default: disabled). May be a local file path prefixed with 'unix:' if the proxy supports it.", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_ELISION, OptionsCategory::CONNECTION); + ProxySetting::Register(argsman); #else - argsman.AddArg("-proxy=", "Connect through SOCKS5 proxy, set -noproxy to disable (default: disabled)", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_ELISION, OptionsCategory::CONNECTION); + ProxySetting2::Register(argsman); #endif - argsman.AddArg("-proxyrandomize", strprintf("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)", DEFAULT_PROXYRANDOMIZE), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-seednode=", "Connect to a node to retrieve peer addresses, and disconnect. This option can be specified multiple times to connect to multiple nodes. During startup, seednodes will be tried before dnsseeds.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-networkactive", "Enable all P2P network activity (default: 1). Can be changed by the setnetworkactive RPC command", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-timeout=", strprintf("Specify socket connection timeout in milliseconds. If an initial attempt to connect is unsuccessful after this amount of time, drop it (minimum: 1, default: %d)", DEFAULT_CONNECT_TIMEOUT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-peertimeout=", strprintf("Specify a p2p connection timeout delay in seconds. After connecting to a peer, wait this amount of time before considering disconnection based on inactivity (minimum: 1, default: %d)", DEFAULT_PEER_CONNECT_TIMEOUT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION); - argsman.AddArg("-torcontrol=:", strprintf("Tor control host and port to use if onion listening enabled (default: %s). If no port is specified, the default port of %i will be used.", DEFAULT_TOR_CONTROL, DEFAULT_TOR_CONTROL_PORT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-torpassword=", "Tor control port password (default: empty)", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::CONNECTION); + ProxyrandomizeSetting::Register(argsman); + SeednodeSetting::Register(argsman); + NetworkactiveSetting::Register(argsman); + TimeoutSetting::Register(argsman); + PeertimeoutSetting::Register(argsman); + TorcontrolSetting::Register(argsman); + TorpasswordSetting::Register(argsman); // UPnP support was dropped. We keep `-upnp` as a hidden arg to display a more user friendly error when set. TODO: remove (here and below) for 30.0. NOTE: removing this option may prevent the GUI from starting, see https://github.com/bitcoin-core/gui/issues/843. - argsman.AddArg("-upnp", "", ArgsManager::ALLOW_ANY, OptionsCategory::HIDDEN); - argsman.AddArg("-natpmp", strprintf("Use PCP or NAT-PMP to map the listening port (default: %u)", DEFAULT_NATPMP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-whitebind=<[permissions@]addr>", strprintf("Bind to the given address and add permission flags to the peers connecting to it. " - "Use [host]:port notation for IPv6. Allowed permissions: %s. " - "Specify multiple permissions separated by commas (default: download,noban,mempool,relay). Can be specified multiple times.", util::Join(NET_PERMISSIONS_DOC, ", ")), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - - argsman.AddArg("-whitelist=<[permissions@]IP address or network>", "Add permission flags to the peers using the given IP address (e.g. 1.2.3.4) or " - "CIDR-notated network (e.g. 1.2.3.0/24). Uses the same permissions as " - "-whitebind. " - "Additional flags \"in\" and \"out\" control whether permissions apply to incoming connections and/or manual (default: incoming only). " - "Can be specified multiple times.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); + UpnpSetting::Register(argsman); + NatpmpSetting::Register(argsman); + WhitebindSetting::Register(argsman); + + WhitelistSetting::Register(argsman); g_wallet_init_interface.AddWalletOptions(argsman); #ifdef ENABLE_ZMQ - argsman.AddArg("-zmqpubhashblock=
", "Enable publish hash block in
", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ); - argsman.AddArg("-zmqpubhashtx=
", "Enable publish hash transaction in
", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ); - argsman.AddArg("-zmqpubrawblock=
", "Enable publish raw block in
", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ); - argsman.AddArg("-zmqpubrawtx=
", "Enable publish raw transaction in
", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ); - argsman.AddArg("-zmqpubsequence=
", "Enable publish hash block and tx sequence in
", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ); - argsman.AddArg("-zmqpubhashblockhwm=", strprintf("Set publish hash block outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ); - argsman.AddArg("-zmqpubhashtxhwm=", strprintf("Set publish hash transaction outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ); - argsman.AddArg("-zmqpubrawblockhwm=", strprintf("Set publish raw block outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ); - argsman.AddArg("-zmqpubrawtxhwm=", strprintf("Set publish raw transaction outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ); - argsman.AddArg("-zmqpubsequencehwm=", strprintf("Set publish hash sequence message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ); + ZmqpubhashblockSetting::Register(argsman); + ZmqpubhashtxSetting::Register(argsman); + ZmqpubrawblockSetting::Register(argsman); + ZmqpubrawtxSetting::Register(argsman); + ZmqpubsequenceSetting::Register(argsman); + ZmqpubhashblockhwmSetting::Register(argsman); + ZmqpubhashtxhwmSetting::Register(argsman); + ZmqpubrawblockhwmSetting::Register(argsman); + ZmqpubrawtxhwmSetting::Register(argsman); + ZmqpubsequencehwmSetting::Register(argsman); #else hidden_args.emplace_back("-zmqpubhashblock=
"); hidden_args.emplace_back("-zmqpubhashtx=
"); @@ -590,79 +569,70 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc) hidden_args.emplace_back("-zmqpubsequencehwm="); #endif - argsman.AddArg("-checkblocks=", strprintf("How many blocks to check at startup (default: %u, 0 = all)", DEFAULT_CHECKBLOCKS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-checklevel=", strprintf("How thorough the block verification of -checkblocks is: %s (0-4, default: %u)", util::Join(CHECKLEVEL_DOC, ", "), DEFAULT_CHECKLEVEL), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-checkblockindex", strprintf("Do a consistency check for the block tree, chainstate, and other validation data structures every operations. Use 0 to disable. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-checkaddrman=", strprintf("Run addrman consistency checks every operations. Use 0 to disable. (default: %u)", DEFAULT_ADDRMAN_CONSISTENCY_CHECKS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-checkmempool=", strprintf("Run mempool consistency checks every transactions. Use 0 to disable. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-checkpoints", strprintf("Enable rejection of any forks from the known historical chain until block %s (default: %u)", defaultChainParams->Checkpoints().GetHeight(), DEFAULT_CHECKPOINTS_ENABLED), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-deprecatedrpc=", "Allows deprecated RPC method(s) to be used", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-stopatheight", strprintf("Stop running after reaching the given height in the main chain (default: %u)", node::DEFAULT_STOPATHEIGHT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-limitancestorcount=", strprintf("Do not accept transactions if number of in-mempool ancestors is or more (default: %u)", DEFAULT_ANCESTOR_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-limitancestorsize=", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT_KVB), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-limitdescendantcount=", strprintf("Do not accept transactions if any ancestor would have or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-limitdescendantsize=", strprintf("Do not accept transactions if any ancestor would have more than kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT_KVB), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-test=