sync: Ensure initialize leaves block_metadata(tip) populated#480
Closed
Cosmos-Harry wants to merge 1 commit into
Closed
sync: Ensure initialize leaves block_metadata(tip) populated#480Cosmos-Harry wants to merge 1 commit into
initialize leaves block_metadata(tip) populated#480Cosmos-Harry wants to merge 1 commit into
Conversation
The scan-range loop in `initialize` can complete without ever routing the tip block through `put_blocks` — e.g. when the wallet has no shielded scan work and `suggest_scan_ranges` returns nothing in the bands the filter accepts. `update_chain_tip` then records the new height but no `BlockMetadata` is committed for it, and any caller asking the wallet for its view of the tip via `getwalletstatus.wallet_tip` sees `None` indefinitely. This strands integration-tests `rebuild_cache`, which spawns several trivially-synced wallets in parallel and waits for all of them to report a `wallet_tip` matching `node_tip`; shards exercising this path hang until the GitHub Actions 6h cap cancels them. Force a tip scan when no scan range covered it. `scan_block` is cheap when there are no notes to detect.
Collaborator
Author
|
Superseded by #483 — same commit ( |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Unblocks the CI hang where shards 0–2 of the integration tests run for the full 6-hour GitHub Actions cap and get cancelled (the pattern that's been hitting #476 dispatches).
This is a targeted workaround in zallet for a deeper API gap in
zcash_client_backend. See "Where the proper fix belongs" below — happy to follow up with alibrustzcashchange if preferred that direction, but I think we want CI unblocked first.Root cause
The scan-range loop in
initializecan legitimately complete without ever routing the tip block throughput_blocks— for example when the wallet has no shielded scan work andsuggest_scan_rangesreturns nothing in the bands the filter accepts (Verify/≥ Historic).update_chain_tiprecords the new height in the scan queue, but noBlockMetadatais committed for the tip, so:WalletRead::chain_heightreturnsSome(tip)✅WalletRead::block_metadata(tip)returnsNone❌getwalletstatus.wallet_tip— implemented aschain_height+block_metadata(chain_height)— is omitted from the responseThis strands integration-tests'
rebuild_cache, which spawns 8 trivially-synced wallets in parallel and waits in awhile True:loop with no timeout for all of them to report awallet_tipmatchingnode_tip. The shards that trigger this path (those withlen(test_list) > 1, which makesrpc-tests.pyinvokecreate_cache.py) wait forever.Empirically on recent #476 dispatches: shards 0, 1, 2 cancelled at exactly 360 min every run; shards 3–9 finished in under 2 min.
Fix in this PR
After the existing scan-range loop in
initialize, ifblock_metadata(current_tip.height)is stillNone, take a fresh chain snapshot, fetch the tip block, and route it through the existingscan_blockhelper. ~25 lines, single file.Behavior for the two real cases:
block_metadata(tip)returnsSome), no scan triggered. Effectively free.put_blockscommits the metadata.The new invariant is "
initializealways leaves committed metadata for the tip it reported viaupdate_chain_tip," which seems independently sensible — every other code path that toucheschain_heightalready assumes scan state up to that height is available.Where the proper fix belongs
The semantic root cause is in
zcash_client_backend::data_api:WalletRead::chain_height()records "the height I've been told about" — independent of scan progress.WalletRead::block_metadata(h)records "data for a fully scanned block."chain_height, so any caller that wants the wallet's view of the tip in (height, hash) form has to go throughblock_metadata— which conflates the two concepts.The clean fix is to extend the trait:
WalletWrite::update_chain_tip_with_hash(height, hash)with a default impl that forwards to the existing height-only method (non-breaking).WalletRead::chain_tip() -> Option<(BlockHeight, BlockHash)>with a default impl returningOk(None)(also non-breaking).zcash_client_sqlitewith a one-rowchain_tiptable populated by the hash-aware update path.getwalletstatus.wallet_tipto readchain_tip(); switchinitializeto callupdate_chain_tip_with_hash.This properly separates tip-awareness from scan progress and matches what
wallet_tip's docstring already promises ("the wallet's view of the chain tip"). I have a draft of this change locally (~50 lines in librustzcash + ~10 lines in zallet, with a sqlite migration and a roundtrip test); happy to open it if maintainers would rather take that route now and skip this workaround.Test plan