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

Check for newer incremental snapshot before downloading #28143

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 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
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions download-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ edition = "2021"
console = "0.15.0"
indicatif = "0.17.1"
log = "0.4.17"
regex = "1.6.0"
reqwest = { version = "0.11.12", default-features = false, features = ["blocking", "brotli", "deflate", "gzip", "rustls-tls", "json"] }
solana-rpc = { path = "../rpc", version = "=1.15.0" }
solana-runtime = { path = "../runtime", version = "=1.15.0" }
solana-sdk = { path = "../sdk", version = "=1.15.0" }

Expand Down
81 changes: 81 additions & 0 deletions download-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use {
console::Emoji,
indicatif::{ProgressBar, ProgressStyle},
log::*,
regex::Regex,
solana_rpc::rpc_service::INCREMENTAL_SNAPSHOT_REQUEST_PATH,
solana_runtime::{
snapshot_package::SnapshotType,
snapshot_utils::{self, ArchiveFormat},
Expand All @@ -13,6 +15,7 @@ use {
io::{self, Read},
net::SocketAddr,
path::{Path, PathBuf},
str::FromStr,
time::{Duration, Instant},
},
};
Expand Down Expand Up @@ -329,3 +332,81 @@ pub fn download_snapshot_archive<'a, 'b>(
desired_snapshot_hash.0, rpc_addr
))
}

/// Checks if the given RPC node has a newer incremental snapshot available
/// Returns Some(slot, hash) if a newer slot is available
/// Returns None otherwise
pub fn check_for_newer_incremental_snapshot(
rpc_addr: SocketAddr,
full_snapshot_slot: u64,
incremental_snapshot_slot: u64,
) -> Option<(u64, Hash)> {
let incremental_redirect_url =
&format!("http://{}{}", rpc_addr, INCREMENTAL_SNAPSHOT_REQUEST_PATH);
let response = reqwest::blocking::get(incremental_redirect_url);
let response = match response {
Ok(r) => r,
Err(_e) => {
return None;
}
};
willhickey marked this conversation as resolved.
Show resolved Hide resolved
willhickey marked this conversation as resolved.
Show resolved Hide resolved

let incremental_snapshot_url = String::from_str(response.url().path());
let incremental_snapshot_url = match incremental_snapshot_url {
Ok(url) => url,
Err(_e) => {
return None;
}
};

// Expected URL format: /incremental-snapshot-<full slot>-<incremental slot>-<incremental slot hash>.tar.zst
// eg: "/incremental-snapshot-152074294-152089382-BqBphVi1gnim96v6xXim7xq1L2PDFX3aDjd1Nn7SbRFM.tar.zst"
let re = Regex::new(r"incremental-snapshot-([0-9]*)-([0-9]*)-(\w*)\.").unwrap();
willhickey marked this conversation as resolved.
Show resolved Hide resolved
let captures = re.captures(&incremental_snapshot_url.as_str());
let captures = match captures {
Some(c) => c,
None => {
return None;
}
};
let full_slot = captures.get(1).map(|m| m.as_str().parse::<u64>());
let full_slot = match full_slot {
Some(s) => match s {
Ok(s) => s,
Err(_e) => {
return None;
}
},
None => {
return None;
}
};
willhickey marked this conversation as resolved.
Show resolved Hide resolved

let recent_inc_slot = captures.get(2).map(|m| m.as_str().parse::<u64>());
let recent_inc_slot = match recent_inc_slot {
Some(s) => match s {
Ok(s) => s,
Err(_e) => {
return None;
}
},
None => {
return None;
}
};

let recent_inc_hash = captures.get(3).map_or("", |m| m.as_str());
let recent_inc_hash = Hash::from_str(recent_inc_hash);
let recent_inc_hash = match recent_inc_hash {
Ok(ih) => ih,
Err(_e) => {
return None;
}
};

if full_snapshot_slot == full_slot && recent_inc_slot > incremental_snapshot_slot {
return Some((recent_inc_slot, recent_inc_hash));
} else {
return None;
}
}
2 changes: 2 additions & 0 deletions programs/bpf/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rpc/src/rpc_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ use {
};

const FULL_SNAPSHOT_REQUEST_PATH: &str = "/snapshot.tar.bz2";
const INCREMENTAL_SNAPSHOT_REQUEST_PATH: &str = "/incremental-snapshot.tar.bz2";
pub const INCREMENTAL_SNAPSHOT_REQUEST_PATH: &str = "/incremental-snapshot.tar.bz2";
const LARGEST_ACCOUNTS_CACHE_DURATION: u64 = 60 * 60 * 2;

pub struct JsonRpcService {
Expand Down
29 changes: 22 additions & 7 deletions validator/src/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use {
rand::{seq::SliceRandom, thread_rng, Rng},
rayon::prelude::*,
solana_core::validator::{ValidatorConfig, ValidatorStartProgress},
solana_download_utils::{download_snapshot_archive, DownloadProgressRecord},
solana_download_utils::{
check_for_newer_incremental_snapshot, download_snapshot_archive, DownloadProgressRecord,
},
solana_genesis_utils::download_then_check_genesis_hash,
solana_gossip::{
cluster_info::{ClusterInfo, Node},
Expand Down Expand Up @@ -1115,19 +1117,32 @@ fn download_snapshots(
)?;
}

// Check and see if we've already got the incremental snapshot; if not, download it
if let Some(incremental_snapshot_hash) = incremental_snapshot_hash {
// If the full snapshot download took more than a few minutes there is probably a newer incremental snapshot
let newest_known_incremental_snapshot = match check_for_newer_incremental_snapshot(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use shadowing here, we don't need original variable below.

let incremental_snapshot_hash = match check_for_newer_incremental_snapshot(
...

And it'll reduce PR too.

PS. I don't have write permission for suggesting.

rpc_contact_info.rpc,
full_snapshot_hash.0,
match incremental_snapshot_hash {
Some(inc) => inc.0,
None => 0,
},
) {
Some(nis) => Some(nis),
willhickey marked this conversation as resolved.
Show resolved Hide resolved
None => incremental_snapshot_hash,
};

// Check if we've already got the incremental snapshot; if not, download it
if let Some(newest_known_incremental_snapshot) = newest_known_incremental_snapshot {
if snapshot_utils::get_incremental_snapshot_archives(incremental_snapshot_archives_dir)
.into_iter()
.any(|snapshot_archive| {
snapshot_archive.slot() == incremental_snapshot_hash.0
&& snapshot_archive.hash() == &incremental_snapshot_hash.1
snapshot_archive.slot() == newest_known_incremental_snapshot.0
&& snapshot_archive.hash() == &newest_known_incremental_snapshot.1
&& snapshot_archive.base_slot() == full_snapshot_hash.0
})
{
info!(
"Incremental snapshot archive already exists locally. Skipping download. slot: {}, hash: {}",
incremental_snapshot_hash.0, incremental_snapshot_hash.1
newest_known_incremental_snapshot.0, newest_known_incremental_snapshot.1
);
} else {
download_snapshot(
Expand All @@ -1141,7 +1156,7 @@ fn download_snapshots(
maximum_snapshot_download_abort,
download_abort_count,
rpc_contact_info,
incremental_snapshot_hash,
newest_known_incremental_snapshot,
SnapshotType::IncrementalSnapshot(full_snapshot_hash.0),
)?;
}
Expand Down