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

merge queue: embarking main (ad015e0) and [#8120 + #8121] together #8122

Closed
wants to merge 5 commits into from
Closed
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
6 changes: 3 additions & 3 deletions .github/workflows/ci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:

- name: Rust files
id: changed-files-rust
uses: tj-actions/[email protected].2
uses: tj-actions/[email protected].3
with:
files: |
**/*.rs
Expand All @@ -56,7 +56,7 @@ jobs:

- name: Workflow files
id: changed-files-workflows
uses: tj-actions/[email protected].2
uses: tj-actions/[email protected].3
with:
files: |
.github/workflows/*.yml
Expand Down Expand Up @@ -151,7 +151,7 @@ jobs:
steps:
- uses: actions/[email protected]
- name: actionlint
uses: reviewdog/action-actionlint@v1.39.1
uses: reviewdog/action-actionlint@v1.40.0
with:
level: warning
fail_on_error: false
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sub-build-docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ jobs:
# Automatic tag management and OCI Image Format Specification for labels
- name: Docker meta
id: meta
uses: docker/metadata-action@v5.3.0
uses: docker/metadata-action@v5.4.0
with:
# list of Docker images to use as base name for tags
images: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sub-build-lightwalletd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ jobs:
# Automatic tag management and OCI Image Format Specification for labels
- name: Docker meta
id: meta
uses: docker/metadata-action@v5.3.0
uses: docker/metadata-action@v5.4.0
with:
# list of Docker images to use as base name for tags
images: |
Expand Down
34 changes: 32 additions & 2 deletions zebra-scan/src/scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,27 @@ pub async fn start(
storage: Storage,
) -> Result<(), Report> {
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.
let key_storage = storage.clone();
let key_heights = tokio::task::spawn_blocking(move || key_storage.sapling_keys_last_heights())
.wait_for_panics()
.await;
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.
// There is some cryptography here, but it should be fast even with thousands of keys.
Expand Down Expand Up @@ -149,7 +162,7 @@ pub async fn scan_height_and_store_results(
let block = match block {
zebra_state::Response::Block(Some(block)) => block,
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.
Expand Down Expand Up @@ -400,3 +413,20 @@ fn scanned_block_to_db_result<Nf>(
fn get_min_height(map: &HashMap<String, Height>) -> Option<Height> {
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"),
}
}
42 changes: 19 additions & 23 deletions zebrad/tests/acceptance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2820,39 +2820,36 @@ async fn fully_synced_rpc_z_getsubtreesbyindex_snapshot_test() -> Result<()> {
#[cfg(feature = "shielded-scan")]
fn scan_task_starts() -> Result<()> {
use indexmap::IndexMap;

use zebra_scan::tests::ZECPAGES_SAPLING_VIEWING_KEY;

let _init_guard = zebra_test::init();

let test_type = TestType::LaunchWithEmptyState {
launches_lightwalletd: false,
};
let mut config = default_test_config(Mainnet)?;
let mut keys = IndexMap::new();
keys.insert(ZECPAGES_SAPLING_VIEWING_KEY.to_string(), 1);
config.shielded_scan.sapling_keys_to_scan = keys;

let testdir = testdir()?.with_config(&mut config)?;
let testdir = &testdir;
// Start zebra with the config.
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.
std::thread::sleep(LAUNCH_DELAY * 2);
child.kill(false)?;
// Look for 2 scanner notices indicating we are below sapling activation.
zebrad.expect_stdout_line_matches("scanner is waiting for sapling activation. Current tip: [0-9]{1,4}, Sapling activation: 419200")?;
zebrad.expect_stdout_line_matches("scanner is waiting for sapling activation. Current tip: [0-9]{1,4}, Sapling activation: 419200")?;

// Check that scan task started and the first scanning is done.
let output = child.wait_with_output()?;
// Kill the node.
zebrad.kill(false)?;

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(),
)?;
*/
// Check that scan task started and the first scanning is done.
let output = zebrad.wait_with_output()?;

// Make sure the command was killed
output.assert_was_killed()?;
Expand All @@ -2878,18 +2875,17 @@ fn scan_task_starts() -> Result<()> {
#[cfg(feature = "shielded-scan")]
fn scan_start_where_left() -> Result<()> {
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();

// use `UpdateZebraCachedStateNoRpc` as the test type to make sure a zebrad cache state is available.
let test_type = TestType::UpdateZebraCachedStateNoRpc;
if let Some(cache_dir) = test_type.zebrad_state_path("scan test") {
// Add a key to the config
const ZECPAGES_VIEWING_KEY: &str = "zxviews1q0duytgcqqqqpqre26wkl45gvwwwd706xw608hucmvfalr759ejwf7qshjf5r9aa7323zulvz6plhttp5mltqcgs9t039cx2d09mgq05ts63n8u35hyv6h9nc9ctqqtue2u7cer2mqegunuulq2luhq3ywjcz35yyljewa4mgkgjzyfwh6fr6jd0dzd44ghk0nxdv2hnv4j5nxfwv24rwdmgllhe0p8568sgqt9ckt02v2kxf5ahtql6s0ltjpkckw8gtymxtxuu9gcr0swvz";
let mut config = default_test_config(Mainnet)?;
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;

// Add the cache dir to shielded scan, make it the same as the zebrad cache state.
Expand Down
Loading