1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use crate::{
    blockstore::Blockstore,
    blockstore_processor::{
        self, BlockstoreProcessorError, BlockstoreProcessorResult, ProcessOptions,
        TransactionStatusSender,
    },
    entry::VerifyRecyclers,
    leader_schedule_cache::LeaderScheduleCache,
};
use log::*;
use solana_runtime::{
    bank_forks::{BankForks, SnapshotConfig},
    snapshot_utils,
};
use solana_sdk::{clock::Slot, genesis_config::GenesisConfig, hash::Hash};
use std::{fs, path::Path, path::PathBuf, process, result};

pub type LoadResult = result::Result<
    (BankForks, LeaderScheduleCache, Option<(Slot, Hash)>),
    BlockstoreProcessorError,
>;

fn to_loadresult(
    brp: BlockstoreProcessorResult,
    snapshot_hash: Option<(Slot, Hash)>,
) -> LoadResult {
    brp.map(|(bank_forks, leader_schedule_cache)| {
        (bank_forks, leader_schedule_cache, snapshot_hash)
    })
}

pub fn load(
    genesis_config: &GenesisConfig,
    blockstore: &Blockstore,
    evm_state_path: impl AsRef<Path>,
    evm_genesis_path: impl AsRef<Path>,
    account_paths: Vec<PathBuf>,
    shrink_paths: Option<Vec<PathBuf>>,
    snapshot_config: Option<&SnapshotConfig>,
    process_options: ProcessOptions,
    transaction_status_sender: Option<TransactionStatusSender>,
) -> LoadResult {
    if let Some(snapshot_config) = snapshot_config.as_ref() {
        info!(
            "Initializing snapshot path: {:?}",
            snapshot_config.snapshot_path
        );
        let _ = fs::remove_dir_all(&snapshot_config.snapshot_path);
        fs::create_dir_all(&snapshot_config.snapshot_path)
            .expect("Couldn't create snapshot directory");

        match snapshot_utils::get_highest_snapshot_archive_path(
            &snapshot_config.snapshot_package_output_path,
        ) {
            Some((archive_filename, (archive_slot, archive_snapshot_hash, compression))) => {
                info!("Loading snapshot package: {:?}", archive_filename);
                // Fail hard here if snapshot fails to load, don't silently continue

                if account_paths.is_empty() {
                    error!("Account paths not present when booting from snapshot");
                    process::exit(1);
                }

                let deserialized_bank = snapshot_utils::bank_from_archive(
                    &evm_state_path.as_ref(),
                    &account_paths,
                    &process_options.frozen_accounts,
                    &snapshot_config.snapshot_path,
                    &archive_filename,
                    compression,
                    genesis_config,
                    process_options.debug_keys.clone(),
                    Some(&crate::builtins::get(process_options.bpf_jit)),
                    process_options.account_indexes.clone(),
                    process_options.accounts_db_caching_enabled,
                )
                .expect("Load from snapshot failed");
                if let Some(shrink_paths) = shrink_paths {
                    deserialized_bank.set_shrink_paths(shrink_paths);
                }

                let deserialized_snapshot_hash = (
                    deserialized_bank.slot(),
                    deserialized_bank.get_accounts_hash(),
                );

                if deserialized_snapshot_hash != (archive_slot, archive_snapshot_hash) {
                    error!(
                        "Snapshot has mismatch:\narchive: {:?}\ndeserialized: {:?}",
                        archive_snapshot_hash, deserialized_snapshot_hash
                    );
                    process::exit(1);
                }

                return to_loadresult(
                    blockstore_processor::process_blockstore_from_root(
                        blockstore,
                        deserialized_bank,
                        &process_options,
                        &VerifyRecyclers::default(),
                        transaction_status_sender,
                    ),
                    Some(deserialized_snapshot_hash),
                );
            }
            None => info!("No snapshot package available"),
        }
    } else {
        info!("Snapshots disabled");
    }

    info!("Processing ledger from genesis");
    to_loadresult(
        blockstore_processor::process_blockstore(
            &genesis_config,
            &blockstore,
            &evm_state_path,
            evm_genesis_path,
            account_paths,
            process_options,
        ),
        None,
    )
}