Test Details Overview

Load every config file through one loader (#5190)

* Load every config file through one loader

Node, RPC, access and wallet configs each had their own copy of the
file-plus-overrides loading logic, the access loader ignored overrides
and the wallet loader wrote the file before reading it. read_config_file
now locates the file, applies overrides and never creates anything, and
deserializes on top of the config it is given; load_config_file keeps the
throwing interface the benchmarks and the log config use. The per-file
functions are wrappers, reading a path no longer creates the file as a
side effect, and writing truncates instead of overwriting in place.

Whether a config file was found is now reported on stderr for every file
rather than only for config-log.toml, which was the one file the shared
helper used to load.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Name the file in config errors

A config error carried only the problem itself, so an operator reading
"Failed to parse value type at line 2" or "Invalid wallet id" could not
tell which of the node, RPC, log, access or wallet config it came from.
The wallet loads both the node and the wallet config and reported a
failure in either with the same message. The loader now prefixes every
error it returns with the name of the file, which reaches every place
that reports one without changing them.

* Move the Qt wallet config reader and writer into the library

They were private members of the wallet executable's daemon class, so no
test binary could reach them. They become free functions next to
wallet_config, unchanged apart from taking the config to write by
const reference.

* Keep the generated wallet defaults when the wallet config is missing

The shared loader reads a missing file as an empty document, which works
for every config whose keys are optional. The Qt wallet config treated
its wallet and account keys as required, so a fresh data directory, or
one whose config-qtwallet.toml had been deleted, refused to start with
"Invalid wallet id". The wallet used to hide this by writing a default
file before reading it.

The two keys now come together: a document with neither is no config
yet and keeps the generated wallet id, which the startup sequence
resolves against the wallet store and persists before the node starts,
while a document with only one of them, or an invalid value, is still
reported. An existing but empty file, as an interrupted write leaves
behind, is read like a missing one.

* Cover reading and writing the Qt wallet config

wallet_config had no tests. The file it holds points the wallet at a
wallet and an account in the wallet store, and startup rewrites it every
time, so the tests pin what that depends on: what is written reads back
unchanged, a damaged file is reported with its name rather than replaced
by defaults, and rewriting leaves nothing of a longer previous file.

* Extract opening the configured wallet from the Qt wallet startup

Resolving which wallet and account the Qt wallet opens, falling back to
an existing one or creating one, was inline in run_wallet next to the
splash screen and the error dialogs, so none of it could be tested. It
moves to open_configured_wallet in the node library and returns the
error instead of showing it; the startup shows it as before.

* Cover the Qt wallet startup sequence

The regression that made a fresh data directory refuse to start went
unnoticed because nothing ran the wallet's startup steps. The tests run
them against a test node the way run_wallet does, reading the config,
opening the wallet it points at and persisting the result, and pin what
must not be lost: a fresh install gets a wallet and an account and
persists the pointer to them, a restart opens the same ones and leaves
the file unchanged, a lost config is recovered from the only wallet in
the store, and a wallet that cannot get an account reports the error
without persisting anything.

* Return an error when the initial wallet cannot be created

wallets::create logs the cause and returns null when the wallet
constructor throws, and open_configured_wallet went on to use that
null. It now returns wallet_create_failed instead, so the Qt wallet
shows the message and exits the way it does for a locked wallet. The
dialog prefix no longer names the account, since the wallet itself
may be what failed.

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

__________

Type: commit

Hash: 55b7360661339f7317d90675a35049b152cf09c6

Created: today

__________

gr0v1ty/nano-node:55b7360661339f7317d90675a35049b152cf09c6

Test Results

Test Case Status Duration Median Deviation Log Graph
5n4pr_conf_10k_bintree PASS 117 s 4.0 s - Show
5n4pr_conf_10k_change PASS 138 s -11.0 s - Show
5n4pr_conf_change_dependant PASS 112 s -3.0 s - -
5n4pr_conf_change_independant PASS 123 s 8.0 s - -
5n4pr_conf_send_dependant PASS 213 s 100.0 s - -
5n4pr_conf_send_independant PASS 121 s 6.0 s - -
5n4pr_rocks_10k_bintree PASS 124 s 8.0 s - -
5n4pr_rocks_10k_change PASS 166 s 6.0 s - -