What happens
On a stock Linux .deb install, the node's wallet seed resolves to ./DigWallet/seed.bin —
relative to the service's working directory — rather than to any per-user or machine location.
dig_wallet::autoseed::user_base() (crates/dig-wallet/src/autoseed.rs:110-120) resolves
LOCALAPPDATA -> HOME -> ".". The shipped unit
packaging/linux/systemd/net.dignetwork.dig-node.service sets neither: it has no User=, no
Group= and no HOME=, its only Environment= line is DIG_NODE_RUN_CONTEXT=service, and it
carries ProtectHome=true. So both lookups miss and the chain falls through to ".".
Under ProtectSystem=full that path is very likely unwritable, so the mint fails and the node comes
up wallet-less.
Why it matters
This is the shape of dig_ecosystem#1928, where a stock .deb came up with no identity and never
joined the network — a defect nobody saw because each individual manifest and unit looked
reasonable.
It also means the two resolvers of "the per-user base" disagree on a stock Linux install with no
operator override at all: dig_node_core::platform_user_base() returns /root, because
directories::BaseDirs' Linux home_dir falls back to getpwuid_r when $HOME is unset
(dirs-sys-0.5.0/src/lib.rs:33-47), while the wallet returns ".". dig-node#392 makes that
divergence audible; it does not make it correct. This ticket is the correctness half.
How this was found
While gating dig-node#392 (PR #489). The #392 fix originally refused to mint under a divergent root,
which would have turned this latent misplacement into a hard "no wallet on any stock Linux install".
The gate caught it and the predicate was narrowed to fire only on a deliberate LOCALAPPDATA
override — so #392 no longer depends on this being fixed, and this is not a release blocker for it.
Scope
- Decide where a Linux service's wallet seed SHOULD live. The machine state dir the service already
resolves and hardens (/var/lib/dig-node, crate::state) is the obvious candidate and is already
the answer for the identity seed and cache via state::service_data_dir_overrides — the wallet
seed was simply never included in that anchoring.
- Do not silently relocate an existing seed. A host that already minted one at some path must
keep opening it; the same reasoning that kept dig-node#392 from re-rooting the wallet applies here
in full. Whatever the fix, an existing wallet must not be orphaned.
"." as a final fallback for a key file is worth reconsidering on its own. A relative path means
the seed location depends on the working directory of whoever started the process.
Related, and worth its own line
CI never runs on Windows. .github/workflows/ci.yml is ubuntu-latest on all four jobs
(Release-script tests, Rustfmt, Clippy, Test + coverage), so no Windows-specific path behaviour in
this crate is exercised anywhere in CI. That was raised by the #392 security gate, which could not
reproduce a Windows-only false-split precisely because nothing runs there. The #392 fix works around
it by making the platform-dependent comparison a pure function with the case-sensitivity as a
parameter, so both arms run on the Linux runner — but that is a workaround for one function, not
coverage.
Parent: #392
What happens
On a stock Linux
.debinstall, the node's wallet seed resolves to./DigWallet/seed.bin—relative to the service's working directory — rather than to any per-user or machine location.
dig_wallet::autoseed::user_base()(crates/dig-wallet/src/autoseed.rs:110-120) resolvesLOCALAPPDATA->HOME->".". The shipped unitpackaging/linux/systemd/net.dignetwork.dig-node.servicesets neither: it has noUser=, noGroup=and noHOME=, its onlyEnvironment=line isDIG_NODE_RUN_CONTEXT=service, and itcarries
ProtectHome=true. So both lookups miss and the chain falls through to".".Under
ProtectSystem=fullthat path is very likely unwritable, so the mint fails and the node comesup wallet-less.
Why it matters
This is the shape of dig_ecosystem#1928, where a stock
.debcame up with no identity and neverjoined the network — a defect nobody saw because each individual manifest and unit looked
reasonable.
It also means the two resolvers of "the per-user base" disagree on a stock Linux install with no
operator override at all:
dig_node_core::platform_user_base()returns/root, becausedirectories::BaseDirs' Linuxhome_dirfalls back togetpwuid_rwhen$HOMEis unset(
dirs-sys-0.5.0/src/lib.rs:33-47), while the wallet returns".". dig-node#392 makes thatdivergence audible; it does not make it correct. This ticket is the correctness half.
How this was found
While gating dig-node#392 (PR #489). The #392 fix originally refused to mint under a divergent root,
which would have turned this latent misplacement into a hard "no wallet on any stock Linux install".
The gate caught it and the predicate was narrowed to fire only on a deliberate
LOCALAPPDATAoverride — so #392 no longer depends on this being fixed, and this is not a release blocker for it.
Scope
resolves and hardens (
/var/lib/dig-node,crate::state) is the obvious candidate and is alreadythe answer for the identity seed and cache via
state::service_data_dir_overrides— the walletseed was simply never included in that anchoring.
keep opening it; the same reasoning that kept dig-node#392 from re-rooting the wallet applies here
in full. Whatever the fix, an existing wallet must not be orphaned.
"."as a final fallback for a key file is worth reconsidering on its own. A relative path meansthe seed location depends on the working directory of whoever started the process.
Related, and worth its own line
CI never runs on Windows.
.github/workflows/ci.ymlisubuntu-lateston all four jobs(Release-script tests, Rustfmt, Clippy, Test + coverage), so no Windows-specific path behaviour in
this crate is exercised anywhere in CI. That was raised by the #392 security gate, which could not
reproduce a Windows-only false-split precisely because nothing runs there. The #392 fix works around
it by making the platform-dependent comparison a pure function with the case-sensitivity as a
parameter, so both arms run on the Linux runner — but that is a workaround for one function, not
coverage.
Parent: #392