The `v_sapling_shard_scan_ranges` view pairs every scan range with every
shard range, such that each row shows an overlapping pair.
For the complete shards, this is an overlap check between two ranges,
which the previous query was performing correctly (if verbosely).
For the last incomplete shard, we have a half-open range that needs to
be handled separately. The previous query only handled the case where a
scan range was contained within the last shard, and did not handle the
case where the scan range contained the last shard.
This led to a puzzling bug, where `WalletDb::get_wallet_summary` was
sometimes treating any note received within the last shard as part of
the wallet's pending balance. If the wallet's scan queue contained a
range that encompassed the last incomplete shard, the bug in the
`v_sapling_shard_scan_ranges` view meant that it omitted any mention of
the last shard, which translated into these notes being considered
unmined when joining `sapling_received_notes` against the sub-view
`v_sapling_shards_scan_state`.
The bug was made harder to diagnose due to the previous commit's bug
that was causing scan ranges to not be correctly merged; this resulted
in smaller scan ranges that were more likely to be contained within the
last shard, making it visible in `v_sapling_shard_scan_ranges` and
enabling notes to be detected as mined.
The fixed view uses a simpler query that enables us to handle complete
and incomplete shards together.
Time spent investigating and fixing: 4.5 hours
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
In the sandblasting block ranges, shard trees only cover a few hundred
blocks at most. When scanning block ranges much larger than this, it is
likely that when a note is discovered, its parent shard tree is entirely
contained within the scan range. In this situation, `extended_range`
would be set to `range`, and then because an extended range existed,
ranges with `FoundNote` priority would always be created - that in this
case are empty.
In an effectively-linear-scanning wallet situation, this leads to a
`SpanningTree` being constructed with adjacent `Scanned` ranges,
separated by empty `FoundNote` ranges, which it was unable to merge.
We address this by both preventing generation of the empty `FoundNote`
ranges, and by defensively fixing `SpanningTree::into_vec` to skip empty
ranges.
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
This modifies `update_chain_tip` and `scan_complete` to ensure that
newly created scan ranged do not extend below the wallet birthday
height.
Fixes#947
The previous code was checking that the existing shard range was at
least partially inside the proposed insertion range, but this didn't
handle the case where the proposed insertion range was fully contained
by the existing shard range.
The intent of this API is to provide a single API which returns in a
single call:
* per-account balances, including pending values
* wallet sync progress
Fixes#865Fixes#900