diff --git a/ledger/src/blockstore_meta.rs b/ledger/src/blockstore_meta.rs index 5066a028336330..6e618154f20751 100644 --- a/ledger/src/blockstore_meta.rs +++ b/ledger/src/blockstore_meta.rs @@ -406,6 +406,35 @@ impl ErasureMeta { } } +#[allow(dead_code)] +impl MerkleRootMeta { + pub(crate) fn from_shred(shred: &Shred) -> Self { + Self { + // An error here after the shred has already sigverified + // can only indicate that the leader is sending + // legacy or malformed shreds. We should still store + // `None` for those cases in blockstore, as a later + // shred that contains a proper merkle root would constitute + // a valid duplicate shred proof. + merkle_root: shred.merkle_root().ok(), + first_received_shred_index: shred.index(), + first_received_shred_type: shred.shred_type(), + } + } + + pub(crate) fn merkle_root(&self) -> Option { + self.merkle_root + } + + pub(crate) fn first_received_shred_index(&self) -> u32 { + self.first_received_shred_index + } + + pub(crate) fn first_received_shred_type(&self) -> ShredType { + self.first_received_shred_type + } +} + impl DuplicateSlotProof { pub(crate) fn new(shred1: Vec, shred2: Vec) -> Self { DuplicateSlotProof { shred1, shred2 } diff --git a/ledger/src/shred.rs b/ledger/src/shred.rs index 5fda160e29b976..4cd4f8b85b918a 100644 --- a/ledger/src/shred.rs +++ b/ledger/src/shred.rs @@ -334,6 +334,7 @@ impl Shred { dispatch!(pub(crate) fn erasure_shard_index(&self) -> Result); dispatch!(pub fn into_payload(self) -> Vec); + dispatch!(pub fn merkle_root(&self) -> Result); dispatch!(pub fn payload(&self) -> &Vec); dispatch!(pub fn sanitize(&self) -> Result<(), Error>); diff --git a/ledger/src/shred/merkle.rs b/ledger/src/shred/merkle.rs index 4f1cd22111e07f..d0d507ae48aba1 100644 --- a/ledger/src/shred/merkle.rs +++ b/ledger/src/shred/merkle.rs @@ -154,7 +154,7 @@ impl ShredData { Ok(Self::SIZE_OF_HEADERS + Self::capacity(proof_size)?) } - fn merkle_root(&self) -> Result { + pub(super) fn merkle_root(&self) -> Result { let proof_size = self.proof_size()?; let index = self.erasure_shard_index()?; let proof_offset = Self::proof_offset(proof_size)?; @@ -266,7 +266,7 @@ impl ShredCode { Ok(Self::SIZE_OF_HEADERS + Self::capacity(proof_size)?) } - fn merkle_root(&self) -> Result { + pub(super) fn merkle_root(&self) -> Result { let proof_size = self.proof_size()?; let index = self.erasure_shard_index()?; let proof_offset = Self::proof_offset(proof_size)?; diff --git a/ledger/src/shred/shred_code.rs b/ledger/src/shred/shred_code.rs index ba85d92af25187..0ad97a0f729a77 100644 --- a/ledger/src/shred/shred_code.rs +++ b/ledger/src/shred/shred_code.rs @@ -6,7 +6,7 @@ use { CodingShredHeader, Error, ShredCommonHeader, ShredType, SignedData, DATA_SHREDS_PER_FEC_BLOCK, MAX_DATA_SHREDS_PER_SLOT, SIZE_OF_NONCE, }, - solana_sdk::{clock::Slot, packet::PACKET_DATA_SIZE, signature::Signature}, + solana_sdk::{clock::Slot, hash::Hash, packet::PACKET_DATA_SIZE, signature::Signature}, static_assertions::const_assert_eq, }; @@ -47,6 +47,13 @@ impl ShredCode { } } + pub(super) fn merkle_root(&self) -> Result { + match self { + Self::Legacy(_) => Err(Error::InvalidShredType), + Self::Merkle(shred) => shred.merkle_root(), + } + } + pub(super) fn new_from_parity_shard( slot: Slot, index: u32, diff --git a/ledger/src/shred/shred_data.rs b/ledger/src/shred/shred_data.rs index 9bf2c0bf05f79e..ecb40367b4ef08 100644 --- a/ledger/src/shred/shred_data.rs +++ b/ledger/src/shred/shred_data.rs @@ -7,7 +7,7 @@ use { DataShredHeader, Error, ShredCommonHeader, ShredFlags, ShredType, ShredVariant, SignedData, MAX_DATA_SHREDS_PER_SLOT, }, - solana_sdk::{clock::Slot, signature::Signature}, + solana_sdk::{clock::Slot, hash::Hash, signature::Signature}, }; #[derive(Clone, Debug, Eq, PartialEq)] @@ -41,6 +41,13 @@ impl ShredData { } } + pub(super) fn merkle_root(&self) -> Result { + match self { + Self::Legacy(_) => Err(Error::InvalidShredType), + Self::Merkle(shred) => shred.merkle_root(), + } + } + pub(super) fn new_from_data( slot: Slot, index: u32,