refactor(audit): batch 7 — RPC/settings/lite/effects mechanical dedups

Six behavior-preserving consolidations from the audit:

- RPCClient::call() overloads share a private performCall() (payload dump +
  curl_easy_perform + http code) and a static parseRpcResult() (error->RpcError
  extraction). The timeout overload restores the prior timeout in both the
  success and catch paths, exactly as before.
- The six UnifiedCallback methods delegate to one splitUnified() that builds
  the (Callback, ErrorCallback) pair once (null-check preserved).
- One liteTrimCopy() in lite_connection_service replaces 5 file-local
  trim-copy helpers across the lite slice.
- lite_wallet_controller's inline height JSON parse now routes through the
  tested parseLiteHeightResponse().
- theme_effects.cpp: unpackRGB()/scaledAlpha() replace 14 RGB-unpack + 5
  alpha-scale copy-paste blocks.
- settings.cpp load() uses loadScalar()/loadClamped() helpers for ~44 scalar
  fields. Besides removing boilerplate this HARDENS loading: ~44 fields that
  previously only checked contains() now also verify the JSON type, so a
  malformed value in settings.json falls back to the default instead of
  throwing/misreading. Custom cases (enum parses, legacy migrations, arrays)
  stay inline; save() is unchanged.

Full-node + Lite build clean; ctest 1/1; hygiene clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-02 19:56:54 -05:00
parent 4635a56e89
commit dcd09dc542
11 changed files with 245 additions and 328 deletions

View File

@@ -1,25 +1,10 @@
#include "lite_wallet_server_selection_adapter.h"
#include <algorithm>
#include <cctype>
namespace dragonx {
namespace wallet {
namespace {
std::string trimCopy(const std::string& value)
{
const auto first = std::find_if_not(value.begin(), value.end(), [](unsigned char ch) {
return std::isspace(ch) != 0;
});
const auto last = std::find_if_not(value.rbegin(), value.rend(), [](unsigned char ch) {
return std::isspace(ch) != 0;
}).base();
if (first >= last) return {};
return std::string(first, last);
}
LiteServerSelectionMode walletModeFromSettings(
config::Settings::LiteServerSelectionPreferenceMode mode)
{
@@ -52,14 +37,14 @@ LiteConnectionSettings liteConnectionSettingsFromAppSettings(const config::Setti
connectionSettings.servers.clear();
for (const auto& server : settings.getLiteServers()) {
connectionSettings.servers.push_back(LiteServerEndpoint{
trimCopy(server.url),
liteTrimCopy(server.url),
server.label,
server.enabled
});
}
connectionSettings.selectionMode = walletModeFromSettings(settings.getLiteServerSelectionMode());
connectionSettings.stickyServerUrl = trimCopy(settings.getLiteStickyServerUrl());
connectionSettings.chainName = trimCopy(settings.getLiteChainName());
connectionSettings.stickyServerUrl = liteTrimCopy(settings.getLiteStickyServerUrl());
connectionSettings.chainName = liteTrimCopy(settings.getLiteChainName());
if (connectionSettings.chainName.empty()) connectionSettings.chainName = kDragonXLiteChainName;
connectionSettings.randomSelectionSeed = settings.getLiteRandomSelectionSeed();
return connectionSettings;
@@ -72,24 +57,24 @@ void applyLiteConnectionSettingsToAppSettings(config::Settings& settings,
servers.reserve(connectionSettings.servers.size());
for (const auto& server : connectionSettings.servers) {
servers.push_back(config::Settings::LiteServerPreference{
trimCopy(server.url),
liteTrimCopy(server.url),
server.label,
server.enabled
});
}
settings.setLiteServerSelectionMode(settingsModeFromWallet(connectionSettings.selectionMode));
settings.setLiteStickyServerUrl(trimCopy(connectionSettings.stickyServerUrl));
settings.setLiteChainName(trimCopy(connectionSettings.chainName).empty()
settings.setLiteStickyServerUrl(liteTrimCopy(connectionSettings.stickyServerUrl));
settings.setLiteChainName(liteTrimCopy(connectionSettings.chainName).empty()
? kDragonXLiteChainName
: trimCopy(connectionSettings.chainName));
: liteTrimCopy(connectionSettings.chainName));
settings.setLiteRandomSelectionSeed(connectionSettings.randomSelectionSeed);
settings.setLiteServers(servers);
}
std::string redactLiteServerSelectionValue(const std::string& value)
{
const std::string trimmed = trimCopy(value);
const std::string trimmed = liteTrimCopy(value);
if (trimmed.empty()) return "<empty>";
const auto scheme = trimmed.find("://");
if (scheme == std::string::npos) return "<redacted>";