Instead of calling `put_block` for each block scanned,
`scan_cached_blocks` will now defer the block writes until the scan of a
batch is complete and will perform the block writes and note commitment
tree updates all within a single transaction.
This should ordinarily be fine in terms of memory consumption, because
the block data being saved is pruned to only that spend an output
information that is related to transactions in the wallet, which will
normally be sparse enough that the block range size that is appropriate
for a given platform to run within a batch scanner adequately bounds the
memory consumption of this pruned representation.
There are cases where we wish to return informaiton that is relevant to
a specific shielded protocol and `Transparent` is an invalid case. This
is a minor preparatory refactoring that makes this distinction
expressible.
In preparation for out-of-order range-based scanning, it is necessary
to ensure that the size of the Sapling note commitment tree is carried
along through the scan process and that stored blocks are always
persisted with the updated note commitment tree size.
Local chain validation will be performed internal to
`scan_cached_blocks`, and as handling of chain reorgs will need to
change to support out-of-order scanning, the `validate_chain` method
will be superfluous. It is removed in advance of other changes in order
to avoid updating it to reflect the forthcoming changes.
We move thes fields out into a separate BlockMetadata struct to ensure
that future additions to block metadata are structurally separated from
future additions to block data.
`rusqlite` includes a mechanism for creating prepared statements that
automatically caches them and reuses the caches when possible. This
means that it's unnecessary for us to do our own caching, and also
offers a minor performance improvement in that we don't need to eagerly
prepare statements that we may not execute in the lifetime of a given
`WalletDb` object. It also improves code locality, because the prepared
statements are now adjacent in the code to the parameter assignment
blocks that correspond to those statements.
This also updates a number of `put_x` methods to use sqlite upsert
functionality via the `ON CONFLICT` clause, instead of having to perform
separate inserts and updates.