Skip to content

Commit

Permalink
ledger-tool: add option to print contents of duplicate slot proofs (#…
Browse files Browse the repository at this point in the history
…2153)

* ledger-tool: add option to print contents of duplicate slot proofs

* pr feedback: Add CliDuplicateSlotProof type for display
  • Loading branch information
AshwinSekar authored Aug 13, 2024
1 parent 223cca3 commit fbae3a6
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 3 deletions.
9 changes: 8 additions & 1 deletion ledger-tool/src/blockstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use {
error::{LedgerToolError, Result},
ledger_path::canonicalize_ledger_path,
ledger_utils::{get_program_ids, get_shred_storage_type},
output::{output_ledger, output_slot, SlotBounds, SlotInfo},
output::{output_ledger, output_slot, CliDuplicateSlotProof, SlotBounds, SlotInfo},
},
chrono::{DateTime, Utc},
clap::{
Expand Down Expand Up @@ -707,8 +707,15 @@ fn do_blockstore_process_command(ledger_path: &Path, matches: &ArgMatches<'_>) -
let blockstore =
crate::open_blockstore(&ledger_path, arg_matches, AccessType::Secondary);
let starting_slot = value_t_or_exit!(arg_matches, "starting_slot", Slot);
let output_format =
OutputFormat::from_matches(arg_matches, "output_format", verbose_level > 1);
for slot in blockstore.duplicate_slots_iterator(starting_slot)? {
println!("{slot}");
if verbose_level > 0 {
let proof = blockstore.get_duplicate_slot(slot).unwrap();
let cli_duplicate_proof = CliDuplicateSlotProof::from(proof);
println!("{}", output_format.formatted_string(&cli_duplicate_proof));
}
}
}
("latest-optimistic-slots", Some(arg_matches)) => {
Expand Down
116 changes: 115 additions & 1 deletion ledger-tool/src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ use {
display::writeln_transaction, CliAccount, CliAccountNewConfig, OutputFormat, QuietDisplay,
VerboseDisplay,
},
solana_ledger::blockstore::{Blockstore, BlockstoreError},
solana_ledger::{
blockstore::{Blockstore, BlockstoreError},
blockstore_meta::{DuplicateSlotProof, ErasureMeta},
shred::{Shred, ShredType},
},
solana_runtime::bank::{Bank, TotalAccountsStats},
solana_sdk::{
account::{AccountSharedData, ReadableAccount},
Expand Down Expand Up @@ -296,6 +300,116 @@ impl fmt::Display for CliBlockWithEntries {
}
}

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CliDuplicateSlotProof {
shred1: CliDuplicateShred,
shred2: CliDuplicateShred,
erasure_consistency: Option<bool>,
}

impl QuietDisplay for CliDuplicateSlotProof {}

impl VerboseDisplay for CliDuplicateSlotProof {
fn write_str(&self, w: &mut dyn std::fmt::Write) -> std::fmt::Result {
write!(w, " Shred1 ")?;
VerboseDisplay::write_str(&self.shred1, w)?;
write!(w, " Shred2 ")?;
VerboseDisplay::write_str(&self.shred2, w)?;
if let Some(erasure_consistency) = self.erasure_consistency {
writeln!(w, " Erasure consistency {}", erasure_consistency)?;
}
Ok(())
}
}

impl fmt::Display for CliDuplicateSlotProof {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, " Shred1 {}", self.shred1)?;
write!(f, " Shred2 {}", self.shred2)?;
if let Some(erasure_consistency) = self.erasure_consistency {
writeln!(f, " Erasure consistency {}", erasure_consistency)?;
}
Ok(())
}
}

impl From<DuplicateSlotProof> for CliDuplicateSlotProof {
fn from(proof: DuplicateSlotProof) -> Self {
let shred1 = Shred::new_from_serialized_shred(proof.shred1).unwrap();
let shred2 = Shred::new_from_serialized_shred(proof.shred2).unwrap();
let erasure_consistency = (shred1.shred_type() == ShredType::Code
&& shred2.shred_type() == ShredType::Code)
.then(|| ErasureMeta::check_erasure_consistency(&shred1, &shred2));

Self {
shred1: CliDuplicateShred::from(shred1),
shred2: CliDuplicateShred::from(shred2),
erasure_consistency,
}
}
}

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CliDuplicateShred {
fec_set_index: u32,
index: u32,
shred_type: ShredType,
version: u16,
merkle_root: Option<Hash>,
chained_merkle_root: Option<Hash>,
last_in_slot: bool,
payload: Vec<u8>,
}

impl CliDuplicateShred {
fn write_common(&self, w: &mut dyn std::fmt::Write) -> std::fmt::Result {
writeln!(
w,
"fec_set_index {}, index {}, shred_type {:?}\n \
version {}, merkle_root {:?}, chained_merkle_root {:?}, last_in_slot {}",
self.fec_set_index,
self.index,
self.shred_type,
self.version,
self.merkle_root,
self.chained_merkle_root,
self.last_in_slot,
)
}
}

impl QuietDisplay for CliDuplicateShred {}

impl VerboseDisplay for CliDuplicateShred {
fn write_str(&self, w: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.write_common(w)?;
writeln!(w, " payload: {:?}", self.payload)
}
}

impl fmt::Display for CliDuplicateShred {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.write_common(f)
}
}

impl From<Shred> for CliDuplicateShred {
fn from(shred: Shred) -> Self {
Self {
fec_set_index: shred.fec_set_index(),
index: shred.index(),
shred_type: shred.shred_type(),
version: shred.version(),
merkle_root: shred.merkle_root().ok(),
chained_merkle_root: shred.chained_merkle_root().ok(),
last_in_slot: shred.last_in_slot(),
payload: shred.payload().clone(),
}
}
}

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EncodedConfirmedBlockWithEntries {
Expand Down
2 changes: 1 addition & 1 deletion ledger/src/shred.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ impl Shred {
dispatch!(fn set_signature(&mut self, signature: Signature));
dispatch!(fn signed_data(&self) -> Result<SignedData, Error>);

dispatch!(pub(crate) fn chained_merkle_root(&self) -> Result<Hash, Error>);
dispatch!(pub fn chained_merkle_root(&self) -> Result<Hash, Error>);
// Returns the portion of the shred's payload which is erasure coded.
dispatch!(pub(crate) fn erasure_shard(self) -> Result<Vec<u8>, Error>);
// Like Shred::erasure_shard but returning a slice.
Expand Down

0 comments on commit fbae3a6

Please sign in to comment.