Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change(zebra-scan): Scan only one key per backend call #8034

Merged
merged 2 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions zebra-scan/src/scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub async fn start(mut state: State, storage: Storage) -> Result<(), Report> {
}
}

/// Returns transactions belonging to any of the given [`ScanningKey`]s.
/// Returns transactions belonging to the given `ScanningKey`.
///
/// TODO:
/// - Remove the `sapling_tree_size` parameter or turn it into an `Option` once we have access to
Expand All @@ -78,7 +78,7 @@ pub fn scan_block<K: ScanningKey>(
network: Network,
block: Arc<Block>,
sapling_tree_size: u32,
scanning_keys: &[&K],
scanning_key: &K,
) -> Result<ScannedBlock<K::Nf>, ScanError> {
// TODO: Implement a check that returns early when the block height is below the Sapling
// activation height.
Expand All @@ -94,10 +94,8 @@ pub fn scan_block<K: ScanningKey>(
// Use a dummy `AccountId` as we don't use accounts yet.
let dummy_account = AccountId::from(0);

let scanning_keys: Vec<_> = scanning_keys
.iter()
.map(|key| (&dummy_account, key))
.collect();
// We only support scanning one key and one block per function call for now.
let scanning_keys = vec![(&dummy_account, scanning_key)];

zcash_client_backend::scanning::scan_block(
&network,
Expand Down
73 changes: 2 additions & 71 deletions zebra-scan/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,80 +34,11 @@ use ff::{Field, PrimeField};
use group::GroupEncoding;

use zebra_chain::{
block::Block, chain_tip::ChainTip, parameters::Network, serialization::ZcashDeserializeInto,
transaction::Hash,
block::Block, chain_tip::ChainTip, serialization::ZcashDeserializeInto, transaction::Hash,
};

use crate::scan::{block_to_compact, scan_block};

/// Scans a continuous chain of Mainnet blocks from tip to genesis.
///
/// Also verifies that no relevant transaction is found in the chain when scanning for a fake
/// account's nullifier.
#[tokio::test]
async fn scanning_from_populated_zebra_state() -> Result<()> {
let network = Network::default();

// Create a continuous chain of mainnet blocks from genesis
let blocks: Vec<Arc<Block>> = zebra_test::vectors::CONTINUOUS_MAINNET_BLOCKS
.iter()
.map(|(_height, block_bytes)| block_bytes.zcash_deserialize_into().unwrap())
.collect();

// Create a populated state service.
let (_state_service, read_only_state_service, latest_chain_tip, _chain_tip_change) =
zebra_state::populated_state(blocks.clone(), network).await;

let db = read_only_state_service.db();

// use the tip as starting height
let mut height = latest_chain_tip.best_tip_height().unwrap();

let mut transactions_found = 0;
let mut transactions_scanned = 0;
let mut blocks_scanned = 0;
// TODO: Accessing the state database directly is ok in the tests, but not in production code.
// Use `Request::Block` if the code is copied to production.
while let Some(block) = db.block(height.into()) {
// We use a dummy size of the Sapling note commitment tree. We can't set the size to zero
// because the underlying scanning function would return
// `zcash_client_backeng::scanning::ScanError::TreeSizeUnknown`.
let sapling_commitment_tree_size = 1;

let orchard_commitment_tree_size = 0;

let chain_metadata = ChainMetadata {
sapling_commitment_tree_size,
orchard_commitment_tree_size,
};

let compact_block = block_to_compact(block.clone(), chain_metadata);

let res =
scan_block::<SaplingIvk>(network, block, sapling_commitment_tree_size, &[]).unwrap();

transactions_found += res.transactions().len();
transactions_scanned += compact_block.vtx.len();
blocks_scanned += 1;

if height.is_min() {
break;
}

// scan backwards
height = height.previous()?;
}

// make sure all blocks and transactions were scanned
assert_eq!(blocks_scanned, 11);
assert_eq!(transactions_scanned, 11);

// no relevant transactions should be found
assert_eq!(transactions_found, 0);

Ok(())
}

/// Prove that we can create fake blocks with fake notes and scan them using the
/// `zcash_client_backend::scanning::scan_block` function:
/// - Function `fake_compact_block` will generate 1 block with one pre created fake nullifier in
Expand Down Expand Up @@ -209,7 +140,7 @@ async fn scanning_zecpages_from_populated_zebra_state() -> Result<()> {

let compact_block = block_to_compact(block.clone(), chain_metadata);

let res = scan_block(network, block, sapling_commitment_tree_size, &[&ivk])
let res = scan_block(network, block, sapling_commitment_tree_size, &ivk)
.expect("scanning block for the ZECpages viewing key should work");

transactions_found += res.transactions().len();
Expand Down
Loading