Skip to content

refactor(platform-wallet): remove dead code in rs-platform-wallet (16 audit entries) - #4637

Open
llbartekll wants to merge 16 commits into
v4.2-devfrom
refactor/wallet-dead-code-rust-core
Open

refactor(platform-wallet): remove dead code in rs-platform-wallet (16 audit entries)#4637
llbartekll wants to merge 16 commits into
v4.2-devfrom
refactor/wallet-dead-code-rust-core

Conversation

@llbartekll

@llbartekll llbartekll commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Issue being fixed or feature implemented

The 2026-09-08 audit (review/wallet-swift-slop-audit:WALLET_SWIFT_SLOP_REVIEW.md) raised 61 dead-code entries. Each was a reviewer's claim, not an established fact — this PR lands only the ones that survived independent verification.

Scope: rust-core, Effort S, Risk low — 16 entries, one commit per entry.

What was done?

Deletions in rs-platform-wallet (plus import-path retargeting in rs-platform-wallet-ffi, with no C ABI impact):

Entry What goes
rust-core-022 transfer_with_change_address and the whole FeeStrategyByAddress machinery, validate_change_address, augment_outputs_with_change, checked_sum_credits, the ChangeBelowMinimumOutput error variant
rust-core-076 accept_incoming_request, remove_incoming_contact_request, the #[allow(dead_code)]-hidden impl block in state/contacts.rs, the EstablishedContact setters, ContactRequest::{is_outgoing,is_incoming}
rust-core-089 derive_contact_payment_addresses, DEFAULT_CONTACT_GAP_LIMIT; auto-accept helpers gated behind #[cfg(test)]
rust-core-093 DashpayAddressMatch and the three match_incoming_dashpay_address* variants; match_in_collection becomes a free function
rust-core-099 six uncalled IdentityWallet methods
rust-core-108 + 187 PrivateKeyData/KeyStorage; the vestigial state::managed_identity::{block_time,key_storage} re-export shim
rust-core-114 + 125 dead broadcast entry points, DapiBroadcaster, add_handler, is_instant_lock_timeout
rust-core-124 six never-constructed PlatformWalletError variants
rust-core-152 operations::shield, trait SelectionResultOwned
rust-core-158 dead items in the shielded layer (per_account_for, get_activity_ids, the witness default, write-only fields)
rust-core-171 list_tracked_locks_blocking
rust-core-177 managed_identity/sync.rs, BlockTime::{new,is_older_than}
rust-core-178 network/top_up.rs
rust-core-200 SpvRuntime::{get_quorum_public_key,update_config} plus visibility narrowing on masternode helpers

Total: 58 files, 2,844 deletions, 221 insertions.

Where this departs from the audit

Two audit claims did not hold up and were rejected:

  • ContactRequestValidation::new() — the audit classed it as dead ("only self-referenced"). It has 9 call sites in validation.rs, two of them on the production path (validate_sender_key, validate_recipient_key). Removing it broke the build; restored.
  • Three symbols gated behind #[cfg(test)] rather than deleted (derive_contact_payment_address, generate_auto_accept_proof, verify_auto_accept_proof + derive_auto_accept_private_key). They leave the public API as the audit intended, but they pin the correctness of code that is live — reconstruct_contact_xpub and the auto-accept proof scheme. Deleting them outright would have dropped real coverage.

Note for reviewers: the audit's line numbers have drifted against v4.2-dev (e.g. SpvRuntime::update_config audit 583 → actually 628). Everything was located by symbol, never by line.

How Has This Been Tested?

All green at the branch tip:

  • cargo check --workspace
  • cargo clippy -p platform-wallet -p platform-wallet-ffi --all-features --all-targets ✅ (the only two warnings — an unused import in rs-drive and default-features in rs-dpp/Cargo.toml — are pre-existing and present on the base branch)
  • cargo test -p platform-wallet955 passed, 0 failed
  • cargo test -p platform-wallet-ffi365 passed, 0 failed

Tests that only exercised the removed code go with it. Tests that check something real but merely built their fixture through the removed setters (metadata preservation on re-establish, account_reference rotation, BlockTime changeset round-trip) were kept and rewritten to assign fields directly.

Breaking Changes

No C ABI change. The removed symbols are public in the platform-wallet crate, but were verified to have no consumer anywhere in the repo (FFI, JNI, Swift, Kotlin, tests, examples).

refresh_identity_with_signer from entry rust-core-099 was deliberately kept — its doc comment explicitly names an out-of-repo consumer (dash-evo-tool's QualifiedIdentity).

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added explicit identity lifecycle statuses and DPNS name metadata.
    • Incoming DashPay payments can be matched against registered contact receiving addresses.
  • Changes

    • Tracked asset locks are now listed asynchronously.
    • Transaction broadcasting now uses the SPV path; the former DAPI fallback is no longer available.
    • Shielded operations use the direct shield_to flow.
  • API Updates

    • Removed several legacy wallet, identity, contact-management, transfer, and broadcasting interfaces.
    • Reduced public exposure of internal helpers and types.

llbartekll and others added 14 commits September 9, 2026 12:03
…eStrategyByAddress

`transfer_with_change_address` and the whole address-keyed fee-strategy
machinery (`FeeStrategyByAddress`, `FeeStrategyStepByAddress`,
`FeeStrategyResolveError`) had no consumer — not in rs-platform-wallet-ffi,
swift-sdk, kotlin-sdk or rs-unified-sdk-jni. The FFI entry point
`platform_address_wallet_transfer` only ever calls `transfer`.

Going with them: `validate_change_address`, `augment_outputs_with_change`,
`checked_sum_credits`, the `ChangeBelowMinimumOutput` error variant (never
mapped in ffi/error.rs), and ~480 lines of tests that covered only this path.
`InputSumOverflow` stays — platform_wallet.rs still uses it.

The `transfer` doc loses its "When to use this vs transfer_with_change_address"
section.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ncoming_dashpay_address variants

The three public variants (`match_incoming_dashpay_address`, `_blocking`,
`try_match_incoming_dashpay_address`) had no call site — not from Rust, and not
through the FFI, Swift or Kotlin. One of them (`_blocking`) panics when called
from a tokio context.

The only live consumer was `payments.rs`, reaching the private
`match_in_collection` helper through an artificial
`DashPayView::<SpvBroadcaster>::` turbofish. That helper becomes a plain free
function `match_receival_address` in payments.rs and returns a pair of
identifiers instead of a struct — `DashpayAddressMatch`'s `address_index` field
had no reader.

`DashpayAddressMatch` goes along with its re-exports in types/dashpay/mod.rs,
types/mod.rs and identity/mod.rs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
No consumer in ffi, jni, Swift or Kotlin — verified by grepping all of
packages/:

- `ManagedIdentity::accept_incoming_request` — a second contact-establishment
  path that bypasses the persist-before-commit rule the live path enforces
  (`add_sent_contact_request` / `add_incoming_contact_request`). Called only by
  its own three tests.
- `ManagedIdentity::remove_incoming_contact_request` — tests only; production
  rejects through `ignore_sender`. The `test_reject_contact_request` integration
  test moves onto `ignore_sender`.
- `state/contacts.rs`: `add_established_contact`, `remove_established_contact`
  and `established_contact` were hiding under an `#[allow(dead_code)]` spanning
  the whole impl block. `established_contact_mut`, the one in use, stays.
- The `EstablishedContact` setters (`set_alias`, `clear_alias`, `set_note`,
  `clear_note`, `hide`, `unhide`, `add_accepted_account`,
  `remove_accepted_account`) — production writes the fields directly via
  `set_contact_metadata`. Tests that still carry their weight (metadata
  preservation on re-establish, account_reference rotation) build their fixture
  by assigning fields.
- `ContactRequest::is_outgoing` / `is_incoming` — own tests only. The
  `is_outgoing` *fields* in the FFI/JNI/Swift persistence layer are a separate
  thing and are left untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…tigial re-export shim

Two related cleanups in the same file.

1. `PrivateKeyData` and `KeyStorage` were never constructed or read —
   `PrivateKeyData::` returns zero hits across all of packages/, including
   rs-platform-wallet-ffi. The doc claimed "the IdentityKeysChangeSet apply path
   constructs one per replay, the FFI key-preview path uses one internally";
   `apply_identity_key_entry` touches neither. `key_storage.rs` is renamed to
   `identity_status.rs` — it now holds only `IdentityStatus` and `DpnsNameInfo`.

2. `state::managed_identity` re-exported `block_time` and `key_storage` under
   the old path so "external users can still reach them" — a comment describing
   a past move, not the current layout. Ten sites in the tree (including
   rs-platform-wallet-ffi/src/memory_explorer.rs) reached the types through the
   shim instead of `crate::wallet::identity::types::*`. All retargeted, shim
   removed.

Import-path changes only — no C ABI impact.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…aster

None of these had a call site in packages/ — not from Rust, and not through the
FFI, Swift or Kotlin:

- `CoreWallet::broadcast_transaction` — one hit in the entire repo, its own
  definition.
- `CoreWallet::broadcast_transaction_releasing_reservation` and its only callee
  `reservations::broadcast_releasing_on_rejection`, together with two tests
  (`broadcast_releases_reservation_on_rejection`,
  `broadcast_keeps_reservation_on_ambiguous_failure`) and the `build_signed_tx`
  helper that existed solely for them. The finalized-handle tests already cover
  those properties.
- `DapiBroadcaster` — 45 lines of a second trait implementation, never
  instantiated. `PlatformWallet.core` is `CoreWallet<SpvBroadcaster>`, and the
  FFI/JNI use `SpvBroadcaster` exclusively. Eight comment sites justified the
  pending-spend fence design by "the DapiBroadcaster path"; rewritten to
  describe the shape (a broadcaster returning before mempool injection) rather
  than naming a type that no longer exists.
- `PlatformEventManager::add_handler` — every `PlatformEventManager::new` site
  passes the full handler list up front.
- `is_instant_lock_timeout` — a one-line `matches!` whose only consumer was its
  own test; production matches `FinalityTimeout` directly.

The `signed_payment_registry` doc stops calling the removed method "the regular
send path".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…tError variants

`WalletLocked`, `NoPrimaryIdentity`, `NoWalletsConfigured`,
`DashpayReceivingAccountAlreadyExists`, `DashpayExternalAccountAlreadyExists`
and `AssetLockExpired` had no constructor anywhere in packages/ — no match arm,
no FFI mapping, no Swift/Kotlin mirror. `From<PlatformWalletError>` in
rs-platform-wallet-ffi routed all six through its `_` arm, so host-visible codes
do not change.

Dead variants widened the public enum and implied concepts this crate does not
have (a wallet lock, a "primary identity"). The two DashPay variants carried
four fields nobody filled.

The `key_wallet::Network` import existed only for those two.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nce wrapper

`network/top_up.rs` is 67 lines: a 10-line module doc explaining that the file
"just hosts the convenience wrapper `top_up_identity`", 20 lines of argument
docs, and a body forwarding to
`top_up_identity_with_funding(id, AssetLockFunding::FromWalletBalance{..}, ..)`.

`top_up_identity` has no call site in packages/. Both FFI entry points
(`identity_top_up.rs`, `identity_registration_funded_with_signer.rs`) call
`top_up_identity_with_funding` directly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Public API kept alive solely by `examples/basic_usage.rs`. The method uses
`tokio::sync::RwLock::blocking_read` and — as its own doc says — panics when
called from an async context, so it doubled the accessor surface with a
footgun variant.

The FFI (`rs-platform-wallet-ffi/src/asset_lock/manager.rs`) and Swift/Kotlin
reach the async `list_tracked_locks` under `block_on`. The example already runs
inside a runtime, so it moves to `.await`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nd BlockTime::{new,is_older_than}

`managed_identity/sync.rs` (62 lines: `needs_balance_update`, `needs_keys_sync`,
`update_keys_sync_block_time`, `update_balance_block_time`) together with
`BlockTime::new` and `BlockTime::is_older_than` existed only to test each other
— the only hits outside their own tests were inside a `#[test]` block in
wallet/apply.rs. Production sets the fields directly
(rs-platform-wallet-ffi/src/managed_identity.rs:
`identity.last_updated_balance_block_time = Some(owned)`).

`is_older_than` computed `(current_timestamp - self.timestamp) > max_age_millis`
— a debug panic, or a wrap in release, if a stored block timestamp ran ahead of
the caller's clock. If a freshness check is ever wanted, the right shape is a
single `age_millis(now)` built on `saturating_sub` at the point of use.

`round_trip_block_time_updates` stays — it covers changeset replay for fields
that are still live — and builds its fixture with a struct literal instead of
the removed setters.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
For each name, a grep across all of packages/ (Rust, Swift, Kotlin, tests,
examples) returns only the definition:

- `refresh_dpns_names` (loading.rs) — its wholesale-replace semantics are
  already covered by the existing `sync_dpns_names`.
- `load_identity_by_dpns_name` (loading.rs) — the only non-definition hit is a
  comment in PlatformWalletPersistenceHandler.swift.
- `register_name_with_signer` (dpns.rs) — returned `dash_sdk::Error` unlike
  every sibling; production uses `register_name_with_external_signer`.
- `dpns_domain_states_for_identity` (dpns_marketplace.rs) along with its
  limit/pagination loop. `dpns_domain_states_page` stays — marketplace sync
  uses it.
- `wallet_manager_read` / `wallet_manager_write` / `try_wallet_manager_write`
  (identity_handle.rs) — these leaked an RwLock guard outside the crate.
- `derive_identity_key_bytes` (identity_handle.rs).

The FFI crate calls 14 `IdentityWallet` methods and none of the above;
kotlin-sdk and rs-unified-sdk-jni do not reference them at all.

`refresh_identity_with_signer` from the same audit entry is KEPT — its doc
explicitly names an out-of-repo consumer (dash-evo-tool's `QualifiedIdentity`).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…helpers from the public API

All of these were exported from the crate root with no consumer in the FFI,
Swift, Kotlin, or in tests outside their own module. They advertised a
seed-resident code path the seedless design deliberately removed.

Removed outright:
- `derive_contact_payment_addresses` (the batch wrapper) and its test,
- `DEFAULT_CONTACT_GAP_LIMIT` and its test,
- the re-exports in crypto/mod.rs, identity/mod.rs and lib.rs.

Gated behind `#[cfg(test)] pub(crate)` rather than deleted, because they pin
the correctness of code that is still live:
- `derive_contact_payment_address` — the pin that `reconstruct_contact_xpub`
  yields an equivalent key (production derives contact addresses through
  key-wallet's `AccountType::DashpayReceivingFunds` pool),
- `generate_auto_accept_proof`, `verify_auto_accept_proof`,
  `derive_auto_accept_private_key` — coverage for the proof scheme; production
  goes through `provider.export_auto_accept_private_key` +
  `verify_auto_accept_proof_with_pubkey`. Their own docs already said "Kept for
  owner-side tests / a self-check".

`ContactRequestValidation::new()` from the same audit entry is KEPT —
verification found 9 call sites in validation.rs, two of them on the production
path (`validate_sender_key`, `validate_recipient_key`). The audit classed
"self-referenced" as dead code; it is not the same thing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nResultOwned trait

`operations::shield` described itself as a "self-shield front for `shield_to`,
preserving the pre-recipient signature for existing callers" — there are no such
callers. The only producer, platform_wallet.rs, calls `shield_to` directly;
beyond that the name appeared only in test-file prose (retargeted to
`shield_to`).

`trait SelectionResultOwned` had one implementation and one requirement, doing
`refs.into_iter().cloned().collect()` in two places. Replaced by a free function
`own_selection` that says so directly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- `MultiSyncNotesResult::per_account_for` — definition only; its doc said it
  feeds "the legacy per-wallet SyncNotesResult shape", which coordinator.rs
  builds inline.
- `_unused_payment_address` — a decoy under `#[allow(dead_code)]` claiming to
  suppress a warning for an `address` field that does not exist
  (`PaymentAddress` is used by `RecoveredOutgoing.recipient`).
- `ShieldedStore::get_activity_ids` with both implementations and
  `SubwalletState::activity_ids` — the scan deriver takes
  `existing_cmxs: BTreeMap<cmx, id>` and the coordinator uses
  `get_activity(*id, 0, usize::MAX)`. The test assertion now counts distinct
  ids on the fetched page.
- The default `ShieldedStore::witness` implementation — its only callers were
  two file_store tests; production goes through `witness_at_depth`. Those tests
  move to `witness_at_depth(pos, 0)`.
- `marked_positions` and `checkpoints` on `InMemoryShieldedStore` — pushed and
  cleared, never read. They made the in-memory tree look more capable than it
  is (it cannot produce a witness).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…masternode helper visibility

`SpvRuntime::get_quorum_public_key` and `SpvRuntime::update_config` have no call
site in rs-platform-wallet, rs-platform-wallet-ffi, rs-unified-sdk-jni,
kotlin-sdk or swift-sdk. (Beware appearances: `get_quorum_public_key` has 62
hits across 26 files in the workspace, but those are the `ContextProvider` trait
method in entirely different crates — only the inherent method on `SpvRuntime`
is removed here. `tests/spv_sync.rs` implements that trait; it does not call the
method.) Each carried its own error mapping and locking code to keep consistent
with the live paths.

Visibility narrowing, no consumers outside the crate:
- `wallet_masternode_index_blocking` → private (called only by
  `masternode_locator_blocking`, a few lines below),
- `registration_from_transaction` → `pub(crate)` (used only within tracked.rs),
- `find_in_summaries`, `locate_in_summaries` and `parse_locator_input` leave the
  `pub use` list in masternode/mod.rs; they remain reachable inside the crate
  through their own modules.

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

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Warning

Review limit reached

Next included review available in 32 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: f8c217d8-e7af-4e5c-b538-355b4c21658d

📥 Commits

Reviewing files that changed from the base of the PR and between f1973ca and 150e7de.

📒 Files selected for processing (1)
  • packages/rs-platform-wallet/src/manager/wallet_lifecycle.rs

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 388c8d02-a8ce-4910-9f24-6d75d1ce8bbf

📥 Commits

Reviewing files that changed from the base of the PR and between 6810971 and f1973ca.

📒 Files selected for processing (3)
  • packages/rs-platform-wallet/src/error.rs
  • packages/rs-platform-wallet/src/wallet/identity/network/discovery.rs
  • packages/rs-platform-wallet/src/wallet/identity/network/payments.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/rs-platform-wallet/src/wallet/identity/network/discovery.rs

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The pull request narrows the platform-wallet public API, removes obsolete identity, broadcasting, transfer, shielded-storage, and runtime paths, relocates identity status types, and updates internal callers and documentation.

Changes

Platform wallet API cleanup

Layer / File(s) Summary
Identity types and state surface
packages/rs-platform-wallet/src/wallet/identity/..., packages/rs-platform-wallet/src/error.rs
Identity status types move to identity_status. Legacy key-storage, block-time synchronization, contact mutators, error variants, and identity exports are removed or narrowed.
Identity network and payment paths
packages/rs-platform-wallet/src/wallet/identity/network/..., packages/rs-platform-wallet/tests/contact_workflow_tests.rs
Legacy identity wrappers and DashPay address matching methods are removed. Incoming payment detection uses match_receival_address.
Broadcasting and reservation API removal
packages/rs-platform-wallet/src/broadcaster.rs, packages/rs-platform-wallet/src/wallet/core/..., packages/rs-platform-wallet/src/wallet/reservations.rs
DapiBroadcaster, direct transaction broadcast methods, and generic rejection cleanup are removed.
Platform transfer API cleanup
packages/rs-platform-wallet/src/wallet/platform_addresses/...
Address-keyed fee strategies, change-address transfer helpers, overflow checking, and related tests are removed.
Shielded storage and operation cleanup
packages/rs-platform-wallet/src/wallet/shielded/...
Legacy activity and witness APIs, in-memory checkpoint state, and the self-shield wrapper are removed.
Runtime and supporting API narrowing
packages/rs-platform-wallet/src/spv/runtime.rs, packages/rs-platform-wallet/src/events.rs, packages/rs-platform-wallet/src/masternode/..., packages/rs-platform-wallet/examples/basic_usage.rs
Runtime configuration and quorum lookup methods are removed. Supporting exports are narrowed, and the example uses the asynchronous lock-listing method.

Priority: ⬇️ Low

Estimated code review effort: 5 (Critical) | ~120 minutes

Merge Risk: ⚪ Minimal · up to f1973

This change removes obsolete wallet APIs and updates remaining internal call paths. No concrete current-head merge risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the platform-wallet refactor and the removal of dead code. It matches the primary changes described in the pull request.
Docstring Coverage ✅ Passed Docstring coverage is 88.57% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 70 functions across 44 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/wallet-dead-code-rust-core

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@thepastaclaw

thepastaclaw commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

✅ Final review complete — no blockers (commit 150e7de) · triage: critical · Phase 2 only (queue backlog)

@llbartekll llbartekll changed the title refactor(platform-wallet): usunięcie martwego kodu w rs-platform-wallet (16 wpisów audytu) refactor(platform-wallet): remove dead code in rs-platform-wallet (16 audit entries) Sep 9, 2026
@llbartekll
llbartekll force-pushed the refactor/wallet-dead-code-rust-core branch from cf6f880 to 6810971 Compare September 9, 2026 12:14
lklimek and others added 2 commits September 9, 2026 15:20
…removed WalletLocked variant

The `v4.2-dev` merge brought in #4586 (`22055ec8ab`), whose
`persister_error_constructors_are_not_interchangeable` test picks
`PlatformWalletError::WalletLocked` as an arbitrary sample variant to prove
`from_restore_failure` preserves the concrete inner error through boxing. This
branch removes `WalletLocked` as never-constructed, so the merge is textually
clean but does not compile — `wallet_lifecycle.rs` references a variant
`error.rs` no longer defines.

`WalletLocked` still has no constructor anywhere; the test only needed *some*
variant. It now uses `SpvAlreadyRunning`, a unit variant production actually
raises (`spv/runtime.rs:160`). The property under test is unchanged.

Verified: `cargo check -p platform-wallet -p platform-wallet-ffi --all-targets`,
`cargo test -p platform-wallet` (983 passed) and `cargo fmt --all -- --check`
are all green on the merge commit.

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

@thepastaclaw thepastaclaw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final validation — Phase 2 only (queue backlog)

The PR’s dead-code removals are consistent with the stated scope, and I found no blocking correctness, security, consensus, or integration issues. One non-blocking performance cleanup remains: after dynamic handler registration was removed, the event handler collection is immutable but still incurs an atomic snapshot load for every event dispatch.

Source: reviewer 1: gpt-6-astra (agent: phase2-reviewer, role: general); reviewer 2: gpt-6-astra (agent: phase2-reviewer, role: rust-quality); final verifier: gpt-6-astra (agent: astra-verifier, role: final-verifier)

Review provenance

  • Triage: critical by gpt-6-astra (effort low) — Despite being dead-code removal, this is a broad 58-file Rust wallet refactor deleting payment, identity/contact, broadcasting, shielded, synchronization, and cryptographic pathways, with potential side effects across funds, networking, persistence, and security-sensitive behavior.
  • Phase 1 reviewers: not run (skipped for throughput: 24 PRs queued, above the 10 limit)
  • Fresh verifier: gpt-6-astra — final-verifier; agent astra-verifier
  • Phase 2 reviewers: gpt-6-astra — general (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — rust-quality (completed, effort xhigh); agent phase2-reviewer

🟡 1 suggestion(s)

🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `packages/rs-platform-wallet/src/events.rs`:
- [SUGGESTION] packages/rs-platform-wallet/src/events.rs:111-113: Simplify the now-immutable event-handler collection
  Removing `add_handler` removed the only writer to `handlers`: the collection is initialized in `new` and is never replaced. Keeping `ArcSwap` therefore adds an atomic load and snapshot-guard lifetime to every wallet, network, sync, and progress event without providing mutation protection. Store a plain `Vec<Arc<dyn PlatformEventHandler>>` and iterate it by shared reference instead. `PlatformEventHandler` inherits the thread-safety requirements of `EventHandler`, and `PlatformEventManager` is already shared through `Arc`, so concurrent read-only dispatch remains safe while avoiding unnecessary synchronization.

Comment on lines 111 to 113
/// Read path (every event): one atomic pointer load, then iterate.
/// Write path (add_handler): clone Vec + atomic swap — rare, not on SPV hot path.
pub struct PlatformEventManager {
handlers: ArcSwap<Vec<Arc<dyn PlatformEventHandler>>>,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: Simplify the now-immutable event-handler collection

Removing add_handler removed the only writer to handlers: the collection is initialized in new and is never replaced. Keeping ArcSwap therefore adds an atomic load and snapshot-guard lifetime to every wallet, network, sync, and progress event without providing mutation protection. Store a plain Vec<Arc<dyn PlatformEventHandler>> and iterate it by shared reference instead. PlatformEventHandler inherits the thread-safety requirements of EventHandler, and PlatformEventManager is already shared through Arc, so concurrent read-only dispatch remains safe while avoiding unnecessary synchronization.

source: ['claude']

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants