`fetch_params.sh` is now deprecated and the bundled proving parameters
from `wagyu-zcash-parameters` are used everywhere, so the tests should
follow suit.
Fixes#1016
This fixes an API issue whereby it was possible to execute a `Proposal`
with a different value of `min_confirmations` than that with which the
`Proposal` was constructed.
`StandardFeeRule` is an enumeration of the standard fees that have
existed in the history of Zcash zips. It is provided to simplify
transition to new fee strategies; legacy elements of this enumeration
are introduced already-deprecated.
The `v_transactions` view is built upon the set of received notes,
received note values being added to the balance for the transaction and
spent notes being deducted from this balance. This fixes an error
wherein if multiple identically-valued notes were spent in a
transaction, only one of those notes' values was being counted as having
been spent.
The `v_transactions` view is built upon the set of received notes,
received note values being added to the balance for the transaction and
spent notes being deducted from this balance. This fixes an error
wherein if multiple identically-valued notes were spent in a
transaction, only one of those notes' values was being counted as having
been spent.
The existing API limited change outputs to having only a single memo
repeated across each change output. This change makes it so that each
proposed change output can have its own associated memo, and leaves it
up to the input selector to determine how requested change memos are
associated with change outputs.
In order to use `uint64` for amounts that must be nonnegative in the
`proposal.proto` file, it is useful to update fee and change computation
to use `NonNegativeAmount` where possible.
When scanning, a wallet only needs to update balance and transaction
information shown to users when the scan has resulted in a change to
wallet state. This modifies `scan_cached_blocks` to return the range of
block heights actually scanned, along with the counts of notes spent and
received by the wallet in that range.
Fixes#918
We don't need to iterate over them, but the `*_extrema` internal methods
are semantically returning inclusive ranges, and using `RangeInclusive`
avoids bugs where the wrong half of the tuple is used (instead moving
the location of the tuple handling inside the `*_extrema` methods, which
cuts the number of occurrences from linear in the number of function
calls to constant).
The MSRV for the main crates is 1.65, which is higher than the Rust
version that stabilised workplace dependencies (1.64). The implicit MSRV
for the component crates is still lower than this, so we don't migrate
these crates.
Previously we used `Uuid::from_fields` to ensure that the various UUID
fields were correctly constructed, but now that we have a CI lint that
checks this automatically, we can consistently use `Uuid::from_u128`
which is easier to prepare from `uuidgen` output.
We don't know at truncation time what the latest chain tip is; the chain
might have reorged to a shorter heavier chain, or the reorg depth might
only be a few blocks. `WalletDb::chain_height` uses the scan queue as
its source of truth, so the `Verify` range we add during truncation
(to prioritise determining whether the rewind was sufficient) can't
extend beyond the block height we know to exist.
The next call to `WalletDb::update_chain_tip` will add additional ranges
beyond this height, which might include a `Verify` range that ends up
merging with the one added during truncation.
The `LEFT OUTER JOIN` was causing the `tx.block IS NULL` check to alias
two cases: an unspent transparent output, and a transparent output spent
in an unmined transaction. The latter only makes sense to include in the
UTXO count if the transaction is expired, and (due to limitations of the
transparent data model in the current wallet) if that expiry won't be
undone by a reorg. We now handle these two cases directly.
Partly reverts 8828276361.
Closeszcash/librustzcash#983.
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
At present, [zcash/zcash-android-wallet-sdk] supports Android API 27,
which bundles SQLite 3.19. SQLite support for the `TRUE` and `FALSE`
constants were introduced in SQLite 3.23, so we cannot currently use
these constants and retain support for Android API 27.
This version support limitation applies only to the `v_transactions`
and `v_tx_outputs` views, which are considered part of the public API
of this crate; other use of more recent SQLite features is fine because
they rely upon the SQLite bundled via our use of the `rusqlite` crate
and feature compatibility is verified via the unit tests of this crate.
This allows us to display additional block information when a
transparent UTXO was provided for a block that we have scanned.
Also, this ensures that memos from a wallet to itself are not
double-counted.
Co-authored-by: str4d <thestr4d@gmail.com>
Under normal usage conditions, the `transactions` table is not currently
populated for transactions involving transparent UTXOs, and so this join
was always resulting in transparent UTXO information being filtered out
from the transaction history.
Fixes [zcash/ZcashLightClientKit#1271]
This adds the `data_api::scanning::spanning_tree` module under
a new `unstable-spanning-tree` feature flag, making it available to
other implementations who want to be able to write their own storage
backends without having to reinvent the spanning tree logic.
This fixes the following bug:
Due to complexities related to non-linear scanning, checkpoints are only
added to the wallet's commitment tree in cases where there are notes
discovered within a scanned block. At present, the `shardtree` API only
makes it possible to add multiple checkpoints of the same tree state
when adding checkpoints at the chain tip, and this functionality is not
used by `zcash_client_backend` because we perform checkpoint insertion
in batches that may contain gaps in the case that multiple blocks
contain no Sapling notes. While it would be possible to fix this by
altering the `shardtree` API to permit explicit insertion of multiple
checkpoints of the same tree state at a given note position, this fix
takes a simpler approach.
Instead of ensuring that a checkpoint exists at every block and
computing the required checkpoint depth directly from the minimum number
of confirmations required when attempting a spend, we alter the
`WalletCommitmentTrees` API to allow internal information of the note
commitment tree to be used to determine this checkpoint depth, given the
minimum number of commitments as an argument. This allows us to select a
usable checkpoint from the sparse checkpoint set that resulted from the
sparse insertion of checkpoints described above.
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
This also removes the zcash_client_sqlite-specific database
initialization procedures in favor of a standardized approach using the
methods available via the data access API.
When `force_rescans` is set to `true` in a call to
`replace_queue_entries`, previously scanned ranges will have their
existing priority overwritten by the scan priority for a provided range;
otherwise, the existing scan priority dominance rule continues to be
enforced. This enables us to require previously scanned ranges be
re-scanned without interfering with higher-priority scan operations.
This change modifies the implementation of `get_spendable_sapling_notes`
and `select_spendable_sapling_notes` to only return notes at positions
where the associated note commitment tree shard has been fully scanned.
This is slightly more conservative than it needs to be, because
there could be cases where witnesses imported into the tree in the
`shardtree_support` migration cover the complete range of a subtree (and
hence that subtree doesn't need to be re-scanned). However, we can't
detect or depend upon that condition in general without attempting to
create a witness for each note retrieved.
A possible alternative to this approach would be to not bound our query
results on the requested total, and instead attempt to construct a
witness for each note we retrieve, skipping the note if we cannot
construct a witness. However, given that accessing the note commitment
tree can be a costly operation requiring nontrivial deserialization
costs, the more conservative database-oriented approach is perhaps
better.
Prior to the scan-before-sync changes, the wallet was able to assume
that the maximum scanned block height at the time of the spend was
within a few blocks of the chain tip. However, under linear scanning
after the spend-before-sync changes this invariant no longer holds,
resulting in a situation where in linear sync conditions the wallet
could attempt to create transactions with already-past expiry heights.
This change separates the notion of "chain tip" from "max scanned
height", relying upon the `scan_queue` table to maintain the wallet's
view of the consensus chain height and using information from the
`blocks` table only in situations where the latest and/or earliest
scanned height is required.
As part of this change, the `WalletRead` interface is also modified to
disambiguate these concepts.
Previously this was not clearly specified, and the implementations in
`zcash_client_sqlite` behaved similarly to when `from_height = None`.
Closeszcash/librustzcash#892.
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.