refactor(audit): batch 2 — remove dead scaffolding from the shipping binary

Two dead-code removals surfaced by the audit; no runtime behavior change.

1. Delete the lite-lifecycle "readiness" scaffold (~1,586 lines). The pure
   dry-run evaluateLiteWalletServerLifecycleReadiness (whose own status text
   says "wallet lifecycle execution is still disabled in this scaffold") had
   zero callers; executeLiteWalletServerSelectionUi had zero callers; and
   executeLiteWalletLifecycleUiRequest's only caller was a fallback in
   settings_page reached only when app->liteWallet() is null. Deleted
   lite_wallet_server_lifecycle_readiness.{h,cpp} and the readiness /
   UI-execution machinery + enums + translation tables from both adapters,
   keeping the genuinely-live helpers (liteConnectionSettingsFromAppSettings,
   applyLiteConnectionSettingsToAppSettings, redactLiteServerSelectionValue,
   and the LiteWalletLifecycleUiExecutionInput DTO the live create/open/
   restore path still uses). The null-backend fallback now sets a plain
   "Lite wallet backend unavailable" status. This is exactly the
   readiness/scaffold pattern CLAUDE.md forbids regrowing.

2. Split the HushChat fixture/capture-manifest/seed-projection tooling
   (~2,050 lines, incl. the libsodium seed-projection) out of
   chat_protocol.cpp (1854 -> 284) and chat_protocol.h (586 -> 105) into a
   new chat_fixture_tooling.{h,cpp} compiled ONLY into the HushChatFixtureCheck
   dev tool — never into the app, lite, or test binaries (verified via nm).
   The app keeps only the runtime slice (memo parsing + tx metadata
   extraction) that network_refresh_service actually calls. Also moved the
   decrypt-preflight/hex helpers, which likewise had no runtime caller.

Note: the HushChat split is on gated-off experimental code and should be
coordinated with the pending dormant-HushChat-content handling (commit
af06b8b) before the lite PR — done here as a pure mechanical split, no redesign.

Full-node + Lite + HushChatFixtureCheck 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 16:20:53 -05:00
parent f8150434d4
commit 7891c689fb
13 changed files with 2126 additions and 3641 deletions

View File

@@ -423,7 +423,6 @@ set(APP_SOURCES
src/wallet/lite_wallet_state_mapper.cpp
src/wallet/lite_wallet_lifecycle_ui_adapter.cpp
src/wallet/lite_wallet_server_selection_adapter.cpp
src/wallet/lite_wallet_server_lifecycle_readiness.cpp
src/wallet/lite_wallet_lifecycle_service.cpp
src/data/wallet_state.cpp
src/data/transaction_history_cache.cpp
@@ -557,7 +556,6 @@ set(APP_HEADERS
src/wallet/lite_wallet_state_mapper.h
src/wallet/lite_wallet_lifecycle_ui_adapter.h
src/wallet/lite_wallet_server_selection_adapter.h
src/wallet/lite_wallet_server_lifecycle_readiness.h
src/wallet/lite_wallet_lifecycle_service.h
src/chat/chat_protocol.h
src/config/version.h
@@ -825,6 +823,7 @@ endif()
add_executable(HushChatFixtureCheck
tools/hushchat_fixture_check.cpp
src/chat/chat_protocol.cpp
src/chat/chat_fixture_tooling.cpp
)
target_include_directories(HushChatFixtureCheck PRIVATE
@@ -1020,7 +1019,6 @@ if(BUILD_TESTING)
src/wallet/lite_wallet_state_mapper.cpp
src/wallet/lite_wallet_lifecycle_ui_adapter.cpp
src/wallet/lite_wallet_server_selection_adapter.cpp
src/wallet/lite_wallet_server_lifecycle_readiness.cpp
src/wallet/lite_wallet_lifecycle_service.cpp
src/ui/explorer/explorer_block_cache.cpp
src/ui/windows/balance_address_list.cpp

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,505 @@
#pragma once
#include "chat_protocol.h"
#include <cstddef>
#include <string>
#include <vector>
// HushChat compatibility-fixture / capture-manifest / seed-projection tooling.
//
// Everything in this header is DEAD AT RUNTIME in the shipping app and test
// binaries — its only caller is the standalone dev CLI
// tools/hushchat_fixture_check.cpp. It is deliberately compiled ONLY into the
// HushChatFixtureCheck target so this validation scaffolding (and its libsodium
// seed-projection path) never reaches the wallet binary. Keep it that way: do
// not add chat_fixture_tooling.cpp to APP_SOURCES or the test target.
//
// It builds on the runtime types declared in chat_protocol.h.
namespace dragonx::chat {
enum class HushChatDecryptPreflightError {
None,
FeatureDisabled,
NonMessageHeader,
InvalidHeaderNumber,
UnsupportedVersion,
MissingReplyAddress,
MissingConversationId,
InvalidSecretstreamHeader,
InvalidPublicKey,
EmptyCiphertext,
OversizedCiphertext,
OddLengthCiphertext,
InvalidCiphertextHex,
TruncatedCiphertext
};
struct HushChatDecryptPreflightInput {
HushChatHeader header;
std::string ciphertext_hex;
};
struct HushChatDecryptPreflightResult {
bool ok = false;
bool feature_enabled = false;
HushChatDecryptPreflightError error = HushChatDecryptPreflightError::None;
const char* error_name = "None";
std::size_t ciphertext_size = 0;
};
enum class HushChatHexDecodeError {
None,
Empty,
OddLength,
InvalidHex,
UnexpectedByteLength
};
struct HushChatHexDecodeResult {
bool ok = false;
HushChatHexDecodeError error = HushChatHexDecodeError::None;
const char* error_name = "None";
std::vector<unsigned char> bytes;
};
enum class HushChatDecryptDirection {
Incoming,
Outgoing
};
enum class HushChatSessionKeySelection {
ClientRx,
ServerTx
};
enum class HushChatDecryptInputError {
None,
FeatureDisabled,
InvalidStoredChatKey,
DecryptPreflightFailed,
InvalidPeerPublicKey,
InvalidStreamHeader,
InvalidCiphertext
};
struct HushChatDecryptInputMaterial {
std::string stored_chat_key_hex;
HushChatHeader header;
std::string ciphertext_hex;
HushChatDecryptDirection direction = HushChatDecryptDirection::Incoming;
std::string peer_public_key_hex;
};
struct HushChatPreparedDecryptInput {
std::vector<unsigned char> stored_chat_key_bytes;
std::vector<unsigned char> seed_bytes;
std::vector<unsigned char> peer_public_key_bytes;
std::vector<unsigned char> stream_header_bytes;
std::vector<unsigned char> ciphertext_bytes;
HushChatDecryptDirection direction = HushChatDecryptDirection::Incoming;
HushChatSessionKeySelection session_key_selection = HushChatSessionKeySelection::ClientRx;
std::size_t plaintext_capacity = 0;
};
struct HushChatDecryptInputPreparationResult {
bool ok = false;
bool feature_enabled = false;
HushChatDecryptInputError error = HushChatDecryptInputError::None;
const char* error_name = "None";
HushChatHexDecodeError hex_error = HushChatHexDecodeError::None;
HushChatDecryptPreflightError preflight_error = HushChatDecryptPreflightError::None;
HushChatPreparedDecryptInput prepared;
};
struct HushChatDecryptFixtureReadinessResult {
bool ready = false;
std::size_t stored_chat_key_size = 0;
std::size_t seed_size = 0;
std::size_t peer_public_key_size = 0;
std::size_t stream_header_size = 0;
std::size_t ciphertext_size = 0;
std::size_t plaintext_capacity = 0;
HushChatSessionKeySelection session_key_selection = HushChatSessionKeySelection::ClientRx;
};
enum class HushChatCompatibilityFixtureError {
None,
FeatureDisabled,
MissingFixtureId,
InvalidLocalPublicKey,
InvalidPeerPublicKey,
InvalidHeaderMemo,
InvalidMemoPair,
NonMemoHeader,
HeaderPublicKeyMismatch,
DecryptInputFailed,
NotFixtureReady,
ExpectedStoredChatKeyLengthMismatch,
ExpectedSeedLengthMismatch,
ExpectedLocalPublicKeyLengthMismatch,
ExpectedPeerPublicKeyLengthMismatch,
ExpectedStreamHeaderLengthMismatch,
ExpectedCiphertextLengthMismatch,
ExpectedPlaintextLengthMismatch,
ExpectedRoleMismatch,
InvalidPlaintextHash
};
struct HushChatCompatibilityFixture {
std::string fixture_id;
std::string stored_chat_key_hex;
std::string local_public_key_hex;
std::string peer_public_key_hex;
std::string header_memo;
std::string ciphertext_memo;
HushChatDecryptDirection direction = HushChatDecryptDirection::Incoming;
HushChatSessionKeySelection expected_session_key_selection = HushChatSessionKeySelection::ClientRx;
std::size_t expected_stored_chat_key_size = 32;
std::size_t expected_seed_size = 32;
std::size_t expected_local_public_key_size = 32;
std::size_t expected_peer_public_key_size = 32;
std::size_t expected_stream_header_size = 24;
std::size_t expected_ciphertext_size = 0;
std::size_t expected_plaintext_size = 0;
std::string expected_plaintext_hash_hex;
};
struct HushChatCompatibilityFixtureVerificationResult {
bool ok = false;
bool feature_enabled = false;
HushChatCompatibilityFixtureError error = HushChatCompatibilityFixtureError::None;
const char* error_name = "None";
HushChatHexDecodeError hex_error = HushChatHexDecodeError::None;
HushChatDecryptInputError decrypt_input_error = HushChatDecryptInputError::None;
HushChatDecryptPreflightError preflight_error = HushChatDecryptPreflightError::None;
HushChatHeader header;
HushChatDecryptInputPreparationResult preparation;
HushChatDecryptFixtureReadinessResult readiness;
std::size_t local_public_key_size = 0;
std::size_t peer_public_key_size = 0;
std::size_t plaintext_hash_size = 0;
};
enum class HushChatCompatibilityFixtureKind {
IncomingMemo,
OutgoingMemo,
SeedPublicKeyProjection,
CorruptedAuthFailure,
ContactExclusion
};
enum class HushChatCompatibilityFixtureFileStatus {
Pending,
Ready
};
enum class HushChatCompatibilityFixtureFileError {
None,
FeatureDisabled,
InvalidJson,
JsonNotObject,
InvalidSchema,
MissingKind,
UnknownKind,
MissingStatus,
UnknownStatus,
MissingFixtureId,
MissingPendingReason,
MissingFixtureObject,
InvalidFixtureField,
FixtureVerificationFailed,
ContactFixtureNotExcluded,
FileReadFailed
};
struct HushChatCompatibilityFixtureFile {
std::string schema;
HushChatCompatibilityFixtureKind kind = HushChatCompatibilityFixtureKind::IncomingMemo;
HushChatCompatibilityFixtureFileStatus status = HushChatCompatibilityFixtureFileStatus::Pending;
std::string fixture_id;
std::string pending_reason;
HushChatCompatibilityFixture fixture;
};
struct HushChatCompatibilityFixtureFileParseResult {
bool ok = false;
bool feature_enabled = false;
bool pending = false;
bool verified = false;
bool excluded_from_decrypt = false;
HushChatCompatibilityFixtureFileError error = HushChatCompatibilityFixtureFileError::None;
const char* error_name = "None";
HushChatCompatibilityFixtureFile file;
HushChatCompatibilityFixtureVerificationResult verification;
};
enum class HushChatSeedPublicKeyProjectionError {
None,
FeatureDisabled,
MissingFixtureId,
InvalidStoredChatKey,
InvalidLocalPublicKey,
ExpectedStoredChatKeyLengthMismatch,
ExpectedSeedLengthMismatch,
ExpectedLocalPublicKeyLengthMismatch,
SodiumInitializationFailed,
KeypairProjectionFailed,
ProjectedPublicKeyMismatch
};
struct HushChatSeedPublicKeyProjectionResult {
bool ok = false;
bool feature_enabled = false;
HushChatSeedPublicKeyProjectionError error = HushChatSeedPublicKeyProjectionError::None;
const char* error_name = "None";
HushChatHexDecodeError hex_error = HushChatHexDecodeError::None;
std::size_t stored_chat_key_size = 0;
std::size_t seed_size = 0;
std::size_t local_public_key_size = 0;
std::size_t projected_public_key_size = 0;
};
enum class HushChatCorruptedAuthFailureReadinessError {
None,
FeatureDisabled,
FixturePending,
WrongFixtureKind,
FixtureNotVerified,
SeedProjectionNotVerified
};
struct HushChatCorruptedAuthFailureReadinessResult {
bool ok = false;
bool feature_enabled = false;
bool structurally_ready_for_future_auth_check = false;
bool requires_future_secretstream_auth_failure = false;
bool decrypted = false;
bool authenticated = false;
HushChatCorruptedAuthFailureReadinessError error = HushChatCorruptedAuthFailureReadinessError::None;
const char* error_name = "None";
};
enum class HushChatCompatibilityFixtureImportError {
None,
FeatureDisabled,
MissingRequiredKind,
DuplicateKind,
FixtureLoadFailed,
FixtureKindMismatch,
FixturePending,
FixtureInvalid,
FixtureNotVerified,
SeedProjectionFailed,
AuthFailureScaffoldFailed,
ContactFixtureNotExcluded
};
struct HushChatCompatibilityFixtureImportCandidate {
HushChatCompatibilityFixtureKind expected_kind = HushChatCompatibilityFixtureKind::IncomingMemo;
std::string path;
};
struct HushChatCompatibilityFixtureImportItem {
HushChatCompatibilityFixtureKind expected_kind = HushChatCompatibilityFixtureKind::IncomingMemo;
HushChatCompatibilityFixtureKind loaded_kind = HushChatCompatibilityFixtureKind::IncomingMemo;
std::string path;
bool supplied = false;
bool pending = false;
bool replacement_eligible = false;
bool seed_projection_verified = false;
bool future_auth_failure_required = false;
bool structurally_ready_for_future_auth_check = false;
HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None;
const char* error_name = "None";
HushChatCompatibilityFixtureFileParseResult parsed;
HushChatSeedPublicKeyProjectionResult seed_projection;
HushChatCorruptedAuthFailureReadinessResult auth_failure_readiness;
};
struct HushChatCompatibilityFixtureImportChecklistResult {
bool ok = false;
bool feature_enabled = false;
bool replacement_ready = false;
HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None;
const char* error_name = "None";
std::size_t required_count = 0;
std::size_t supplied_count = 0;
std::size_t missing_count = 0;
std::size_t pending_count = 0;
std::size_t verified_count = 0;
std::size_t seed_projection_verified_count = 0;
std::size_t future_auth_failure_required_count = 0;
std::size_t auth_failure_structural_ready_count = 0;
std::size_t excluded_count = 0;
std::size_t rejected_count = 0;
std::vector<HushChatCompatibilityFixtureImportItem> items;
};
struct HushChatCompatibilityFixtureReplacementReportItem {
HushChatCompatibilityFixtureKind expected_kind = HushChatCompatibilityFixtureKind::IncomingMemo;
HushChatCompatibilityFixtureKind loaded_kind = HushChatCompatibilityFixtureKind::IncomingMemo;
std::string path;
bool supplied = false;
bool pending = false;
bool replacement_eligible = false;
bool refused = true;
bool seed_projection_verified = false;
bool future_auth_failure_required = false;
bool structurally_ready_for_future_auth_check = false;
bool cont_excluded = false;
bool decrypted = false;
bool authenticated = false;
HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None;
const char* error_name = "None";
};
struct HushChatCompatibilityFixtureReplacementDryRunResult {
bool ok = false;
bool feature_enabled = false;
bool dry_run_only = true;
bool redacted_report = true;
bool would_replace = false;
bool replacement_refused = true;
HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None;
const char* error_name = "None";
std::size_t required_count = 0;
std::size_t supplied_count = 0;
std::size_t missing_count = 0;
std::size_t pending_count = 0;
std::size_t verified_count = 0;
std::size_t seed_projection_verified_count = 0;
std::size_t future_auth_failure_required_count = 0;
std::size_t auth_failure_structural_ready_count = 0;
std::size_t excluded_count = 0;
std::size_t rejected_count = 0;
std::vector<HushChatCompatibilityFixtureReplacementReportItem> report_items;
};
enum class HushChatCaptureManifestError {
None,
FeatureDisabled,
FileReadFailed,
InvalidJson,
JsonNotObject,
InvalidSchema,
MissingManifestId,
MissingStatus,
UnknownStatus,
MissingFixtureDirectory,
MissingDryRunCommand,
InvalidDryRunCommand,
MissingProvenance,
MissingSourceClient,
InvalidSourceClient,
MissingSourceClientVersion,
MissingCaptureDate,
MissingNetwork,
MissingCaptureMethod,
MissingHandling,
MissingHandlingFlag,
HandlingFlagNotTrue,
MissingCategories,
InvalidCategoryEntry,
UnknownCategory,
DuplicateCategory,
MissingRequiredCategory,
ProhibitedFieldPresent
};
enum class HushChatCaptureManifestStatus {
Staged
};
struct HushChatCaptureManifestCategoryReport {
HushChatCompatibilityFixtureKind kind = HushChatCompatibilityFixtureKind::IncomingMemo;
std::string staged_filename;
bool declared = false;
};
struct HushChatCaptureManifestValidationResult {
bool ok = false;
bool feature_enabled = false;
bool redacted_report = true;
bool validates_provenance_only = true;
bool no_sensitive_material_declared = false;
bool has_dry_run_command = false;
HushChatCaptureManifestError error = HushChatCaptureManifestError::None;
const char* error_name = "None";
HushChatCaptureManifestStatus status = HushChatCaptureManifestStatus::Staged;
std::string manifest_path;
std::string fixture_directory;
std::size_t required_count = 0;
std::size_t declared_count = 0;
std::size_t missing_count = 0;
std::size_t duplicate_count = 0;
std::size_t prohibited_field_count = 0;
std::size_t handling_flag_count = 0;
std::vector<HushChatCaptureManifestCategoryReport> categories;
};
constexpr std::size_t kHushChatSecretstreamABytes = 17;
constexpr std::size_t kHushChatStoredChatKeyByteLength = 32;
constexpr std::size_t kHushChatStoredChatKeyHexLength = kHushChatStoredChatKeyByteLength * 2;
constexpr std::size_t kHushChatSeedByteLength = 32;
constexpr std::size_t kHushChatPublicKeyByteLength = kHushChatPublicKeyHexLength / 2;
constexpr std::size_t kHushChatSecretstreamHeaderByteLength = kHushChatSecretstreamHeaderHexLength / 2;
constexpr const char* kHushChatCompatibilityFixtureSchema = "dragonx.hushchat.compat-fixture.v1";
constexpr const char* kHushChatCaptureManifestSchema = "dragonx.hushchat.capture-manifest.v1";
HushChatDecryptPreflightResult validateHushChatMemoDecryptPreflight(
const HushChatDecryptPreflightInput& input,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatHexDecodeResult decodeHushChatHexBytes(const std::string& hex,
std::size_t expectedByteLength);
HushChatDecryptInputPreparationResult prepareHushChatDecryptInput(
const HushChatDecryptInputMaterial& material,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatDecryptFixtureReadinessResult inspectHushChatDecryptFixtureReadiness(
const HushChatPreparedDecryptInput& prepared);
HushChatSessionKeySelection hushChatSessionKeySelectionForDirection(HushChatDecryptDirection direction);
HushChatCompatibilityFixtureVerificationResult verifyHushChatCompatibilityFixture(
const HushChatCompatibilityFixture& fixture,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCompatibilityFixtureFileParseResult parseHushChatCompatibilityFixtureFile(
const std::string& jsonText,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCompatibilityFixtureFileParseResult loadHushChatCompatibilityFixtureFile(
const std::string& path,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatSeedPublicKeyProjectionResult verifyHushChatSeedPublicKeyProjection(
const HushChatCompatibilityFixture& fixture,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCorruptedAuthFailureReadinessResult inspectHushChatCorruptedAuthFailureReadiness(
const HushChatCompatibilityFixtureFileParseResult& parsed,
const HushChatSeedPublicKeyProjectionResult& seedProjection,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
std::vector<HushChatCompatibilityFixtureKind> hushChatRequiredCompatibilityFixtureKinds();
HushChatCompatibilityFixtureImportChecklistResult inspectHushChatCompatibilityFixtureImportChecklist(
const std::vector<HushChatCompatibilityFixtureImportCandidate>& candidates,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCompatibilityFixtureReplacementDryRunResult inspectHushChatCompatibilityFixtureReplacementDryRun(
const std::vector<HushChatCompatibilityFixtureImportCandidate>& candidates,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCaptureManifestValidationResult validateHushChatCaptureManifest(
const std::string& jsonText,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCaptureManifestValidationResult loadHushChatCaptureManifestFile(
const std::string& path,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
const char* hushChatDecryptPreflightErrorName(HushChatDecryptPreflightError error);
const char* hushChatHexDecodeErrorName(HushChatHexDecodeError error);
const char* hushChatDecryptDirectionName(HushChatDecryptDirection direction);
const char* hushChatSessionKeySelectionName(HushChatSessionKeySelection selection);
const char* hushChatDecryptInputErrorName(HushChatDecryptInputError error);
const char* hushChatCompatibilityFixtureErrorName(HushChatCompatibilityFixtureError error);
const char* hushChatCompatibilityFixtureKindName(HushChatCompatibilityFixtureKind kind);
const char* hushChatCompatibilityFixtureFileStatusName(HushChatCompatibilityFixtureFileStatus status);
const char* hushChatCompatibilityFixtureFileErrorName(HushChatCompatibilityFixtureFileError error);
const char* hushChatSeedPublicKeyProjectionErrorName(HushChatSeedPublicKeyProjectionError error);
const char* hushChatCorruptedAuthFailureReadinessErrorName(HushChatCorruptedAuthFailureReadinessError error);
const char* hushChatCompatibilityFixtureImportErrorName(HushChatCompatibilityFixtureImportError error);
const char* hushChatCaptureManifestErrorName(HushChatCaptureManifestError error);
} // namespace dragonx::chat

File diff suppressed because it is too large Load Diff

View File

@@ -84,438 +84,10 @@ struct HushChatTransactionExtractionResult {
std::size_t ignored_memo_count = 0;
};
enum class HushChatDecryptPreflightError {
None,
FeatureDisabled,
NonMessageHeader,
InvalidHeaderNumber,
UnsupportedVersion,
MissingReplyAddress,
MissingConversationId,
InvalidSecretstreamHeader,
InvalidPublicKey,
EmptyCiphertext,
OversizedCiphertext,
OddLengthCiphertext,
InvalidCiphertextHex,
TruncatedCiphertext
};
struct HushChatDecryptPreflightInput {
HushChatHeader header;
std::string ciphertext_hex;
};
struct HushChatDecryptPreflightResult {
bool ok = false;
bool feature_enabled = false;
HushChatDecryptPreflightError error = HushChatDecryptPreflightError::None;
const char* error_name = "None";
std::size_t ciphertext_size = 0;
};
enum class HushChatHexDecodeError {
None,
Empty,
OddLength,
InvalidHex,
UnexpectedByteLength
};
struct HushChatHexDecodeResult {
bool ok = false;
HushChatHexDecodeError error = HushChatHexDecodeError::None;
const char* error_name = "None";
std::vector<unsigned char> bytes;
};
enum class HushChatDecryptDirection {
Incoming,
Outgoing
};
enum class HushChatSessionKeySelection {
ClientRx,
ServerTx
};
enum class HushChatDecryptInputError {
None,
FeatureDisabled,
InvalidStoredChatKey,
DecryptPreflightFailed,
InvalidPeerPublicKey,
InvalidStreamHeader,
InvalidCiphertext
};
struct HushChatDecryptInputMaterial {
std::string stored_chat_key_hex;
HushChatHeader header;
std::string ciphertext_hex;
HushChatDecryptDirection direction = HushChatDecryptDirection::Incoming;
std::string peer_public_key_hex;
};
struct HushChatPreparedDecryptInput {
std::vector<unsigned char> stored_chat_key_bytes;
std::vector<unsigned char> seed_bytes;
std::vector<unsigned char> peer_public_key_bytes;
std::vector<unsigned char> stream_header_bytes;
std::vector<unsigned char> ciphertext_bytes;
HushChatDecryptDirection direction = HushChatDecryptDirection::Incoming;
HushChatSessionKeySelection session_key_selection = HushChatSessionKeySelection::ClientRx;
std::size_t plaintext_capacity = 0;
};
struct HushChatDecryptInputPreparationResult {
bool ok = false;
bool feature_enabled = false;
HushChatDecryptInputError error = HushChatDecryptInputError::None;
const char* error_name = "None";
HushChatHexDecodeError hex_error = HushChatHexDecodeError::None;
HushChatDecryptPreflightError preflight_error = HushChatDecryptPreflightError::None;
HushChatPreparedDecryptInput prepared;
};
struct HushChatDecryptFixtureReadinessResult {
bool ready = false;
std::size_t stored_chat_key_size = 0;
std::size_t seed_size = 0;
std::size_t peer_public_key_size = 0;
std::size_t stream_header_size = 0;
std::size_t ciphertext_size = 0;
std::size_t plaintext_capacity = 0;
HushChatSessionKeySelection session_key_selection = HushChatSessionKeySelection::ClientRx;
};
enum class HushChatCompatibilityFixtureError {
None,
FeatureDisabled,
MissingFixtureId,
InvalidLocalPublicKey,
InvalidPeerPublicKey,
InvalidHeaderMemo,
InvalidMemoPair,
NonMemoHeader,
HeaderPublicKeyMismatch,
DecryptInputFailed,
NotFixtureReady,
ExpectedStoredChatKeyLengthMismatch,
ExpectedSeedLengthMismatch,
ExpectedLocalPublicKeyLengthMismatch,
ExpectedPeerPublicKeyLengthMismatch,
ExpectedStreamHeaderLengthMismatch,
ExpectedCiphertextLengthMismatch,
ExpectedPlaintextLengthMismatch,
ExpectedRoleMismatch,
InvalidPlaintextHash
};
struct HushChatCompatibilityFixture {
std::string fixture_id;
std::string stored_chat_key_hex;
std::string local_public_key_hex;
std::string peer_public_key_hex;
std::string header_memo;
std::string ciphertext_memo;
HushChatDecryptDirection direction = HushChatDecryptDirection::Incoming;
HushChatSessionKeySelection expected_session_key_selection = HushChatSessionKeySelection::ClientRx;
std::size_t expected_stored_chat_key_size = 32;
std::size_t expected_seed_size = 32;
std::size_t expected_local_public_key_size = 32;
std::size_t expected_peer_public_key_size = 32;
std::size_t expected_stream_header_size = 24;
std::size_t expected_ciphertext_size = 0;
std::size_t expected_plaintext_size = 0;
std::string expected_plaintext_hash_hex;
};
struct HushChatCompatibilityFixtureVerificationResult {
bool ok = false;
bool feature_enabled = false;
HushChatCompatibilityFixtureError error = HushChatCompatibilityFixtureError::None;
const char* error_name = "None";
HushChatHexDecodeError hex_error = HushChatHexDecodeError::None;
HushChatDecryptInputError decrypt_input_error = HushChatDecryptInputError::None;
HushChatDecryptPreflightError preflight_error = HushChatDecryptPreflightError::None;
HushChatHeader header;
HushChatDecryptInputPreparationResult preparation;
HushChatDecryptFixtureReadinessResult readiness;
std::size_t local_public_key_size = 0;
std::size_t peer_public_key_size = 0;
std::size_t plaintext_hash_size = 0;
};
enum class HushChatCompatibilityFixtureKind {
IncomingMemo,
OutgoingMemo,
SeedPublicKeyProjection,
CorruptedAuthFailure,
ContactExclusion
};
enum class HushChatCompatibilityFixtureFileStatus {
Pending,
Ready
};
enum class HushChatCompatibilityFixtureFileError {
None,
FeatureDisabled,
InvalidJson,
JsonNotObject,
InvalidSchema,
MissingKind,
UnknownKind,
MissingStatus,
UnknownStatus,
MissingFixtureId,
MissingPendingReason,
MissingFixtureObject,
InvalidFixtureField,
FixtureVerificationFailed,
ContactFixtureNotExcluded,
FileReadFailed
};
struct HushChatCompatibilityFixtureFile {
std::string schema;
HushChatCompatibilityFixtureKind kind = HushChatCompatibilityFixtureKind::IncomingMemo;
HushChatCompatibilityFixtureFileStatus status = HushChatCompatibilityFixtureFileStatus::Pending;
std::string fixture_id;
std::string pending_reason;
HushChatCompatibilityFixture fixture;
};
struct HushChatCompatibilityFixtureFileParseResult {
bool ok = false;
bool feature_enabled = false;
bool pending = false;
bool verified = false;
bool excluded_from_decrypt = false;
HushChatCompatibilityFixtureFileError error = HushChatCompatibilityFixtureFileError::None;
const char* error_name = "None";
HushChatCompatibilityFixtureFile file;
HushChatCompatibilityFixtureVerificationResult verification;
};
enum class HushChatSeedPublicKeyProjectionError {
None,
FeatureDisabled,
MissingFixtureId,
InvalidStoredChatKey,
InvalidLocalPublicKey,
ExpectedStoredChatKeyLengthMismatch,
ExpectedSeedLengthMismatch,
ExpectedLocalPublicKeyLengthMismatch,
SodiumInitializationFailed,
KeypairProjectionFailed,
ProjectedPublicKeyMismatch
};
struct HushChatSeedPublicKeyProjectionResult {
bool ok = false;
bool feature_enabled = false;
HushChatSeedPublicKeyProjectionError error = HushChatSeedPublicKeyProjectionError::None;
const char* error_name = "None";
HushChatHexDecodeError hex_error = HushChatHexDecodeError::None;
std::size_t stored_chat_key_size = 0;
std::size_t seed_size = 0;
std::size_t local_public_key_size = 0;
std::size_t projected_public_key_size = 0;
};
enum class HushChatCorruptedAuthFailureReadinessError {
None,
FeatureDisabled,
FixturePending,
WrongFixtureKind,
FixtureNotVerified,
SeedProjectionNotVerified
};
struct HushChatCorruptedAuthFailureReadinessResult {
bool ok = false;
bool feature_enabled = false;
bool structurally_ready_for_future_auth_check = false;
bool requires_future_secretstream_auth_failure = false;
bool decrypted = false;
bool authenticated = false;
HushChatCorruptedAuthFailureReadinessError error = HushChatCorruptedAuthFailureReadinessError::None;
const char* error_name = "None";
};
enum class HushChatCompatibilityFixtureImportError {
None,
FeatureDisabled,
MissingRequiredKind,
DuplicateKind,
FixtureLoadFailed,
FixtureKindMismatch,
FixturePending,
FixtureInvalid,
FixtureNotVerified,
SeedProjectionFailed,
AuthFailureScaffoldFailed,
ContactFixtureNotExcluded
};
struct HushChatCompatibilityFixtureImportCandidate {
HushChatCompatibilityFixtureKind expected_kind = HushChatCompatibilityFixtureKind::IncomingMemo;
std::string path;
};
struct HushChatCompatibilityFixtureImportItem {
HushChatCompatibilityFixtureKind expected_kind = HushChatCompatibilityFixtureKind::IncomingMemo;
HushChatCompatibilityFixtureKind loaded_kind = HushChatCompatibilityFixtureKind::IncomingMemo;
std::string path;
bool supplied = false;
bool pending = false;
bool replacement_eligible = false;
bool seed_projection_verified = false;
bool future_auth_failure_required = false;
bool structurally_ready_for_future_auth_check = false;
HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None;
const char* error_name = "None";
HushChatCompatibilityFixtureFileParseResult parsed;
HushChatSeedPublicKeyProjectionResult seed_projection;
HushChatCorruptedAuthFailureReadinessResult auth_failure_readiness;
};
struct HushChatCompatibilityFixtureImportChecklistResult {
bool ok = false;
bool feature_enabled = false;
bool replacement_ready = false;
HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None;
const char* error_name = "None";
std::size_t required_count = 0;
std::size_t supplied_count = 0;
std::size_t missing_count = 0;
std::size_t pending_count = 0;
std::size_t verified_count = 0;
std::size_t seed_projection_verified_count = 0;
std::size_t future_auth_failure_required_count = 0;
std::size_t auth_failure_structural_ready_count = 0;
std::size_t excluded_count = 0;
std::size_t rejected_count = 0;
std::vector<HushChatCompatibilityFixtureImportItem> items;
};
struct HushChatCompatibilityFixtureReplacementReportItem {
HushChatCompatibilityFixtureKind expected_kind = HushChatCompatibilityFixtureKind::IncomingMemo;
HushChatCompatibilityFixtureKind loaded_kind = HushChatCompatibilityFixtureKind::IncomingMemo;
std::string path;
bool supplied = false;
bool pending = false;
bool replacement_eligible = false;
bool refused = true;
bool seed_projection_verified = false;
bool future_auth_failure_required = false;
bool structurally_ready_for_future_auth_check = false;
bool cont_excluded = false;
bool decrypted = false;
bool authenticated = false;
HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None;
const char* error_name = "None";
};
struct HushChatCompatibilityFixtureReplacementDryRunResult {
bool ok = false;
bool feature_enabled = false;
bool dry_run_only = true;
bool redacted_report = true;
bool would_replace = false;
bool replacement_refused = true;
HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None;
const char* error_name = "None";
std::size_t required_count = 0;
std::size_t supplied_count = 0;
std::size_t missing_count = 0;
std::size_t pending_count = 0;
std::size_t verified_count = 0;
std::size_t seed_projection_verified_count = 0;
std::size_t future_auth_failure_required_count = 0;
std::size_t auth_failure_structural_ready_count = 0;
std::size_t excluded_count = 0;
std::size_t rejected_count = 0;
std::vector<HushChatCompatibilityFixtureReplacementReportItem> report_items;
};
enum class HushChatCaptureManifestError {
None,
FeatureDisabled,
FileReadFailed,
InvalidJson,
JsonNotObject,
InvalidSchema,
MissingManifestId,
MissingStatus,
UnknownStatus,
MissingFixtureDirectory,
MissingDryRunCommand,
InvalidDryRunCommand,
MissingProvenance,
MissingSourceClient,
InvalidSourceClient,
MissingSourceClientVersion,
MissingCaptureDate,
MissingNetwork,
MissingCaptureMethod,
MissingHandling,
MissingHandlingFlag,
HandlingFlagNotTrue,
MissingCategories,
InvalidCategoryEntry,
UnknownCategory,
DuplicateCategory,
MissingRequiredCategory,
ProhibitedFieldPresent
};
enum class HushChatCaptureManifestStatus {
Staged
};
struct HushChatCaptureManifestCategoryReport {
HushChatCompatibilityFixtureKind kind = HushChatCompatibilityFixtureKind::IncomingMemo;
std::string staged_filename;
bool declared = false;
};
struct HushChatCaptureManifestValidationResult {
bool ok = false;
bool feature_enabled = false;
bool redacted_report = true;
bool validates_provenance_only = true;
bool no_sensitive_material_declared = false;
bool has_dry_run_command = false;
HushChatCaptureManifestError error = HushChatCaptureManifestError::None;
const char* error_name = "None";
HushChatCaptureManifestStatus status = HushChatCaptureManifestStatus::Staged;
std::string manifest_path;
std::string fixture_directory;
std::size_t required_count = 0;
std::size_t declared_count = 0;
std::size_t missing_count = 0;
std::size_t duplicate_count = 0;
std::size_t prohibited_field_count = 0;
std::size_t handling_flag_count = 0;
std::vector<HushChatCaptureManifestCategoryReport> categories;
};
constexpr int kHushChatSupportedVersion = 0;
constexpr std::size_t kHushChatMemoByteLimit = 512;
constexpr std::size_t kHushChatPublicKeyHexLength = 64;
constexpr std::size_t kHushChatSecretstreamHeaderHexLength = 48;
constexpr std::size_t kHushChatSecretstreamABytes = 17;
constexpr std::size_t kHushChatStoredChatKeyByteLength = 32;
constexpr std::size_t kHushChatStoredChatKeyHexLength = kHushChatStoredChatKeyByteLength * 2;
constexpr std::size_t kHushChatSeedByteLength = 32;
constexpr std::size_t kHushChatPublicKeyByteLength = kHushChatPublicKeyHexLength / 2;
constexpr std::size_t kHushChatSecretstreamHeaderByteLength = kHushChatSecretstreamHeaderHexLength / 2;
constexpr const char* kHushChatCompatibilityFixtureSchema = "dragonx.hushchat.compat-fixture.v1";
constexpr const char* kHushChatCaptureManifestSchema = "dragonx.hushchat.capture-manifest.v1";
constexpr bool hushChatFeatureEnabledAtBuild()
{
@@ -527,60 +99,7 @@ HushChatMemoGroupingResult groupHushChatMemoOutputs(const std::vector<HushChatMe
HushChatTransactionExtractionResult extractHushChatTransactionMetadata(
const HushChatTransactionInput& transaction,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatDecryptPreflightResult validateHushChatMemoDecryptPreflight(
const HushChatDecryptPreflightInput& input,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatHexDecodeResult decodeHushChatHexBytes(const std::string& hex,
std::size_t expectedByteLength);
HushChatDecryptInputPreparationResult prepareHushChatDecryptInput(
const HushChatDecryptInputMaterial& material,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatDecryptFixtureReadinessResult inspectHushChatDecryptFixtureReadiness(
const HushChatPreparedDecryptInput& prepared);
HushChatSessionKeySelection hushChatSessionKeySelectionForDirection(HushChatDecryptDirection direction);
HushChatCompatibilityFixtureVerificationResult verifyHushChatCompatibilityFixture(
const HushChatCompatibilityFixture& fixture,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCompatibilityFixtureFileParseResult parseHushChatCompatibilityFixtureFile(
const std::string& jsonText,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCompatibilityFixtureFileParseResult loadHushChatCompatibilityFixtureFile(
const std::string& path,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatSeedPublicKeyProjectionResult verifyHushChatSeedPublicKeyProjection(
const HushChatCompatibilityFixture& fixture,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCorruptedAuthFailureReadinessResult inspectHushChatCorruptedAuthFailureReadiness(
const HushChatCompatibilityFixtureFileParseResult& parsed,
const HushChatSeedPublicKeyProjectionResult& seedProjection,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
std::vector<HushChatCompatibilityFixtureKind> hushChatRequiredCompatibilityFixtureKinds();
HushChatCompatibilityFixtureImportChecklistResult inspectHushChatCompatibilityFixtureImportChecklist(
const std::vector<HushChatCompatibilityFixtureImportCandidate>& candidates,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCompatibilityFixtureReplacementDryRunResult inspectHushChatCompatibilityFixtureReplacementDryRun(
const std::vector<HushChatCompatibilityFixtureImportCandidate>& candidates,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCaptureManifestValidationResult validateHushChatCaptureManifest(
const std::string& jsonText,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCaptureManifestValidationResult loadHushChatCaptureManifestFile(
const std::string& path,
bool featureEnabled = hushChatFeatureEnabledAtBuild());
const char* hushChatHeaderTypeName(HushChatHeaderType type);
const char* hushChatMemoGroupingIssueName(HushChatMemoGroupingIssue issue);
const char* hushChatDecryptPreflightErrorName(HushChatDecryptPreflightError error);
const char* hushChatHexDecodeErrorName(HushChatHexDecodeError error);
const char* hushChatDecryptDirectionName(HushChatDecryptDirection direction);
const char* hushChatSessionKeySelectionName(HushChatSessionKeySelection selection);
const char* hushChatDecryptInputErrorName(HushChatDecryptInputError error);
const char* hushChatCompatibilityFixtureErrorName(HushChatCompatibilityFixtureError error);
const char* hushChatCompatibilityFixtureKindName(HushChatCompatibilityFixtureKind kind);
const char* hushChatCompatibilityFixtureFileStatusName(HushChatCompatibilityFixtureFileStatus status);
const char* hushChatCompatibilityFixtureFileErrorName(HushChatCompatibilityFixtureFileError error);
const char* hushChatSeedPublicKeyProjectionErrorName(HushChatSeedPublicKeyProjectionError error);
const char* hushChatCorruptedAuthFailureReadinessErrorName(HushChatCorruptedAuthFailureReadinessError error);
const char* hushChatCompatibilityFixtureImportErrorName(HushChatCompatibilityFixtureImportError error);
const char* hushChatCaptureManifestErrorName(HushChatCaptureManifestError error);
} // namespace dragonx::chat
} // namespace dragonx::chat

View File

@@ -287,16 +287,12 @@ static void evaluateLiteLifecycleRequestFromPageState(App* app) {
return;
}
const auto result = wallet::executeLiteWalletLifecycleUiRequest(*app->settings(), input);
s_settingsState.lite_lifecycle_summary = result.requestSummaryRedacted;
if (result.ok) {
s_settingsState.lite_lifecycle_status = "Ready";
} else {
s_settingsState.lite_lifecycle_status = result.error.empty()
? wallet::liteWalletLifecycleUiExecutionStatusName(result.status)
: result.error;
Notifications::instance().warning(s_settingsState.lite_lifecycle_status);
}
// No linked lite backend to execute against (full-node build, or the lite backend
// failed to load / rollout-disabled). The live path above returns when a backend is
// present, so reaching here means there is nothing to run.
s_settingsState.lite_lifecycle_summary.clear();
s_settingsState.lite_lifecycle_status = "Lite wallet backend unavailable";
Notifications::instance().warning(s_settingsState.lite_lifecycle_status);
}
// (APPEARANCE card now uses ChannelsSplit like all other cards)

View File

@@ -1,428 +1,7 @@
#include "lite_wallet_lifecycle_ui_adapter.h"
#include <sstream>
#include <utility>
namespace dragonx {
namespace wallet {
namespace {
void addIssue(std::vector<LiteWalletLifecycleUiExecutionIssueInfo>& issues,
LiteWalletLifecycleUiExecutionIssue issue,
std::string message)
{
issues.push_back(LiteWalletLifecycleUiExecutionIssueInfo{issue, std::move(message)});
}
LiteWalletLifecycleUiExecutionResult stoppedResult(
LiteWalletLifecycleUiExecutionResult result,
LiteWalletLifecycleUiExecutionStatus status,
LiteWalletLifecycleUiExecutionIssue issue,
const std::string& message)
{
result.status = status;
result.error = message;
result.ok = false;
addIssue(result.issues, issue, message);
return result;
}
LiteWalletLifecycleUiExecutionStatus statusFromServerSelection(
LiteWalletServerSelectionUiExecutionStatus status)
{
switch (status) {
case LiteWalletServerSelectionUiExecutionStatus::ReadyForFutureLifecycle:
return LiteWalletLifecycleUiExecutionStatus::ReadyForFutureLifecycleRequest;
case LiteWalletServerSelectionUiExecutionStatus::WaitingForLiteBuild:
return LiteWalletLifecycleUiExecutionStatus::WaitingForLiteBuild;
case LiteWalletServerSelectionUiExecutionStatus::WaitingForBackendCapability:
return LiteWalletLifecycleUiExecutionStatus::WaitingForBackendCapability;
case LiteWalletServerSelectionUiExecutionStatus::WaitingForSettings:
return LiteWalletLifecycleUiExecutionStatus::WaitingForSettings;
case LiteWalletServerSelectionUiExecutionStatus::WaitingForServerSelection:
return LiteWalletLifecycleUiExecutionStatus::WaitingForServerSelection;
case LiteWalletServerSelectionUiExecutionStatus::WaitingForPersistenceOwner:
return LiteWalletLifecycleUiExecutionStatus::WaitingForPersistedServerSelection;
case LiteWalletServerSelectionUiExecutionStatus::WaitingForDisplayStatus:
return LiteWalletLifecycleUiExecutionStatus::WaitingForDisplayStatus;
case LiteWalletServerSelectionUiExecutionStatus::WaitingForLifecycleUi:
return LiteWalletLifecycleUiExecutionStatus::WaitingForLifecycleUi;
case LiteWalletServerSelectionUiExecutionStatus::WaitingForPrivateDataRedaction:
return LiteWalletLifecycleUiExecutionStatus::WaitingForPrivateDataRedaction;
case LiteWalletServerSelectionUiExecutionStatus::WaitingForSyncPlannerFeed:
return LiteWalletLifecycleUiExecutionStatus::WaitingForSyncPlannerFeed;
case LiteWalletServerSelectionUiExecutionStatus::SettingsSaveFailed:
return LiteWalletLifecycleUiExecutionStatus::WaitingForSettings;
case LiteWalletServerSelectionUiExecutionStatus::RuntimeExecutionDisabled:
return LiteWalletLifecycleUiExecutionStatus::RuntimeExecutionDisabled;
}
return LiteWalletLifecycleUiExecutionStatus::WaitingForSettings;
}
LiteWalletLifecycleUiExecutionStatus statusFromLifecycle(
LiteWalletServerLifecycleReadinessStatus status)
{
switch (status) {
case LiteWalletServerLifecycleReadinessStatus::ReadyForFutureLifecycle:
return LiteWalletLifecycleUiExecutionStatus::ReadyForFutureLifecycleRequest;
case LiteWalletServerLifecycleReadinessStatus::WaitingForLiteBuild:
return LiteWalletLifecycleUiExecutionStatus::WaitingForLiteBuild;
case LiteWalletServerLifecycleReadinessStatus::WaitingForBackendCapability:
return LiteWalletLifecycleUiExecutionStatus::WaitingForBackendCapability;
case LiteWalletServerLifecycleReadinessStatus::WaitingForServerSelection:
return LiteWalletLifecycleUiExecutionStatus::WaitingForServerSelection;
case LiteWalletServerLifecycleReadinessStatus::WaitingForPersistenceIntent:
return LiteWalletLifecycleUiExecutionStatus::WaitingForPersistedServerSelection;
case LiteWalletServerLifecycleReadinessStatus::WaitingForDisplayStatus:
return LiteWalletLifecycleUiExecutionStatus::WaitingForDisplayStatus;
case LiteWalletServerLifecycleReadinessStatus::WaitingForLifecycleUi:
return LiteWalletLifecycleUiExecutionStatus::WaitingForLifecycleUi;
case LiteWalletServerLifecycleReadinessStatus::WaitingForPrivateDataRedaction:
return LiteWalletLifecycleUiExecutionStatus::WaitingForPrivateDataRedaction;
case LiteWalletServerLifecycleReadinessStatus::WaitingForSyncPlannerFeed:
return LiteWalletLifecycleUiExecutionStatus::WaitingForSyncPlannerFeed;
case LiteWalletServerLifecycleReadinessStatus::RuntimeExecutionDisabled:
return LiteWalletLifecycleUiExecutionStatus::RuntimeExecutionDisabled;
}
return LiteWalletLifecycleUiExecutionStatus::WaitingForSettings;
}
LiteWalletLifecycleUiExecutionIssue issueFromLifecycle(
LiteWalletServerLifecycleReadinessIssue issue)
{
switch (issue) {
case LiteWalletServerLifecycleReadinessIssue::FullNodeBuild:
return LiteWalletLifecycleUiExecutionIssue::FullNodeBuild;
case LiteWalletServerLifecycleReadinessIssue::LiteBackendCapabilityMissing:
return LiteWalletLifecycleUiExecutionIssue::LiteBackendCapabilityMissing;
case LiteWalletServerLifecycleReadinessIssue::PersistedSettingsNotLoaded:
return LiteWalletLifecycleUiExecutionIssue::SettingsNotLoaded;
case LiteWalletServerLifecycleReadinessIssue::PersistedServerSelectionIntentMissing:
return LiteWalletLifecycleUiExecutionIssue::PersistedServerSelectionIntentMissing;
case LiteWalletServerLifecycleReadinessIssue::ServerSelectionMissing:
return LiteWalletLifecycleUiExecutionIssue::ServerSelectionMissing;
case LiteWalletServerLifecycleReadinessIssue::ServerPersistenceOwnerMissing:
return LiteWalletLifecycleUiExecutionIssue::PersistedServerSelectionIntentMissing;
case LiteWalletServerLifecycleReadinessIssue::SelectedServerDisplayMissing:
return LiteWalletLifecycleUiExecutionIssue::SelectedServerDisplayMissing;
case LiteWalletServerLifecycleReadinessIssue::LifecycleUiOwnerMissing:
return LiteWalletLifecycleUiExecutionIssue::LifecycleUiOwnerMissing;
case LiteWalletServerLifecycleReadinessIssue::LifecycleOperationUnconfirmed:
return LiteWalletLifecycleUiExecutionIssue::LifecycleOperationUnconfirmed;
case LiteWalletServerLifecycleReadinessIssue::OpenWalletPathMissing:
return LiteWalletLifecycleUiExecutionIssue::OpenWalletPathMissing;
case LiteWalletServerLifecycleReadinessIssue::RestoreSeedMissing:
return LiteWalletLifecycleUiExecutionIssue::RestoreSeedMissing;
case LiteWalletServerLifecycleReadinessIssue::PrivateDataRedactionMissing:
return LiteWalletLifecycleUiExecutionIssue::PrivateDataRedactionMissing;
case LiteWalletServerLifecycleReadinessIssue::SyncPlannerFeedMissing:
return LiteWalletLifecycleUiExecutionIssue::SyncPlannerFeedMissing;
case LiteWalletServerLifecycleReadinessIssue::RealLifecycleExecutionRequested:
return LiteWalletLifecycleUiExecutionIssue::WalletLifecycleExecutionRequested;
}
return LiteWalletLifecycleUiExecutionIssue::SettingsNotLoaded;
}
LiteWalletLifecycleUiExecutionIssue issueFromServerSelection(
LiteWalletServerSelectionUiExecutionIssue issue)
{
switch (issue) {
case LiteWalletServerSelectionUiExecutionIssue::FullNodeBuild:
return LiteWalletLifecycleUiExecutionIssue::FullNodeBuild;
case LiteWalletServerSelectionUiExecutionIssue::LiteBackendCapabilityMissing:
return LiteWalletLifecycleUiExecutionIssue::LiteBackendCapabilityMissing;
case LiteWalletServerSelectionUiExecutionIssue::SettingsNotLoaded:
return LiteWalletLifecycleUiExecutionIssue::SettingsNotLoaded;
case LiteWalletServerSelectionUiExecutionIssue::ServerSelectionMissing:
return LiteWalletLifecycleUiExecutionIssue::ServerSelectionMissing;
case LiteWalletServerSelectionUiExecutionIssue::ServerPersistenceOwnerMissing:
return LiteWalletLifecycleUiExecutionIssue::PersistedServerSelectionIntentMissing;
case LiteWalletServerSelectionUiExecutionIssue::SelectedServerDisplayMissing:
return LiteWalletLifecycleUiExecutionIssue::SelectedServerDisplayMissing;
case LiteWalletServerSelectionUiExecutionIssue::LifecycleUiOwnerMissing:
return LiteWalletLifecycleUiExecutionIssue::LifecycleUiOwnerMissing;
case LiteWalletServerSelectionUiExecutionIssue::PrivateDataRedactionMissing:
return LiteWalletLifecycleUiExecutionIssue::PrivateDataRedactionMissing;
case LiteWalletServerSelectionUiExecutionIssue::SyncPlannerFeedMissing:
return LiteWalletLifecycleUiExecutionIssue::SyncPlannerFeedMissing;
case LiteWalletServerSelectionUiExecutionIssue::SettingsSaveFailed:
return LiteWalletLifecycleUiExecutionIssue::SettingsNotLoaded;
case LiteWalletServerSelectionUiExecutionIssue::ServerConnectivityCheckRequested:
return LiteWalletLifecycleUiExecutionIssue::ServerConnectivityCheckRequested;
case LiteWalletServerSelectionUiExecutionIssue::WalletLifecycleExecutionRequested:
return LiteWalletLifecycleUiExecutionIssue::WalletLifecycleExecutionRequested;
case LiteWalletServerSelectionUiExecutionIssue::SyncRequested:
return LiteWalletLifecycleUiExecutionIssue::SyncRequested;
case LiteWalletServerSelectionUiExecutionIssue::SyncStatusPollingRequested:
return LiteWalletLifecycleUiExecutionIssue::SyncStatusPollingRequested;
case LiteWalletServerSelectionUiExecutionIssue::WorkerQueueRequested:
return LiteWalletLifecycleUiExecutionIssue::WorkerQueueRequested;
case LiteWalletServerSelectionUiExecutionIssue::WalletStateMutationRequested:
return LiteWalletLifecycleUiExecutionIssue::WalletStateMutationRequested;
case LiteWalletServerSelectionUiExecutionIssue::WalletFilePersistenceRequested:
return LiteWalletLifecycleUiExecutionIssue::WalletFilePersistenceRequested;
case LiteWalletServerSelectionUiExecutionIssue::SendImportExportRequested:
return LiteWalletLifecycleUiExecutionIssue::SendImportExportRequested;
}
return LiteWalletLifecycleUiExecutionIssue::SettingsNotLoaded;
}
void copyServerSelectionIssues(LiteWalletLifecycleUiExecutionResult& result)
{
for (const auto& issue : result.serverSelectionReport.issues) {
addIssue(result.issues, issueFromServerSelection(issue.issue), issue.message);
}
}
void copyLifecycleIssues(LiteWalletLifecycleUiExecutionResult& result)
{
for (const auto& issue : result.lifecycleReadiness.issues) {
addIssue(result.issues, issueFromLifecycle(issue.issue), issue.message);
}
}
LiteWalletServerSelectionUiExecutionInput makeServerSelectionInput(
const LiteWalletLifecycleUiExecutionInput& input,
const config::Settings& settings)
{
LiteWalletServerSelectionUiExecutionInput selection;
selection.capabilities = input.capabilities;
selection.persistence.settingsLoaded = input.settingsLoaded;
selection.persistence.havePersistedSelectionIntent =
!input.requirePersistedServerSelectionIntent || settings.getLitePersistSelectedServer();
selection.persistence.persistSelectedServer = false;
selection.persistence.persistenceOwnerReady = true;
selection.persistence.writeSettings = false;
selection.ui = input.ui;
selection.operation = input.request.operation;
selection.createRequest = input.request.createRequest;
selection.openRequest = input.request.openRequest;
selection.restoreRequest = input.request.restoreRequest;
selection.requireLifecycleReadiness = true;
return selection;
}
std::string buildDiagnosticSummary(const LiteWalletLifecycleUiExecutionResult& result)
{
std::ostringstream out;
out << "operation=" << liteWalletLifecycleOperationName(result.lifecycleInput.operation)
<< ";server=" << result.selectedServerUrlRedacted
<< ";request=" << result.requestSummaryRedacted
<< ";network=false;bridge=false;lifecycle=false;sync=false;wallet_state=false;wallet_file=false";
return out.str();
}
} // namespace
const char* liteWalletLifecycleUiExecutionStatusName(
LiteWalletLifecycleUiExecutionStatus status)
{
switch (status) {
case LiteWalletLifecycleUiExecutionStatus::ReadyForFutureLifecycleRequest:
return "ReadyForFutureLifecycleRequest";
case LiteWalletLifecycleUiExecutionStatus::WaitingForLiteBuild:
return "WaitingForLiteBuild";
case LiteWalletLifecycleUiExecutionStatus::WaitingForBackendCapability:
return "WaitingForBackendCapability";
case LiteWalletLifecycleUiExecutionStatus::WaitingForSettings:
return "WaitingForSettings";
case LiteWalletLifecycleUiExecutionStatus::WaitingForPersistedServerSelection:
return "WaitingForPersistedServerSelection";
case LiteWalletLifecycleUiExecutionStatus::WaitingForServerSelection:
return "WaitingForServerSelection";
case LiteWalletLifecycleUiExecutionStatus::WaitingForDisplayStatus:
return "WaitingForDisplayStatus";
case LiteWalletLifecycleUiExecutionStatus::WaitingForLifecycleUi:
return "WaitingForLifecycleUi";
case LiteWalletLifecycleUiExecutionStatus::WaitingForRequest:
return "WaitingForRequest";
case LiteWalletLifecycleUiExecutionStatus::WaitingForPrivateDataRedaction:
return "WaitingForPrivateDataRedaction";
case LiteWalletLifecycleUiExecutionStatus::WaitingForSyncPlannerFeed:
return "WaitingForSyncPlannerFeed";
case LiteWalletLifecycleUiExecutionStatus::RuntimeExecutionDisabled:
return "RuntimeExecutionDisabled";
}
return "WaitingForSettings";
}
const char* liteWalletLifecycleUiExecutionIssueName(
LiteWalletLifecycleUiExecutionIssue issue)
{
switch (issue) {
case LiteWalletLifecycleUiExecutionIssue::FullNodeBuild:
return "FullNodeBuild";
case LiteWalletLifecycleUiExecutionIssue::LiteBackendCapabilityMissing:
return "LiteBackendCapabilityMissing";
case LiteWalletLifecycleUiExecutionIssue::SettingsNotLoaded:
return "SettingsNotLoaded";
case LiteWalletLifecycleUiExecutionIssue::PersistedServerSelectionIntentMissing:
return "PersistedServerSelectionIntentMissing";
case LiteWalletLifecycleUiExecutionIssue::ServerSelectionMissing:
return "ServerSelectionMissing";
case LiteWalletLifecycleUiExecutionIssue::SelectedServerDisplayMissing:
return "SelectedServerDisplayMissing";
case LiteWalletLifecycleUiExecutionIssue::LifecycleUiOwnerMissing:
return "LifecycleUiOwnerMissing";
case LiteWalletLifecycleUiExecutionIssue::LifecycleOperationUnconfirmed:
return "LifecycleOperationUnconfirmed";
case LiteWalletLifecycleUiExecutionIssue::OpenWalletPathMissing:
return "OpenWalletPathMissing";
case LiteWalletLifecycleUiExecutionIssue::RestoreSeedMissing:
return "RestoreSeedMissing";
case LiteWalletLifecycleUiExecutionIssue::PrivateDataRedactionMissing:
return "PrivateDataRedactionMissing";
case LiteWalletLifecycleUiExecutionIssue::SyncPlannerFeedMissing:
return "SyncPlannerFeedMissing";
case LiteWalletLifecycleUiExecutionIssue::ServerConnectivityCheckRequested:
return "ServerConnectivityCheckRequested";
case LiteWalletLifecycleUiExecutionIssue::WalletExistsCheckRequested:
return "WalletExistsCheckRequested";
case LiteWalletLifecycleUiExecutionIssue::WalletLifecycleExecutionRequested:
return "WalletLifecycleExecutionRequested";
case LiteWalletLifecycleUiExecutionIssue::SyncRequested:
return "SyncRequested";
case LiteWalletLifecycleUiExecutionIssue::SyncStatusPollingRequested:
return "SyncStatusPollingRequested";
case LiteWalletLifecycleUiExecutionIssue::WorkerQueueRequested:
return "WorkerQueueRequested";
case LiteWalletLifecycleUiExecutionIssue::WalletStateMutationRequested:
return "WalletStateMutationRequested";
case LiteWalletLifecycleUiExecutionIssue::WalletFilePersistenceRequested:
return "WalletFilePersistenceRequested";
case LiteWalletLifecycleUiExecutionIssue::SendImportExportRequested:
return "SendImportExportRequested";
case LiteWalletLifecycleUiExecutionIssue::SettingsWriteRequested:
return "SettingsWriteRequested";
}
return "SettingsNotLoaded";
}
LiteWalletLifecycleUiExecutionResult executeLiteWalletLifecycleUiRequest(
config::Settings& settings,
const LiteWalletLifecycleUiExecutionInput& input)
{
LiteWalletLifecycleUiExecutionResult result;
auto stopForRuntime = [&](LiteWalletLifecycleUiExecutionIssue issue,
const std::string& message) {
return stoppedResult(std::move(result),
LiteWalletLifecycleUiExecutionStatus::RuntimeExecutionDisabled,
issue,
message);
};
if (input.settingsWriteRequested) {
return stopForRuntime(LiteWalletLifecycleUiExecutionIssue::SettingsWriteRequested,
"lite lifecycle request adapter cannot write settings");
}
if (input.serverConnectivityCheckRequested) {
return stopForRuntime(LiteWalletLifecycleUiExecutionIssue::ServerConnectivityCheckRequested,
"lite lifecycle request adapter cannot check server connectivity");
}
if (input.walletExistsCheckRequested) {
return stopForRuntime(LiteWalletLifecycleUiExecutionIssue::WalletExistsCheckRequested,
"lite lifecycle request adapter cannot check wallet existence");
}
if (input.walletLifecycleExecutionRequested || input.ui.realLifecycleExecutionRequested) {
return stopForRuntime(LiteWalletLifecycleUiExecutionIssue::WalletLifecycleExecutionRequested,
"lite lifecycle request adapter cannot execute wallet lifecycle actions");
}
if (input.syncStartRequested) {
return stopForRuntime(LiteWalletLifecycleUiExecutionIssue::SyncRequested,
"lite lifecycle request adapter cannot start sync");
}
if (input.syncStatusPollingRequested) {
return stopForRuntime(LiteWalletLifecycleUiExecutionIssue::SyncStatusPollingRequested,
"lite lifecycle request adapter cannot poll syncstatus");
}
if (input.workerQueueEnqueueRequested) {
return stopForRuntime(LiteWalletLifecycleUiExecutionIssue::WorkerQueueRequested,
"lite lifecycle request adapter cannot enqueue wallet workers");
}
if (input.walletStateMutationRequested) {
return stopForRuntime(LiteWalletLifecycleUiExecutionIssue::WalletStateMutationRequested,
"lite lifecycle request adapter cannot mutate WalletState");
}
if (input.walletFilePersistenceRequested) {
return stopForRuntime(LiteWalletLifecycleUiExecutionIssue::WalletFilePersistenceRequested,
"lite lifecycle request adapter cannot persist wallet files");
}
if (input.sendImportExportExecutionRequested) {
return stopForRuntime(LiteWalletLifecycleUiExecutionIssue::SendImportExportRequested,
"lite lifecycle request adapter cannot execute send/import/export flows");
}
if (!input.settingsLoaded) {
return stoppedResult(std::move(result),
LiteWalletLifecycleUiExecutionStatus::WaitingForSettings,
LiteWalletLifecycleUiExecutionIssue::SettingsNotLoaded,
"lite lifecycle settings are not loaded");
}
if (!input.request.requestProvided) {
return stoppedResult(std::move(result),
LiteWalletLifecycleUiExecutionStatus::WaitingForRequest,
LiteWalletLifecycleUiExecutionIssue::LifecycleUiOwnerMissing,
"lite lifecycle request intent is missing");
}
if (input.requirePersistedServerSelectionIntent && !settings.getLitePersistSelectedServer()) {
return stoppedResult(std::move(result),
LiteWalletLifecycleUiExecutionStatus::WaitingForPersistedServerSelection,
LiteWalletLifecycleUiExecutionIssue::PersistedServerSelectionIntentMissing,
"lite lifecycle requires persisted selected-server intent");
}
result.connectionSettings = liteConnectionSettingsFromAppSettings(settings);
result.selectedServerSettingsLoaded = true;
LiteWalletServerSelectionUiExecutionInput selectionInput = makeServerSelectionInput(input, settings);
result.serverSelectionReport = executeLiteWalletServerSelectionUi(settings, selectionInput);
result.connectionSettings = result.serverSelectionReport.connectionSettings;
result.selectedServer = result.serverSelectionReport.selectedServer;
result.selectedServerUrlRedacted = result.serverSelectionReport.selectedServerUrlRedacted;
result.selectedServerIntentAccepted = result.serverSelectionReport.selectedServerIntentAccepted;
result.status = statusFromServerSelection(result.serverSelectionReport.status);
result.lifecycleInput = result.serverSelectionReport.lifecycleInput;
result.lifecycleReadiness = result.serverSelectionReport.lifecycleReadiness;
result.lifecycleReadinessAccepted = result.lifecycleReadiness.ok;
result.lifecycleReportCouldFeedSyncPlanners =
result.lifecycleReadiness.lifecycleReportCouldFeedSyncPlanners;
result.requestAccepted = result.lifecycleReadiness.requestAccepted;
result.privateDataRedacted = result.lifecycleReadiness.requestPlan.privateInputsRedacted;
result.privateData = result.lifecycleReadiness.requestPlan.privateData;
result.requestSummaryRedacted = result.lifecycleReadiness.requestPlan.requestSummary;
result.diagnosticSummary = buildDiagnosticSummary(result);
copyServerSelectionIssues(result);
copyLifecycleIssues(result);
const bool lifecycleReadinessEvaluated = result.lifecycleReadiness.ok ||
!result.lifecycleReadiness.issues.empty() ||
!result.lifecycleReadiness.error.empty() ||
result.lifecycleReadiness.serverSelectionAccepted ||
result.lifecycleReadiness.requestAccepted;
if (!result.serverSelectionReport.ok && !lifecycleReadinessEvaluated) {
result.ok = false;
result.status = statusFromServerSelection(result.serverSelectionReport.status);
result.error = result.serverSelectionReport.error;
return result;
}
if (!result.lifecycleReadiness.ok) {
result.ok = false;
result.status = statusFromLifecycle(result.lifecycleReadiness.status);
result.error = result.lifecycleReadiness.error.empty()
? result.serverSelectionReport.error
: result.lifecycleReadiness.error;
return result;
}
result.ok = true;
result.status = LiteWalletLifecycleUiExecutionStatus::ReadyForFutureLifecycleRequest;
return result;
}
} // namespace wallet
} // namespace dragonx
// The lite-wallet lifecycle UI adapter is now header-only: it declares the live
// LiteWalletLifecycleUiExecutionInput DTO (and its request-intent / prerequisites
// sub-structs) that Settings drives the App-owned controller with. The former
// dry-run "readiness" executor and its status/issue reporting were removed as dead
// scaffolding, leaving no out-of-line definitions in this translation unit.

View File

@@ -1,53 +1,21 @@
#pragma once
#include "lite_wallet_server_selection_adapter.h"
#include "lite_wallet_lifecycle_service.h"
#include "wallet_capabilities.h"
#include "../config/settings.h"
#include <string>
#include <vector>
namespace dragonx {
namespace wallet {
enum class LiteWalletLifecycleUiExecutionStatus {
ReadyForFutureLifecycleRequest,
WaitingForLiteBuild,
WaitingForBackendCapability,
WaitingForSettings,
WaitingForPersistedServerSelection,
WaitingForServerSelection,
WaitingForDisplayStatus,
WaitingForLifecycleUi,
WaitingForRequest,
WaitingForPrivateDataRedaction,
WaitingForSyncPlannerFeed,
RuntimeExecutionDisabled
};
enum class LiteWalletLifecycleUiExecutionIssue {
FullNodeBuild,
LiteBackendCapabilityMissing,
SettingsNotLoaded,
PersistedServerSelectionIntentMissing,
ServerSelectionMissing,
SelectedServerDisplayMissing,
LifecycleUiOwnerMissing,
LifecycleOperationUnconfirmed,
OpenWalletPathMissing,
RestoreSeedMissing,
PrivateDataRedactionMissing,
SyncPlannerFeedMissing,
ServerConnectivityCheckRequested,
WalletExistsCheckRequested,
WalletLifecycleExecutionRequested,
SyncRequested,
SyncStatusPollingRequested,
WorkerQueueRequested,
WalletStateMutationRequested,
WalletFilePersistenceRequested,
SendImportExportRequested,
SettingsWriteRequested
struct LiteWalletLifecycleUiPrerequisites {
bool selectedServerDisplayReady = false;
bool lifecycleUiOwnerReady = false;
bool operationConfirmed = false;
bool privateDataRedactionReady = false;
bool syncPlannerFeedReady = false;
bool realLifecycleExecutionRequested = false;
};
struct LiteWalletLifecycleUiRequestIntent {
@@ -77,59 +45,5 @@ struct LiteWalletLifecycleUiExecutionInput {
bool sendImportExportExecutionRequested = false;
};
struct LiteWalletLifecycleUiExecutionIssueInfo {
LiteWalletLifecycleUiExecutionIssue issue = LiteWalletLifecycleUiExecutionIssue::SettingsNotLoaded;
std::string message;
};
struct LiteWalletLifecycleUiExecutionResult {
bool ok = false;
bool dryRunOnly = true;
bool noNetwork = true;
bool noBridgeCalls = true;
bool noServerHealthChecked = true;
bool noWalletExistsChecked = true;
bool noWalletCreated = true;
bool noWalletOpened = true;
bool noWalletRestored = true;
bool noSyncStarted = true;
bool noSyncStatusPolled = true;
bool noWalletPersistence = true;
bool noSettingsPersistence = true;
bool noSendImportExportExecution = true;
bool settingsWritten = false;
bool workerQueueEnqueued = false;
bool stateMutationAllowed = false;
bool stateMutated = false;
bool walletStateWritten = false;
bool selectedServerSettingsLoaded = false;
bool selectedServerIntentAccepted = false;
bool lifecycleReadinessAccepted = false;
bool requestAccepted = false;
bool privateDataRedacted = false;
bool lifecycleReportCouldFeedSyncPlanners = false;
LiteWalletLifecycleUiExecutionStatus status = LiteWalletLifecycleUiExecutionStatus::WaitingForSettings;
std::string error;
std::string selectedServerUrlRedacted;
std::string requestSummaryRedacted;
std::string diagnosticSummary;
LiteConnectionSettings connectionSettings;
LiteServerSelectionResult selectedServer;
LiteWalletServerSelectionUiExecutionResult serverSelectionReport;
LiteWalletServerLifecycleReadinessInput lifecycleInput;
LiteWalletServerLifecycleReadinessResult lifecycleReadiness;
std::vector<LiteRedactedPrivateData> privateData;
std::vector<LiteWalletLifecycleUiExecutionIssueInfo> issues;
};
const char* liteWalletLifecycleUiExecutionStatusName(
LiteWalletLifecycleUiExecutionStatus status);
const char* liteWalletLifecycleUiExecutionIssueName(
LiteWalletLifecycleUiExecutionIssue issue);
LiteWalletLifecycleUiExecutionResult executeLiteWalletLifecycleUiRequest(
config::Settings& settings,
const LiteWalletLifecycleUiExecutionInput& input);
} // namespace wallet
} // namespace dragonx
} // namespace dragonx

View File

@@ -1,386 +0,0 @@
#include "wallet/lite_wallet_server_lifecycle_readiness.h"
#include <cctype>
#include <utility>
namespace dragonx::wallet {
namespace {
std::string trimCopy(const std::string& value)
{
auto begin = value.begin();
while (begin != value.end() && std::isspace(static_cast<unsigned char>(*begin))) ++begin;
auto end = value.end();
while (end != begin && std::isspace(static_cast<unsigned char>(*(end - 1)))) --end;
return std::string(begin, end);
}
void addIssue(LiteWalletServerLifecycleReadinessResult& result,
LiteWalletServerLifecycleReadinessIssue issue,
std::string message)
{
result.issues.push_back(LiteWalletServerLifecycleReadinessIssueInfo{issue, std::move(message)});
}
LiteWalletServerLifecycleReadinessResult stoppedResult(
LiteWalletServerLifecycleReadinessResult result,
LiteWalletServerLifecycleReadinessStatus status,
LiteWalletServerLifecycleReadinessIssue issue,
std::string message)
{
result.status = status;
addIssue(result, issue, std::move(message));
result.error = result.issues.back().message;
result.lifecycleStatus = WalletBackendStatus{WalletBackendState::Unavailable, result.error, {}, {}, 0.0};
return result;
}
LiteRedactedPrivateData redactedPrivateField(LitePrivateDataKind kind, const std::string& value)
{
return LiteRedactedPrivateData{kind, !trimCopy(value).empty(), redactLitePrivateDataValue(value)};
}
bool privateDataIsRedacted(const std::vector<LiteRedactedPrivateData>& privateData)
{
for (const auto& item : privateData) {
if (!item.present && item.redactedValue != "<empty>") return false;
if (item.present && item.redactedValue != "<redacted>") return false;
}
return true;
}
LiteWalletSelectedServerDisplayReport displayReportForSelection(
const LiteServerSelectionResult& selection)
{
LiteWalletSelectedServerDisplayReport report;
if (!selection.ok) {
report.status = LiteWalletSelectedServerDisplayStatus::Missing;
report.message = selection.error.empty() ? "no usable lite server is selected" : selection.error;
return report;
}
report.ok = true;
report.status = selection.customServer
? LiteWalletSelectedServerDisplayStatus::CustomServer
: LiteWalletSelectedServerDisplayStatus::SelectedServer;
report.label = selection.server.label;
report.url = selection.server.url;
report.serverIndex = selection.serverIndex;
report.customServer = selection.customServer;
report.message = selection.customServer
? "custom lite server selected for display"
: "configured lite server selected for display";
return report;
}
LiteWalletLifecyclePlan lifecyclePlanForRequest(
LiteWalletLifecycleOperation operation,
const LiteServerSelectionResult& selection)
{
LiteWalletLifecyclePlan plan;
plan.operation = operation;
plan.bridgeExecutionAllowed = false;
if (!selection.ok) {
plan.error = selection.error.empty() ? "no usable lite server is selected" : selection.error;
return plan;
}
plan.ok = true;
plan.server = selection.server;
plan.serverIndex = selection.serverIndex;
plan.customServer = selection.customServer;
return plan;
}
LiteWalletLifecycleUiRequestPlan requestPlanForInput(
const LiteWalletServerLifecycleReadinessInput& input,
const LiteServerSelectionResult& selection)
{
LiteWalletLifecycleUiRequestPlan plan;
plan.operation = input.operation;
plan.lifecyclePlan = lifecyclePlanForRequest(input.operation, selection);
if (!plan.lifecyclePlan.ok) {
plan.error = plan.lifecyclePlan.error;
return plan;
}
switch (input.operation) {
case LiteWalletLifecycleOperation::CreateNew:
plan.privateData.push_back(redactedPrivateField(
LitePrivateDataKind::Passphrase,
input.createRequest.passphrase));
plan.requestSummary = "operation=create;server=<selected>;passphrase=" +
std::string(input.createRequest.passphrase.empty() ? "<empty>" : "<redacted>");
break;
case LiteWalletLifecycleOperation::OpenExisting:
if (trimCopy(input.openRequest.walletPath).empty()) {
plan.error = "lite wallet open requires a wallet path selected by the UI";
return plan;
}
plan.privateData.push_back(redactedPrivateField(
LitePrivateDataKind::WalletPath,
input.openRequest.walletPath));
plan.privateData.push_back(redactedPrivateField(
LitePrivateDataKind::Passphrase,
input.openRequest.passphrase));
plan.requestSummary = "operation=open;server=<selected>;wallet_path=<redacted>;passphrase=" +
std::string(input.openRequest.passphrase.empty() ? "<empty>" : "<redacted>");
break;
case LiteWalletLifecycleOperation::RestoreFromSeed:
if (trimCopy(input.restoreRequest.seedPhrase).empty()) {
plan.error = "lite wallet restore requires redacted seed material metadata";
return plan;
}
plan.privateData.push_back(redactedPrivateField(
LitePrivateDataKind::SeedPhrase,
input.restoreRequest.seedPhrase));
plan.privateData.push_back(redactedPrivateField(
LitePrivateDataKind::WalletPath,
input.restoreRequest.walletPath));
plan.privateData.push_back(redactedPrivateField(
LitePrivateDataKind::Passphrase,
input.restoreRequest.passphrase));
plan.requestSummary = "operation=restore;server=<selected>;seed=<redacted>;wallet_path=" +
std::string(input.restoreRequest.walletPath.empty() ? "<empty>" : "<redacted>") +
";passphrase=" +
std::string(input.restoreRequest.passphrase.empty() ? "<empty>" : "<redacted>");
break;
}
plan.privateInputsRedacted = privateDataIsRedacted(plan.privateData);
plan.lifecyclePlan.privateData = plan.privateData;
plan.ok = plan.privateInputsRedacted;
if (!plan.ok) plan.error = "lite wallet lifecycle private inputs are not redacted";
return plan;
}
LiteWalletServerSelectionPersistencePlan persistencePlanForInput(
const LiteWalletServerLifecycleReadinessInput& input,
const LiteServerSelectionResult& selection)
{
LiteWalletServerSelectionPersistencePlan plan;
plan.settingsLoaded = input.persistence.settingsLoaded;
plan.persistedSelectionIntentAccepted = input.persistence.havePersistedSelectionIntent;
plan.wouldPersistSelectedServer = input.persistence.persistSelectedServer;
plan.persistenceOwnerAccepted = input.persistence.persistenceOwnerReady;
plan.selectionMode = input.settings.selectionMode;
if (selection.ok) {
plan.selectedServerUrl = selection.server.url;
plan.selectedServerIndex = selection.serverIndex;
plan.selectedServerCustom = selection.customServer;
}
plan.settingsWritten = false;
plan.ok = true;
return plan;
}
WalletBackendStatus readyLifecycleStatus(const LiteWalletSelectedServerDisplayReport& display)
{
const std::string serverLabel = display.label.empty() ? display.url : display.label;
return WalletBackendStatus{
WalletBackendState::Disconnected,
"lite lifecycle UI readiness accepted for " + serverLabel + "; wallet lifecycle execution is still disabled",
{},
{},
0.0
};
}
} // namespace
const char* liteWalletServerLifecycleReadinessStatusName(
LiteWalletServerLifecycleReadinessStatus status)
{
switch (status) {
case LiteWalletServerLifecycleReadinessStatus::ReadyForFutureLifecycle: return "ReadyForFutureLifecycle";
case LiteWalletServerLifecycleReadinessStatus::WaitingForLiteBuild: return "WaitingForLiteBuild";
case LiteWalletServerLifecycleReadinessStatus::WaitingForBackendCapability: return "WaitingForBackendCapability";
case LiteWalletServerLifecycleReadinessStatus::WaitingForServerSelection: return "WaitingForServerSelection";
case LiteWalletServerLifecycleReadinessStatus::WaitingForPersistenceIntent: return "WaitingForPersistenceIntent";
case LiteWalletServerLifecycleReadinessStatus::WaitingForDisplayStatus: return "WaitingForDisplayStatus";
case LiteWalletServerLifecycleReadinessStatus::WaitingForLifecycleUi: return "WaitingForLifecycleUi";
case LiteWalletServerLifecycleReadinessStatus::WaitingForPrivateDataRedaction: return "WaitingForPrivateDataRedaction";
case LiteWalletServerLifecycleReadinessStatus::WaitingForSyncPlannerFeed: return "WaitingForSyncPlannerFeed";
case LiteWalletServerLifecycleReadinessStatus::RuntimeExecutionDisabled: return "RuntimeExecutionDisabled";
}
return "Unknown";
}
const char* liteWalletServerLifecycleReadinessIssueName(
LiteWalletServerLifecycleReadinessIssue issue)
{
switch (issue) {
case LiteWalletServerLifecycleReadinessIssue::FullNodeBuild: return "FullNodeBuild";
case LiteWalletServerLifecycleReadinessIssue::LiteBackendCapabilityMissing: return "LiteBackendCapabilityMissing";
case LiteWalletServerLifecycleReadinessIssue::PersistedSettingsNotLoaded: return "PersistedSettingsNotLoaded";
case LiteWalletServerLifecycleReadinessIssue::PersistedServerSelectionIntentMissing: return "PersistedServerSelectionIntentMissing";
case LiteWalletServerLifecycleReadinessIssue::ServerSelectionMissing: return "ServerSelectionMissing";
case LiteWalletServerLifecycleReadinessIssue::ServerPersistenceOwnerMissing: return "ServerPersistenceOwnerMissing";
case LiteWalletServerLifecycleReadinessIssue::SelectedServerDisplayMissing: return "SelectedServerDisplayMissing";
case LiteWalletServerLifecycleReadinessIssue::LifecycleUiOwnerMissing: return "LifecycleUiOwnerMissing";
case LiteWalletServerLifecycleReadinessIssue::LifecycleOperationUnconfirmed: return "LifecycleOperationUnconfirmed";
case LiteWalletServerLifecycleReadinessIssue::OpenWalletPathMissing: return "OpenWalletPathMissing";
case LiteWalletServerLifecycleReadinessIssue::RestoreSeedMissing: return "RestoreSeedMissing";
case LiteWalletServerLifecycleReadinessIssue::PrivateDataRedactionMissing: return "PrivateDataRedactionMissing";
case LiteWalletServerLifecycleReadinessIssue::SyncPlannerFeedMissing: return "SyncPlannerFeedMissing";
case LiteWalletServerLifecycleReadinessIssue::RealLifecycleExecutionRequested: return "RealLifecycleExecutionRequested";
}
return "Unknown";
}
const char* liteWalletSelectedServerDisplayStatusName(
LiteWalletSelectedServerDisplayStatus status)
{
switch (status) {
case LiteWalletSelectedServerDisplayStatus::Hidden: return "Hidden";
case LiteWalletSelectedServerDisplayStatus::SelectedServer: return "SelectedServer";
case LiteWalletSelectedServerDisplayStatus::CustomServer: return "CustomServer";
case LiteWalletSelectedServerDisplayStatus::Missing: return "Missing";
}
return "Unknown";
}
LiteWalletServerLifecycleReadinessResult evaluateLiteWalletServerLifecycleReadiness(
const LiteWalletServerLifecycleReadinessInput& input,
LiteWalletServerLifecycleReadinessOptions options)
{
LiteWalletServerLifecycleReadinessResult result;
result.capabilities = input.capabilities;
result.persistencePlan = persistencePlanForInput(input, {});
if (options.requireLiteBuild && !isLiteBuild(input.capabilities)) {
return stoppedResult(
std::move(result),
LiteWalletServerLifecycleReadinessStatus::WaitingForLiteBuild,
LiteWalletServerLifecycleReadinessIssue::FullNodeBuild,
"lite server lifecycle readiness requires a lite build");
}
result.liteBuildAccepted = true;
if (options.requireLiteBackendCapability && !supportsLiteBackend(input.capabilities)) {
return stoppedResult(
std::move(result),
LiteWalletServerLifecycleReadinessStatus::WaitingForBackendCapability,
LiteWalletServerLifecycleReadinessIssue::LiteBackendCapabilityMissing,
"lite backend capability is required before lifecycle UI readiness can feed sync planners");
}
result.backendCapabilityAccepted = true;
if (options.requirePersistedSettingsLoaded && !input.persistence.settingsLoaded) {
return stoppedResult(
std::move(result),
LiteWalletServerLifecycleReadinessStatus::WaitingForPersistenceIntent,
LiteWalletServerLifecycleReadinessIssue::PersistedSettingsNotLoaded,
"lite server settings must be loaded before lifecycle UI readiness is evaluated");
}
if (options.requirePersistedSelectionIntent && !input.persistence.havePersistedSelectionIntent) {
return stoppedResult(
std::move(result),
LiteWalletServerLifecycleReadinessStatus::WaitingForPersistenceIntent,
LiteWalletServerLifecycleReadinessIssue::PersistedServerSelectionIntentMissing,
"lite server selection persistence intent is missing");
}
result.selectedServer = selectLiteServer(input.settings);
result.persistencePlan = persistencePlanForInput(input, result.selectedServer);
if (!result.selectedServer.ok) {
return stoppedResult(
std::move(result),
LiteWalletServerLifecycleReadinessStatus::WaitingForServerSelection,
LiteWalletServerLifecycleReadinessIssue::ServerSelectionMissing,
result.selectedServer.error.empty()
? "no usable lite server is selected"
: result.selectedServer.error);
}
result.serverSelectionAccepted = true;
if (input.persistence.persistSelectedServer && !input.persistence.persistenceOwnerReady) {
return stoppedResult(
std::move(result),
LiteWalletServerLifecycleReadinessStatus::WaitingForPersistenceIntent,
LiteWalletServerLifecycleReadinessIssue::ServerPersistenceOwnerMissing,
"lite server selection persistence owner is not ready");
}
result.persistenceIntentAccepted = true;
result.persistencePlan.ok = true;
result.selectedServerDisplay = displayReportForSelection(result.selectedServer);
if (options.requireSelectedServerDisplay && !input.ui.selectedServerDisplayReady) {
return stoppedResult(
std::move(result),
LiteWalletServerLifecycleReadinessStatus::WaitingForDisplayStatus,
LiteWalletServerLifecycleReadinessIssue::SelectedServerDisplayMissing,
"selected lite server display status is not ready");
}
result.selectedServerDisplayAccepted = true;
if (options.requireLifecycleUiOwner && !input.ui.lifecycleUiOwnerReady) {
return stoppedResult(
std::move(result),
LiteWalletServerLifecycleReadinessStatus::WaitingForLifecycleUi,
LiteWalletServerLifecycleReadinessIssue::LifecycleUiOwnerMissing,
"lite wallet lifecycle UI owner is not ready");
}
result.lifecycleUiOwnerAccepted = true;
if (input.ui.realLifecycleExecutionRequested) {
return stoppedResult(
std::move(result),
LiteWalletServerLifecycleReadinessStatus::RuntimeExecutionDisabled,
LiteWalletServerLifecycleReadinessIssue::RealLifecycleExecutionRequested,
"real lite wallet lifecycle execution is disabled in this scaffold");
}
if (options.requireOperationConfirmation && !input.ui.operationConfirmed) {
return stoppedResult(
std::move(result),
LiteWalletServerLifecycleReadinessStatus::WaitingForLifecycleUi,
LiteWalletServerLifecycleReadinessIssue::LifecycleOperationUnconfirmed,
"lite wallet lifecycle operation requires explicit UI confirmation");
}
result.requestPlan = requestPlanForInput(input, result.selectedServer);
if (!result.requestPlan.ok) {
const auto issue = input.operation == LiteWalletLifecycleOperation::OpenExisting
? LiteWalletServerLifecycleReadinessIssue::OpenWalletPathMissing
: LiteWalletServerLifecycleReadinessIssue::RestoreSeedMissing;
return stoppedResult(
std::move(result),
LiteWalletServerLifecycleReadinessStatus::WaitingForLifecycleUi,
issue,
result.requestPlan.error.empty()
? "lite wallet lifecycle UI request is incomplete"
: result.requestPlan.error);
}
result.requestAccepted = true;
if (options.requirePrivateDataRedaction && !input.ui.privateDataRedactionReady) {
return stoppedResult(
std::move(result),
LiteWalletServerLifecycleReadinessStatus::WaitingForPrivateDataRedaction,
LiteWalletServerLifecycleReadinessIssue::PrivateDataRedactionMissing,
"lite wallet lifecycle private-data redaction owner is not ready");
}
result.privateDataRedactionAccepted = true;
if (options.requireSyncPlannerFeed && !input.ui.syncPlannerFeedReady) {
return stoppedResult(
std::move(result),
LiteWalletServerLifecycleReadinessStatus::WaitingForSyncPlannerFeed,
LiteWalletServerLifecycleReadinessIssue::SyncPlannerFeedMissing,
"lite lifecycle readiness feed for sync planners is not ready");
}
result.syncPlannerFeedAccepted = true;
result.ok = true;
result.status = LiteWalletServerLifecycleReadinessStatus::ReadyForFutureLifecycle;
result.futureLifecycleCouldBeEnabled = true;
result.lifecycleReportCouldFeedSyncPlanners = true;
result.lifecycleStatus = readyLifecycleStatus(result.selectedServerDisplay);
return result;
}
} // namespace dragonx::wallet

View File

@@ -1,181 +0,0 @@
#pragma once
#include "lite_wallet_lifecycle_service.h"
#include <cstddef>
#include <string>
#include <vector>
namespace dragonx::wallet {
enum class LiteWalletServerLifecycleReadinessStatus {
ReadyForFutureLifecycle,
WaitingForLiteBuild,
WaitingForBackendCapability,
WaitingForServerSelection,
WaitingForPersistenceIntent,
WaitingForDisplayStatus,
WaitingForLifecycleUi,
WaitingForPrivateDataRedaction,
WaitingForSyncPlannerFeed,
RuntimeExecutionDisabled,
};
enum class LiteWalletServerLifecycleReadinessIssue {
FullNodeBuild,
LiteBackendCapabilityMissing,
PersistedSettingsNotLoaded,
PersistedServerSelectionIntentMissing,
ServerSelectionMissing,
ServerPersistenceOwnerMissing,
SelectedServerDisplayMissing,
LifecycleUiOwnerMissing,
LifecycleOperationUnconfirmed,
OpenWalletPathMissing,
RestoreSeedMissing,
PrivateDataRedactionMissing,
SyncPlannerFeedMissing,
RealLifecycleExecutionRequested,
};
enum class LiteWalletSelectedServerDisplayStatus {
Hidden,
SelectedServer,
CustomServer,
Missing,
};
struct LiteWalletServerSelectionPersistenceInput {
bool settingsLoaded = false;
bool havePersistedSelectionIntent = false;
bool persistSelectedServer = false;
bool persistenceOwnerReady = false;
};
struct LiteWalletLifecycleUiPrerequisites {
bool selectedServerDisplayReady = false;
bool lifecycleUiOwnerReady = false;
bool operationConfirmed = false;
bool privateDataRedactionReady = false;
bool syncPlannerFeedReady = false;
bool realLifecycleExecutionRequested = false;
};
struct LiteWalletServerLifecycleReadinessInput {
WalletCapabilities capabilities;
LiteConnectionSettings settings;
LiteWalletLifecycleOperation operation = LiteWalletLifecycleOperation::CreateNew;
LiteWalletServerSelectionPersistenceInput persistence;
LiteWalletLifecycleUiPrerequisites ui;
LiteWalletCreateRequest createRequest;
LiteWalletOpenRequest openRequest;
LiteWalletRestoreRequest restoreRequest;
};
struct LiteWalletServerLifecycleReadinessOptions {
bool requireLiteBuild = true;
bool requireLiteBackendCapability = true;
bool requirePersistedSettingsLoaded = true;
bool requirePersistedSelectionIntent = true;
bool requireSelectedServerDisplay = true;
bool requireLifecycleUiOwner = true;
bool requireOperationConfirmation = true;
bool requirePrivateDataRedaction = true;
bool requireSyncPlannerFeed = true;
};
struct LiteWalletSelectedServerDisplayReport {
bool ok = false;
LiteWalletSelectedServerDisplayStatus status = LiteWalletSelectedServerDisplayStatus::Hidden;
std::string label;
std::string url;
std::size_t serverIndex = 0;
bool customServer = false;
std::string message;
};
struct LiteWalletServerSelectionPersistencePlan {
bool ok = false;
bool settingsLoaded = false;
bool persistedSelectionIntentAccepted = false;
bool wouldPersistSelectedServer = false;
bool persistenceOwnerAccepted = false;
bool settingsWritten = false;
LiteServerSelectionMode selectionMode = LiteServerSelectionMode::Sticky;
std::string selectedServerUrl;
std::size_t selectedServerIndex = 0;
bool selectedServerCustom = false;
std::string error;
};
struct LiteWalletLifecycleUiRequestPlan {
bool ok = false;
LiteWalletLifecycleOperation operation = LiteWalletLifecycleOperation::CreateNew;
LiteWalletLifecyclePlan lifecyclePlan;
std::vector<LiteRedactedPrivateData> privateData;
bool privateInputsRedacted = true;
std::string requestSummary;
std::string error;
};
struct LiteWalletServerLifecycleReadinessIssueInfo {
LiteWalletServerLifecycleReadinessIssue issue = LiteWalletServerLifecycleReadinessIssue::FullNodeBuild;
std::string message;
};
struct LiteWalletServerLifecycleReadinessResult {
bool ok = false;
bool dryRunOnly = true;
bool noNetwork = true;
bool noBridgeCalls = true;
bool noServerHealthChecked = true;
bool noWalletExistsChecked = true;
bool noWalletCreated = true;
bool noWalletOpened = true;
bool noWalletRestored = true;
bool noSyncStarted = true;
bool noSyncStatusPolled = true;
bool noWalletPersistence = true;
bool noSettingsPersistence = true;
bool settingsWritten = false;
bool workerQueueEnqueued = false;
bool stateMutationAllowed = false;
bool stateMutated = false;
bool walletStateWritten = false;
bool walletReady = false;
bool liteBuildAccepted = false;
bool backendCapabilityAccepted = false;
bool serverSelectionAccepted = false;
bool persistenceIntentAccepted = false;
bool selectedServerDisplayAccepted = false;
bool lifecycleUiOwnerAccepted = false;
bool requestAccepted = false;
bool privateDataRedactionAccepted = false;
bool syncPlannerFeedAccepted = false;
bool futureLifecycleCouldBeEnabled = false;
bool lifecycleReportCouldFeedSyncPlanners = false;
LiteWalletServerLifecycleReadinessStatus status = LiteWalletServerLifecycleReadinessStatus::WaitingForLiteBuild;
WalletCapabilities capabilities;
LiteServerSelectionResult selectedServer;
LiteWalletSelectedServerDisplayReport selectedServerDisplay;
LiteWalletServerSelectionPersistencePlan persistencePlan;
LiteWalletLifecycleUiRequestPlan requestPlan;
WalletBackendStatus lifecycleStatus;
std::vector<LiteWalletServerLifecycleReadinessIssueInfo> issues;
std::string error;
};
const char* liteWalletServerLifecycleReadinessStatusName(
LiteWalletServerLifecycleReadinessStatus status);
const char* liteWalletServerLifecycleReadinessIssueName(
LiteWalletServerLifecycleReadinessIssue issue);
const char* liteWalletSelectedServerDisplayStatusName(
LiteWalletSelectedServerDisplayStatus status);
LiteWalletServerLifecycleReadinessResult evaluateLiteWalletServerLifecycleReadiness(
const LiteWalletServerLifecycleReadinessInput& input,
LiteWalletServerLifecycleReadinessOptions options = {});
} // namespace dragonx::wallet

View File

@@ -2,8 +2,6 @@
#include <algorithm>
#include <cctype>
#include <sstream>
#include <utility>
namespace dragonx {
namespace wallet {
@@ -46,146 +44,6 @@ config::Settings::LiteServerSelectionPreferenceMode settingsModeFromWallet(
return config::Settings::LiteServerSelectionPreferenceMode::Sticky;
}
void addIssue(std::vector<LiteWalletServerSelectionUiExecutionIssueInfo>& issues,
LiteWalletServerSelectionUiExecutionIssue issue,
std::string message)
{
issues.push_back(LiteWalletServerSelectionUiExecutionIssueInfo{issue, std::move(message)});
}
LiteWalletServerSelectionUiExecutionStatus statusFromLifecycle(
LiteWalletServerLifecycleReadinessStatus status)
{
switch (status) {
case LiteWalletServerLifecycleReadinessStatus::ReadyForFutureLifecycle:
return LiteWalletServerSelectionUiExecutionStatus::ReadyForFutureLifecycle;
case LiteWalletServerLifecycleReadinessStatus::WaitingForLiteBuild:
return LiteWalletServerSelectionUiExecutionStatus::WaitingForLiteBuild;
case LiteWalletServerLifecycleReadinessStatus::WaitingForBackendCapability:
return LiteWalletServerSelectionUiExecutionStatus::WaitingForBackendCapability;
case LiteWalletServerLifecycleReadinessStatus::WaitingForPersistenceIntent:
return LiteWalletServerSelectionUiExecutionStatus::WaitingForSettings;
case LiteWalletServerLifecycleReadinessStatus::WaitingForServerSelection:
return LiteWalletServerSelectionUiExecutionStatus::WaitingForServerSelection;
case LiteWalletServerLifecycleReadinessStatus::WaitingForDisplayStatus:
return LiteWalletServerSelectionUiExecutionStatus::WaitingForDisplayStatus;
case LiteWalletServerLifecycleReadinessStatus::WaitingForLifecycleUi:
return LiteWalletServerSelectionUiExecutionStatus::WaitingForLifecycleUi;
case LiteWalletServerLifecycleReadinessStatus::WaitingForPrivateDataRedaction:
return LiteWalletServerSelectionUiExecutionStatus::WaitingForPrivateDataRedaction;
case LiteWalletServerLifecycleReadinessStatus::WaitingForSyncPlannerFeed:
return LiteWalletServerSelectionUiExecutionStatus::WaitingForSyncPlannerFeed;
case LiteWalletServerLifecycleReadinessStatus::RuntimeExecutionDisabled:
return LiteWalletServerSelectionUiExecutionStatus::RuntimeExecutionDisabled;
}
return LiteWalletServerSelectionUiExecutionStatus::WaitingForSettings;
}
LiteWalletServerSelectionUiExecutionIssue issueFromLifecycle(
LiteWalletServerLifecycleReadinessIssue issue)
{
switch (issue) {
case LiteWalletServerLifecycleReadinessIssue::FullNodeBuild:
return LiteWalletServerSelectionUiExecutionIssue::FullNodeBuild;
case LiteWalletServerLifecycleReadinessIssue::LiteBackendCapabilityMissing:
return LiteWalletServerSelectionUiExecutionIssue::LiteBackendCapabilityMissing;
case LiteWalletServerLifecycleReadinessIssue::PersistedSettingsNotLoaded:
case LiteWalletServerLifecycleReadinessIssue::PersistedServerSelectionIntentMissing:
return LiteWalletServerSelectionUiExecutionIssue::SettingsNotLoaded;
case LiteWalletServerLifecycleReadinessIssue::ServerSelectionMissing:
return LiteWalletServerSelectionUiExecutionIssue::ServerSelectionMissing;
case LiteWalletServerLifecycleReadinessIssue::ServerPersistenceOwnerMissing:
return LiteWalletServerSelectionUiExecutionIssue::ServerPersistenceOwnerMissing;
case LiteWalletServerLifecycleReadinessIssue::SelectedServerDisplayMissing:
return LiteWalletServerSelectionUiExecutionIssue::SelectedServerDisplayMissing;
case LiteWalletServerLifecycleReadinessIssue::LifecycleUiOwnerMissing:
case LiteWalletServerLifecycleReadinessIssue::LifecycleOperationUnconfirmed:
case LiteWalletServerLifecycleReadinessIssue::OpenWalletPathMissing:
case LiteWalletServerLifecycleReadinessIssue::RestoreSeedMissing:
return LiteWalletServerSelectionUiExecutionIssue::LifecycleUiOwnerMissing;
case LiteWalletServerLifecycleReadinessIssue::PrivateDataRedactionMissing:
return LiteWalletServerSelectionUiExecutionIssue::PrivateDataRedactionMissing;
case LiteWalletServerLifecycleReadinessIssue::SyncPlannerFeedMissing:
return LiteWalletServerSelectionUiExecutionIssue::SyncPlannerFeedMissing;
case LiteWalletServerLifecycleReadinessIssue::RealLifecycleExecutionRequested:
return LiteWalletServerSelectionUiExecutionIssue::WalletLifecycleExecutionRequested;
}
return LiteWalletServerSelectionUiExecutionIssue::SettingsNotLoaded;
}
void copyLifecycleIssues(LiteWalletServerSelectionUiExecutionResult& result)
{
for (const auto& issue : result.lifecycleReadiness.issues) {
addIssue(result.issues, issueFromLifecycle(issue.issue), issue.message);
}
}
LiteWalletServerSelectionUiExecutionResult stoppedResult(
LiteWalletServerSelectionUiExecutionResult result,
LiteWalletServerSelectionUiExecutionStatus status,
LiteWalletServerSelectionUiExecutionIssue issue,
const std::string& message)
{
result.status = status;
result.error = message;
result.ok = false;
addIssue(result.issues, issue, message);
return result;
}
std::string buildDiagnosticSummary(const LiteWalletServerSelectionUiExecutionResult& result)
{
std::ostringstream out;
out << "mode=" << liteServerSelectionModeName(result.connectionSettings.selectionMode)
<< ";server=" << result.selectedServerUrlRedacted
<< ";settings_written=" << (result.settingsWritten ? "true" : "false")
<< ";network=false;bridge=false;lifecycle=false;sync=false;wallet_state=false";
return out.str();
}
LiteConnectionSettings settingsWithIntent(const LiteConnectionSettings& current,
const LiteWalletServerSelectionUiIntent& intent)
{
LiteConnectionSettings settings = current;
if (!intent.selectedServerIntentProvided) return settings;
settings.selectionMode = intent.selectionMode;
if (!intent.chainName.empty()) settings.chainName = trimCopy(intent.chainName);
if (intent.replaceServers) settings.servers = intent.servers;
switch (intent.selectionMode) {
case LiteServerSelectionMode::Sticky:
settings.stickyServerUrl = trimCopy(intent.selectedServerUrl);
break;
case LiteServerSelectionMode::Random:
settings.randomSelectionSeed = intent.randomSelectionSeed;
break;
}
return settings;
}
LiteWalletServerLifecycleReadinessInput makeLifecycleInput(
const LiteWalletServerSelectionUiExecutionInput& input,
const LiteConnectionSettings& connectionSettings)
{
LiteWalletServerLifecycleReadinessInput lifecycle;
lifecycle.capabilities = input.capabilities;
lifecycle.settings = connectionSettings;
lifecycle.operation = input.operation;
lifecycle.persistence.settingsLoaded = input.persistence.settingsLoaded;
lifecycle.persistence.havePersistedSelectionIntent =
input.persistence.havePersistedSelectionIntent || input.intent.selectedServerIntentProvided;
lifecycle.persistence.persistSelectedServer = input.persistence.persistSelectedServer;
lifecycle.persistence.persistenceOwnerReady = input.persistence.persistenceOwnerReady;
lifecycle.ui = input.ui;
lifecycle.ui.realLifecycleExecutionRequested =
lifecycle.ui.realLifecycleExecutionRequested || input.walletLifecycleExecutionRequested;
lifecycle.createRequest = input.createRequest;
lifecycle.openRequest = input.openRequest;
lifecycle.restoreRequest = input.restoreRequest;
return lifecycle;
}
} // namespace
LiteConnectionSettings liteConnectionSettingsFromAppSettings(const config::Settings& settings)
@@ -229,82 +87,6 @@ void applyLiteConnectionSettingsToAppSettings(config::Settings& settings,
settings.setLiteServers(servers);
}
const char* liteWalletServerSelectionUiExecutionStatusName(
LiteWalletServerSelectionUiExecutionStatus status)
{
switch (status) {
case LiteWalletServerSelectionUiExecutionStatus::ReadyForFutureLifecycle:
return "ReadyForFutureLifecycle";
case LiteWalletServerSelectionUiExecutionStatus::WaitingForLiteBuild:
return "WaitingForLiteBuild";
case LiteWalletServerSelectionUiExecutionStatus::WaitingForBackendCapability:
return "WaitingForBackendCapability";
case LiteWalletServerSelectionUiExecutionStatus::WaitingForSettings:
return "WaitingForSettings";
case LiteWalletServerSelectionUiExecutionStatus::WaitingForServerSelection:
return "WaitingForServerSelection";
case LiteWalletServerSelectionUiExecutionStatus::WaitingForPersistenceOwner:
return "WaitingForPersistenceOwner";
case LiteWalletServerSelectionUiExecutionStatus::WaitingForDisplayStatus:
return "WaitingForDisplayStatus";
case LiteWalletServerSelectionUiExecutionStatus::WaitingForLifecycleUi:
return "WaitingForLifecycleUi";
case LiteWalletServerSelectionUiExecutionStatus::WaitingForPrivateDataRedaction:
return "WaitingForPrivateDataRedaction";
case LiteWalletServerSelectionUiExecutionStatus::WaitingForSyncPlannerFeed:
return "WaitingForSyncPlannerFeed";
case LiteWalletServerSelectionUiExecutionStatus::SettingsSaveFailed:
return "SettingsSaveFailed";
case LiteWalletServerSelectionUiExecutionStatus::RuntimeExecutionDisabled:
return "RuntimeExecutionDisabled";
}
return "WaitingForSettings";
}
const char* liteWalletServerSelectionUiExecutionIssueName(
LiteWalletServerSelectionUiExecutionIssue issue)
{
switch (issue) {
case LiteWalletServerSelectionUiExecutionIssue::FullNodeBuild:
return "FullNodeBuild";
case LiteWalletServerSelectionUiExecutionIssue::LiteBackendCapabilityMissing:
return "LiteBackendCapabilityMissing";
case LiteWalletServerSelectionUiExecutionIssue::SettingsNotLoaded:
return "SettingsNotLoaded";
case LiteWalletServerSelectionUiExecutionIssue::ServerSelectionMissing:
return "ServerSelectionMissing";
case LiteWalletServerSelectionUiExecutionIssue::ServerPersistenceOwnerMissing:
return "ServerPersistenceOwnerMissing";
case LiteWalletServerSelectionUiExecutionIssue::SelectedServerDisplayMissing:
return "SelectedServerDisplayMissing";
case LiteWalletServerSelectionUiExecutionIssue::LifecycleUiOwnerMissing:
return "LifecycleUiOwnerMissing";
case LiteWalletServerSelectionUiExecutionIssue::PrivateDataRedactionMissing:
return "PrivateDataRedactionMissing";
case LiteWalletServerSelectionUiExecutionIssue::SyncPlannerFeedMissing:
return "SyncPlannerFeedMissing";
case LiteWalletServerSelectionUiExecutionIssue::SettingsSaveFailed:
return "SettingsSaveFailed";
case LiteWalletServerSelectionUiExecutionIssue::ServerConnectivityCheckRequested:
return "ServerConnectivityCheckRequested";
case LiteWalletServerSelectionUiExecutionIssue::WalletLifecycleExecutionRequested:
return "WalletLifecycleExecutionRequested";
case LiteWalletServerSelectionUiExecutionIssue::SyncRequested:
return "SyncRequested";
case LiteWalletServerSelectionUiExecutionIssue::SyncStatusPollingRequested:
return "SyncStatusPollingRequested";
case LiteWalletServerSelectionUiExecutionIssue::WorkerQueueRequested:
return "WorkerQueueRequested";
case LiteWalletServerSelectionUiExecutionIssue::WalletStateMutationRequested:
return "WalletStateMutationRequested";
case LiteWalletServerSelectionUiExecutionIssue::WalletFilePersistenceRequested:
return "WalletFilePersistenceRequested";
case LiteWalletServerSelectionUiExecutionIssue::SendImportExportRequested:
return "SendImportExportRequested";
}
return "SettingsNotLoaded";
}
std::string redactLiteServerSelectionValue(const std::string& value)
{
const std::string trimmed = trimCopy(value);
@@ -314,138 +96,5 @@ std::string redactLiteServerSelectionValue(const std::string& value)
return trimmed.substr(0, scheme + 3) + "<redacted>";
}
LiteWalletServerSelectionUiExecutionResult executeLiteWalletServerSelectionUi(
config::Settings& settings,
const LiteWalletServerSelectionUiExecutionInput& input)
{
LiteWalletServerSelectionUiExecutionResult result;
auto stopForRuntime = [&](LiteWalletServerSelectionUiExecutionIssue issue,
const std::string& message) {
return stoppedResult(std::move(result),
LiteWalletServerSelectionUiExecutionStatus::RuntimeExecutionDisabled,
issue,
message);
};
if (input.serverConnectivityCheckRequested) {
return stopForRuntime(LiteWalletServerSelectionUiExecutionIssue::ServerConnectivityCheckRequested,
"lite server selection settings adapter cannot check server connectivity");
}
if (input.walletExistsCheckRequested) {
return stopForRuntime(LiteWalletServerSelectionUiExecutionIssue::ServerConnectivityCheckRequested,
"lite server selection settings adapter cannot check wallet existence");
}
if (input.walletLifecycleExecutionRequested || input.ui.realLifecycleExecutionRequested) {
return stopForRuntime(LiteWalletServerSelectionUiExecutionIssue::WalletLifecycleExecutionRequested,
"lite server selection settings adapter cannot execute wallet lifecycle actions");
}
if (input.syncStartRequested) {
return stopForRuntime(LiteWalletServerSelectionUiExecutionIssue::SyncRequested,
"lite server selection settings adapter cannot start sync");
}
if (input.syncStatusPollingRequested) {
return stopForRuntime(LiteWalletServerSelectionUiExecutionIssue::SyncStatusPollingRequested,
"lite server selection settings adapter cannot poll syncstatus");
}
if (input.workerQueueEnqueueRequested) {
return stopForRuntime(LiteWalletServerSelectionUiExecutionIssue::WorkerQueueRequested,
"lite server selection settings adapter cannot enqueue wallet workers");
}
if (input.walletStateMutationRequested) {
return stopForRuntime(LiteWalletServerSelectionUiExecutionIssue::WalletStateMutationRequested,
"lite server selection settings adapter cannot mutate WalletState");
}
if (input.walletFilePersistenceRequested) {
return stopForRuntime(LiteWalletServerSelectionUiExecutionIssue::WalletFilePersistenceRequested,
"lite server selection settings adapter cannot persist wallet files");
}
if (input.sendImportExportExecutionRequested) {
return stopForRuntime(LiteWalletServerSelectionUiExecutionIssue::SendImportExportRequested,
"lite server selection settings adapter cannot execute send/import/export flows");
}
if (!input.persistence.settingsLoaded) {
return stoppedResult(std::move(result),
LiteWalletServerSelectionUiExecutionStatus::WaitingForSettings,
LiteWalletServerSelectionUiExecutionIssue::SettingsNotLoaded,
"lite server settings are not loaded");
}
result.connectionSettings = settingsWithIntent(
liteConnectionSettingsFromAppSettings(settings), input.intent);
if (input.intent.selectedServerIntentProvided &&
input.intent.selectionMode == LiteServerSelectionMode::Sticky &&
!isLiteServerUrlUsable(trimCopy(input.intent.selectedServerUrl))) {
result.selectedServerUrlRedacted = redactLiteServerSelectionValue(input.intent.selectedServerUrl);
result.selectedServerRedacted = true;
return stoppedResult(std::move(result),
LiteWalletServerSelectionUiExecutionStatus::WaitingForServerSelection,
LiteWalletServerSelectionUiExecutionIssue::ServerSelectionMissing,
"lite server selection URL is not usable");
}
result.selectedServer = selectLiteServer(result.connectionSettings);
result.selectedServerUrlRedacted = result.selectedServer.ok
? redactLiteServerSelectionValue(result.selectedServer.server.url)
: redactLiteServerSelectionValue(result.connectionSettings.stickyServerUrl);
result.selectedServerRedacted = true;
if (!result.selectedServer.ok) {
return stoppedResult(std::move(result),
LiteWalletServerSelectionUiExecutionStatus::WaitingForServerSelection,
LiteWalletServerSelectionUiExecutionIssue::ServerSelectionMissing,
result.selectedServer.error.empty()
? "lite server selection is missing"
: result.selectedServer.error);
}
result.selectedServerIntentAccepted = true;
if ((input.persistence.persistSelectedServer || input.persistence.writeSettings) &&
!input.persistence.persistenceOwnerReady) {
return stoppedResult(std::move(result),
LiteWalletServerSelectionUiExecutionStatus::WaitingForPersistenceOwner,
LiteWalletServerSelectionUiExecutionIssue::ServerPersistenceOwnerMissing,
"lite server settings persistence owner is not ready");
}
result.settingsPersistenceAccepted = true;
if (input.persistence.persistSelectedServer || input.persistence.writeSettings) {
applyLiteConnectionSettingsToAppSettings(settings, result.connectionSettings);
settings.setLitePersistSelectedServer(input.persistence.persistSelectedServer);
result.settingsMutated = true;
}
if (input.persistence.writeSettings) {
result.noSettingsPersistence = false;
const bool saved = input.persistence.settingsSavePath.empty()
? settings.save()
: settings.save(input.persistence.settingsSavePath);
if (!saved) {
return stoppedResult(std::move(result),
LiteWalletServerSelectionUiExecutionStatus::SettingsSaveFailed,
LiteWalletServerSelectionUiExecutionIssue::SettingsSaveFailed,
"failed to save lite server settings");
}
result.settingsWritten = true;
}
result.lifecycleInput = makeLifecycleInput(input, result.connectionSettings);
result.lifecycleReadiness = evaluateLiteWalletServerLifecycleReadiness(result.lifecycleInput);
result.lifecycleReadinessAccepted = result.lifecycleReadiness.ok;
result.lifecycleReportCouldFeedSyncPlanners = result.lifecycleReadiness.lifecycleReportCouldFeedSyncPlanners;
result.status = statusFromLifecycle(result.lifecycleReadiness.status);
copyLifecycleIssues(result);
result.diagnosticSummary = buildDiagnosticSummary(result);
if (input.requireLifecycleReadiness && !result.lifecycleReadiness.ok) {
result.ok = false;
result.error = result.lifecycleReadiness.error;
return result;
}
result.ok = true;
return result;
}
} // namespace wallet
} // namespace dragonx
} // namespace dragonx

View File

@@ -1,150 +1,19 @@
#pragma once
#include "lite_connection_service.h"
#include "lite_wallet_server_lifecycle_readiness.h"
#include "wallet_capabilities.h"
#include "../config/settings.h"
#include <cstddef>
#include <string>
#include <vector>
namespace dragonx {
namespace wallet {
enum class LiteWalletServerSelectionUiExecutionStatus {
ReadyForFutureLifecycle,
WaitingForLiteBuild,
WaitingForBackendCapability,
WaitingForSettings,
WaitingForServerSelection,
WaitingForPersistenceOwner,
WaitingForDisplayStatus,
WaitingForLifecycleUi,
WaitingForPrivateDataRedaction,
WaitingForSyncPlannerFeed,
SettingsSaveFailed,
RuntimeExecutionDisabled
};
enum class LiteWalletServerSelectionUiExecutionIssue {
FullNodeBuild,
LiteBackendCapabilityMissing,
SettingsNotLoaded,
ServerSelectionMissing,
ServerPersistenceOwnerMissing,
SelectedServerDisplayMissing,
LifecycleUiOwnerMissing,
PrivateDataRedactionMissing,
SyncPlannerFeedMissing,
SettingsSaveFailed,
ServerConnectivityCheckRequested,
WalletLifecycleExecutionRequested,
SyncRequested,
SyncStatusPollingRequested,
WorkerQueueRequested,
WalletStateMutationRequested,
WalletFilePersistenceRequested,
SendImportExportRequested
};
struct LiteWalletServerSelectionUiIntent {
bool selectedServerIntentProvided = false;
LiteServerSelectionMode selectionMode = LiteServerSelectionMode::Sticky;
std::string selectedServerUrl;
std::size_t randomSelectionSeed = 0;
std::string chainName;
bool replaceServers = false;
std::vector<LiteServerEndpoint> servers;
};
struct LiteWalletServerSelectionPersistenceExecutionInput {
bool settingsLoaded = true;
bool havePersistedSelectionIntent = true;
bool persistSelectedServer = true;
bool persistenceOwnerReady = true;
bool writeSettings = false;
std::string settingsSavePath;
};
struct LiteWalletServerSelectionUiExecutionInput {
WalletCapabilities capabilities;
LiteWalletServerSelectionUiIntent intent;
LiteWalletServerSelectionPersistenceExecutionInput persistence;
LiteWalletLifecycleUiPrerequisites ui;
LiteWalletLifecycleOperation operation = LiteWalletLifecycleOperation::CreateNew;
LiteWalletCreateRequest createRequest;
LiteWalletOpenRequest openRequest;
LiteWalletRestoreRequest restoreRequest;
bool requireLifecycleReadiness = false;
bool serverConnectivityCheckRequested = false;
bool walletExistsCheckRequested = false;
bool walletLifecycleExecutionRequested = false;
bool syncStartRequested = false;
bool syncStatusPollingRequested = false;
bool workerQueueEnqueueRequested = false;
bool walletStateMutationRequested = false;
bool walletFilePersistenceRequested = false;
bool sendImportExportExecutionRequested = false;
};
struct LiteWalletServerSelectionUiExecutionIssueInfo {
LiteWalletServerSelectionUiExecutionIssue issue = LiteWalletServerSelectionUiExecutionIssue::SettingsNotLoaded;
std::string message;
};
struct LiteWalletServerSelectionUiExecutionResult {
bool ok = false;
bool dryRunOnly = true;
bool noNetwork = true;
bool noBridgeCalls = true;
bool noServerHealthChecked = true;
bool noWalletExistsChecked = true;
bool noWalletCreated = true;
bool noWalletOpened = true;
bool noWalletRestored = true;
bool noSyncStarted = true;
bool noSyncStatusPolled = true;
bool noWalletPersistence = true;
bool noSendImportExportExecution = true;
bool workerQueueEnqueued = false;
bool stateMutationAllowed = false;
bool stateMutated = false;
bool walletStateWritten = false;
bool settingsMutationAllowed = true;
bool settingsMutated = false;
bool noSettingsPersistence = true;
bool settingsWritten = false;
bool settingsPersistenceAccepted = false;
bool selectedServerIntentAccepted = false;
bool lifecycleReadinessAccepted = false;
bool lifecycleReportCouldFeedSyncPlanners = false;
bool selectedServerRedacted = false;
LiteWalletServerSelectionUiExecutionStatus status = LiteWalletServerSelectionUiExecutionStatus::WaitingForSettings;
std::string error;
std::string selectedServerUrlRedacted;
std::string diagnosticSummary;
LiteConnectionSettings connectionSettings;
LiteServerSelectionResult selectedServer;
LiteWalletServerLifecycleReadinessInput lifecycleInput;
LiteWalletServerLifecycleReadinessResult lifecycleReadiness;
std::vector<LiteWalletServerSelectionUiExecutionIssueInfo> issues;
};
LiteConnectionSettings liteConnectionSettingsFromAppSettings(const config::Settings& settings);
void applyLiteConnectionSettingsToAppSettings(config::Settings& settings,
const LiteConnectionSettings& connectionSettings);
const char* liteWalletServerSelectionUiExecutionStatusName(
LiteWalletServerSelectionUiExecutionStatus status);
const char* liteWalletServerSelectionUiExecutionIssueName(
LiteWalletServerSelectionUiExecutionIssue issue);
std::string redactLiteServerSelectionValue(const std::string& value);
LiteWalletServerSelectionUiExecutionResult executeLiteWalletServerSelectionUi(
config::Settings& settings,
const LiteWalletServerSelectionUiExecutionInput& input);
} // namespace wallet
} // namespace dragonx
} // namespace dragonx

View File

@@ -1,4 +1,4 @@
#include "chat/chat_protocol.h"
#include "chat/chat_fixture_tooling.h"
#include <algorithm>
#include <filesystem>