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
dannywillems pushed a commit that referenced this pull request Jun 10, 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>
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