Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
74d6958
docs(user-stories): add missing entries surfaced by v1.0 parity audit
lklimek Jul 13, 2026
27467fe
refactor(network-chooser): drop dead dashmate_password_input field
lklimek Jul 13, 2026
0a64eae
merge: group6 — expert-mode toggle audit + dead RPC-password field cl…
lklimek Jul 13, 2026
4d26fe3
docs: close v1.0 parity audit disclosure gaps (group 8)
lklimek Jul 13, 2026
8324ec7
merge: group8 — v1.0 parity audit disclosure closure (B1/B2/B4)
lklimek Jul 13, 2026
3599597
fix(tokens): keep dismissed token balances out of refresh watch sets
lklimek Jul 13, 2026
138cb91
merge: group5 — fix token "stop tracking" not surviving refresh (A9)
lklimek Jul 13, 2026
a209288
feat(shielded): restore shielded receive-address view and copy
lklimek Jul 13, 2026
6724ef9
feat(identity-hub): wire Contacts actions, real contact list, alias, …
lklimek Jul 13, 2026
3ab07d9
fix(dashpay): clear a stale rejection marker when re-adding a contact
lklimek Jul 13, 2026
5a6dc76
merge: group3 — restore shielded receive-address view (A6, High sever…
lklimek Jul 13, 2026
4386531
fix(migration): import settings, scheduled votes and top-ups from leg…
lklimek Jul 13, 2026
025cf27
fix(wallets): remove dead RPC-mode gate on single-key send, surface l…
lklimek Jul 13, 2026
361b260
feat(nav): wire the masternode and Wallets global-nav pills
lklimek Jul 13, 2026
c55d643
merge: group1 — Identity Hub Contacts: A1-A4
lklimek Jul 13, 2026
0110add
merge: group7 — settings/data migration on upgrade (A12, High severity)
lklimek Jul 13, 2026
444d735
merge: group4 — single-key wallet send/monitoring: blocked upstream (…
lklimek Jul 13, 2026
860e2b8
merge: group2 — global nav pills: masternode object pill + Wallets pi…
lklimek Jul 13, 2026
4902fb5
fix(dashpay): narrow the cancel race window and add a way back for hi…
lklimek Jul 13, 2026
e6057db
docs(user-stories): record the hidden-contact recovery path in DPY-009
lklimek Jul 13, 2026
273c042
fix(ui,tokens): re-disable single-key send, ungate DashPay pay button…
lklimek Jul 13, 2026
167b5ff
docs: drop stale Resync references from shielded_tab doc comments
lklimek Jul 13, 2026
8120110
merge: fix-contacts — QA follow-up (cancel-race narrowing, unhide, sh…
lklimek Jul 13, 2026
74d2af8
fix(migration): stop a corrupt vote row from blocking the wallet drain
lklimek Jul 13, 2026
42830e9
merge: fix-single-key-a4 — QA follow-up (send-screen safety, gating c…
lklimek Jul 13, 2026
875920f
merge: fix-migration — QA-101/QA-103: decouple vote import from walle…
lklimek Jul 13, 2026
108af44
refactor: consolidate six duplicated code paths from the DRY audit
lklimek Jul 13, 2026
0fcb6e7
test(migration): lock the v0.9.3 -> v1.0 upgrade path end to end
lklimek Jul 13, 2026
771b9d7
fix(tokens): stop concurrent dismissals from clobbering each other
lklimek Jul 13, 2026
27f5291
fix(dashpay): scope contact results to their identity, split resoluti…
lklimek Jul 13, 2026
86e6cc2
merge: fix-contact-requests — bot-review fixes 2, 7, 9
lklimek Jul 13, 2026
c61da82
fix(migration): stop the legacy import from losing top-ups, votes and…
lklimek Jul 13, 2026
cd7f034
merge: fix-migration-2 — bot-review fixes 5, 6, 8
lklimek Jul 13, 2026
05f6897
docs(migration): design the v0.9.3 legacy identity import
lklimek Jul 13, 2026
ff05c3a
fix(dashpay): stop the Contacts tab losing loads, clicks and accepted…
lklimek Jul 13, 2026
c56139f
merge: fix-contacts-ui — bot-review fixes 1, 3, 4 (+ legacy wipe)
lklimek Jul 13, 2026
453cd15
feat(migration): import legacy v0.9.3 identities and their keys
lklimek Jul 13, 2026
f6d89a2
merge: reconcile with v0.9.3 upgrade-path lock test (0fcb6e7e)
lklimek Jul 13, 2026
ce1205a
fix(migration): never let a corrupt vote queue strand identity keys
lklimek Jul 13, 2026
54e9374
test: allow-list v093_upgrade.rs's legacy wallet-table fixture read
lklimek Jul 13, 2026
64a6d3d
test: stabilize suite timing and close kittest wiring race (#884)
lklimek Jul 13, 2026
b94a868
merge: bring PR #860 (platform-wallet rewrite) into the v1.0 parity b…
lklimek Jul 13, 2026
1d61b22
test(wallets): pin the pill-click mirroring seam on the Wallets page
lklimek Jul 13, 2026
e2c0970
merge: bring the v1.0 parity batch into the legacy identity import
lklimek Jul 13, 2026
b56ebff
fix(migration): honor legacy alias fallback and guard identity-import…
lklimek Jul 13, 2026
4fc2c76
feat(edition): add Edition type and masternode-owner-edition feature
lklimek Jul 13, 2026
638b67f
feat(edition): gate navigation and force first-run role for the maste…
lklimek Jul 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
reproduced. Re-establishing the contact from both sides restores full
functionality.

- **Shielded notes — no per-note detail view**: the Shielded tab no longer lists
individual notes (value, block height, spent/unspent status) or a synced-index
and note-count summary. Your shielded balance total is still accurate; only the
note-level breakdown is unavailable in this release.

### Removed

- Proof log screen (internal developer tool, not part of the public feature set).
Proof-log records now go only to the `tracing` log target — both the persisted
history and the in-app viewer are gone; there is no replacement UI to inspect
past entries.
- QR-code wallet import flow for identity funding and top-up screens.
- The "fund identity directly from a transaction output" option on the identity
registration and top-up screens (replaced by the single asset-lock funding flow
Expand All @@ -148,9 +156,25 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- The unreachable Dash-Qt launcher and its settings — the executable path, the
overwrite-config option, and the close-on-exit option. There was no way to launch
Dash-Qt from the app, so the controls had no effect and have been removed.
- The Masternode List Diff inspector (Tools), which showed additions, removals, and
changes to the masternode list between blocks. No replacement is planned.
- The "Total Received (DASH)" column on the wallet address table. There is no
upstream source for cumulative historical receipts post-migration, so the column
cannot be populated.

### Fixed

- **Your settings and scheduled votes now survive an upgrade**: upgrading from an
earlier version no longer starts the app with a blank configuration. The first
launch after the upgrade brings across your selected network, start screen,
theme, onboarding state, Dash-Qt path and the remaining toggles — so a testnet
user is no longer relaunched on Mainnet — along with your scheduled DPNS votes
(choice, time and already-cast state) and your identities' top-up history.
Scheduled votes are imported even on an install whose wallets were already
moved by a previous launch. If a scheduled vote cannot be read, the app says so
in a banner with a "Retry now" action instead of dropping it silently; the
original data is never deleted from the previous version's storage.

- **Expert mode now reveals the Masternodes tab without a restart**: turning on
Expert mode in Settings immediately shows the "Masternodes" entry in the left
nav. Previously the Expert-mode flag was stored separately per network, so the
Expand Down
18 changes: 18 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ raw-cpuid = "11.5.0"
[features]
default = []
testing = []
# Masternode-owner edition: a stripped-down build that exposes only the
# Masternodes screen and Settings. A runtime UX restriction, not a security or
# binary-size boundary. See docs/ai-design/2026-07-13-masternode-owner-edition/.
masternode-owner-edition = []
bench = []
mcp = ["dep:rmcp", "rmcp/server", "rmcp/macros", "rmcp/transport-streamable-http-server", "dep:axum", "dep:subtle"]
cli = ["dep:rmcp", "rmcp/server", "rmcp/macros", "rmcp/client", "rmcp/transport-io", "rmcp/transport-streamable-http-client-reqwest", "dep:clap", "dep:clap_complete"]
Expand Down Expand Up @@ -151,6 +155,20 @@ winres = "0.1"
[profile.dev.package."*"]
debug = "line-tables-only"

# Argon2id is deliberately memory-hard; unoptimized (opt-level=0) each 64 MiB
# derivation runs for seconds AND holds its memory that whole time, so the
# wallet_backend secret-storage tests both ran slowly (5-23s each) and, under
# whole-suite parallelism, overlapped enough to push the host into swap.
# opt-level=3 shrinks each derivation to tens of ms, which also collapses the
# memory-hold window and the swap pressure. This mirrors platform's own root
# argon2 stanza, which does NOT propagate downstream: Cargo honors [profile.*]
# tables only from the workspace root, so DET must declare its own.
[profile.dev.package.argon2]
opt-level = 3

[profile.test.package.argon2]
opt-level = 3

[lints.rust.unexpected_cfgs]
level = "warn"
check-cfg = ["cfg(tokio_unstable)", "cfg(feature, values(\"testing\", \"bench\", \"mcp\", \"cli\", \"headless\"))"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ The `BackendTask` enum (`src/backend_task/mod.rs:92-100`) and the action/channel
| `CoreTask::CreateAssetLock` | **modified** | Build via upstream; broadcast via `SpvRuntime`. Result unchanged. |
| `CoreTask::ListCoreWallets` | **hard-removed** | Named Core wallets are RPC-only; meaningless without RPC mode. Hard-removed immediately; UI entry point (Core-wallet picker) deleted same release (Decision #8). |
| `CoreTask::RecoverAssetLocks` | **hard-removed** | Upstream `AssetLockManager` tracks continuously; explicit recovery is obsolete. Hard-removed immediately; UI entry point deleted same release (Decision #8 — no one-release grace). |
| `IdentityTask::RegisterIdentity` / `IdentityTask::TopUpIdentity` | **modified — `FundWithUtxo` variants removed** | DAPI/SDK state-transition flows. `RegisterIdentityFundingMethod::FundWithUtxo` and `TopUpIdentityFundingMethod::FundWithUtxo` are removed in P4a.5 (no upstream funding-outpoint API exists at #3625 head; cannot be preserved). Accepted user-facing behavior change: identity registration and top-up are funded only from wallet-managed balance via `WalletBackend::create_asset_lock_proof`. External scanned-outpoint direct funding is removed and disclosed via the one-time post-migration notice. All other identity task variants (transfer, withdraw, add_key, load, discover, refresh) are internally rewired with signatures stable and UI unaffected. |
| `IdentityTask::RegisterIdentity` / `IdentityTask::TopUpIdentity` | **modified — `FundWithUtxo` variants removed** | DAPI/SDK state-transition flows. `RegisterIdentityFundingMethod::FundWithUtxo` and `TopUpIdentityFundingMethod::FundWithUtxo` are removed in P4a.5 (no upstream funding-outpoint API exists at #3625 head; cannot be preserved). Accepted user-facing behavior change: identity registration and top-up are funded only from wallet-managed balance via `WalletBackend::create_asset_lock_proof`. External scanned-outpoint direct funding is removed and disclosed via CHANGELOG. All other identity task variants (transfer, withdraw, add_key, load, discover, refresh) are internally rewired with signatures stable and UI unaffected. |
| `IdentityTask::*` (transfer/withdraw/add_key/load/discover/refresh) | **mostly kept, internally rewired** | DAPI/SDK state-transition flows — zero `CoreBackendMode` branches. Identity state read via upstream `IdentityManager`/`IdentityWallet`; `QualifiedIdentity` blob retained. Signatures stable; UI unaffected. `discover_identities` keeps DET Devnet path (see [open-questions.md #4](open-questions.md)). |
| `IdentityTask::RegisterDpnsName`, DPNS load/refresh | **kept** | No upstream DPNS register flow (`DpnsNameInfo` is read-only). DET-owned permanently. |
| `DashPayTask::*` (contact request/accept, profile, avatar, auto-accept, incoming payments) | **modified, hybrid** | Contact-request/established-contact/profile state + crypto via upstream; DET keeps orchestration, avatar I/O, auto-accept proof, incoming-payment detection (Decision #5 hybrid split). DIP-14/15 derivation delegated upstream (`dip14_derivation.rs`/`hd_derivation.rs` deleted, subject to migration execution). Contacts are re-established on upstream derivation unconditionally — no quarantine error path (Decision #6, 2026-05-18 re-resolution; see [data-model-and-migration.md](data-model-and-migration.md) — "Accepted fund-accessibility trade-off"). `TaskError::DashPayContactDerivationIrreconcilable` is unused by the migration path — candidate for P4 removal if no other caller. Result variants stable; UI unchanged. |
Expand All @@ -62,4 +62,4 @@ Result variants and the action/channel contract are preserved — UI screens are
2. Single-key screens show a not-supported banner (read-only view of preserved data).
3. SPV sync-progress UI fed from upstream `sync_progress()` via thin `ConnectionStatus` adapter — visual parity, different source.
4. `RefreshWalletInfo` returns near-instantly (upstream is already syncing).
5. **`FundWithUtxo` removed (P4a.5):** The option to fund an identity directly from a scanned external outpoint (QR-direct-fund UI) is no longer available. Identity registration and top-up accept only wallet-managed balance as the funding source. This change is disclosed via the one-time post-migration informational notice shown to all migrated users.
5. **`FundWithUtxo` removed (P4a.5):** The option to fund an identity directly from a scanned external outpoint (QR-direct-fund UI) is no longer available. Identity registration and top-up accept only wallet-managed balance as the funding source. This change is disclosed via CHANGELOG.
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ No funding-outpoint API exists in `platform-wallet` at PR #3625 head. The `FundW
- `top_up_asset_lock_transaction_for_utxo`
- `asset_lock_transaction_for_utxo_from_private_key`

This is a user-facing capability removal. It is disclosed via the one-time post-migration notice (see [data-model-and-migration.md § Mandatory one-time informational notice](data-model-and-migration.md#accepted-fund-accessibility-trade-off-user-decision-2026-05-18)).
This is a user-facing capability removal. It is disclosed via CHANGELOG.

**Path 3 — `received_transaction_finality` slim (asset-lock-finality-only).**
Slim `context/transaction_processing.rs::received_transaction_finality` to handle only asset-lock finality. Delete the `Wallet.utxos` / `address_balances` / legacy-`utxos`-table write branches. RETAIN the asset-lock detection and registration branch: `store_asset_lock_transaction` + the finality-wait channel that `broadcast_and_commit_asset_lock` and `wait_for_asset_lock_proof` depend on. ZMQ call sites at `app.rs:1267,1285` stay — ZMQ is still required for asset-lock detection.
Expand Down Expand Up @@ -191,8 +191,7 @@ The Smythe security audit is a **release-blocking gate** at P5. No push to #860
|---|---|---|
| **I1** | Authoritative selection at construction | No code path selects spendable inputs from `WalletSnapshot` or any `Wallet.utxos` snapshot. All coin-selection goes through `WalletBackend::create_asset_lock_proof` or `WalletBackend::send_payment` (upstream live UTXO set). |
| **I2** | No DET-side parallel spend engine | The functions `select_unspent_utxos_for`, `select_utxos_with_fee_retry`, `generic_asset_lock_transaction`, `registration_asset_lock_transaction_for_utxo`, `top_up_asset_lock_transaction_for_utxo`, `asset_lock_transaction_for_utxo_from_private_key`, `remove_selected_utxos`, `build_multi_recipient_payment_transaction` are deleted, not orphaned. No dead caller, no commented-out call, no unreachable arm. |
<!-- TODO(DOC-003): Promised one-time post-migration notice (invariant I3) never shipped -->
| **I3** | `FundWithUtxo` removal disclosed | The one-time post-migration notice text ships in the release build. `RegisterIdentityFundingMethod::FundWithUtxo` and `TopUpIdentityFundingMethod::FundWithUtxo` variants are gone. No dead erroring arm remains in any match on either enum. |
| **I3** | `FundWithUtxo` removal disclosed | The removal is disclosed via CHANGELOG (no in-app one-time notice ships). `RegisterIdentityFundingMethod::FundWithUtxo` and `TopUpIdentityFundingMethod::FundWithUtxo` variants are gone. No dead erroring arm remains in any match on either enum. |
| **I4** | Crash-retry no-double-broadcast | Asset-lock transactions are stored (durable) before broadcast. Upstream deduplication prevents double-broadcast on retry. Store-before-broadcast ordering is verified by test. |
| **I5** | Path 3 deletion leaves asset-lock detection intact | `received_transaction_finality` no longer writes to `Wallet.utxos` / `address_balances` / legacy `utxos` table. The asset-lock detection branch (`store_asset_lock_transaction` + finality-wait channel) is fully functional. `broadcast_and_commit_asset_lock` and `wait_for_asset_lock_proof` succeed in test without any `Wallet` mutation. |
| **I6** | No frame-thread blocking | No code path added in P4a, P4a.5, or P4b causes the egui frame thread to await or block on a wallet operation. All upstream calls are dispatched through `BackendTask` / `WalletBackend` async methods. |
Expand Down
32 changes: 20 additions & 12 deletions docs/ai-design/2026-05-28-migration-tool/notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,19 +203,27 @@ idempotency is confirmed.

### `identity` (DET source file: `src/database/identities.rs`)

- **Source:** `identity` in `data.db`
- **Destination:** `identities.entry_blob` (typed BLOB column) in `platform-wallet-storage`
- **Mapping:** Deserialize DET's stored identity representation → serialize as
bincode-encoded `QualifiedIdentity` with a leading version byte prepended
- **Per-network split:** Yes
- **Gotchas:** Upstream schema uses a leading version byte in `entry_blob` for
forward/backward compatibility — this byte must be present and set correctly, or upstream
deserialization will silently produce garbage. Confirm the byte format with the
platform-wallet-storage author before implementing. This is the highest-risk table in the
migration.
> **SUPERSEDED (2026-07-13).** Design and task breakdown now live in
> `docs/ai-design/2026-07-13-legacy-identity-migration/design.md`. The entry below is kept
> for context; two of its claims are wrong. The destination is **not** upstream's
> `identities.entry_blob` — commit `b14bf32c` moved it to DET's own per-network k/v
> (`det:identity:v1` under `DetScope::Identity`, roster at `det:identity_index:v1`). And the
> version byte needs no agreement with the platform-wallet-storage author: `DetKv::put`
> prepends `kv::SCHEMA_VERSION` automatically, so an importer that goes through
> `AppContext::insert_local_qualified_identity` gets it for free.

- **Source:** `identity` in `data.db` (`is_local = 1 AND data IS NOT NULL`)
- **Destination:** `StoredQualifiedIdentity` in DET's per-network k/v — see the design doc
- **Mapping:** `QualifiedIdentity::from_bytes(row.data)` → restore `status` from its column →
`AppContext::insert_local_qualified_identity(&qi, &wallet_link)`. The `data` BLOB carries
**all identity key material**; there is no second key table in v0.9.3.
- **Per-network split:** Yes — two-value filter (`mainnet` / legacy `dash`)
- **Gotchas:** The real risk is cross-version bincode compatibility of the `data` BLOB, not a
version byte. Every DET-side and dpp-side struct in the blob was verified unchanged between
v0.9.3 and HEAD; only the `bincode` rc.3 → 2.0.1 wire format is unproven, and a golden-blob
test closes it. Still the highest-risk table in the migration.
- **Status:** DONE for new-install path — see commit `b14bf32c` (identities + tokens →
per-network k/v). Migration tool still needs to import legacy rows with the version-byte
contract correct.
per-network k/v). Migration tool still needs to import legacy rows.

---

Expand Down
3 changes: 2 additions & 1 deletion docs/ai-design/2026-06-01-pr860-gap-audit/gaps.md
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,7 @@ absent in the working tree; none is a new gap.
| SPV peer-source expert setting ("Use local Dash Core node" for peer discovery) | OLD `network_chooser_screen.rs:1222-1269`; `db.get_use_local_spv_node()` | `removal-inventory.md:55` | Upstream owns peer discovery; devnet/regtest host config via `.env` unchanged. Record-only (was GAPCMP-D-06). |
| Proof Log screen + persistence | OLD `src/ui/tools/proof_log_screen.rs` (426 lines), `src/database/proof_log.rs`, `insert_proof_log_item` writers | `CHANGELOG.md:50`; commit `7778eb64` | Replaced by `tracing` target `"proof_log"` — history no longer survives restart. Stale doc refs → DOC-002. |
| "Total Received (DASH)" address-table column | OLD `address_table.rs` `TotalReceived` sortable column | In-code comment ("no upstream source post-migration") | CHANGELOG line missing → DOC-001. |
| Masternode List Diff inspector (`RootScreenType` slot 23) | OLD `src/ui/tools/masternode_list_diff_screen.rs` (~4460 lines) | `CHANGELOG.md` "Removed"; gravestone comment at `src/model/settings.rs` slot 23; `docs/user-stories.md` DEV-006 `[Removed]` | No replacement planned. Was undisclosed for six weeks after first flagged 2026-06-29; closed 2026-07-13. |

---

Expand Down Expand Up @@ -794,7 +795,7 @@ counted as new open gaps): TC-SK-010, TC-A11Y-008, TC-PERF-003.
| PROJ-021 | CHANGELOG omits single-key capability limits and DIP-14 trade-off | `CHANGELOG.md:31-46` | LOW | **RESOLVED (`f39b085d`)** | `### Known Limitations` section now states single-key send/refresh is unsupported this release and documents the DIP-14 non-mainnet/non-account-0 contact-fund re-establishment trade-off. |
| DOC-001 | CHANGELOG disclosure sweep — Removed/Known-Limitations/Fixed sections incomplete | `CHANGELOG.md:33-56` | MEDIUM | **RESOLVED 2026-06-11** (`1871c59f` + `23b81718`) — CHANGELOG Removed and Known Limitations sections updated; ZMQ and Dash-Qt launcher removals recorded in `23b81718`. |
| DOC-002 | Proof-log removal untracked in audit + stale user-story/persona refs | `docs/user-stories.md:878` (DEV-002 still `[Implemented]`); `docs/personas/platform-developer.md:27,75` | LOW | **RESOLVED 2026-06-11** (`1871c59f`) — DEV-002 user story tag flipped and persona references corrected. (was GAPCMP-B-3 + D-01) |
| DOC-003 | Promised one-time post-migration notice (invariant I3) never shipped | `docs/ai-design/2026-05-18-platform-wallet-migration/backendtask-contract.md:43,65`; `phasing.md:194` (I3); `docs/user-stories.md` IDN-014 rationale | LOW | OPEN (deferred-with-TODO, `727e8d6a`) | Three doc sites commit to an in-app one-time notice disclosing the QR-direct-fund removal; the only post-migration banner is the generic "Storage update complete — your wallet is ready." (`src/app.rs:1130-1137`). Either ship the notice text or amend I3 + the three doc sites to say "disclosed via CHANGELOG". (was GAPCMP-B-4) |
| DOC-003 | Promised one-time post-migration notice (invariant I3) never shipped | `docs/ai-design/2026-05-18-platform-wallet-migration/backendtask-contract.md:43,65`; `phasing.md:194` (I3); `docs/user-stories.md` IDN-014 rationale | LOW | **RESOLVED 2026-07-13** — the notice was never shipped and none is planned; all three sites (`backendtask-contract.md:43,65`, `phasing.md` I3) now say the removal is disclosed via CHANGELOG instead of promising an in-app notice. (was GAPCMP-B-4) |

**PROJ-018 (PARTIAL).** Verified at `docs/ai-design/2026-06-03-pr860-doc-followups/external-docs-draft.md`:
a full external-docs draft now exists, targeting `dashpay/docs` →
Expand Down
Loading