Skip to content

Persist the Zano wallet file once synced and run adopted wallets - #1090

Open
j0ntz wants to merge 1 commit into
masterfrom
jon/ios-perf-zano-xmr
Open

Persist the Zano wallet file once synced and run adopted wallets#1090
j0ntz wants to merge 1 commit into
masterfrom
jon/ios-perf-zano-xmr

Conversation

@j0ntz

@j0ntz j0ntz commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Technical Design Document

zano-migration-off-module-queue.md

CHANGELOG

Does this branch warrant an entry to the CHANGELOG?

  • Yes
  • No

Dependencies

EdgeApp/react-native-zano#17 (behavioral, not build-time: the adopt-path run_wallet call only matters under that PR's postponed-run mode, and is a harmless no-op on react-native-zano 0.4.0, so this PR builds and passes CI standalone)

Description

Part of the fix for the iOS performance regression investigated in https://app.asana.com/0/1215088146871429/1217559756673909.

The Zano native library only writes the wallet file to disk when a wallet closes, and a mobile app is killed rather than closed, so a wallet's sync progress was almost never persisted. Every cold launch re-scanned everything since the file was last written, a window that only grows, re-paid at full multi-core CPU on each launch (measured ~200-420% process CPU for ~6 minutes per launch on a sim account whose three Zano wallets were 26 days behind).

  • syncNetwork's synced branch now stores the wallet file through the per-wallet RPC (invoke {"method":"store"}): once when the wallet first reaches synced, then at most every ten minutes, and only when the wallet height advanced past the last store. It runs only while synced, when the refresh worker is idle and the per-wallet lock is free, so the call cannot block behind a scan. A failed store logs and moves on, costing only a longer catch-up on the next launch.
  • The ALREADY_EXISTS adopt path now starts the refresh worker (run_wallet, idempotent) for the adopted wallet. Under react-native-zano's postponed-run mode a wallet left open by an interrupted startWallet is not yet running, and adopting it without this call would hand back a wallet that never syncs. A failed run_wallet throws rather than returning the id, so the lifecycle manager retries the start instead of holding a never-syncing wallet.
  • resyncBlockchain resets the store gates, so the rebuilt wallet's file is written at the first synced tick after the rescan instead of waiting out the throttle.

Verified on the iOS sim (edge-funds, three Zano wallets): after each wallet reached synced its file was rewritten within the interval (1.7KB restore stubs grew to 80-158KB full wallets), and a subsequent relaunch opened all three wallets already at the chain tip with no catch-up scan, idling where the pre-fix build re-paid the full multi-minute scan every launch.

@j0ntz

j0ntz commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

📸 Test evidence

after fix relaunch

after fix relaunch

Captured by the agent's in-app test run (build-and-test).

@j0ntz
j0ntz marked this pull request as ready for review August 18, 2026 20:59
@j0ntz
j0ntz force-pushed the jon/ios-perf-zano-xmr branch from 49cefa5 to e5ee4ae Compare August 18, 2026 20:59
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e5ee4ae. Configure here.

Comment thread src/zano/ZanoEngine.ts
Comment thread src/zano/ZanoEngine.ts
@j0ntz
j0ntz force-pushed the jon/ios-perf-zano-xmr branch from e5ee4ae to 422e70c Compare August 18, 2026 21:10
paullinator

This comment was marked as outdated.

@paullinator
paullinator dismissed their stale review August 20, 2026 03:31

Retracting review so comments can be filtered locally first.

paullinator

This comment was marked as outdated.

@paullinator paullinator left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Moving the in-flight storeWalletFile warning onto the new method.

Additional Findings

  • warning 422e70c4331cbc873469ce5363b5480a91474ac5:1: Commit subject is 64 characters: “Persist the Zano wallet file once synced and run adopted wallets”. Edge commit subjects must be at most 50 characters.
    • Shorten to ≤50 characters, e.g. “Persist synced Zano wallets and run adopted ones”.

Comment thread src/zano/ZanoEngine.ts
@j0ntz
j0ntz force-pushed the jon/ios-perf-zano-xmr branch from 422e70c to 903a893 Compare August 20, 2026 18:40
The native library only writes the wallet file when a wallet closes, and
a mobile app is killed rather than closed, so every launch re-scanned
everything since the file was last written. Store the file when the
wallet reaches synced and every ten minutes afterwards, from the synced
branch where the refresh worker is idle and the per-wallet lock is free.

Also start the refresh worker when adopting an already-open wallet:
react-native-zano 0.4.1 opens wallets with the worker postponed, so a
wallet left open by an interrupted startWallet would otherwise sit idle.
The call is idempotent, so it is safe on a wallet that is already
running.
@j0ntz
j0ntz force-pushed the jon/ios-perf-zano-xmr branch from 903a893 to 510e72b Compare August 20, 2026 19:39
@j0ntz

j0ntz commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

Commit subject is now 48 characters: Persist synced Zano wallets and run adopted ones.

The three inline threads from this review round are fixed and resolved: the store/run_wallet responses go through asMaybe(asJSON(...)), the adopt-path comment is tied to postponed-run from 0.4.1 (the range stays ^0.4.0 because the call is a no-op there), and resyncBlockchain bumps a store generation that storeWalletFile re-checks before recording lastStoreTime/lastStoreHeight.

The wider findings in your dismissed review of the same day are not addressed here. Two of them are real and Zano-side (onStart awaiting keysPromise with no abort, and the adopt path throwing on an address mismatch without closing the handle); the Monero and Zcash engine items sit outside this PR's diff. Say if you want any of them folded in and I will take them, otherwise they are worth their own task.

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.

2 participants