feat(scanner): Don't scan and log if we are below sapling height (#8121)
* do not scan and notify if we are below sapling height * separate tip logic check into its own loop
This commit is contained in:
parent
141ea89aad
commit
085bfdc067
|
@ -63,6 +63,19 @@ pub async fn start(
|
||||||
storage: Storage,
|
storage: Storage,
|
||||||
) -> Result<(), Report> {
|
) -> Result<(), Report> {
|
||||||
let network = storage.network();
|
let network = storage.network();
|
||||||
|
let sapling_activation_height = storage.min_sapling_birthday_height();
|
||||||
|
|
||||||
|
// Do not scan and notify if we are below sapling activation height.
|
||||||
|
loop {
|
||||||
|
let tip_height = tip_height(state.clone()).await?;
|
||||||
|
if tip_height < sapling_activation_height {
|
||||||
|
info!("scanner is waiting for sapling activation. Current tip: {}, Sapling activation: {}", tip_height.0, sapling_activation_height.0);
|
||||||
|
tokio::time::sleep(CHECK_INTERVAL).await;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Read keys from the storage on disk, which can block async execution.
|
// Read keys from the storage on disk, which can block async execution.
|
||||||
let key_storage = storage.clone();
|
let key_storage = storage.clone();
|
||||||
let key_heights = tokio::task::spawn_blocking(move || key_storage.sapling_keys_last_heights())
|
let key_heights = tokio::task::spawn_blocking(move || key_storage.sapling_keys_last_heights())
|
||||||
|
@ -70,7 +83,7 @@ pub async fn start(
|
||||||
.await;
|
.await;
|
||||||
let key_heights = Arc::new(key_heights);
|
let key_heights = Arc::new(key_heights);
|
||||||
|
|
||||||
let mut height = get_min_height(&key_heights).unwrap_or(storage.min_sapling_birthday_height());
|
let mut height = get_min_height(&key_heights).unwrap_or(sapling_activation_height);
|
||||||
|
|
||||||
// Parse and convert keys once, then use them to scan all blocks.
|
// Parse and convert keys once, then use them to scan all blocks.
|
||||||
// There is some cryptography here, but it should be fast even with thousands of keys.
|
// There is some cryptography here, but it should be fast even with thousands of keys.
|
||||||
|
@ -149,7 +162,7 @@ pub async fn scan_height_and_store_results(
|
||||||
let block = match block {
|
let block = match block {
|
||||||
zebra_state::Response::Block(Some(block)) => block,
|
zebra_state::Response::Block(Some(block)) => block,
|
||||||
zebra_state::Response::Block(None) => return Ok(None),
|
zebra_state::Response::Block(None) => return Ok(None),
|
||||||
_ => unreachable!("unmatched response to a state::Tip request"),
|
_ => unreachable!("unmatched response to a state::Block request"),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Scan it with all the keys.
|
// Scan it with all the keys.
|
||||||
|
@ -400,3 +413,20 @@ fn scanned_block_to_db_result<Nf>(
|
||||||
fn get_min_height(map: &HashMap<String, Height>) -> Option<Height> {
|
fn get_min_height(map: &HashMap<String, Height>) -> Option<Height> {
|
||||||
map.values().cloned().min()
|
map.values().cloned().min()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get tip height or return genesis block height if no tip is available.
|
||||||
|
async fn tip_height(mut state: State) -> Result<Height, Report> {
|
||||||
|
let tip = state
|
||||||
|
.ready()
|
||||||
|
.await
|
||||||
|
.map_err(|e| eyre!(e))?
|
||||||
|
.call(zebra_state::Request::Tip)
|
||||||
|
.await
|
||||||
|
.map_err(|e| eyre!(e))?;
|
||||||
|
|
||||||
|
match tip {
|
||||||
|
zebra_state::Response::Tip(Some((height, _hash))) => Ok(height),
|
||||||
|
zebra_state::Response::Tip(None) => Ok(Height(0)),
|
||||||
|
_ => unreachable!("unmatched response to a state::Tip request"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2820,39 +2820,36 @@ async fn fully_synced_rpc_z_getsubtreesbyindex_snapshot_test() -> Result<()> {
|
||||||
#[cfg(feature = "shielded-scan")]
|
#[cfg(feature = "shielded-scan")]
|
||||||
fn scan_task_starts() -> Result<()> {
|
fn scan_task_starts() -> Result<()> {
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use zebra_scan::tests::ZECPAGES_SAPLING_VIEWING_KEY;
|
use zebra_scan::tests::ZECPAGES_SAPLING_VIEWING_KEY;
|
||||||
|
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
|
let test_type = TestType::LaunchWithEmptyState {
|
||||||
|
launches_lightwalletd: false,
|
||||||
|
};
|
||||||
let mut config = default_test_config(Mainnet)?;
|
let mut config = default_test_config(Mainnet)?;
|
||||||
let mut keys = IndexMap::new();
|
let mut keys = IndexMap::new();
|
||||||
keys.insert(ZECPAGES_SAPLING_VIEWING_KEY.to_string(), 1);
|
keys.insert(ZECPAGES_SAPLING_VIEWING_KEY.to_string(), 1);
|
||||||
config.shielded_scan.sapling_keys_to_scan = keys;
|
config.shielded_scan.sapling_keys_to_scan = keys;
|
||||||
|
|
||||||
let testdir = testdir()?.with_config(&mut config)?;
|
// Start zebra with the config.
|
||||||
let testdir = &testdir;
|
let mut zebrad = testdir()?
|
||||||
|
.with_exact_config(&config)?
|
||||||
|
.spawn_child(args!["start"])?
|
||||||
|
.with_timeout(test_type.zebrad_timeout());
|
||||||
|
|
||||||
let mut child = testdir.spawn_child(args!["start"])?;
|
// Check scanner was started.
|
||||||
|
zebrad.expect_stdout_line_matches("loaded Zebra scanner cache")?;
|
||||||
|
|
||||||
// Run the program and kill it after the scanner starts and the first scanning is done.
|
// Look for 2 scanner notices indicating we are below sapling activation.
|
||||||
std::thread::sleep(LAUNCH_DELAY * 2);
|
zebrad.expect_stdout_line_matches("scanner is waiting for sapling activation. Current tip: [0-9]{1,4}, Sapling activation: 419200")?;
|
||||||
child.kill(false)?;
|
zebrad.expect_stdout_line_matches("scanner is waiting for sapling activation. Current tip: [0-9]{1,4}, Sapling activation: 419200")?;
|
||||||
|
|
||||||
|
// Kill the node.
|
||||||
|
zebrad.kill(false)?;
|
||||||
|
|
||||||
// Check that scan task started and the first scanning is done.
|
// Check that scan task started and the first scanning is done.
|
||||||
let output = child.wait_with_output()?;
|
let output = zebrad.wait_with_output()?;
|
||||||
|
|
||||||
output.stdout_line_contains("spawning shielded scanner with configured viewing keys")?;
|
|
||||||
/*
|
|
||||||
TODO: these lines only happen when we reach sapling activation height
|
|
||||||
output.stdout_line_contains("Scanning the blockchain: now at block")?;
|
|
||||||
output.stdout_line_contains(
|
|
||||||
format!(
|
|
||||||
"Scanning the blockchain for key 0, started at block",
|
|
||||||
)
|
|
||||||
.as_str(),
|
|
||||||
)?;
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Make sure the command was killed
|
// Make sure the command was killed
|
||||||
output.assert_was_killed()?;
|
output.assert_was_killed()?;
|
||||||
|
@ -2878,7 +2875,7 @@ fn scan_task_starts() -> Result<()> {
|
||||||
#[cfg(feature = "shielded-scan")]
|
#[cfg(feature = "shielded-scan")]
|
||||||
fn scan_start_where_left() -> Result<()> {
|
fn scan_start_where_left() -> Result<()> {
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use zebra_scan::storage::db::SCANNER_DATABASE_KIND;
|
use zebra_scan::{storage::db::SCANNER_DATABASE_KIND, tests::ZECPAGES_SAPLING_VIEWING_KEY};
|
||||||
|
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
|
@ -2886,10 +2883,9 @@ fn scan_start_where_left() -> Result<()> {
|
||||||
let test_type = TestType::UpdateZebraCachedStateNoRpc;
|
let test_type = TestType::UpdateZebraCachedStateNoRpc;
|
||||||
if let Some(cache_dir) = test_type.zebrad_state_path("scan test") {
|
if let Some(cache_dir) = test_type.zebrad_state_path("scan test") {
|
||||||
// Add a key to the config
|
// Add a key to the config
|
||||||
const ZECPAGES_VIEWING_KEY: &str = "zxviews1q0duytgcqqqqpqre26wkl45gvwwwd706xw608hucmvfalr759ejwf7qshjf5r9aa7323zulvz6plhttp5mltqcgs9t039cx2d09mgq05ts63n8u35hyv6h9nc9ctqqtue2u7cer2mqegunuulq2luhq3ywjcz35yyljewa4mgkgjzyfwh6fr6jd0dzd44ghk0nxdv2hnv4j5nxfwv24rwdmgllhe0p8568sgqt9ckt02v2kxf5ahtql6s0ltjpkckw8gtymxtxuu9gcr0swvz";
|
|
||||||
let mut config = default_test_config(Mainnet)?;
|
let mut config = default_test_config(Mainnet)?;
|
||||||
let mut keys = IndexMap::new();
|
let mut keys = IndexMap::new();
|
||||||
keys.insert(ZECPAGES_VIEWING_KEY.to_string(), 1);
|
keys.insert(ZECPAGES_SAPLING_VIEWING_KEY.to_string(), 1);
|
||||||
config.shielded_scan.sapling_keys_to_scan = keys;
|
config.shielded_scan.sapling_keys_to_scan = keys;
|
||||||
|
|
||||||
// Add the cache dir to shielded scan, make it the same as the zebrad cache state.
|
// Add the cache dir to shielded scan, make it the same as the zebrad cache state.
|
||||||
|
|
Loading…
Reference in New Issue