Prechádzať zdrojové kódy

Move unpacking related code to agave_snapshots (#8428)

Kamil Skalski 1 mesiac pred
rodič
commit
712151c13b

+ 15 - 5
Cargo.lock

@@ -326,8 +326,19 @@ dependencies = [
 name = "agave-snapshots"
 version = "3.1.0"
 dependencies = [
+ "assert_matches",
+ "bzip2",
+ "crossbeam-channel",
+ "log",
  "lz4",
+ "rand 0.8.5",
+ "solana-accounts-db",
+ "solana-genesis-config",
+ "solana-logger",
  "strum",
+ "tar",
+ "tempfile",
+ "thiserror 2.0.17",
  "zstd",
 ]
 
@@ -7003,7 +7014,6 @@ dependencies = [
  "bv",
  "bytemuck",
  "bytemuck_derive",
- "bzip2",
  "criterion",
  "crossbeam-channel",
  "dashmap",
@@ -7072,7 +7082,6 @@ dependencies = [
  "static_assertions",
  "strum",
  "strum_macros",
- "tar",
  "tempfile",
  "test-case",
  "thiserror 2.0.17",
@@ -8676,6 +8685,7 @@ name = "solana-genesis"
 version = "3.1.0"
 dependencies = [
  "agave-feature-set",
+ "agave-snapshots",
  "base64 0.22.1",
  "bincode",
  "clap 2.33.3",
@@ -8684,7 +8694,6 @@ dependencies = [
  "serde_json",
  "serde_yaml 0.9.34+deprecated",
  "solana-account",
- "solana-accounts-db",
  "solana-borsh",
  "solana-clap-utils",
  "solana-cli-config",
@@ -8751,8 +8760,8 @@ dependencies = [
 name = "solana-genesis-utils"
 version = "3.1.0"
 dependencies = [
+ "agave-snapshots",
  "log",
- "solana-accounts-db",
  "solana-download-utils",
  "solana-genesis-config",
  "solana-hash",
@@ -9043,6 +9052,7 @@ version = "3.1.0"
 dependencies = [
  "agave-feature-set",
  "agave-reserved-account-keys",
+ "agave-snapshots",
  "anyhow",
  "assert_matches",
  "bincode",
@@ -11878,6 +11888,7 @@ dependencies = [
 name = "solana-wen-restart"
 version = "3.1.0"
 dependencies = [
+ "agave-snapshots",
  "anyhow",
  "assert_matches",
  "crossbeam-channel",
@@ -11889,7 +11900,6 @@ dependencies = [
  "rand 0.8.5",
  "rayon",
  "serial_test",
- "solana-accounts-db",
  "solana-clock",
  "solana-entry",
  "solana-gossip",

+ 0 - 2
accounts-db/Cargo.toml

@@ -41,7 +41,6 @@ blake3 = { workspace = true }
 bv = { workspace = true, features = ["serde"] }
 bytemuck = { workspace = true }
 bytemuck_derive = { workspace = true }
-bzip2 = { workspace = true }
 crossbeam-channel = { workspace = true }
 dashmap = { workspace = true, features = ["rayon", "raw-api"] }
 indexmap = { workspace = true }
@@ -101,7 +100,6 @@ solana-transaction-error = { workspace = true }
 solana-vote-program = { workspace = true, optional = true }
 spl-generic-token = { workspace = true }
 static_assertions = { workspace = true }
-tar = { workspace = true }
 tempfile = { workspace = true }
 thiserror = { workspace = true }
 

+ 3 - 2
accounts-db/src/lib.rs

@@ -26,7 +26,6 @@ mod bucket_map_holder_stats;
 mod buffered_reader;
 pub mod contains;
 mod file_io;
-pub mod hardened_unpack;
 mod io_uring;
 pub mod is_loadable;
 mod is_zero_lamport;
@@ -47,7 +46,9 @@ pub mod waitable_condvar;
 
 pub use {
     buffered_reader::large_file_buf_reader,
-    file_io::validate_memlock_limit_for_disk_io,
+    file_io::{
+        file_creator, set_path_permissions, validate_memlock_limit_for_disk_io, FileCreator,
+    },
     obsolete_accounts::{ObsoleteAccountItem, ObsoleteAccounts},
 };
 

+ 6 - 4
core/src/validator.rs

@@ -32,7 +32,12 @@ use {
         tpu::{ForwardingClientOption, Tpu, TpuSockets, DEFAULT_TPU_COALESCE},
         tvu::{Tvu, TvuConfig, TvuSockets},
     },
-    agave_snapshots::SnapshotInterval,
+    agave_snapshots::{
+        hardened_unpack::{
+            open_genesis_config, OpenGenesisConfigError, MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
+        },
+        SnapshotInterval,
+    },
     anyhow::{anyhow, Context, Result},
     crossbeam_channel::{bounded, unbounded, Receiver},
     quinn::Endpoint,
@@ -41,9 +46,6 @@ use {
     solana_accounts_db::{
         accounts_db::{AccountsDbConfig, ACCOUNTS_DB_CONFIG_FOR_TESTING},
         accounts_update_notifier_interface::AccountsUpdateNotifier,
-        hardened_unpack::{
-            open_genesis_config, OpenGenesisConfigError, MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
-        },
         utils::move_and_async_delete_path_contents,
     },
     solana_client::{

+ 1 - 1
genesis-utils/Cargo.toml

@@ -17,8 +17,8 @@ crate-type = ["lib"]
 name = "solana_genesis_utils"
 
 [dependencies]
+agave-snapshots = { workspace = true }
 log = { workspace = true }
-solana-accounts-db = { workspace = true }
 solana-download-utils = { workspace = true }
 solana-genesis-config = { workspace = true }
 solana-hash = { workspace = true }

+ 1 - 1
genesis-utils/src/lib.rs

@@ -1,6 +1,6 @@
 use {
+    agave_snapshots::hardened_unpack::unpack_genesis_archive,
     log::*,
-    solana_accounts_db::hardened_unpack::unpack_genesis_archive,
     solana_download_utils::download_genesis_if_missing,
     solana_genesis_config::{GenesisConfig, DEFAULT_GENESIS_ARCHIVE},
     solana_hash::Hash,

+ 1 - 1
genesis/Cargo.toml

@@ -21,6 +21,7 @@ path = "src/main.rs"
 
 [dependencies]
 agave-feature-set = { workspace = true }
+agave-snapshots = { workspace = true }
 base64 = { workspace = true }
 bincode = { workspace = true }
 clap = { workspace = true }
@@ -29,7 +30,6 @@ serde = { workspace = true }
 serde_json = { workspace = true }
 serde_yaml = { workspace = true }
 solana-account = "=3.1.0"
-solana-accounts-db = { workspace = true }
 solana-clap-utils = { workspace = true }
 solana-cli-config = { workspace = true }
 solana-clock = "=3.0.0"

+ 1 - 1
genesis/src/main.rs

@@ -3,11 +3,11 @@
 
 use {
     agave_feature_set::FEATURE_NAMES,
+    agave_snapshots::hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
     base64::{prelude::BASE64_STANDARD, Engine},
     clap::{crate_description, crate_name, value_t, value_t_or_exit, App, Arg, ArgMatches},
     itertools::Itertools,
     solana_account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
-    solana_accounts_db::hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
     solana_clap_utils::{
         input_parsers::{
             cluster_type_of, pubkey_of, pubkeys_of, unix_timestamp_from_rfc3339_datetime,

+ 1 - 1
ledger-tool/src/args.rs

@@ -346,7 +346,7 @@ pub fn hardforks_of(matches: &ArgMatches<'_>, name: &str) -> Option<Vec<Slot>> {
 
 #[cfg(test)]
 mod tests {
-    use {super::*, solana_accounts_db::hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE};
+    use {super::*, agave_snapshots::hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE};
 
     #[test]
     fn test_max_genesis_archive_unpacked_size_constant() {

+ 3 - 3
ledger-tool/src/ledger_utils.rs

@@ -1,11 +1,11 @@
 use {
     crate::LEDGER_TOOL_DIRECTORY,
+    agave_snapshots::hardened_unpack::open_genesis_config,
     clap::{value_t, value_t_or_exit, values_t_or_exit, ArgMatches},
     crossbeam_channel::unbounded,
     log::*,
-    solana_accounts_db::{
-        hardened_unpack::open_genesis_config,
-        utils::{create_all_accounts_run_and_snapshot_dirs, move_and_async_delete_path_contents},
+    solana_accounts_db::utils::{
+        create_all_accounts_run_and_snapshot_dirs, move_and_async_delete_path_contents,
     },
     solana_clock::Slot,
     solana_core::validator::BlockVerificationMethod,

+ 1 - 1
ledger-tool/src/main.rs

@@ -1786,7 +1786,7 @@ fn main() {
                     create_new_ledger(
                         &output_directory,
                         &genesis_config,
-                        solana_accounts_db::hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
+                        agave_snapshots::hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
                         LedgerColumnOptions::default(),
                     )
                     .unwrap_or_else(|err| {

+ 1 - 0
ledger/Cargo.toml

@@ -28,6 +28,7 @@ agave-unstable-api = []
 [dependencies]
 agave-feature-set = { workspace = true }
 agave-reserved-account-keys = { workspace = true }
+agave-snapshots = { workspace = true }
 anyhow = { workspace = true }
 assert_matches = { workspace = true }
 bincode = { workspace = true }

+ 4 - 4
ledger/src/blockstore.rs

@@ -24,6 +24,7 @@ use {
         transaction_address_lookup_table_scanner::scan_transaction,
     },
     agave_feature_set::FeatureSet,
+    agave_snapshots::hardened_unpack::unpack_genesis_archive,
     assert_matches::debug_assert_matches,
     bincode::{deserialize, serialize},
     crossbeam_channel::{bounded, Receiver, Sender, TrySendError},
@@ -34,7 +35,6 @@ use {
     rayon::iter::{IntoParallelIterator, ParallelIterator},
     rocksdb::{DBRawIterator, LiveFile},
     solana_account::ReadableAccount,
-    solana_accounts_db::hardened_unpack::unpack_genesis_archive,
     solana_address_lookup_table_interface::state::AddressLookupTable,
     solana_clock::{Slot, UnixTimestamp, DEFAULT_TICKS_PER_SECOND},
     solana_entry::entry::{create_ticks, Entry},
@@ -5219,14 +5219,14 @@ pub mod tests {
             leader_schedule::{FixedSchedule, IdentityKeyedLeaderSchedule},
             shred::{max_ticks_per_n_shreds, MAX_DATA_SHREDS_PER_SLOT},
         },
+        agave_snapshots::hardened_unpack::{
+            open_genesis_config, MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
+        },
         assert_matches::assert_matches,
         bincode::{serialize, Options},
         crossbeam_channel::unbounded,
         rand::{seq::SliceRandom, thread_rng},
         solana_account_decoder::parse_token::UiTokenAmount,
-        solana_accounts_db::hardened_unpack::{
-            open_genesis_config, MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
-        },
         solana_clock::{DEFAULT_MS_PER_SLOT, DEFAULT_TICKS_PER_SLOT},
         solana_entry::entry::{next_entry, next_entry_mut},
         solana_hash::Hash,

+ 1 - 3
ledger/src/blockstore/error.rs

@@ -1,8 +1,6 @@
 //! The error that can be produced from Blockstore operations.
 
-use {
-    log::*, solana_accounts_db::hardened_unpack::UnpackError, solana_clock::Slot, thiserror::Error,
-};
+use {agave_snapshots::hardened_unpack::UnpackError, log::*, solana_clock::Slot, thiserror::Error};
 
 #[derive(Error, Debug)]
 pub enum BlockstoreError {

+ 1 - 1
ledger/src/lib.rs

@@ -50,7 +50,7 @@ extern crate solana_frozen_abi_macro;
 
 #[doc(hidden)]
 pub mod macro_reexports {
-    pub use solana_accounts_db::hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE;
+    pub use agave_snapshots::hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE;
 }
 
 mod wire_format_tests;

+ 2 - 4
local-cluster/tests/local_cluster.rs

@@ -1,6 +1,6 @@
 #![allow(clippy::arithmetic_side_effects)]
 use {
-    agave_snapshots::SnapshotInterval,
+    agave_snapshots::{hardened_unpack::open_genesis_config, SnapshotInterval},
     assert_matches::assert_matches,
     crossbeam_channel::{unbounded, Receiver},
     gag::BufferRedirect,
@@ -9,9 +9,7 @@ use {
     rand::seq::SliceRandom,
     serial_test::serial,
     solana_account::AccountSharedData,
-    solana_accounts_db::{
-        hardened_unpack::open_genesis_config, utils::create_accounts_run_and_snapshot_dirs,
-    },
+    solana_accounts_db::utils::create_accounts_run_and_snapshot_dirs,
     solana_client_traits::AsyncClient,
     solana_clock::{
         self as clock, Slot, DEFAULT_SLOTS_PER_EPOCH, DEFAULT_TICKS_PER_SLOT, MAX_PROCESSING_AGE,

+ 10 - 3
programs/sbf/Cargo.lock

@@ -146,8 +146,16 @@ dependencies = [
 name = "agave-snapshots"
 version = "3.1.0"
 dependencies = [
+ "bzip2",
+ "crossbeam-channel",
+ "log",
  "lz4",
+ "rand 0.8.5",
+ "solana-accounts-db",
+ "solana-genesis-config",
  "strum",
+ "tar",
+ "thiserror 2.0.17",
  "zstd",
 ]
 
@@ -5726,7 +5734,6 @@ dependencies = [
  "bv",
  "bytemuck",
  "bytemuck_derive",
- "bzip2",
  "crossbeam-channel",
  "dashmap",
  "indexmap 2.11.4",
@@ -5778,7 +5785,6 @@ dependencies = [
  "solana-vote-program",
  "spl-generic-token",
  "static_assertions",
- "tar",
  "tempfile",
  "thiserror 2.0.17",
 ]
@@ -6829,8 +6835,8 @@ dependencies = [
 name = "solana-genesis-utils"
 version = "3.1.0"
 dependencies = [
+ "agave-snapshots",
  "log",
- "solana-accounts-db",
  "solana-download-utils",
  "solana-genesis-config",
  "solana-hash",
@@ -7070,6 +7076,7 @@ version = "3.1.0"
 dependencies = [
  "agave-feature-set",
  "agave-reserved-account-keys",
+ "agave-snapshots",
  "anyhow",
  "assert_matches",
  "bincode",

+ 5 - 53
runtime/src/snapshot_utils.rs

@@ -19,7 +19,9 @@ use {
             get_slot_and_append_vec_id, SnapshotStorageRebuilder,
         },
     },
-    agave_snapshots::{ArchiveFormat, ArchiveFormatDecompressor, SnapshotVersion},
+    agave_snapshots::{
+        hardened_unpack::UnpackError, streaming_unarchive_snapshot, ArchiveFormat, SnapshotVersion,
+    },
     crossbeam_channel::{Receiver, Sender},
     log::*,
     regex::Regex,
@@ -31,7 +33,6 @@ use {
             AccountStorageEntry, AccountsDbConfig, AccountsFileId, AtomicAccountsFileId,
         },
         accounts_file::{AccountsFile, AccountsFileError, StorageAccess},
-        hardened_unpack::{self, UnpackError},
         utils::{move_and_async_delete_path, ACCOUNTS_RUN_DIR, ACCOUNTS_SNAPSHOT_DIR},
     },
     solana_clock::{Epoch, Slot},
@@ -41,7 +42,7 @@ use {
         cmp::Ordering,
         collections::{HashMap, HashSet},
         fs,
-        io::{self, BufRead, BufReader, BufWriter, Error as IoError, Read, Seek, Write},
+        io::{self, BufReader, BufWriter, Error as IoError, Read, Seek, Write},
         mem,
         num::{NonZeroU64, NonZeroUsize},
         ops::RangeInclusive,
@@ -49,9 +50,8 @@ use {
         process::ExitStatus,
         str::FromStr,
         sync::{Arc, LazyLock},
-        thread::{Builder, JoinHandle},
     },
-    tar::{self, Archive},
+    tar,
     tempfile::TempDir,
     thiserror::Error,
 };
@@ -94,9 +94,6 @@ pub const FULL_SNAPSHOT_ARCHIVE_FILENAME_REGEX: &str =
     r"^snapshot-(?P<slot>[[:digit:]]+)-(?P<hash>[[:alnum:]]+)\.(?P<ext>tar\.zst|tar\.lz4)$";
 pub const INCREMENTAL_SNAPSHOT_ARCHIVE_FILENAME_REGEX: &str = r"^incremental-snapshot-(?P<base>[[:digit:]]+)-(?P<slot>[[:digit:]]+)-(?P<hash>[[:alnum:]]+)\.(?P<ext>tar\.zst|tar\.lz4)$";
 
-// Allows scheduling a large number of reads such that temporary disk access delays
-// shouldn't block decompression (unless read bandwidth is saturated).
-const MAX_SNAPSHOT_READER_BUF_SIZE: u64 = 128 * 1024 * 1024;
 // Balance large and small files order in snapshot tar with bias towards small (4 small + 1 large),
 // such that during unpacking large writes are mixed with file metadata operations
 // and towards the end of archive (sizes equalize) writes are >256KiB / file.
@@ -1688,51 +1685,6 @@ pub fn verify_and_unarchive_snapshots(
     ))
 }
 
-/// Streams unpacked files across channel
-fn streaming_unarchive_snapshot(
-    file_sender: Sender<PathBuf>,
-    account_paths: Vec<PathBuf>,
-    ledger_dir: PathBuf,
-    snapshot_archive_path: PathBuf,
-    archive_format: ArchiveFormat,
-    memlock_budget_size: usize,
-) -> JoinHandle<Result<()>> {
-    Builder::new()
-        .name("solTarUnpack".to_string())
-        .spawn(move || {
-            let archive_size = fs::metadata(&snapshot_archive_path)?.len() as usize;
-            let read_write_budget_size = (memlock_budget_size / 2).min(archive_size);
-            let read_buf_size = MAX_SNAPSHOT_READER_BUF_SIZE.min(read_write_budget_size as u64);
-            let decompressor =
-                decompressed_tar_reader(archive_format, snapshot_archive_path, read_buf_size)?;
-            hardened_unpack::streaming_unpack_snapshot(
-                Archive::new(decompressor),
-                read_write_budget_size,
-                ledger_dir.as_path(),
-                &account_paths,
-                &file_sender,
-            )?;
-            Ok(())
-        })
-        .unwrap()
-}
-
-fn decompressed_tar_reader(
-    archive_format: ArchiveFormat,
-    archive_path: impl AsRef<Path>,
-    buf_size: u64,
-) -> Result<ArchiveFormatDecompressor<impl BufRead>> {
-    let buf_reader =
-        solana_accounts_db::large_file_buf_reader(archive_path.as_ref(), buf_size as usize)
-            .map_err(|err| {
-                io::Error::other(format!(
-                    "failed to open snapshot archive '{}': {err}",
-                    archive_path.as_ref().display(),
-                ))
-            })?;
-    Ok(ArchiveFormatDecompressor::new(archive_format, buf_reader)?)
-}
-
 /// Used to determine if a filename is structured like a version file, bank file, or storage file
 #[derive(PartialEq, Debug)]
 enum SnapshotFileKind {

+ 13 - 0
snapshots/Cargo.toml

@@ -21,6 +21,19 @@ agave-unstable-api = []
 default = ["agave-unstable-api"]
 
 [dependencies]
+bzip2 = { workspace = true }
+crossbeam-channel = { workspace = true }
+log = { workspace = true }
 lz4 = { workspace = true }
+rand = { workspace = true }
+solana-accounts-db = { workspace = true }
+solana-genesis-config = { workspace = true }
 strum = { workspace = true, features = ["derive"] }
+tar = { workspace = true }
+thiserror = { workspace = true }
 zstd = { workspace = true }
+
+[dev-dependencies]
+assert_matches = { workspace = true }
+solana-logger = { workspace = true }
+tempfile = { workspace = true }

+ 4 - 1
accounts-db/src/hardened_unpack.rs → snapshots/src/hardened_unpack.rs

@@ -1,9 +1,9 @@
 use {
-    crate::file_io::{file_creator, set_path_permissions, FileCreator},
     bzip2::bufread::BzDecoder,
     crossbeam_channel::Sender,
     log::*,
     rand::{thread_rng, Rng},
+    solana_accounts_db::{file_creator, set_path_permissions, FileCreator},
     solana_genesis_config::{GenesisConfig, DEFAULT_GENESIS_ARCHIVE, DEFAULT_GENESIS_FILE},
     std::{
         collections::HashMap,
@@ -65,6 +65,7 @@ fn checked_total_size_sum(total_size: u64, entry_size: u64, limit_size: u64) ->
     Ok(total_size)
 }
 
+#[allow(clippy::arithmetic_side_effects)]
 fn checked_total_count_increment(total_count: u64, limit_count: u64) -> Result<u64> {
     let total_count = total_count + 1;
     if total_count > limit_count {
@@ -91,6 +92,7 @@ pub enum UnpackPath<'a> {
     Invalid,
 }
 
+#[allow(clippy::arithmetic_side_effects)]
 fn unpack_archive<'a, A, C, D>(
     mut archive: Archive<A>,
     memlock_budget_size: usize,
@@ -433,6 +435,7 @@ fn all_digits(v: &str) -> bool {
     true
 }
 
+#[allow(clippy::arithmetic_side_effects)]
 fn like_storage(v: &str) -> bool {
     let mut periods = 0;
     let mut saw_numbers = false;

+ 3 - 0
snapshots/src/lib.rs

@@ -1,9 +1,12 @@
 #![cfg(feature = "agave-unstable-api")]
 
 mod archive_format;
+pub mod hardened_unpack;
 mod snapshot_interval;
 mod snapshot_version;
+mod unarchive;
 
 pub use {
     archive_format::*, snapshot_interval::SnapshotInterval, snapshot_version::SnapshotVersion,
+    unarchive::streaming_unarchive_snapshot,
 };

+ 63 - 0
snapshots/src/unarchive.rs

@@ -0,0 +1,63 @@
+use {
+    crate::{
+        hardened_unpack::{self, UnpackError},
+        ArchiveFormat, ArchiveFormatDecompressor,
+    },
+    crossbeam_channel::Sender,
+    std::{
+        fs,
+        io::{self, BufRead},
+        path::{Path, PathBuf},
+        thread::{self, JoinHandle},
+    },
+    tar::Archive,
+};
+
+// Allows scheduling a large number of reads such that temporary disk access delays
+// shouldn't block decompression (unless read bandwidth is saturated).
+const MAX_SNAPSHOT_READER_BUF_SIZE: u64 = 128 * 1024 * 1024;
+
+/// Streams unpacked files across channel
+pub fn streaming_unarchive_snapshot(
+    file_sender: Sender<PathBuf>,
+    account_paths: Vec<PathBuf>,
+    ledger_dir: PathBuf,
+    snapshot_archive_path: PathBuf,
+    archive_format: ArchiveFormat,
+    memlock_budget_size: usize,
+) -> JoinHandle<Result<(), UnpackError>> {
+    thread::Builder::new()
+        .name("solTarUnpack".to_string())
+        .spawn(move || {
+            let archive_size = fs::metadata(&snapshot_archive_path)?.len() as usize;
+            let read_write_budget_size = (memlock_budget_size / 2).min(archive_size);
+            let read_buf_size = MAX_SNAPSHOT_READER_BUF_SIZE.min(read_write_budget_size as u64);
+            let decompressor =
+                decompressed_tar_reader(archive_format, snapshot_archive_path, read_buf_size)?;
+            hardened_unpack::streaming_unpack_snapshot(
+                Archive::new(decompressor),
+                read_write_budget_size,
+                ledger_dir.as_path(),
+                &account_paths,
+                &file_sender,
+            )?;
+            Ok(())
+        })
+        .unwrap()
+}
+
+fn decompressed_tar_reader(
+    archive_format: ArchiveFormat,
+    archive_path: impl AsRef<Path>,
+    buf_size: u64,
+) -> io::Result<ArchiveFormatDecompressor<impl BufRead>> {
+    let buf_reader =
+        solana_accounts_db::large_file_buf_reader(archive_path.as_ref(), buf_size as usize)
+            .map_err(|err| {
+                io::Error::other(format!(
+                    "failed to open snapshot archive '{}': {err}",
+                    archive_path.as_ref().display(),
+                ))
+            })?;
+    ArchiveFormatDecompressor::new(archive_format, buf_reader)
+}

+ 1 - 2
test-validator/src/lib.rs

@@ -1,14 +1,13 @@
 #![allow(clippy::arithmetic_side_effects)]
 use {
     agave_feature_set::{alpenglow, raise_cpi_nesting_limit_to_8, FeatureSet, FEATURE_NAMES},
-    agave_snapshots::SnapshotInterval,
+    agave_snapshots::{hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE, SnapshotInterval},
     base64::{prelude::BASE64_STANDARD, Engine},
     crossbeam_channel::Receiver,
     log::*,
     solana_account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
     solana_accounts_db::{
         accounts_db::AccountsDbConfig, accounts_index::AccountsIndexConfig,
-        hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
         utils::create_accounts_run_and_snapshot_dirs,
     },
     solana_cli_output::CliAccount,

+ 6 - 6
validator/src/cli.rs

@@ -1,12 +1,12 @@
 use {
     crate::commands,
-    agave_snapshots::{SnapshotVersion, DEFAULT_ARCHIVE_COMPRESSION},
+    agave_snapshots::{
+        hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE, SnapshotVersion,
+        DEFAULT_ARCHIVE_COMPRESSION,
+    },
     clap::{crate_description, crate_name, App, AppSettings, Arg, ArgMatches, SubCommand},
-    solana_accounts_db::{
-        accounts_db::{
-            DEFAULT_ACCOUNTS_SHRINK_OPTIMIZE_TOTAL_SPACE, DEFAULT_ACCOUNTS_SHRINK_RATIO,
-        },
-        hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
+    solana_accounts_db::accounts_db::{
+        DEFAULT_ACCOUNTS_SHRINK_OPTIMIZE_TOTAL_SPACE, DEFAULT_ACCOUNTS_SHRINK_RATIO,
     },
     solana_clap_utils::{
         hidden_unless_forced,

+ 4 - 2
validator/src/commands/run/execute.rs

@@ -6,7 +6,10 @@ use {
         commands::{run::args::RunArgs, FromClapArgMatches},
         ledger_lockfile, lock_ledger,
     },
-    agave_snapshots::{ArchiveFormat, SnapshotInterval, SnapshotVersion},
+    agave_snapshots::{
+        hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE, ArchiveFormat, SnapshotInterval,
+        SnapshotVersion,
+    },
     clap::{crate_name, value_t, value_t_or_exit, values_t, values_t_or_exit, ArgMatches},
     crossbeam_channel::unbounded,
     log::*,
@@ -15,7 +18,6 @@ use {
         accounts_db::{AccountShrinkThreshold, AccountsDbConfig, MarkObsoleteAccounts},
         accounts_file::StorageAccess,
         accounts_index::{AccountSecondaryIndexes, AccountsIndexConfig, IndexLimitMb, ScanFilter},
-        hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
         utils::{
             create_all_accounts_run_and_snapshot_dirs, create_and_canonicalize_directories,
             create_and_canonicalize_directory,

+ 1 - 1
wen-restart/Cargo.toml

@@ -45,11 +45,11 @@ prost-build = { workspace = true }
 protobuf-src = { workspace = true }
 
 [dev-dependencies]
+agave-snapshots = { workspace = true }
 assert_matches = { workspace = true }
 crossbeam-channel = { workspace = true }
 rand = { workspace = true }
 serial_test = { workspace = true }
-solana-accounts-db = { workspace = true }
 solana-entry = { workspace = true }
 solana-keypair = { workspace = true }
 solana-ledger = { workspace = true, features = ["dev-context-only-utils"] }

+ 1 - 1
wen-restart/src/wen_restart.rs

@@ -1409,8 +1409,8 @@ pub(crate) fn write_wen_restart_records(
 mod tests {
     use {
         crate::wen_restart::{tests::wen_restart_proto::LastVotedForkSlotsAggregateFinal, *},
+        agave_snapshots::hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
         crossbeam_channel::unbounded,
-        solana_accounts_db::hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
         solana_entry::entry::create_ticks,
         solana_gossip::{
             cluster_info::ClusterInfo,