zcash_client_backend: Add `WalletRead::block_max_scanned`

Fixes #941
This commit is contained in:
Kris Nuttycombe 2023-09-06 08:47:51 -06:00
parent b4772e948d
commit 65420f59df
5 changed files with 55 additions and 6 deletions

View File

@ -34,8 +34,10 @@ and this library adheres to Rust's notion of
- `ShieldedProtocol`
- `WalletCommitmentTrees`
- `WalletSummary`
- `WalletRead::{chain_height, block_metadata, block_fully_scanned, suggest_scan_ranges,
get_wallet_birthday, get_account_birthday, get_wallet_summary}`
- `WalletRead::{
chain_height, block_metadata, block_max_scanned, block_fully_scanned,
suggest_scan_ranges, get_wallet_birthday, get_account_birthday, get_wallet_summary
}`
- `WalletWrite::{put_blocks, update_chain_tip}`
- `chain::CommitmentTreeRoot`
- `scanning` A new module containing types required for `suggest_scan_ranges`

View File

@ -233,6 +233,13 @@ pub trait WalletRead {
/// block.
fn block_fully_scanned(&self) -> Result<Option<BlockMetadata>, Self::Error>;
/// Returns block metadata for the maximum height that the wallet has scanned.
///
/// If the wallet is fully synced, this will be equivalent to `block_fully_scanned`;
/// otherwise the maximal scanned height is likely to be greater than the fully scanned height
/// due to the fact that out-of-order scanning can leave gaps.
fn block_max_scanned(&self) -> Result<Option<BlockMetadata>, Self::Error>;
/// Returns a vector of suggested scan ranges based upon the current wallet state.
///
/// This method should only be used in cases where the [`CompactBlock`] data that will be made
@ -945,6 +952,10 @@ pub mod testing {
Ok(None)
}
fn block_max_scanned(&self) -> Result<Option<BlockMetadata>, Self::Error> {
Ok(None)
}
fn suggest_scan_ranges(&self) -> Result<Vec<ScanRange>, Self::Error> {
Ok(vec![])
}

View File

@ -180,6 +180,10 @@ impl<C: Borrow<rusqlite::Connection>, P: consensus::Parameters> WalletRead for W
wallet::block_fully_scanned(self.conn.borrow())
}
fn block_max_scanned(&self) -> Result<Option<BlockMetadata>, Self::Error> {
wallet::block_max_scanned(self.conn.borrow())
}
fn suggest_scan_ranges(&self) -> Result<Vec<ScanRange>, Self::Error> {
wallet::scanning::suggest_scan_ranges(self.conn.borrow(), ScanPriority::Historic)
.map_err(SqliteClientError::from)

View File

@ -1086,6 +1086,33 @@ pub(crate) fn block_fully_scanned(
}
}
pub(crate) fn block_max_scanned(
conn: &rusqlite::Connection,
) -> Result<Option<BlockMetadata>, SqliteClientError> {
conn.query_row(
"SELECT blocks.height, hash, sapling_commitment_tree_size, sapling_tree
FROM blocks
JOIN (SELECT MAX(height) AS height FROM blocks) blocks_max
ON blocks.height = blocks_max.height",
[],
|row| {
let height: u32 = row.get(0)?;
let block_hash: Vec<u8> = row.get(1)?;
let sapling_tree_size: Option<u32> = row.get(2)?;
let sapling_tree: Vec<u8> = row.get(3)?;
Ok((
BlockHeight::from(height),
block_hash,
sapling_tree_size,
sapling_tree,
))
},
)
.optional()
.map_err(SqliteClientError::from)
.and_then(|meta_row| meta_row.map(parse_block_metadata).transpose())
}
/// Returns the block height at which the specified transaction was mined,
/// if any.
pub(crate) fn get_tx_height(
@ -1892,8 +1919,6 @@ pub(crate) fn prune_nullifier_map(
mod tests {
use std::num::NonZeroU32;
use zcash_primitives::transaction::components::Amount;
use zcash_client_backend::data_api::{AccountBirthday, WalletRead};
use crate::{testing::TestBuilder, AccountId};
@ -1906,7 +1931,7 @@ mod tests {
},
zcash_primitives::{
consensus::BlockHeight,
transaction::components::{OutPoint, TxOut},
transaction::components::{Amount, OutPoint, TxOut},
},
};

View File

@ -465,7 +465,7 @@ pub(crate) mod tests {
use crate::{
error::SqliteClientError,
testing::{AddressType, BlockCache, TestBuilder, TestState},
wallet::commitment_tree,
wallet::{block_max_scanned, commitment_tree},
AccountId, NoteId, ReceivedNoteId,
};
@ -501,6 +501,13 @@ pub(crate) mod tests {
// Verified balance matches total balance
assert_eq!(st.get_total_balance(account), value);
assert_eq!(
block_max_scanned(&st.wallet().conn)
.unwrap()
.unwrap()
.block_height(),
h
);
let to_extsk = ExtendedSpendingKey::master(&[]);
let to: RecipientAddress = to_extsk.default_address().1.into();