Skip to content

wallet.py: add sync barriers to fix flaky wallet-scan race#106

Closed
oxarbitrage wants to merge 1 commit into
mainfrom
fix/wallet-py-sync-race
Closed

wallet.py: add sync barriers to fix flaky wallet-scan race#106
oxarbitrage wants to merge 1 commit into
mainfrom
fix/wallet-py-sync-race

Conversation

@oxarbitrage

Copy link
Copy Markdown
Contributor

Closes #105

Motivation

wallet.py reads wallet state (z_gettotalbalance / z_listtransactions)
immediately after mining, before the embedded wallet has scanned and committed
the newly mined blocks. The transparent-balance assertion races the asynchronous
wallet scan and intermittently fails with 0 instead of the expected 6.25.

There is no synchronous "wallet has synced to height N" RPC to await yet
(tracked upstream in zcash/wallet#316), so the test must poll for the expected
wallet view rather than assuming immediate consistency after mining.

Solution

Add poll-barriers before the wallet-side assertions:

  • wait_for_wallet_transparent — wait until the transparent balance reflects the
    matured coinbase.
  • wait_for_wallet_txcount — wait until the wallet observes the expected number
    of transactions.

This mirrors the sync-barrier idiom already used in the migrated tests. No test
logic or coverage is changed — only the ordering guarantee that the wallet has
scanned before we assert on its view.

Test evidence

Run locally against zebrad + zainod + zallet (the zallet built with the
zcash/wallet#455 fix so sync reaches the wallet-scan stage):

wallet.py passes 3/3 consecutive runs (~7-8s each, exit 0,
"Missing Orchard tree state" = 0). Without the barriers the transparent-balance
assertion fails intermittently (0 vs 6.25).

Notes

wallet.py read z_gettotalbalance / z_listtransactions immediately after mining,
before the wallet had scanned and committed the new blocks, causing a flaky
transparent-balance assertion (0 vs 6.25). Poll for the expected wallet view
(no synchronous wallet-sync RPC yet, zcash/wallet#316) before the wallet-side
assertions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
oxarbitrage added a commit that referenced this pull request Jun 5, 2026
…s in wallet.py

The getwalletstatus sync barrier indexed `wallet_tip` unconditionally, but the
RPC omits that field (Option + skip_serializing_if) until the wallet has a
committed tip — which happens transiently right after blocks are mined. The
barrier therefore raised `KeyError: 'wallet_tip'` ~1 run in 4, exactly during
the window it is meant to poll through. Treat an absent wallet_tip as "not
synced yet" and keep polling, in sync_blocks, sync_mempools, and rebuild_cache.

Also make wallet.py use the now wallet-aware self.sync_all() instead of an
immediate read and a fixed time.sleep(1), removing the remaining flaky
wallet-scan race (and the unused `import time`). This supersedes the bespoke
pollers in #106.

Validated 10/10 green locally against a zallet carrying zcash/wallet#367
(getwalletstatus) + zcash/wallet#455 (empty shielded tree fix).

Closes #105

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@oxarbitrage

Copy link
Copy Markdown
Contributor Author

Superseded by #56. Now that zcash/wallet#367 adds getwalletstatus, the wallet-scan race is fixed the idiomatic way — wallet.py calls the now wallet-aware self.sync_all() instead of the bespoke wait_for_* pollers added here. #56 carries that change plus a fix for a KeyError: 'wallet_tip' in the new barrier, and Closes #105. Validated 10/10 green locally.

Branch fix/wallet-py-sync-race left in place for reference.

@oxarbitrage oxarbitrage closed this Jun 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant