Add ability to fork a local cluster from the latest mainnet-beta snapshot
This commit is contained in:
parent
450c667aa7
commit
df7710a131
|
@ -5,7 +5,10 @@ use clap::{
|
||||||
use log::*;
|
use log::*;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use solana_clap_utils::input_validators::{is_parsable, is_slot};
|
use solana_clap_utils::{
|
||||||
|
input_parsers::{pubkey_of, pubkeys_of},
|
||||||
|
input_validators::{is_parsable, is_pubkey_or_keypair, is_slot, is_valid_percentage},
|
||||||
|
};
|
||||||
use solana_ledger::entry::Entry;
|
use solana_ledger::entry::Entry;
|
||||||
use solana_ledger::{
|
use solana_ledger::{
|
||||||
ancestor_iterator::AncestorIterator,
|
ancestor_iterator::AncestorIterator,
|
||||||
|
@ -23,15 +26,22 @@ use solana_runtime::{
|
||||||
snapshot_utils::SnapshotVersion,
|
snapshot_utils::SnapshotVersion,
|
||||||
};
|
};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
|
account::Account,
|
||||||
clock::{Epoch, Slot},
|
clock::{Epoch, Slot},
|
||||||
genesis_config::GenesisConfig,
|
genesis_config::{GenesisConfig, OperatingMode},
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
inflation::Inflation,
|
inflation::Inflation,
|
||||||
native_token::{lamports_to_sol, Sol},
|
native_token::{lamports_to_sol, sol_to_lamports, Sol},
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
|
rent::Rent,
|
||||||
shred_version::compute_shred_version,
|
shred_version::compute_shred_version,
|
||||||
|
system_program,
|
||||||
|
};
|
||||||
|
use solana_stake_program::stake_state::{self, StakeState};
|
||||||
|
use solana_vote_program::{
|
||||||
|
self,
|
||||||
|
vote_state::{self, VoteState},
|
||||||
};
|
};
|
||||||
use solana_vote_program::vote_state::VoteState;
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, BTreeSet, HashMap, HashSet},
|
collections::{BTreeMap, BTreeSet, HashMap, HashSet},
|
||||||
convert::{TryFrom, TryInto},
|
convert::{TryFrom, TryInto},
|
||||||
|
@ -764,6 +774,15 @@ fn main() {
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.default_value(&default_genesis_archive_unpacked_size)
|
.default_value(&default_genesis_archive_unpacked_size)
|
||||||
.help("maximum total uncompressed size of unpacked genesis archive");
|
.help("maximum total uncompressed size of unpacked genesis archive");
|
||||||
|
let hashes_per_tick = Arg::with_name("hashes_per_tick")
|
||||||
|
.long("hashes-per-tick")
|
||||||
|
.value_name("NUM_HASHES|\"sleep\"")
|
||||||
|
.takes_value(true)
|
||||||
|
.help(
|
||||||
|
"How many PoH hashes to roll before emitting the next tick. \
|
||||||
|
If \"sleep\", for development \
|
||||||
|
sleep for the target tick duration instead of hashing",
|
||||||
|
);
|
||||||
let snapshot_version_arg = Arg::with_name("snapshot_version")
|
let snapshot_version_arg = Arg::with_name("snapshot_version")
|
||||||
.long("snapshot-version")
|
.long("snapshot-version")
|
||||||
.value_name("SNAPSHOT_VERSION")
|
.value_name("SNAPSHOT_VERSION")
|
||||||
|
@ -771,6 +790,15 @@ fn main() {
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.default_value(SnapshotVersion::default().into())
|
.default_value(SnapshotVersion::default().into())
|
||||||
.help("Output snapshot version");
|
.help("Output snapshot version");
|
||||||
|
|
||||||
|
let rent = Rent::default();
|
||||||
|
let default_bootstrap_validator_lamports = &sol_to_lamports(500.0)
|
||||||
|
.max(VoteState::get_rent_exempt_reserve(&rent))
|
||||||
|
.to_string();
|
||||||
|
let default_bootstrap_validator_stake_lamports = &sol_to_lamports(0.5)
|
||||||
|
.max(StakeState::get_rent_exempt_reserve(&rent))
|
||||||
|
.to_string();
|
||||||
|
|
||||||
let matches = App::new(crate_name!())
|
let matches = App::new(crate_name!())
|
||||||
.about(crate_description!())
|
.about(crate_description!())
|
||||||
.version(solana_version::version!())
|
.version(solana_version::version!())
|
||||||
|
@ -913,6 +941,23 @@ fn main() {
|
||||||
.about("Prints the ledger's genesis hash")
|
.about("Prints the ledger's genesis hash")
|
||||||
.arg(&max_genesis_archive_unpacked_size_arg)
|
.arg(&max_genesis_archive_unpacked_size_arg)
|
||||||
)
|
)
|
||||||
|
.subcommand(
|
||||||
|
SubCommand::with_name("modify-genesis")
|
||||||
|
.about("Modifies genesis parameters")
|
||||||
|
.arg(&max_genesis_archive_unpacked_size_arg)
|
||||||
|
.arg(&hashes_per_tick)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("operating_mode")
|
||||||
|
.long("operating-mode")
|
||||||
|
.possible_value("development")
|
||||||
|
.possible_value("preview")
|
||||||
|
.possible_value("stable")
|
||||||
|
.takes_value(true)
|
||||||
|
.help(
|
||||||
|
"Selects the features that will be enabled for the cluster"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("shred-version")
|
SubCommand::with_name("shred-version")
|
||||||
.about("Prints the ledger's shred hash")
|
.about("Prints the ledger's shred hash")
|
||||||
|
@ -1008,6 +1053,72 @@ fn main() {
|
||||||
.help("After loading the snapshot slot warp the ledger to WARP_SLOT, \
|
.help("After loading the snapshot slot warp the ledger to WARP_SLOT, \
|
||||||
which could be a slot in a galaxy far far away"),
|
which could be a slot in a galaxy far far away"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("faucet_lamports")
|
||||||
|
.short("t")
|
||||||
|
.long("faucet-lamports")
|
||||||
|
.value_name("LAMPORTS")
|
||||||
|
.takes_value(true)
|
||||||
|
.requires("faucet_pubkey")
|
||||||
|
.help("Number of lamports to assign to the faucet"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("faucet_pubkey")
|
||||||
|
.short("m")
|
||||||
|
.long("faucet-pubkey")
|
||||||
|
.value_name("PUBKEY")
|
||||||
|
.takes_value(true)
|
||||||
|
.validator(is_pubkey_or_keypair)
|
||||||
|
.requires("faucet_lamports")
|
||||||
|
.help("Path to file containing the faucet's pubkey"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("bootstrap_validator")
|
||||||
|
.short("b")
|
||||||
|
.long("bootstrap-validator")
|
||||||
|
.value_name("IDENTITY_PUBKEY VOTE_PUBKEY STAKE_PUBKEY")
|
||||||
|
.takes_value(true)
|
||||||
|
.validator(is_pubkey_or_keypair)
|
||||||
|
.number_of_values(3)
|
||||||
|
.multiple(true)
|
||||||
|
.help("The bootstrap validator's identity, vote and stake pubkeys"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("bootstrap_stake_authorized_pubkey")
|
||||||
|
.long("bootstrap-stake-authorized-pubkey")
|
||||||
|
.value_name("BOOTSTRAP STAKE AUTHORIZED PUBKEY")
|
||||||
|
.takes_value(true)
|
||||||
|
.validator(is_pubkey_or_keypair)
|
||||||
|
.help(
|
||||||
|
"Path to file containing the pubkey authorized to manage the bootstrap \
|
||||||
|
validator's stake [default: --bootstrap-validator IDENTITY_PUBKEY]",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("bootstrap_validator_lamports")
|
||||||
|
.long("bootstrap-validator-lamports")
|
||||||
|
.value_name("LAMPORTS")
|
||||||
|
.takes_value(true)
|
||||||
|
.default_value(default_bootstrap_validator_lamports)
|
||||||
|
.help("Number of lamports to assign to the bootstrap validator"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("bootstrap_validator_stake_lamports")
|
||||||
|
.long("bootstrap-validator-stake-lamports")
|
||||||
|
.value_name("LAMPORTS")
|
||||||
|
.takes_value(true)
|
||||||
|
.default_value(default_bootstrap_validator_stake_lamports)
|
||||||
|
.help("Number of lamports to assign to the bootstrap validator's stake account"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("rent_burn_percentage")
|
||||||
|
.long("rent-burn-percentage")
|
||||||
|
.value_name("NUMBER")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("Adjust percentage of collected rent to burn")
|
||||||
|
.validator(is_valid_percentage),
|
||||||
|
)
|
||||||
|
.arg(&hashes_per_tick)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("rehash")
|
Arg::with_name("rehash")
|
||||||
.required(false)
|
.required(false)
|
||||||
|
@ -1015,6 +1126,13 @@ fn main() {
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Re-calculate the bank hash and overwrite the original bank hash."),
|
.help("Re-calculate the bank hash and overwrite the original bank hash."),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("remove_stake_accounts")
|
||||||
|
.required(false)
|
||||||
|
.long("remove-stake-accounts")
|
||||||
|
.takes_value(false)
|
||||||
|
.help("Remove all existing stake accounts from the new snapshot.")
|
||||||
|
)
|
||||||
).subcommand(
|
).subcommand(
|
||||||
SubCommand::with_name("accounts")
|
SubCommand::with_name("accounts")
|
||||||
.about("Print account contents after processing in the ledger")
|
.about("Print account contents after processing in the ledger")
|
||||||
|
@ -1199,6 +1317,31 @@ fn main() {
|
||||||
open_genesis_config_by(&ledger_path, arg_matches).hash()
|
open_genesis_config_by(&ledger_path, arg_matches).hash()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
("modify-genesis", Some(arg_matches)) => {
|
||||||
|
let mut genesis_config = open_genesis_config_by(&ledger_path, arg_matches);
|
||||||
|
|
||||||
|
if let Some(operating_mode) = arg_matches.value_of("operating_mode") {
|
||||||
|
genesis_config.operating_mode = match operating_mode {
|
||||||
|
"development" => OperatingMode::Development,
|
||||||
|
"stable" => OperatingMode::Stable,
|
||||||
|
"preview" => OperatingMode::Preview,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(hashes_per_tick) = arg_matches.value_of("hashes_per_tick") {
|
||||||
|
genesis_config.poh_config.hashes_per_tick = match hashes_per_tick {
|
||||||
|
// Note: Unlike `solana-genesis`, "auto" is not supported here.
|
||||||
|
"sleep" => None,
|
||||||
|
_ => Some(value_t_or_exit!(arg_matches, "hashes_per_tick", u64)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
genesis_config.write(&ledger_path).unwrap_or_else(|err| {
|
||||||
|
eprintln!("Failed to write genesis config: {:?}", err);
|
||||||
|
exit(1);
|
||||||
|
});
|
||||||
|
println!("{}", open_genesis_config_by(&ledger_path, arg_matches));
|
||||||
|
}
|
||||||
("shred-version", Some(arg_matches)) => {
|
("shred-version", Some(arg_matches)) => {
|
||||||
let process_options = ProcessOptions {
|
let process_options = ProcessOptions {
|
||||||
dev_halt_at_slot: Some(0),
|
dev_halt_at_slot: Some(0),
|
||||||
|
@ -1426,8 +1569,30 @@ fn main() {
|
||||||
("create-snapshot", Some(arg_matches)) => {
|
("create-snapshot", Some(arg_matches)) => {
|
||||||
let snapshot_slot = value_t_or_exit!(arg_matches, "snapshot_slot", Slot);
|
let snapshot_slot = value_t_or_exit!(arg_matches, "snapshot_slot", Slot);
|
||||||
let output_directory = value_t_or_exit!(arg_matches, "output_directory", String);
|
let output_directory = value_t_or_exit!(arg_matches, "output_directory", String);
|
||||||
let warp_slot = value_t!(arg_matches, "warp_slot", Slot).ok();
|
let mut warp_slot = value_t!(arg_matches, "warp_slot", Slot).ok();
|
||||||
let rehash = arg_matches.is_present("rehash");
|
let mut rehash = arg_matches.is_present("rehash");
|
||||||
|
let remove_stake_accounts = arg_matches.is_present("remove_stake_accounts");
|
||||||
|
let new_hard_forks = hardforks_of(arg_matches, "hard_forks");
|
||||||
|
|
||||||
|
let faucet_pubkey = pubkey_of(&arg_matches, "faucet_pubkey");
|
||||||
|
let faucet_lamports = value_t!(arg_matches, "faucet_lamports", u64).unwrap_or(0);
|
||||||
|
|
||||||
|
let rent_burn_percentage = value_t!(arg_matches, "rent_burn_percentage", u8);
|
||||||
|
let hashes_per_tick = arg_matches.value_of("hashes_per_tick");
|
||||||
|
|
||||||
|
let bootstrap_stake_authorized_pubkey =
|
||||||
|
pubkey_of(&arg_matches, "bootstrap_stake_authorized_pubkey");
|
||||||
|
let bootstrap_validator_lamports =
|
||||||
|
value_t_or_exit!(arg_matches, "bootstrap_validator_lamports", u64);
|
||||||
|
let bootstrap_validator_stake_lamports =
|
||||||
|
value_t_or_exit!(arg_matches, "bootstrap_validator_stake_lamports", u64);
|
||||||
|
let minimum_stake_lamports = StakeState::get_rent_exempt_reserve(&rent);
|
||||||
|
if bootstrap_validator_stake_lamports < minimum_stake_lamports {
|
||||||
|
eprintln!("Error: insufficient --bootstrap-validator-stake-lamports. Minimum amount is {}", minimum_stake_lamports);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
let bootstrap_validator_pubkeys = pubkeys_of(&arg_matches, "bootstrap_validator");
|
||||||
|
|
||||||
let snapshot_version =
|
let snapshot_version =
|
||||||
arg_matches
|
arg_matches
|
||||||
.value_of("snapshot_version")
|
.value_of("snapshot_version")
|
||||||
|
@ -1439,7 +1604,7 @@ fn main() {
|
||||||
});
|
});
|
||||||
let process_options = ProcessOptions {
|
let process_options = ProcessOptions {
|
||||||
dev_halt_at_slot: Some(snapshot_slot),
|
dev_halt_at_slot: Some(snapshot_slot),
|
||||||
new_hard_forks: hardforks_of(arg_matches, "hard_forks"),
|
new_hard_forks,
|
||||||
poh_verify: false,
|
poh_verify: false,
|
||||||
..ProcessOptions::default()
|
..ProcessOptions::default()
|
||||||
};
|
};
|
||||||
|
@ -1454,7 +1619,7 @@ fn main() {
|
||||||
snapshot_archive_path,
|
snapshot_archive_path,
|
||||||
) {
|
) {
|
||||||
Ok((bank_forks, _leader_schedule_cache, _snapshot_hash)) => {
|
Ok((bank_forks, _leader_schedule_cache, _snapshot_hash)) => {
|
||||||
let bank = bank_forks
|
let mut bank = bank_forks
|
||||||
.get(snapshot_slot)
|
.get(snapshot_slot)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
eprintln!("Error: Slot {} is not available", snapshot_slot);
|
eprintln!("Error: Slot {} is not available", snapshot_slot);
|
||||||
|
@ -1462,6 +1627,136 @@ fn main() {
|
||||||
})
|
})
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
|
if rent_burn_percentage.is_ok() || hashes_per_tick.is_some() {
|
||||||
|
let mut child_bank =
|
||||||
|
Bank::new_from_parent(&bank, bank.collector_id(), bank.slot() + 1);
|
||||||
|
|
||||||
|
if let Ok(rent_burn_percentage) = rent_burn_percentage {
|
||||||
|
child_bank.set_rent_burn_percentage(rent_burn_percentage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(hashes_per_tick) = hashes_per_tick {
|
||||||
|
child_bank.set_hashes_per_tick(match hashes_per_tick {
|
||||||
|
// Note: Unlike `solana-genesis`, "auto" is not supported here.
|
||||||
|
"sleep" => None,
|
||||||
|
_ => Some(value_t_or_exit!(arg_matches, "hashes_per_tick", u64)),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
bank = Arc::new(child_bank);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(faucet_pubkey) = faucet_pubkey {
|
||||||
|
rehash = true;
|
||||||
|
bank.store_account(
|
||||||
|
&faucet_pubkey,
|
||||||
|
&Account::new(faucet_lamports, 0, &system_program::id()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if remove_stake_accounts {
|
||||||
|
for (address, mut account) in bank
|
||||||
|
.get_program_accounts(Some(&solana_stake_program::id()))
|
||||||
|
.into_iter()
|
||||||
|
{
|
||||||
|
account.lamports = 0;
|
||||||
|
bank.store_account(&address, &account);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(bootstrap_validator_pubkeys) = bootstrap_validator_pubkeys {
|
||||||
|
rehash = true;
|
||||||
|
|
||||||
|
assert_eq!(bootstrap_validator_pubkeys.len() % 3, 0);
|
||||||
|
|
||||||
|
// Ensure there are no duplicated pubkeys in the --bootstrap-validator list
|
||||||
|
{
|
||||||
|
let mut v = bootstrap_validator_pubkeys.clone();
|
||||||
|
v.sort();
|
||||||
|
v.dedup();
|
||||||
|
if v.len() != bootstrap_validator_pubkeys.len() {
|
||||||
|
eprintln!(
|
||||||
|
"Error: --bootstrap-validator pubkeys cannot be duplicated"
|
||||||
|
);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete existing vote accounts
|
||||||
|
for (address, mut account) in bank
|
||||||
|
.get_program_accounts(Some(&solana_vote_program::id()))
|
||||||
|
.into_iter()
|
||||||
|
{
|
||||||
|
account.lamports = 0;
|
||||||
|
bank.store_account(&address, &account);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a new identity/vote/stake account for each of the provided bootstrap
|
||||||
|
// validators
|
||||||
|
let mut bootstrap_validator_pubkeys_iter =
|
||||||
|
bootstrap_validator_pubkeys.iter();
|
||||||
|
loop {
|
||||||
|
let identity_pubkey = match bootstrap_validator_pubkeys_iter.next() {
|
||||||
|
None => break,
|
||||||
|
Some(identity_pubkey) => identity_pubkey,
|
||||||
|
};
|
||||||
|
let vote_pubkey = bootstrap_validator_pubkeys_iter.next().unwrap();
|
||||||
|
let stake_pubkey = bootstrap_validator_pubkeys_iter.next().unwrap();
|
||||||
|
|
||||||
|
bank.store_account(
|
||||||
|
identity_pubkey,
|
||||||
|
&Account::new(
|
||||||
|
bootstrap_validator_lamports,
|
||||||
|
0,
|
||||||
|
&system_program::id(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
let vote_account = vote_state::create_account_with_authorized(
|
||||||
|
&identity_pubkey,
|
||||||
|
&identity_pubkey,
|
||||||
|
&identity_pubkey,
|
||||||
|
100,
|
||||||
|
VoteState::get_rent_exempt_reserve(&rent).max(1),
|
||||||
|
);
|
||||||
|
|
||||||
|
bank.store_account(
|
||||||
|
stake_pubkey,
|
||||||
|
&stake_state::create_account(
|
||||||
|
bootstrap_stake_authorized_pubkey
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&identity_pubkey),
|
||||||
|
&vote_pubkey,
|
||||||
|
&vote_account,
|
||||||
|
&rent,
|
||||||
|
bootstrap_validator_stake_lamports,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
bank.store_account(vote_pubkey, &vote_account);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warp ahead at least two epochs to ensure that the leader schedule will be
|
||||||
|
// updated to reflect the new bootstrap validator(s)
|
||||||
|
let minimum_warp_slot =
|
||||||
|
genesis_config.epoch_schedule.get_first_slot_in_epoch(
|
||||||
|
genesis_config.epoch_schedule.get_epoch(snapshot_slot) + 2,
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(warp_slot) = warp_slot {
|
||||||
|
if warp_slot < minimum_warp_slot {
|
||||||
|
eprintln!(
|
||||||
|
"Error: --warp-slot too close. Must be >= {}",
|
||||||
|
minimum_warp_slot
|
||||||
|
);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("Warping to slot {}", minimum_warp_slot);
|
||||||
|
warp_slot = Some(minimum_warp_slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bank.set_capitalization();
|
||||||
|
|
||||||
let bank = if let Some(warp_slot) = warp_slot {
|
let bank = if let Some(warp_slot) = warp_slot {
|
||||||
Arc::new(Bank::warp_from_parent(
|
Arc::new(Bank::warp_from_parent(
|
||||||
&bank,
|
&bank,
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
here=$(dirname "$0")
|
||||||
|
# shellcheck source=multinode-demo/common.sh
|
||||||
|
source "$here"/common.sh
|
||||||
|
|
||||||
|
|
||||||
|
rm -rf "$SOLANA_CONFIG_DIR"/latest-mainnet-beta-snapshot
|
||||||
|
mkdir -p "$SOLANA_CONFIG_DIR"/latest-mainnet-beta-snapshot
|
||||||
|
(
|
||||||
|
cd "$SOLANA_CONFIG_DIR"/latest-mainnet-beta-snapshot || exit 1
|
||||||
|
set -x
|
||||||
|
wget http://api.mainnet-beta.solana.com/genesis.tar.bz2
|
||||||
|
wget --trust-server-names http://api.mainnet-beta.solana.com/snapshot.tar.bz2
|
||||||
|
)
|
||||||
|
|
||||||
|
snapshot=$(ls "$SOLANA_CONFIG_DIR"/latest-mainnet-beta-snapshot/snapshot-[0-9]*-*.tar.bz2)
|
||||||
|
if [[ -z $snapshot ]]; then
|
||||||
|
echo Error: Unable to find latest snapshot
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! $snapshot =~ snapshot-([0-9]*)-.*.tar.bz2 ]]; then
|
||||||
|
echo Error: Unable to determine snapshot slot for "$snapshot"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
snapshot_slot="${BASH_REMATCH[1]}"
|
||||||
|
|
||||||
|
rm -rf "$SOLANA_CONFIG_DIR"/bootstrap-validator
|
||||||
|
mkdir -p "$SOLANA_CONFIG_DIR"/bootstrap-validator
|
||||||
|
|
||||||
|
|
||||||
|
# Create genesis ledger
|
||||||
|
if [[ -r $FAUCET_KEYPAIR ]]; then
|
||||||
|
cp -f "$FAUCET_KEYPAIR" "$SOLANA_CONFIG_DIR"/faucet.json
|
||||||
|
else
|
||||||
|
$solana_keygen new --no-passphrase -fso "$SOLANA_CONFIG_DIR"/faucet.json
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f $BOOTSTRAP_VALIDATOR_IDENTITY_KEYPAIR ]]; then
|
||||||
|
cp -f "$BOOTSTRAP_VALIDATOR_IDENTITY_KEYPAIR" "$SOLANA_CONFIG_DIR"/bootstrap-validator/identity.json
|
||||||
|
else
|
||||||
|
$solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/bootstrap-validator/identity.json
|
||||||
|
fi
|
||||||
|
|
||||||
|
$solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/bootstrap-validator/vote-account.json
|
||||||
|
$solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/bootstrap-validator/stake-account.json
|
||||||
|
|
||||||
|
|
||||||
|
cp "$SOLANA_CONFIG_DIR"/latest-mainnet-beta-snapshot/genesis.tar.bz2 \
|
||||||
|
"$SOLANA_CONFIG_DIR"/bootstrap-validator
|
||||||
|
|
||||||
|
$solana_ledger_tool modify-genesis \
|
||||||
|
--ledger "$SOLANA_CONFIG_DIR"/bootstrap-validator \
|
||||||
|
--hashes-per-tick sleep \
|
||||||
|
#--operating-mode preview \
|
||||||
|
|
||||||
|
$solana_ledger_tool create-snapshot \
|
||||||
|
--hashes-per-tick sleep \
|
||||||
|
--ledger "$SOLANA_CONFIG_DIR"/latest-mainnet-beta-snapshot \
|
||||||
|
--faucet-pubkey "$SOLANA_CONFIG_DIR"/faucet.json \
|
||||||
|
--faucet-lamports 500000000000000000 \
|
||||||
|
--bootstrap-validator "$SOLANA_CONFIG_DIR"/bootstrap-validator/identity.json \
|
||||||
|
"$SOLANA_CONFIG_DIR"/bootstrap-validator/vote-account.json \
|
||||||
|
"$SOLANA_CONFIG_DIR"/bootstrap-validator/stake-account.json \
|
||||||
|
"$snapshot_slot" "$SOLANA_CONFIG_DIR"/bootstrap-validator
|
Loading…
Reference in New Issue