fix(lite): don't run the full-node RPC loop in lite; drive isConnected() from the wallet

Runtime monitoring of ObsidianDragonLite (WSLg) showed the full-node RPC connect
state machine running in the lite build — `tryConnect()` fired every ~5s and
failed ("Couldn't connect to server / no daemon"). It's called unconditionally
from the main loop with no lite guard.

Worse than noise: `state_.connected` (App::isConnected()) was therefore ALWAYS
false in lite, and it gates the wallet UI — receive_tab disables the new-address
button + shows "not connected", send_tab disables send, transactions_tab shows
not-connected. So the M3/M4 GUI wiring was effectively unreachable: a lite user
could never generate an address or send, even with an open, synced wallet.

Fix:
- tryConnect() no-ops in lite builds (isLiteBuild()), so no RPC attempts.
- App::update() derives state_.connected from lite_wallet_->walletOpen() each
  frame — a non-blocking proxy for "lite backend operational" (a wallet opens
  only after a successful backend init against the lite server). This enables the
  wallet UI once a wallet is open.

Full-node is unaffected (both branches are runtime-gated: isLiteBuild() is false
and lite_wallet_ is null there).

Verified by re-running the app: RPC connection attempts dropped from 7/30s to 0;
clean launch (GL 4.2) + clean shutdown; tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-05 16:11:58 -05:00
parent 9d7054b245
commit 89bd21018a
2 changed files with 12 additions and 1 deletions

View File

@@ -403,6 +403,12 @@ void App::update()
// Apply any lite-wallet refresh the controller's background worker produced (main thread).
if (lite_wallet_) {
// Lite has no RPC daemon (tryConnect() is a no-op in lite builds), so derive the app's
// "online" state — which gates the wallet UI via isConnected() — from the lite wallet.
// A wallet is open only after a successful backend init against the lite server, so this
// is a non-blocking proxy for "lite backend operational".
state_.connected = lite_wallet_->walletOpen();
wallet::LiteWalletAppRefreshModel liteModel;
if (lite_wallet_->takeRefreshedModel(liteModel)) {
wallet::applyLiteRefreshModelToWalletState(liteModel, state_);

View File

@@ -164,8 +164,13 @@ static WarmupText translateWarmup(const std::string& raw)
void App::tryConnect()
{
// Lite builds have no full node / RPC daemon, so never run the RPC connection state machine
// (it would just fail every tick). The lite controller drives the wallet; "online" status is
// derived from it each frame in App::update(), which also gates the wallet UI (isConnected()).
if (isLiteBuild()) return;
if (connection_in_progress_) return;
static int connect_attempt = 0;
++connect_attempt;