In general, it is preferable to use globally relevant identifiers where
possible. This PR removes the `WalletRead::TxRef` associated type in
favor of using `TxId` directly for the transaction identifier, and
restricts the use of the `NoteRef` type to those scenarios where the
result of one query is intended to be used directly as the input to
another query.
Closes#834
The `add_checkpoint` method is intended to be idempotent. In the case
that we add a checkpoint at an already-checkpointed block height, we
should only raise an error in the case that the note commitment tree
position or the set of notes spent in the checkpointed block has
changed.
The `shardtree` migration is applied to a database state that was
created via linear scanning, so we have complete wallet information for
those blocks.
We only need to load frontiers into the ShardTree that are close enough
to the wallet's known chain tip to fill `PRUNING_DEPTH` checkpoints, so
that ShardTree's witness generation will be able to correctly handle
anchor depths. Loading frontiers further back than this doesn't add any
useful nodes to the ShardTree (as we don't support rollbacks beyond
`PRUNING_DEPTH`, and we won't be finding notes in earlier blocks), and
hurts performance (as frontier importing has a significant Merkle tree
hashing cost).
Closeszcash/librustzcash#877.
Previously `extended_range` only covered the extent of the leaves of
all subtrees in which notes were found during a scan. When the scanned
range was large, this was not guaranteed to be contained within the
subtree leaves, causing an assertion failure when an invalid `ScanRange`
was constructed.
The Merkle hashes used for the note commitment trees are domain
separated by level, so when pretending that the subtree roots are leaves
of the cap tree, we need to adjust for their level not being zero.
Closeszcash/librustzcash#874.
Co-authored-by: Sean Bowe <ewillbefull@gmail.com>
This implements a priority queue backed by the wallet database for scan
range ordering. The scan queue is updated on each call to `put_blocks`
or to `update_chain_tip`.
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.
Memos may be absent for both sent and received notes in cases where only
compact block information has been used to populate the wallet database.
This fixes a potential crash in the case that we attempt to decode a
SQLite `NULL` as a byte array.
Fixes#384
(cherry picked from commit d99b4d4d6e)
Memos may be absent for both sent and received notes in cases where only
compact block information has been used to populate the wallet database.
This fixes a potential crash in the case that we attempt to decode a
SQLite `NULL` as a byte array. It does, however, introduce a slight
semantic confusion that will need to be considered in the case of future
updates where a note may not have an associated memo; at present, the
only reason we might not have the memo is that we might not have
retrieved the full transaction information from the chain, but in the
future there might be other possible reasons for this absence.
Fixes#384
This removes the `CommitmentTree`, `IncrementalWitness`, and
`MerklePath` types in favor of equivalent versions available
from the `incrementalmerkletree` crate.
This is in preparation for extraction into the `incrementalmerkletree`
crate, which is not Sapling-specific and therefore cannot hard-code
the depths of these data structures.
This better reflects the semantics of wallet behavior. Also, this
adds a `zcash_client_backend::WalletRead::get_min_unspent_height`
method that replaces the deprecated & removed (and misleadingly
named) `get_rewind_height` method.
This change also settles on `account_value_delta` as the name of the
column in `v_transactions` that describes the transaction's effect on
the value of the associated account.
This removes the path-based dependencies on the `zcash_note_encryption`
crate in favor of using versioned dependencies locally. This better
reflects the future state in which `zcash_note_encryption` is factored
out of the workspace and maintained in a separate repository.
The `halo2_proofs/multicore` flag must be disabled when running wasm
builds; this ensures that we do not accidentally include it as a
transitive dependency when building with `--no-default-features`.
This change makes it possible for wallets using the
`zcash_client_backend::data_api::wallet` module to perform transaction
preparation, including input selection and fee calculation, as an
independent step prior to creating proofs and signatures. This can be
used to improve user experience by making it possible to report the
proposed effects of the transaction to the wallet user (including
privacy implications) prior to authorizing the transaction.
Previously, if a caller wanted to use a block source to perform
scanning from the first available block, they would have to guess
at the block height to start from. Changing this to an optional
argument makes this explicit.
This allows callers to validate smaller intervals of the given
`BlockSourceT` shortening processing times of the function call at the
expense of obtaining a partial result on a given section of interest of
the block source.
`params: &ParamsT` has been removed from the arguments since they were
only needed to fall back to `sapling_activation_height` when `None` as
passed as the `validate_from` argument. Passing `None` as validation
start point on a pre-populated `block_source` would result in an error
`ChainError::block_height_discontinuity(sapling_activation_height - 1, current_height)`
With this new API callers must specify a concrete `validate_from`
argument and assume that `validate_chain` will not take any default
fallbacks to chain `ParamsT`.
The addition of a `limit` to the chain validation function changes the
meaning of its successful output, being now a `BlockHeight, BlockHash)`
tuple indicating the block height and block hash up to which the chain
as been validated on its continuity of heights and hashes. Callers
providing a `limit` aregument are responsible of subsequent calls to
`validate_chain()` to complete validating the remaining blocks stored on
the `block_source`.
Closeszcash/librustzcash#705
The MSRVs of the component crates are left as-is, partly because our
dependencies don't require us to bump them, and partly because those
crates have no pending changes and are relatively stable. We also plan
to split the component crates out into a separate repository, where it
will be easier to have a separate MSRV.
Closeszcash/librustzcash#759.