ledger-tool: Add flag to find non-vote optimistic slots (#30580)
In cluster restart scenarios, it is desirable to know the latest optimistic slot(s), which the subcommand latest-optimistic-slots will return. However, it is also useful to know whether slots contain only votes or if they contain votes and user transactions. This PR adds an extra column of output to show whether an optimistically confirmed slot is vote only (contains zero non-vote transactions). Additionally, a flag has been added to enable filtering output to exclude vote only slots.
This commit is contained in:
parent
b14fcf5a12
commit
8db35eb7e5
|
@ -2354,6 +2354,12 @@ fn main() {
|
|||
.required(false)
|
||||
.help("Number of slots in the output"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("exclude_vote_only_slots")
|
||||
.long("exclude-vote-only-slots")
|
||||
.required(false)
|
||||
.help("Exclude slots that contain only votes from output"),
|
||||
)
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("repair-roots")
|
||||
|
@ -4230,11 +4236,37 @@ fn main() {
|
|||
force_update_to_open,
|
||||
);
|
||||
let num_slots = value_t_or_exit!(arg_matches, "num_slots", usize);
|
||||
let slots = blockstore
|
||||
.get_latest_optimistic_slots(num_slots)
|
||||
.expect("Failed to get latest optimistic slots");
|
||||
println!("{:>20} {:>44} {:>32}", "Slot", "Hash", "Timestamp");
|
||||
for (slot, hash, timestamp) in slots.iter() {
|
||||
let exclude_vote_only_slots = arg_matches.is_present("exclude_vote_only_slots");
|
||||
|
||||
let slots_iter = blockstore
|
||||
.reversed_optimistic_slots_iterator()
|
||||
.expect("Failed to get reversed optimistic slots iterator")
|
||||
.map(|(slot, hash, timestamp)| {
|
||||
let (entries, _, _) = blockstore
|
||||
.get_slot_entries_with_shred_info(slot, 0, false)
|
||||
.expect("Failed to get slot entries");
|
||||
let contains_nonvote = entries
|
||||
.iter()
|
||||
.flat_map(|entry| entry.transactions.iter())
|
||||
.flat_map(get_program_ids)
|
||||
.any(|program_id| *program_id != solana_vote_program::id());
|
||||
(slot, hash, timestamp, contains_nonvote)
|
||||
});
|
||||
|
||||
let slots: Vec<_> = if exclude_vote_only_slots {
|
||||
slots_iter
|
||||
.filter(|(_, _, _, contains_nonvote)| *contains_nonvote)
|
||||
.take(num_slots)
|
||||
.collect()
|
||||
} else {
|
||||
slots_iter.take(num_slots).collect()
|
||||
};
|
||||
|
||||
println!(
|
||||
"{:>20} {:>44} {:>32} {:>13}",
|
||||
"Slot", "Hash", "Timestamp", "Vote Only?"
|
||||
);
|
||||
for (slot, hash, timestamp, contains_nonvote) in slots.iter() {
|
||||
let time_str = {
|
||||
let secs: u64 = (timestamp / 1_000) as u64;
|
||||
let nanos: u32 = ((timestamp % 1_000) * 1_000_000) as u32;
|
||||
|
@ -4243,7 +4275,10 @@ fn main() {
|
|||
datetime.to_rfc3339()
|
||||
};
|
||||
let hash_str = format!("{hash}");
|
||||
println!("{:>20} {:>44} {:>32}", slot, &hash_str, &time_str);
|
||||
println!(
|
||||
"{:>20} {:>44} {:>32} {:>13}",
|
||||
slot, &hash_str, &time_str, !contains_nonvote
|
||||
);
|
||||
}
|
||||
}
|
||||
("repair-roots", Some(arg_matches)) => {
|
||||
|
|
|
@ -552,6 +552,16 @@ impl Blockstore {
|
|||
self.prepare_rooted_slot_iterator(slot, IteratorDirection::Reverse)
|
||||
}
|
||||
|
||||
pub fn reversed_optimistic_slots_iterator(
|
||||
&self,
|
||||
) -> Result<impl Iterator<Item = (Slot, Hash, UnixTimestamp)> + '_> {
|
||||
let iter = self.db.iter::<cf::OptimisticSlots>(IteratorMode::End)?;
|
||||
Ok(iter.map(|(slot, bytes)| {
|
||||
let meta: OptimisticSlotMetaVersioned = deserialize(&bytes).unwrap();
|
||||
(slot, meta.hash(), meta.timestamp())
|
||||
}))
|
||||
}
|
||||
|
||||
/// Determines if we can iterate from `starting_slot` to >= `ending_slot` by full slots
|
||||
/// `starting_slot` is excluded from the `is_full()` check
|
||||
pub fn slot_range_connected(&self, starting_slot: Slot, ending_slot: Slot) -> bool {
|
||||
|
@ -3103,15 +3113,8 @@ impl Blockstore {
|
|||
&self,
|
||||
num: usize,
|
||||
) -> Result<Vec<(Slot, Hash, UnixTimestamp)>> {
|
||||
Ok(self
|
||||
.db
|
||||
.iter::<cf::OptimisticSlots>(IteratorMode::End)?
|
||||
.take(num)
|
||||
.map(|(slot, data)| {
|
||||
let meta: OptimisticSlotMetaVersioned = deserialize(&data).unwrap();
|
||||
(slot, meta.hash(), meta.timestamp())
|
||||
})
|
||||
.collect())
|
||||
let iter = self.reversed_optimistic_slots_iterator()?;
|
||||
Ok(iter.take(num).collect())
|
||||
}
|
||||
|
||||
pub fn set_duplicate_confirmed_slots_and_hashes(
|
||||
|
|
Loading…
Reference in New Issue