zcash_client_backend: Add desired Sapling shard index to `WalletSummary`

Closes zcash/librustzcash#1124.
This commit is contained in:
Jack Grigg 2024-01-24 17:31:23 +00:00
parent 11355e4095
commit db071f2e1f
4 changed files with 50 additions and 1 deletions

View File

@ -21,6 +21,7 @@ and this library adheres to Rust's notion of
with_orchard_balance_mut,
add_unshielded_value
}`
- `WalletSummary::next_sapling_subtree_index`
- `wallet::propose_standard_transfer_to_address`
- `wallet::input_selection::Proposal::{from_parts, shielded_inputs}`
- `wallet::input_selection::ShieldedInputs`
@ -81,6 +82,8 @@ and this library adheres to Rust's notion of
- Fields of `Balance` and `AccountBalance` have been made private and the values
of these fields have been made available via methods having the same names
as the previously-public fields.
- `WalletSummary::new` now takes an additional `next_sapling_subtree_index`
argument.
- `WalletWrite::get_next_available_address` now takes an additional
`UnifiedAddressRequest` argument.
- `chain::scan_cached_blocks` now returns a `ScanSummary` containing metadata

View File

@ -288,6 +288,7 @@ pub struct WalletSummary {
chain_tip_height: BlockHeight,
fully_scanned_height: BlockHeight,
scan_progress: Option<Ratio<u64>>,
next_sapling_subtree_index: u64,
}
impl WalletSummary {
@ -297,12 +298,14 @@ impl WalletSummary {
chain_tip_height: BlockHeight,
fully_scanned_height: BlockHeight,
scan_progress: Option<Ratio<u64>>,
next_sapling_subtree_idx: u64,
) -> Self {
Self {
account_balances,
chain_tip_height,
fully_scanned_height,
scan_progress,
next_sapling_subtree_index: next_sapling_subtree_idx,
}
}
@ -332,6 +335,12 @@ impl WalletSummary {
self.scan_progress
}
/// Returns the Sapling subtree index that should start the next range of subtree
/// roots passed to [`WalletCommitmentTrees::put_sapling_subtree_roots`].
pub fn next_sapling_subtree_index(&self) -> u64 {
self.next_sapling_subtree_index
}
/// Returns whether or not wallet scanning is complete.
pub fn is_synced(&self) -> bool {
self.chain_tip_height == self.fully_scanned_height

View File

@ -66,7 +66,7 @@
use incrementalmerkletree::Retention;
use rusqlite::{self, named_params, OptionalExtension};
use shardtree::ShardTree;
use shardtree::{error::ShardTreeError, store::ShardStore, ShardTree};
use std::collections::{BTreeMap, HashMap};
use std::convert::TryFrom;
use std::io::{self, Cursor};
@ -744,11 +744,34 @@ pub(crate) fn get_wallet_summary<P: consensus::Parameters>(
drop(transparent_trace);
}
let next_sapling_subtree_index = {
// This will return a runtime error if we call `get_wallet_summary` from two
// threads at the same time, as transactions cannot nest.
let tx = conn.unchecked_transaction()?;
let shard_store =
SqliteShardStore::<_, ::sapling::Node, SAPLING_SHARD_HEIGHT>::from_connection(
&tx,
SAPLING_TABLES_PREFIX,
)?;
// The last shard will be incomplete, and we want the next range to overlap with
// the last complete shard, so return the index of the second-to-last shard root.
shard_store
.get_shard_roots()
.map_err(ShardTreeError::Storage)?
.iter()
.rev()
.nth(1)
.map(|addr| addr.index())
.unwrap_or(0)
};
let summary = WalletSummary::new(
account_balances,
chain_tip_height,
fully_scanned_height,
sapling_scan_progress,
next_sapling_subtree_index,
);
Ok(Some(summary))

View File

@ -636,6 +636,16 @@ pub(crate) mod tests {
scan_range((sap_active + 300)..(sap_active + 310), ChainTip)
]
);
// The wallet summary should be requesting the second-to-last root, as the last
// shard is incomplete.
assert_eq!(
st.wallet()
.get_wallet_summary(0)
.unwrap()
.map(|s| s.next_sapling_subtree_index()),
Some(2),
);
}
pub(crate) fn test_with_canopy_birthday() -> (
@ -970,6 +980,10 @@ pub(crate) mod tests {
// We have scanned a block, so we now have a starting tree position, 500 blocks above the
// wallet birthday but before the end of the shard.
let summary = st.get_wallet_summary(1);
assert_eq!(
summary.as_ref().map(|s| s.next_sapling_subtree_index()),
Some(0),
);
assert_eq!(
summary.and_then(|s| s.scan_progress()),
Some(Ratio::new(1, 0x1 << SAPLING_SHARD_HEIGHT))