snapshots.rs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. #![allow(clippy::arithmetic_side_effects)]
  2. use {
  3. crate::snapshot_utils::create_tmp_accounts_dir_for_tests,
  4. agave_snapshots::{snapshot_config::SnapshotConfig, SnapshotInterval},
  5. crossbeam_channel::unbounded,
  6. itertools::Itertools,
  7. log::{info, trace},
  8. solana_accounts_db::accounts_db::ACCOUNTS_DB_CONFIG_FOR_TESTING,
  9. solana_clock::Slot,
  10. solana_core::snapshot_packager_service::SnapshotPackagerService,
  11. solana_genesis_config::GenesisConfig,
  12. solana_gossip::{cluster_info::ClusterInfo, contact_info::ContactInfo},
  13. solana_keypair::Keypair,
  14. solana_pubkey::Pubkey,
  15. solana_runtime::{
  16. accounts_background_service::{
  17. AbsRequestHandlers, AccountsBackgroundService, PendingSnapshotPackages,
  18. PrunedBanksRequestHandler, SendDroppedBankCallback, SnapshotRequestHandler,
  19. },
  20. bank::{Bank, BankTestConfig},
  21. bank_forks::BankForks,
  22. genesis_utils::{create_genesis_config_with_leader, GenesisConfigInfo},
  23. runtime_config::RuntimeConfig,
  24. snapshot_archive_info::FullSnapshotArchiveInfo,
  25. snapshot_bank_utils,
  26. snapshot_controller::SnapshotController,
  27. snapshot_utils,
  28. status_cache::MAX_CACHE_ENTRIES,
  29. },
  30. solana_sha256_hasher::hashv,
  31. solana_signer::Signer,
  32. solana_streamer::socket::SocketAddrSpace,
  33. solana_system_transaction as system_transaction,
  34. solana_time_utils::timestamp,
  35. std::{
  36. num::NonZeroU64,
  37. path::PathBuf,
  38. sync::{
  39. atomic::{AtomicBool, Ordering},
  40. Arc, Mutex, RwLock,
  41. },
  42. time::{Duration, Instant},
  43. },
  44. tempfile::TempDir,
  45. };
  46. struct SnapshotTestConfig {
  47. bank_forks: Arc<RwLock<BankForks>>,
  48. genesis_config_info: GenesisConfigInfo,
  49. snapshot_config: SnapshotConfig,
  50. incremental_snapshot_archives_dir: TempDir,
  51. full_snapshot_archives_dir: TempDir,
  52. bank_snapshots_dir: TempDir,
  53. accounts_dir: PathBuf,
  54. // as the underscore prefix indicates, this isn't explicitly used; but it's needed to keep
  55. // TempDir::drop from running to retain that dir for the duration of test
  56. _accounts_tmp_dir: TempDir,
  57. }
  58. impl SnapshotTestConfig {
  59. fn new(
  60. full_snapshot_archive_interval: SnapshotInterval,
  61. incremental_snapshot_archive_interval: SnapshotInterval,
  62. ) -> SnapshotTestConfig {
  63. let (accounts_tmp_dir, accounts_dir) = create_tmp_accounts_dir_for_tests();
  64. let bank_snapshots_dir = TempDir::new().unwrap();
  65. let full_snapshot_archives_dir = TempDir::new().unwrap();
  66. let incremental_snapshot_archives_dir = TempDir::new().unwrap();
  67. // validator_stake_lamports should be non-zero otherwise stake
  68. // account will not be stored in accounts-db but still cached in
  69. // bank stakes which results in mismatch when banks are loaded from
  70. // snapshots.
  71. let genesis_config_info = create_genesis_config_with_leader(
  72. 10_000, // mint_lamports
  73. &solana_pubkey::new_rand(), // validator_pubkey
  74. 1, // validator_stake_lamports
  75. );
  76. let bank0 = Bank::new_with_paths_for_tests(
  77. &genesis_config_info.genesis_config,
  78. Arc::<RuntimeConfig>::default(),
  79. BankTestConfig::default(),
  80. vec![accounts_dir.clone()],
  81. );
  82. bank0.freeze();
  83. let bank_forks_arc = BankForks::new_rw_arc(bank0);
  84. let snapshot_config = SnapshotConfig {
  85. full_snapshot_archive_interval,
  86. incremental_snapshot_archive_interval,
  87. full_snapshot_archives_dir: full_snapshot_archives_dir.path().to_path_buf(),
  88. incremental_snapshot_archives_dir: incremental_snapshot_archives_dir
  89. .path()
  90. .to_path_buf(),
  91. bank_snapshots_dir: bank_snapshots_dir.path().to_path_buf(),
  92. ..SnapshotConfig::default()
  93. };
  94. SnapshotTestConfig {
  95. bank_forks: bank_forks_arc.clone(),
  96. genesis_config_info,
  97. snapshot_config,
  98. incremental_snapshot_archives_dir,
  99. full_snapshot_archives_dir,
  100. bank_snapshots_dir,
  101. accounts_dir,
  102. _accounts_tmp_dir: accounts_tmp_dir,
  103. }
  104. }
  105. }
  106. fn restore_from_snapshot(
  107. old_bank_forks: Arc<RwLock<BankForks>>,
  108. old_last_slot: Slot,
  109. old_genesis_config: &GenesisConfig,
  110. snapshot_config: &SnapshotConfig,
  111. account_paths: &[PathBuf],
  112. ) {
  113. let old_bank_forks = old_bank_forks.read().unwrap();
  114. let old_last_bank = old_bank_forks.get(old_last_slot).unwrap();
  115. let full_snapshot_archive_path = snapshot_utils::build_full_snapshot_archive_path(
  116. &snapshot_config.full_snapshot_archives_dir,
  117. old_last_bank.slot(),
  118. &old_last_bank.get_snapshot_hash(),
  119. snapshot_config.archive_format,
  120. );
  121. let full_snapshot_archive_info =
  122. FullSnapshotArchiveInfo::new_from_path(full_snapshot_archive_path).unwrap();
  123. let deserialized_bank = snapshot_bank_utils::bank_from_snapshot_archives(
  124. account_paths,
  125. &snapshot_config.bank_snapshots_dir,
  126. &full_snapshot_archive_info,
  127. None,
  128. old_genesis_config,
  129. &RuntimeConfig::default(),
  130. None,
  131. None,
  132. false,
  133. false,
  134. false,
  135. ACCOUNTS_DB_CONFIG_FOR_TESTING,
  136. None,
  137. Arc::default(),
  138. )
  139. .unwrap();
  140. let bank = old_bank_forks.get(deserialized_bank.slot()).unwrap();
  141. assert_eq!(bank.as_ref(), &deserialized_bank);
  142. }
  143. // creates banks up to "last_slot" and runs the input function `f` on each bank created
  144. // also marks each bank as root and generates snapshots
  145. // finally tries to restore from the last bank's snapshot and compares the restored bank to the
  146. // `last_slot` bank
  147. fn run_bank_forks_snapshot_n<F>(last_slot: Slot, f: F, set_root_interval: u64)
  148. where
  149. F: Fn(&Bank, &Keypair),
  150. {
  151. agave_logger::setup();
  152. // Set up snapshotting config
  153. let snapshot_test_config = SnapshotTestConfig::new(
  154. SnapshotInterval::Slots(NonZeroU64::new(set_root_interval).unwrap()),
  155. SnapshotInterval::Disabled,
  156. );
  157. let bank_forks = snapshot_test_config.bank_forks.clone();
  158. let mint_keypair = &snapshot_test_config.genesis_config_info.mint_keypair;
  159. let pending_snapshot_packages = Arc::new(Mutex::new(PendingSnapshotPackages::default()));
  160. let (snapshot_request_sender, snapshot_request_receiver) = unbounded();
  161. let snapshot_controller = Arc::new(SnapshotController::new(
  162. snapshot_request_sender.clone(),
  163. snapshot_test_config.snapshot_config.clone(),
  164. bank_forks.read().unwrap().root(),
  165. ));
  166. let snapshot_request_handler = SnapshotRequestHandler {
  167. snapshot_controller: snapshot_controller.clone(),
  168. snapshot_request_receiver,
  169. pending_snapshot_packages,
  170. };
  171. for slot in 1..=last_slot {
  172. let bank = Bank::new_from_parent(
  173. bank_forks.read().unwrap().get(slot - 1).unwrap().clone(),
  174. &Pubkey::default(),
  175. slot,
  176. );
  177. let bank = bank_forks.write().unwrap().insert(bank);
  178. f(bank.clone_without_scheduler().as_ref(), mint_keypair);
  179. // Set root to make sure we don't end up with too many account storage entries
  180. // and to allow snapshotting of bank and the purging logic on status_cache to
  181. // kick in
  182. if slot % set_root_interval == 0 || slot == last_slot {
  183. if !bank.is_complete() {
  184. bank.fill_bank_with_ticks_for_tests();
  185. }
  186. bank_forks.read().unwrap().prune_program_cache(bank.slot());
  187. // set_root should send a snapshot request
  188. bank_forks
  189. .write()
  190. .unwrap()
  191. .set_root(bank.slot(), Some(&snapshot_controller), None);
  192. snapshot_request_handler.handle_snapshot_requests(0);
  193. }
  194. }
  195. // Generate a snapshot package for last bank
  196. let snapshot_config = snapshot_controller.snapshot_config();
  197. let last_bank = bank_forks.read().unwrap().get(last_slot).unwrap();
  198. snapshot_bank_utils::bank_to_full_snapshot_archive(
  199. &snapshot_config.bank_snapshots_dir,
  200. &last_bank,
  201. Some(snapshot_config.snapshot_version),
  202. &snapshot_config.full_snapshot_archives_dir,
  203. &snapshot_config.incremental_snapshot_archives_dir,
  204. snapshot_config.archive_format,
  205. )
  206. .unwrap();
  207. // Restore bank from snapshot
  208. let (_tmp_dir, temporary_accounts_dir) = create_tmp_accounts_dir_for_tests();
  209. let account_paths = &[temporary_accounts_dir];
  210. let genesis_config = &snapshot_test_config.genesis_config_info.genesis_config;
  211. restore_from_snapshot(
  212. snapshot_test_config.bank_forks.clone(),
  213. last_slot,
  214. genesis_config,
  215. snapshot_config,
  216. account_paths,
  217. );
  218. }
  219. #[test]
  220. fn test_bank_forks_snapshot() {
  221. // create banks up to slot 4 and create 1 new account in each bank. test that bank 4 snapshots
  222. // and restores correctly
  223. run_bank_forks_snapshot_n(
  224. 4,
  225. |bank, mint_keypair| {
  226. let key1 = Keypair::new().pubkey();
  227. let tx = system_transaction::transfer(mint_keypair, &key1, 1, bank.last_blockhash());
  228. assert_eq!(bank.process_transaction(&tx), Ok(()));
  229. let key2 = Keypair::new().pubkey();
  230. let tx = system_transaction::transfer(mint_keypair, &key2, 0, bank.last_blockhash());
  231. assert_eq!(bank.process_transaction(&tx), Ok(()));
  232. },
  233. 1,
  234. );
  235. }
  236. fn goto_end_of_slot(bank: &Bank) {
  237. let mut tick_hash = bank.last_blockhash();
  238. loop {
  239. tick_hash = hashv(&[tick_hash.as_ref(), &[42]]);
  240. bank.register_tick_for_test(&tick_hash);
  241. if tick_hash == bank.last_blockhash() {
  242. bank.freeze();
  243. return;
  244. }
  245. }
  246. }
  247. #[test]
  248. fn test_slots_to_snapshot() {
  249. agave_logger::setup();
  250. let num_set_roots = MAX_CACHE_ENTRIES * 2;
  251. for add_root_interval in &[1, 3, 9] {
  252. let (snapshot_sender, _snapshot_receiver) = unbounded();
  253. // Make sure this test never clears bank.slots_since_snapshot
  254. let snapshot_test_config = SnapshotTestConfig::new(
  255. SnapshotInterval::Slots(
  256. NonZeroU64::new((*add_root_interval * num_set_roots * 2) as Slot).unwrap(),
  257. ),
  258. SnapshotInterval::Disabled,
  259. );
  260. let bank_forks = snapshot_test_config.bank_forks.clone();
  261. let bank_forks_r = bank_forks.read().unwrap();
  262. let mut current_bank = bank_forks_r[0].clone();
  263. drop(bank_forks_r);
  264. let snapshot_controller = SnapshotController::new(
  265. snapshot_sender,
  266. snapshot_test_config.snapshot_config.clone(),
  267. bank_forks.read().unwrap().root(),
  268. );
  269. for _ in 0..num_set_roots {
  270. for _ in 0..*add_root_interval {
  271. let new_slot = current_bank.slot() + 1;
  272. let new_bank = Bank::new_from_parent(current_bank, &Pubkey::default(), new_slot);
  273. current_bank = bank_forks.write().unwrap().insert(new_bank).clone();
  274. }
  275. bank_forks
  276. .read()
  277. .unwrap()
  278. .prune_program_cache(current_bank.slot());
  279. bank_forks.write().unwrap().set_root(
  280. current_bank.slot(),
  281. Some(&snapshot_controller),
  282. None,
  283. );
  284. }
  285. let num_old_slots = num_set_roots * *add_root_interval - MAX_CACHE_ENTRIES + 1;
  286. let expected_slots_to_snapshot =
  287. num_old_slots as u64..=num_set_roots as u64 * *add_root_interval as u64;
  288. let slots_to_snapshot = bank_forks
  289. .read()
  290. .unwrap()
  291. .root_bank()
  292. .status_cache
  293. .read()
  294. .unwrap()
  295. .roots()
  296. .iter()
  297. .cloned()
  298. .sorted();
  299. assert!(slots_to_snapshot.into_iter().eq(expected_slots_to_snapshot));
  300. }
  301. }
  302. #[test]
  303. fn test_bank_forks_status_cache_snapshot() {
  304. // create banks up to slot (MAX_CACHE_ENTRIES * 2) + 1 while transferring 1 lamport into 2 different accounts each time
  305. // this is done to ensure the AccountStorageEntries keep getting cleaned up as the root moves
  306. // ahead. Also tests the status_cache purge and status cache snapshotting.
  307. // Makes sure that the last bank is restored correctly
  308. let key1 = Keypair::new().pubkey();
  309. let key2 = Keypair::new().pubkey();
  310. for set_root_interval in &[1, 4] {
  311. run_bank_forks_snapshot_n(
  312. (MAX_CACHE_ENTRIES * 2) as u64,
  313. |bank, mint_keypair| {
  314. let tx = system_transaction::transfer(
  315. mint_keypair,
  316. &key1,
  317. 1,
  318. bank.parent().unwrap().last_blockhash(),
  319. );
  320. assert_eq!(bank.process_transaction(&tx), Ok(()));
  321. let tx = system_transaction::transfer(
  322. mint_keypair,
  323. &key2,
  324. 1,
  325. bank.parent().unwrap().last_blockhash(),
  326. );
  327. assert_eq!(bank.process_transaction(&tx), Ok(()));
  328. goto_end_of_slot(bank);
  329. },
  330. *set_root_interval,
  331. );
  332. }
  333. }
  334. #[test]
  335. fn test_bank_forks_incremental_snapshot() {
  336. agave_logger::setup();
  337. const SET_ROOT_INTERVAL: Slot = 2;
  338. const INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS: Slot = SET_ROOT_INTERVAL * 2;
  339. const FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS: Slot =
  340. INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS * 5;
  341. const LAST_SLOT: Slot = FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS * 2 - 1;
  342. info!(
  343. "Running bank forks incremental snapshot test, full snapshot interval: \
  344. {FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS} slots, incremental snapshot interval: \
  345. {INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS} slots, last slot: {LAST_SLOT}, set root \
  346. interval: {SET_ROOT_INTERVAL} slots"
  347. );
  348. let snapshot_test_config = SnapshotTestConfig::new(
  349. SnapshotInterval::Slots(NonZeroU64::new(FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS).unwrap()),
  350. SnapshotInterval::Slots(
  351. NonZeroU64::new(INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS).unwrap(),
  352. ),
  353. );
  354. trace!(
  355. "SnapshotTestConfig:\naccounts_dir: {}\nbank_snapshots_dir: \
  356. {}\nfull_snapshot_archives_dir: {}\nincremental_snapshot_archives_dir: {}",
  357. snapshot_test_config.accounts_dir.display(),
  358. snapshot_test_config.bank_snapshots_dir.path().display(),
  359. snapshot_test_config
  360. .full_snapshot_archives_dir
  361. .path()
  362. .display(),
  363. snapshot_test_config
  364. .incremental_snapshot_archives_dir
  365. .path()
  366. .display()
  367. );
  368. let bank_forks = snapshot_test_config.bank_forks.clone();
  369. let mint_keypair = &snapshot_test_config.genesis_config_info.mint_keypair;
  370. let pending_snapshot_packages = Arc::new(Mutex::new(PendingSnapshotPackages::default()));
  371. let (snapshot_request_sender, snapshot_request_receiver) = unbounded();
  372. let snapshot_controller = Arc::new(SnapshotController::new(
  373. snapshot_request_sender.clone(),
  374. snapshot_test_config.snapshot_config.clone(),
  375. bank_forks.read().unwrap().root(),
  376. ));
  377. let snapshot_request_handler = SnapshotRequestHandler {
  378. snapshot_controller: snapshot_controller.clone(),
  379. snapshot_request_receiver,
  380. pending_snapshot_packages,
  381. };
  382. let mut latest_full_snapshot_slot = None;
  383. for slot in 1..=LAST_SLOT {
  384. // Make a new bank and perform some transactions
  385. let bank = {
  386. let parent = bank_forks.read().unwrap().get(slot - 1).unwrap();
  387. let bank = Bank::new_from_parent(parent, &Pubkey::default(), slot);
  388. let bank_scheduler = bank_forks.write().unwrap().insert(bank);
  389. let bank = bank_scheduler.clone_without_scheduler();
  390. let key = solana_pubkey::new_rand();
  391. let tx = system_transaction::transfer(mint_keypair, &key, 1, bank.last_blockhash());
  392. assert_eq!(bank.process_transaction(&tx), Ok(()));
  393. let key = solana_pubkey::new_rand();
  394. let tx = system_transaction::transfer(mint_keypair, &key, 0, bank.last_blockhash());
  395. assert_eq!(bank.process_transaction(&tx), Ok(()));
  396. bank.fill_bank_with_ticks_for_tests();
  397. bank_scheduler
  398. };
  399. // Set root to make sure we don't end up with too many account storage entries
  400. // and to allow snapshotting of bank and the purging logic on status_cache to
  401. // kick in
  402. if slot % SET_ROOT_INTERVAL == 0 {
  403. // set_root sends a snapshot request
  404. bank_forks.read().unwrap().prune_program_cache(bank.slot());
  405. bank_forks
  406. .write()
  407. .unwrap()
  408. .set_root(bank.slot(), Some(&snapshot_controller), None);
  409. snapshot_request_handler.handle_snapshot_requests(0);
  410. }
  411. // Since AccountsBackgroundService isn't running, manually make a full snapshot archive
  412. // at the right interval
  413. if snapshot_utils::should_take_full_snapshot(slot, FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS) {
  414. make_full_snapshot_archive(&bank, snapshot_controller.snapshot_config()).unwrap();
  415. latest_full_snapshot_slot = Some(slot);
  416. }
  417. // Similarly, make an incremental snapshot archive at the right interval, but only if
  418. // there's been at least one full snapshot first, and a full snapshot wasn't already
  419. // taken at this slot.
  420. //
  421. // Then, after making an incremental snapshot, restore the bank and verify it is correct
  422. else if snapshot_utils::should_take_incremental_snapshot(
  423. slot,
  424. INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS,
  425. latest_full_snapshot_slot,
  426. ) && slot != latest_full_snapshot_slot.unwrap()
  427. {
  428. make_incremental_snapshot_archive(
  429. &bank,
  430. latest_full_snapshot_slot.unwrap(),
  431. snapshot_controller.snapshot_config(),
  432. )
  433. .unwrap();
  434. // Accounts directory needs to be separate from the active accounts directory
  435. // so that dropping append vecs in the active accounts directory doesn't
  436. // delete the unpacked appendvecs in the snapshot
  437. let (_tmp_dir, temporary_accounts_dir) = create_tmp_accounts_dir_for_tests();
  438. restore_from_snapshots_and_check_banks_are_equal(
  439. &bank,
  440. snapshot_controller.snapshot_config(),
  441. temporary_accounts_dir,
  442. &snapshot_test_config.genesis_config_info.genesis_config,
  443. )
  444. .unwrap();
  445. }
  446. }
  447. }
  448. fn make_full_snapshot_archive(
  449. bank: &Bank,
  450. snapshot_config: &SnapshotConfig,
  451. ) -> snapshot_utils::Result<()> {
  452. info!(
  453. "Making full snapshot archive from bank at slot: {}",
  454. bank.slot(),
  455. );
  456. snapshot_bank_utils::bank_to_full_snapshot_archive(
  457. &snapshot_config.bank_snapshots_dir,
  458. bank,
  459. Some(snapshot_config.snapshot_version),
  460. &snapshot_config.full_snapshot_archives_dir,
  461. &snapshot_config.incremental_snapshot_archives_dir,
  462. snapshot_config.archive_format,
  463. )?;
  464. Ok(())
  465. }
  466. fn make_incremental_snapshot_archive(
  467. bank: &Bank,
  468. incremental_snapshot_base_slot: Slot,
  469. snapshot_config: &SnapshotConfig,
  470. ) -> snapshot_utils::Result<()> {
  471. info!(
  472. "Making incremental snapshot archive from bank at slot: {}, and base slot: {}",
  473. bank.slot(),
  474. incremental_snapshot_base_slot,
  475. );
  476. snapshot_bank_utils::bank_to_incremental_snapshot_archive(
  477. &snapshot_config.bank_snapshots_dir,
  478. bank,
  479. incremental_snapshot_base_slot,
  480. Some(snapshot_config.snapshot_version),
  481. &snapshot_config.full_snapshot_archives_dir,
  482. &snapshot_config.incremental_snapshot_archives_dir,
  483. snapshot_config.archive_format,
  484. )?;
  485. Ok(())
  486. }
  487. fn restore_from_snapshots_and_check_banks_are_equal(
  488. bank: &Bank,
  489. snapshot_config: &SnapshotConfig,
  490. accounts_dir: PathBuf,
  491. genesis_config: &GenesisConfig,
  492. ) -> snapshot_utils::Result<()> {
  493. let (deserialized_bank, ..) = snapshot_bank_utils::bank_from_latest_snapshot_archives(
  494. &snapshot_config.bank_snapshots_dir,
  495. &snapshot_config.full_snapshot_archives_dir,
  496. &snapshot_config.incremental_snapshot_archives_dir,
  497. &[accounts_dir],
  498. genesis_config,
  499. &RuntimeConfig::default(),
  500. None,
  501. None,
  502. false,
  503. false,
  504. false,
  505. ACCOUNTS_DB_CONFIG_FOR_TESTING,
  506. None,
  507. Arc::default(),
  508. )?;
  509. assert_eq!(bank, &deserialized_bank);
  510. Ok(())
  511. }
  512. /// Spin up the background services fully then test taking & verifying snapshots
  513. #[test]
  514. fn test_snapshots_with_background_services() {
  515. agave_logger::setup();
  516. const SET_ROOT_INTERVAL_SLOTS: Slot = 2;
  517. const BANK_SNAPSHOT_INTERVAL_SLOTS: Slot = SET_ROOT_INTERVAL_SLOTS * 2;
  518. const INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS: Slot = BANK_SNAPSHOT_INTERVAL_SLOTS * 3;
  519. const FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS: Slot =
  520. INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS * 5;
  521. const LAST_SLOT: Slot =
  522. FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS * 3 + INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS * 2;
  523. // Maximum amount of time to wait for each snapshot archive to be created.
  524. // This should be enough time, but if it times-out in CI, try increasing it.
  525. const MAX_WAIT_DURATION: Duration = Duration::from_secs(10);
  526. info!("Running snapshots with background services test...");
  527. #[rustfmt::skip]
  528. trace!(
  529. "Test configuration parameters:\
  530. \n\tfull snapshot archive interval: {FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS} slots\
  531. \n\tincremental snapshot archive interval: {INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS} slots\
  532. \n\tbank snapshot interval: {BANK_SNAPSHOT_INTERVAL_SLOTS} slots\
  533. \n\tset root interval: {SET_ROOT_INTERVAL_SLOTS} slots\
  534. \n\tlast slot: {LAST_SLOT}"
  535. );
  536. let snapshot_test_config = SnapshotTestConfig::new(
  537. SnapshotInterval::Slots(NonZeroU64::new(FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS).unwrap()),
  538. SnapshotInterval::Slots(
  539. NonZeroU64::new(INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS).unwrap(),
  540. ),
  541. );
  542. let node_keypair = Arc::new(Keypair::new());
  543. let cluster_info = Arc::new(ClusterInfo::new(
  544. ContactInfo::new_localhost(&node_keypair.pubkey(), timestamp()),
  545. node_keypair,
  546. SocketAddrSpace::Unspecified,
  547. ));
  548. let (pruned_banks_sender, pruned_banks_receiver) = unbounded();
  549. let (snapshot_request_sender, snapshot_request_receiver) = unbounded();
  550. let pending_snapshot_packages = Arc::new(Mutex::new(PendingSnapshotPackages::default()));
  551. let bank_forks = snapshot_test_config.bank_forks.clone();
  552. bank_forks
  553. .read()
  554. .unwrap()
  555. .root_bank()
  556. .rc
  557. .accounts
  558. .accounts_db
  559. .enable_bank_drop_callback();
  560. let callback = SendDroppedBankCallback::new(pruned_banks_sender);
  561. for bank in bank_forks.read().unwrap().banks().values() {
  562. bank.set_callback(Some(Box::new(callback.clone())));
  563. }
  564. let snapshot_controller = Arc::new(SnapshotController::new(
  565. snapshot_request_sender.clone(),
  566. snapshot_test_config.snapshot_config.clone(),
  567. bank_forks.read().unwrap().root(),
  568. ));
  569. let snapshot_request_handler = SnapshotRequestHandler {
  570. snapshot_controller: snapshot_controller.clone(),
  571. snapshot_request_receiver,
  572. pending_snapshot_packages: pending_snapshot_packages.clone(),
  573. };
  574. let pruned_banks_request_handler = PrunedBanksRequestHandler {
  575. pruned_banks_receiver,
  576. };
  577. let abs_request_handler = AbsRequestHandlers {
  578. snapshot_request_handler,
  579. pruned_banks_request_handler,
  580. };
  581. let exit = Arc::new(AtomicBool::new(false));
  582. let snapshot_packager_service = SnapshotPackagerService::new(
  583. pending_snapshot_packages.clone(),
  584. None,
  585. exit.clone(),
  586. None,
  587. cluster_info.clone(),
  588. snapshot_controller.clone(),
  589. false,
  590. );
  591. let accounts_background_service =
  592. AccountsBackgroundService::new(bank_forks.clone(), exit.clone(), abs_request_handler);
  593. let mut latest_full_snapshot_slot = None;
  594. let mut latest_incremental_snapshot_slot = None;
  595. let mint_keypair = &snapshot_test_config.genesis_config_info.mint_keypair;
  596. for slot in 1..=LAST_SLOT {
  597. // Make a new bank and process some transactions
  598. {
  599. let bank = Bank::new_from_parent(
  600. bank_forks.read().unwrap().get(slot - 1).unwrap(),
  601. &Pubkey::default(),
  602. slot,
  603. );
  604. let bank = bank_forks
  605. .write()
  606. .unwrap()
  607. .insert(bank)
  608. .clone_without_scheduler();
  609. let key = solana_pubkey::new_rand();
  610. let tx = system_transaction::transfer(mint_keypair, &key, 1, bank.last_blockhash());
  611. assert_eq!(bank.process_transaction(&tx), Ok(()));
  612. let key = solana_pubkey::new_rand();
  613. let tx = system_transaction::transfer(mint_keypair, &key, 0, bank.last_blockhash());
  614. assert_eq!(bank.process_transaction(&tx), Ok(()));
  615. bank.fill_bank_with_ticks_for_tests();
  616. }
  617. // Call `BankForks::set_root()` to cause snapshots to be taken
  618. if slot % SET_ROOT_INTERVAL_SLOTS == 0 {
  619. bank_forks
  620. .write()
  621. .unwrap()
  622. .set_root(slot, Some(&snapshot_controller), None);
  623. }
  624. // If a snapshot should be taken this slot, wait for it to complete
  625. if slot % FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS == 0 {
  626. let timer = Instant::now();
  627. while snapshot_utils::get_highest_full_snapshot_archive_slot(
  628. &snapshot_test_config
  629. .snapshot_config
  630. .full_snapshot_archives_dir,
  631. ) != Some(slot)
  632. {
  633. assert!(
  634. timer.elapsed() < MAX_WAIT_DURATION,
  635. "Waiting for full snapshot {slot} exceeded the {MAX_WAIT_DURATION:?} maximum \
  636. wait duration!",
  637. );
  638. std::thread::sleep(Duration::from_secs(1));
  639. }
  640. latest_full_snapshot_slot = Some(slot);
  641. } else if slot % INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS == 0
  642. && latest_full_snapshot_slot.is_some()
  643. {
  644. let timer = Instant::now();
  645. while snapshot_utils::get_highest_incremental_snapshot_archive_slot(
  646. &snapshot_test_config
  647. .snapshot_config
  648. .incremental_snapshot_archives_dir,
  649. latest_full_snapshot_slot.unwrap(),
  650. ) != Some(slot)
  651. {
  652. assert!(
  653. timer.elapsed() < MAX_WAIT_DURATION,
  654. "Waiting for incremental snapshot {slot} exceeded the {MAX_WAIT_DURATION:?} \
  655. maximum wait duration!",
  656. );
  657. std::thread::sleep(Duration::from_secs(1));
  658. }
  659. latest_incremental_snapshot_slot = Some(slot);
  660. }
  661. }
  662. // Load the snapshot and ensure it matches what's in BankForks
  663. let (_tmp_dir, temporary_accounts_dir) = create_tmp_accounts_dir_for_tests();
  664. let snapshot_config = snapshot_controller.snapshot_config();
  665. let (deserialized_bank, ..) = snapshot_bank_utils::bank_from_latest_snapshot_archives(
  666. &snapshot_config.bank_snapshots_dir,
  667. &snapshot_config.full_snapshot_archives_dir,
  668. &snapshot_config.incremental_snapshot_archives_dir,
  669. &[temporary_accounts_dir],
  670. &snapshot_test_config.genesis_config_info.genesis_config,
  671. &RuntimeConfig::default(),
  672. None,
  673. None,
  674. false,
  675. false,
  676. false,
  677. ACCOUNTS_DB_CONFIG_FOR_TESTING,
  678. None,
  679. exit.clone(),
  680. )
  681. .unwrap();
  682. assert_eq!(
  683. deserialized_bank.slot(),
  684. latest_incremental_snapshot_slot.unwrap()
  685. );
  686. assert_eq!(
  687. &deserialized_bank,
  688. bank_forks
  689. .read()
  690. .unwrap()
  691. .get(deserialized_bank.slot())
  692. .unwrap()
  693. .as_ref()
  694. );
  695. // Stop the background services, ignore any errors
  696. info!("Shutting down background services...");
  697. exit.store(true, Ordering::Relaxed);
  698. _ = accounts_background_service.join();
  699. _ = snapshot_packager_service.join();
  700. }