parent
5b070ad014
commit
8b5598fabd
|
@ -19,7 +19,6 @@ use crate::{
|
||||||
tvu::{Sockets, Tvu},
|
tvu::{Sockets, Tvu},
|
||||||
};
|
};
|
||||||
use crossbeam_channel::unbounded;
|
use crossbeam_channel::unbounded;
|
||||||
use solana_ledger::shred::Shred;
|
|
||||||
use solana_ledger::{
|
use solana_ledger::{
|
||||||
bank_forks::{BankForks, SnapshotConfig},
|
bank_forks::{BankForks, SnapshotConfig},
|
||||||
bank_forks_utils,
|
bank_forks_utils,
|
||||||
|
@ -28,13 +27,14 @@ use solana_ledger::{
|
||||||
create_new_tmp_ledger,
|
create_new_tmp_ledger,
|
||||||
leader_schedule::FixedSchedule,
|
leader_schedule::FixedSchedule,
|
||||||
leader_schedule_cache::LeaderScheduleCache,
|
leader_schedule_cache::LeaderScheduleCache,
|
||||||
|
shred_version::compute_shred_version,
|
||||||
};
|
};
|
||||||
use solana_metrics::datapoint_info;
|
use solana_metrics::datapoint_info;
|
||||||
use solana_runtime::{bank::Bank, hard_forks::HardForks};
|
use solana_runtime::bank::Bank;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
clock::{Slot, DEFAULT_SLOTS_PER_TURN},
|
clock::{Slot, DEFAULT_SLOTS_PER_TURN},
|
||||||
genesis_config::GenesisConfig,
|
genesis_config::GenesisConfig,
|
||||||
hash::{extend_and_hash, Hash},
|
hash::Hash,
|
||||||
poh_config::PohConfig,
|
poh_config::PohConfig,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{Keypair, KeypairUtil},
|
signature::{Keypair, KeypairUtil},
|
||||||
|
@ -193,7 +193,7 @@ impl Validator {
|
||||||
|
|
||||||
node.info.wallclock = timestamp();
|
node.info.wallclock = timestamp();
|
||||||
node.info.shred_version =
|
node.info.shred_version =
|
||||||
compute_shred_version(&genesis_hash, &bank.hard_forks().read().unwrap());
|
compute_shred_version(&genesis_hash, Some(&bank.hard_forks().read().unwrap()));
|
||||||
Self::print_node_info(&node);
|
Self::print_node_info(&node);
|
||||||
|
|
||||||
if let Some(expected_shred_version) = config.expected_shred_version {
|
if let Some(expected_shred_version) = config.expected_shred_version {
|
||||||
|
@ -471,20 +471,6 @@ impl Validator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_shred_version(genesis_hash: &Hash, hard_forks: &HardForks) -> u16 {
|
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
|
||||||
|
|
||||||
let mut hash = *genesis_hash;
|
|
||||||
for (slot, count) in hard_forks.iter() {
|
|
||||||
let mut buf = [0u8; 16];
|
|
||||||
LittleEndian::write_u64(&mut buf[..8], *slot);
|
|
||||||
LittleEndian::write_u64(&mut buf[8..], *count as u64);
|
|
||||||
hash = extend_and_hash(&hash, &buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
Shred::version_from_hash(&hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_banks_from_blockstore(
|
fn new_banks_from_blockstore(
|
||||||
expected_genesis_hash: Option<Hash>,
|
expected_genesis_hash: Option<Hash>,
|
||||||
blockstore_path: &Path,
|
blockstore_path: &Path,
|
||||||
|
@ -698,16 +684,6 @@ mod tests {
|
||||||
use crate::genesis_utils::create_genesis_config_with_leader;
|
use crate::genesis_utils::create_genesis_config_with_leader;
|
||||||
use std::fs::remove_dir_all;
|
use std::fs::remove_dir_all;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_compute_shred_version() {
|
|
||||||
let mut hard_forks = HardForks::default();
|
|
||||||
assert_eq!(compute_shred_version(&Hash::default(), &hard_forks), 1);
|
|
||||||
hard_forks.register(1);
|
|
||||||
assert_eq!(compute_shred_version(&Hash::default(), &hard_forks), 55551);
|
|
||||||
hard_forks.register(1);
|
|
||||||
assert_eq!(compute_shred_version(&Hash::default(), &hard_forks), 46353);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn validator_exit() {
|
fn validator_exit() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
|
|
|
@ -7,7 +7,10 @@ use solana_clap_utils::{
|
||||||
input_validators::{is_rfc3339_datetime, is_valid_percentage},
|
input_validators::{is_rfc3339_datetime, is_valid_percentage},
|
||||||
};
|
};
|
||||||
use solana_genesis::{genesis_accounts::add_genesis_accounts, Base64Account};
|
use solana_genesis::{genesis_accounts::add_genesis_accounts, Base64Account};
|
||||||
use solana_ledger::{blockstore::create_new_ledger, poh::compute_hashes_per_tick};
|
use solana_ledger::{
|
||||||
|
blockstore::create_new_ledger, poh::compute_hashes_per_tick,
|
||||||
|
shred_version::compute_shred_version,
|
||||||
|
};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::Account,
|
account::Account,
|
||||||
clock,
|
clock,
|
||||||
|
@ -521,10 +524,19 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
create_new_ledger(&ledger_path, &genesis_config)?;
|
create_new_ledger(&ledger_path, &genesis_config)?;
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"Genesis hash: {}\nCreation time: {}\nOperating mode: {:?}\nHashes per tick: {:?}\nSlots per epoch: {}\nCapitalization: {} SOL in {} accounts",
|
"\
|
||||||
genesis_config.hash(),
|
Creation time: {}\n\
|
||||||
|
Operating mode: {:?}\n\
|
||||||
|
Genesis hash: {}\n\
|
||||||
|
Shred version: {}\n\
|
||||||
|
Hashes per tick: {:?}\n\
|
||||||
|
Slots per epoch: {}\n\
|
||||||
|
Capitalization: {} SOL in {} accounts\
|
||||||
|
",
|
||||||
Utc.timestamp(genesis_config.creation_time, 0).to_rfc3339(),
|
Utc.timestamp(genesis_config.creation_time, 0).to_rfc3339(),
|
||||||
operating_mode,
|
operating_mode,
|
||||||
|
genesis_config.hash(),
|
||||||
|
compute_shred_version(&genesis_config.hash(), None),
|
||||||
genesis_config.poh_config.hashes_per_tick,
|
genesis_config.poh_config.hashes_per_tick,
|
||||||
slots_per_epoch,
|
slots_per_epoch,
|
||||||
lamports_to_sol(
|
lamports_to_sol(
|
||||||
|
@ -537,7 +549,8 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
}
|
}
|
||||||
account.lamports
|
account.lamports
|
||||||
})
|
})
|
||||||
.sum::<u64>()),
|
.sum::<u64>()
|
||||||
|
),
|
||||||
genesis_config.accounts.len()
|
genesis_config.accounts.len()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ use solana_ledger::{
|
||||||
blockstore_db::{self, Column, Database},
|
blockstore_db::{self, Column, Database},
|
||||||
blockstore_processor::{BankForksInfo, BlockstoreProcessorResult, ProcessOptions},
|
blockstore_processor::{BankForksInfo, BlockstoreProcessorResult, ProcessOptions},
|
||||||
rooted_slot_iterator::RootedSlotIterator,
|
rooted_slot_iterator::RootedSlotIterator,
|
||||||
|
shred_version::compute_shred_version,
|
||||||
snapshot_utils,
|
snapshot_utils,
|
||||||
};
|
};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
|
@ -526,6 +527,7 @@ fn hardforks_of(matches: &ArgMatches<'_>, name: &str) -> Option<Vec<Slot>> {
|
||||||
fn load_bank_forks(
|
fn load_bank_forks(
|
||||||
arg_matches: &ArgMatches,
|
arg_matches: &ArgMatches,
|
||||||
ledger_path: &PathBuf,
|
ledger_path: &PathBuf,
|
||||||
|
genesis_config: &GenesisConfig,
|
||||||
process_options: ProcessOptions,
|
process_options: ProcessOptions,
|
||||||
) -> BlockstoreProcessorResult {
|
) -> BlockstoreProcessorResult {
|
||||||
let snapshot_config = if arg_matches.is_present("no_snapshot") {
|
let snapshot_config = if arg_matches.is_present("no_snapshot") {
|
||||||
|
@ -544,7 +546,7 @@ fn load_bank_forks(
|
||||||
};
|
};
|
||||||
|
|
||||||
bank_forks_utils::load(
|
bank_forks_utils::load(
|
||||||
&open_genesis_config(&ledger_path),
|
&genesis_config,
|
||||||
&open_blockstore(&ledger_path),
|
&open_blockstore(&ledger_path),
|
||||||
account_paths,
|
account_paths,
|
||||||
snapshot_config.as_ref(),
|
snapshot_config.as_ref(),
|
||||||
|
@ -615,9 +617,14 @@ fn main() {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("print-genesis-hash")
|
SubCommand::with_name("genesis-hash")
|
||||||
.about("Prints the ledger's genesis hash")
|
.about("Prints the ledger's genesis hash")
|
||||||
)
|
)
|
||||||
|
.subcommand(
|
||||||
|
SubCommand::with_name("shred-version")
|
||||||
|
.about("Prints the ledger's shred hash")
|
||||||
|
.arg(&hard_forks_arg)
|
||||||
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("bounds")
|
SubCommand::with_name("bounds")
|
||||||
.about("Print lowest and highest non-empty slots. Note that there may be empty slots within the bounds")
|
.about("Print lowest and highest non-empty slots. Note that there may be empty slots within the bounds")
|
||||||
|
@ -741,19 +748,49 @@ fn main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
("print", Some(args_matches)) => {
|
("print", Some(arg_matches)) => {
|
||||||
let starting_slot = value_t_or_exit!(args_matches, "starting_slot", Slot);
|
let starting_slot = value_t_or_exit!(arg_matches, "starting_slot", Slot);
|
||||||
output_ledger(
|
output_ledger(
|
||||||
open_blockstore(&ledger_path),
|
open_blockstore(&ledger_path),
|
||||||
starting_slot,
|
starting_slot,
|
||||||
LedgerOutputMethod::Print,
|
LedgerOutputMethod::Print,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
("print-genesis-hash", Some(_args_matches)) => {
|
("genesis-hash", Some(_arg_matches)) => {
|
||||||
println!("{}", open_genesis_config(&ledger_path).hash());
|
println!("{}", open_genesis_config(&ledger_path).hash());
|
||||||
}
|
}
|
||||||
("print-slot", Some(args_matches)) => {
|
("shred-version", Some(arg_matches)) => {
|
||||||
let slots = values_t_or_exit!(args_matches, "slots", Slot);
|
let genesis_config = open_genesis_config(&ledger_path);
|
||||||
|
println!("{}", genesis_config.hash());
|
||||||
|
|
||||||
|
let process_options = ProcessOptions {
|
||||||
|
dev_halt_at_slot: Some(0),
|
||||||
|
new_hard_forks: hardforks_of(arg_matches, "hard_forks"),
|
||||||
|
poh_verify: false,
|
||||||
|
..ProcessOptions::default()
|
||||||
|
};
|
||||||
|
let genesis_config = open_genesis_config(&ledger_path);
|
||||||
|
match load_bank_forks(arg_matches, &ledger_path, &genesis_config, process_options) {
|
||||||
|
Ok((bank_forks, bank_forks_info, _leader_schedule_cache)) => {
|
||||||
|
let bank_info = &bank_forks_info[0];
|
||||||
|
let bank = bank_forks[bank_info.bank_slot].clone();
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
compute_shred_version(
|
||||||
|
&genesis_config.hash(),
|
||||||
|
Some(&bank.hard_forks().read().unwrap())
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("Failed to load ledger: {:?}", err);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
("print-slot", Some(arg_matches)) => {
|
||||||
|
let slots = values_t_or_exit!(arg_matches, "slots", Slot);
|
||||||
for slot in slots {
|
for slot in slots {
|
||||||
println!("Slot {}", slot);
|
println!("Slot {}", slot);
|
||||||
output_slot(
|
output_slot(
|
||||||
|
@ -763,8 +800,8 @@ fn main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
("json", Some(args_matches)) => {
|
("json", Some(arg_matches)) => {
|
||||||
let starting_slot = value_t_or_exit!(args_matches, "starting_slot", Slot);
|
let starting_slot = value_t_or_exit!(arg_matches, "starting_slot", Slot);
|
||||||
output_ledger(
|
output_ledger(
|
||||||
open_blockstore(&ledger_path),
|
open_blockstore(&ledger_path),
|
||||||
starting_slot,
|
starting_slot,
|
||||||
|
@ -778,8 +815,15 @@ fn main() {
|
||||||
poh_verify: !arg_matches.is_present("skip_poh_verify"),
|
poh_verify: !arg_matches.is_present("skip_poh_verify"),
|
||||||
..ProcessOptions::default()
|
..ProcessOptions::default()
|
||||||
};
|
};
|
||||||
|
println!("{}", open_genesis_config(&ledger_path).hash());
|
||||||
|
|
||||||
load_bank_forks(arg_matches, &ledger_path, process_options).unwrap_or_else(|err| {
|
load_bank_forks(
|
||||||
|
arg_matches,
|
||||||
|
&ledger_path,
|
||||||
|
&open_genesis_config(&ledger_path),
|
||||||
|
process_options,
|
||||||
|
)
|
||||||
|
.unwrap_or_else(|err| {
|
||||||
eprintln!("Ledger verification failed: {:?}", err);
|
eprintln!("Ledger verification failed: {:?}", err);
|
||||||
exit(1);
|
exit(1);
|
||||||
});
|
});
|
||||||
|
@ -795,7 +839,12 @@ fn main() {
|
||||||
..ProcessOptions::default()
|
..ProcessOptions::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
match load_bank_forks(arg_matches, &ledger_path, process_options) {
|
match load_bank_forks(
|
||||||
|
arg_matches,
|
||||||
|
&ledger_path,
|
||||||
|
&open_genesis_config(&ledger_path),
|
||||||
|
process_options,
|
||||||
|
) {
|
||||||
Ok((bank_forks, bank_forks_info, _leader_schedule_cache)) => {
|
Ok((bank_forks, bank_forks_info, _leader_schedule_cache)) => {
|
||||||
let dot = graph_forks(
|
let dot = graph_forks(
|
||||||
&bank_forks,
|
&bank_forks,
|
||||||
|
@ -834,7 +883,8 @@ fn main() {
|
||||||
poh_verify: false,
|
poh_verify: false,
|
||||||
..ProcessOptions::default()
|
..ProcessOptions::default()
|
||||||
};
|
};
|
||||||
match load_bank_forks(arg_matches, &ledger_path, process_options) {
|
let genesis_config = open_genesis_config(&ledger_path);
|
||||||
|
match load_bank_forks(arg_matches, &ledger_path, &genesis_config, process_options) {
|
||||||
Ok((bank_forks, _bank_forks_info, _leader_schedule_cache)) => {
|
Ok((bank_forks, _bank_forks_info, _leader_schedule_cache)) => {
|
||||||
let bank = bank_forks.get(snapshot_slot).unwrap_or_else(|| {
|
let bank = bank_forks.get(snapshot_slot).unwrap_or_else(|| {
|
||||||
eprintln!("Error: Slot {} is not available", snapshot_slot);
|
eprintln!("Error: Slot {} is not available", snapshot_slot);
|
||||||
|
@ -865,6 +915,13 @@ fn main() {
|
||||||
"Successfully created snapshot for slot {}: {:?}",
|
"Successfully created snapshot for slot {}: {:?}",
|
||||||
snapshot_slot, package.tar_output_file
|
snapshot_slot, package.tar_output_file
|
||||||
);
|
);
|
||||||
|
println!(
|
||||||
|
"Shred version: {}",
|
||||||
|
compute_shred_version(
|
||||||
|
&genesis_config.hash(),
|
||||||
|
Some(&bank.hard_forks().read().unwrap())
|
||||||
|
)
|
||||||
|
);
|
||||||
ok
|
ok
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -879,8 +936,8 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
("prune", Some(args_matches)) => {
|
("prune", Some(arg_matches)) => {
|
||||||
if let Some(prune_file_path) = args_matches.value_of("slot_list") {
|
if let Some(prune_file_path) = arg_matches.value_of("slot_list") {
|
||||||
let blockstore = open_blockstore(&ledger_path);
|
let blockstore = open_blockstore(&ledger_path);
|
||||||
let prune_file = File::open(prune_file_path.to_string()).unwrap();
|
let prune_file = File::open(prune_file_path.to_string()).unwrap();
|
||||||
let slot_hashes: BTreeMap<u64, String> =
|
let slot_hashes: BTreeMap<u64, String> =
|
||||||
|
@ -916,14 +973,14 @@ fn main() {
|
||||||
blockstore.prune(*target_slot);
|
blockstore.prune(*target_slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
("list-roots", Some(args_matches)) => {
|
("list-roots", Some(arg_matches)) => {
|
||||||
let blockstore = open_blockstore(&ledger_path);
|
let blockstore = open_blockstore(&ledger_path);
|
||||||
let max_height = if let Some(height) = args_matches.value_of("max_height") {
|
let max_height = if let Some(height) = arg_matches.value_of("max_height") {
|
||||||
usize::from_str(height).expect("Maximum height must be a number")
|
usize::from_str(height).expect("Maximum height must be a number")
|
||||||
} else {
|
} else {
|
||||||
panic!("Maximum height must be provided");
|
panic!("Maximum height must be provided");
|
||||||
};
|
};
|
||||||
let num_roots = if let Some(roots) = args_matches.value_of("num_roots") {
|
let num_roots = if let Some(roots) = arg_matches.value_of("num_roots") {
|
||||||
usize::from_str(roots).expect("Number of roots must be a number")
|
usize::from_str(roots).expect("Number of roots must be a number")
|
||||||
} else {
|
} else {
|
||||||
usize::from_str(DEFAULT_ROOT_COUNT).unwrap()
|
usize::from_str(DEFAULT_ROOT_COUNT).unwrap()
|
||||||
|
@ -948,7 +1005,7 @@ fn main() {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut output_file: Box<dyn Write> =
|
let mut output_file: Box<dyn Write> =
|
||||||
if let Some(path) = args_matches.value_of("slot_list") {
|
if let Some(path) = arg_matches.value_of("slot_list") {
|
||||||
match File::create(path) {
|
match File::create(path) {
|
||||||
Ok(file) => Box::new(file),
|
Ok(file) => Box::new(file),
|
||||||
_ => Box::new(stdout()),
|
_ => Box::new(stdout()),
|
||||||
|
@ -969,10 +1026,10 @@ fn main() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
("bounds", Some(args_matches)) => {
|
("bounds", Some(arg_matches)) => {
|
||||||
match open_blockstore(&ledger_path).slot_meta_iterator(0) {
|
match open_blockstore(&ledger_path).slot_meta_iterator(0) {
|
||||||
Ok(metas) => {
|
Ok(metas) => {
|
||||||
let all = args_matches.is_present("all");
|
let all = arg_matches.is_present("all");
|
||||||
|
|
||||||
println!("Collecting Ledger information...");
|
println!("Collecting Ledger information...");
|
||||||
let slots: Vec<_> = metas.map(|(slot, _)| slot).collect();
|
let slots: Vec<_> = metas.map(|(slot, _)| slot).collect();
|
||||||
|
|
|
@ -15,6 +15,7 @@ pub mod leader_schedule_utils;
|
||||||
pub mod poh;
|
pub mod poh;
|
||||||
pub mod rooted_slot_iterator;
|
pub mod rooted_slot_iterator;
|
||||||
pub mod shred;
|
pub mod shred;
|
||||||
|
pub mod shred_version;
|
||||||
pub mod sigverify_shreds;
|
pub mod sigverify_shreds;
|
||||||
pub mod snapshot_package;
|
pub mod snapshot_package;
|
||||||
pub mod snapshot_utils;
|
pub mod snapshot_utils;
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
use crate::shred::Shred;
|
||||||
|
use solana_runtime::hard_forks::HardForks;
|
||||||
|
use solana_sdk::hash::{extend_and_hash, Hash};
|
||||||
|
|
||||||
|
pub fn compute_shred_version(genesis_hash: &Hash, hard_forks: Option<&HardForks>) -> u16 {
|
||||||
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
|
|
||||||
|
let mut hash = *genesis_hash;
|
||||||
|
if let Some(hard_forks) = hard_forks {
|
||||||
|
for (slot, count) in hard_forks.iter() {
|
||||||
|
let mut buf = [0u8; 16];
|
||||||
|
LittleEndian::write_u64(&mut buf[..8], *slot);
|
||||||
|
LittleEndian::write_u64(&mut buf[8..], *count as u64);
|
||||||
|
hash = extend_and_hash(&hash, &buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Shred::version_from_hash(&hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_compute_shred_version() {
|
||||||
|
assert_eq!(compute_shred_version(&Hash::default(), None), 1);
|
||||||
|
let mut hard_forks = HardForks::default();
|
||||||
|
assert_eq!(
|
||||||
|
compute_shred_version(&Hash::default(), Some(&hard_forks)),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
hard_forks.register(1);
|
||||||
|
assert_eq!(
|
||||||
|
compute_shred_version(&Hash::default(), Some(&hard_forks)),
|
||||||
|
55551
|
||||||
|
);
|
||||||
|
hard_forks.register(1);
|
||||||
|
assert_eq!(
|
||||||
|
compute_shred_version(&Hash::default(), Some(&hard_forks)),
|
||||||
|
46353
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue