diff --git a/ledger/src/blockstore_meta.rs b/ledger/src/blockstore_meta.rs index 002d4970dd5403..f3940fe618444d 100644 --- a/ledger/src/blockstore_meta.rs +++ b/ledger/src/blockstore_meta.rs @@ -122,7 +122,11 @@ pub struct ShredIndex { /// Erasure coding information pub struct ErasureMeta { /// Which erasure set in the slot this is - fec_set_index: u64, + #[serde( + serialize_with = "serde_compat_cast::serialize::<_, u64, _>", + deserialize_with = "serde_compat_cast::deserialize::<_, u64, _>" + )] + fec_set_index: u32, /// First coding index in the FEC set first_coding_index: u64, /// Index of the first received coding shred in the FEC set @@ -131,6 +135,39 @@ pub struct ErasureMeta { config: ErasureConfig, } +// Helper module to serde values by type-casting to an intermediate +// type for backward compatibility. +mod serde_compat_cast { + use super::*; + + // Serializes a value of type T by first type-casting to type R. + pub(super) fn serialize( + &val: &T, + serializer: S, + ) -> Result + where + R: TryFrom + Serialize, + >::Error: std::fmt::Display, + { + R::try_from(val) + .map_err(serde::ser::Error::custom)? + .serialize(serializer) + } + + // Deserializes a value of type R and type-casts it to type T. + pub(super) fn deserialize<'de, D, R, T>(deserializer: D) -> Result + where + D: Deserializer<'de>, + R: Deserialize<'de>, + T: TryFrom, + >::Error: std::fmt::Display, + { + R::deserialize(deserializer) + .map(T::try_from)? + .map_err(serde::de::Error::custom) + } +} + #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] pub(crate) struct ErasureConfig { num_data: usize, @@ -349,7 +386,7 @@ impl ErasureMeta { let first_coding_index = u64::from(shred.first_coding_index()?); let first_received_coding_index = u64::from(shred.index()); let erasure_meta = ErasureMeta { - fec_set_index: u64::from(shred.fec_set_index()), + fec_set_index: shred.fec_set_index(), config, first_coding_index, first_received_coding_index, @@ -384,7 +421,8 @@ impl ErasureMeta { pub(crate) fn data_shreds_indices(&self) -> Range { let num_data = self.config.num_data as u64; - self.fec_set_index..self.fec_set_index + num_data + let fec_set_index = u64::from(self.fec_set_index); + fec_set_index..fec_set_index + num_data } pub(crate) fn coding_shreds_indices(&self) -> Range { @@ -397,11 +435,8 @@ impl ErasureMeta { } pub(crate) fn next_fec_set_index(&self) -> Option { - let num_data = u64::try_from(self.config.num_data).ok()?; - self.fec_set_index - .checked_add(num_data) - .map(u32::try_from)? - .ok() + let num_data = u32::try_from(self.config.num_data).ok()?; + self.fec_set_index.checked_add(num_data) } pub(crate) fn status(&self, index: &Index) -> ErasureMetaStatus { @@ -575,7 +610,7 @@ mod test { }; let e_meta = ErasureMeta { fec_set_index, - first_coding_index: fec_set_index, + first_coding_index: u64::from(fec_set_index), config: erasure_config, first_received_coding_index: 0, }; @@ -754,7 +789,7 @@ mod test { config: erasure_config, }; let mut new_erasure_meta = ErasureMeta { - fec_set_index: set_index, + fec_set_index: u32::try_from(set_index).unwrap(), first_coding_index: set_index, first_received_coding_index: 0, config: erasure_config,