diff --git a/ledger/src/erasure.rs b/ledger/src/erasure.rs index cf4052e41..04cc684de 100644 --- a/ledger/src/erasure.rs +++ b/ledger/src/erasure.rs @@ -41,10 +41,7 @@ //! //! -use { - reed_solomon_erasure::{galois_8::Field, ReconstructShard, ReedSolomon}, - serde::{Deserialize, Serialize}, -}; +use serde::{Deserialize, Serialize}; #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct ErasureConfig { @@ -68,116 +65,3 @@ impl ErasureConfig { self.num_coding } } - -type Result = std::result::Result; - -/// Represents an erasure "session" with a particular configuration and number of data and coding -/// shreds -#[derive(Debug, Clone)] -pub struct Session(ReedSolomon); - -impl Session { - pub fn new(data_count: usize, coding_count: usize) -> Result { - let rs = ReedSolomon::new(data_count, coding_count)?; - - Ok(Session(rs)) - } - - pub fn new_from_config(config: &ErasureConfig) -> Result { - let rs = ReedSolomon::new(config.num_data, config.num_coding)?; - - Ok(Session(rs)) - } - - /// Create coding blocks by overwriting `parity` - pub fn encode(&self, data: &[T], parity: &mut [U]) -> Result<()> - where - T: AsRef<[u8]>, - U: AsRef<[u8]> + AsMut<[u8]>, - { - self.0.encode_sep(data, parity) - } - - /// Recover data + coding blocks into data blocks - pub fn decode_blocks(&self, blocks: &mut [T]) -> Result<()> - where - T: ReconstructShard, - { - self.0.reconstruct_data(blocks) - } -} - -#[cfg(test)] -pub mod test { - use {super::*, log::*, solana_sdk::clock::Slot}; - - /// Specifies the contents of a 16-data-shred and 4-coding-shred erasure set - /// Exists to be passed to `generate_blockstore_with_coding` - #[derive(Debug, Copy, Clone)] - pub struct ErasureSpec { - /// Which 16-shred erasure set this represents - pub set_index: u64, - pub num_data: usize, - pub num_coding: usize, - } - - /// Specifies the contents of a slot - /// Exists to be passed to `generate_blockstore_with_coding` - #[derive(Debug, Clone)] - pub struct SlotSpec { - pub slot: Slot, - pub set_specs: Vec, - } - - #[test] - fn test_coding() { - const N_DATA: usize = 4; - const N_CODING: usize = 2; - - let session = Session::new(N_DATA, N_CODING).unwrap(); - - let mut vs: Vec> = (0..N_DATA as u8).map(|i| (i..(16 + i)).collect()).collect(); - let v_orig: Vec = vs[0].clone(); - - let mut coding_blocks: Vec<_> = (0..N_CODING).map(|_| vec![0u8; 16]).collect(); - - let mut coding_blocks_slices: Vec<_> = - coding_blocks.iter_mut().map(Vec::as_mut_slice).collect(); - let v_slices: Vec<_> = vs.iter().map(Vec::as_slice).collect(); - - session - .encode(v_slices.as_slice(), coding_blocks_slices.as_mut_slice()) - .expect("encoding must succeed"); - - trace!("test_coding: coding blocks:"); - for b in &coding_blocks { - trace!("test_coding: {:?}", b); - } - - let erasure: usize = 1; - let mut present = vec![true; N_DATA + N_CODING]; - present[erasure] = false; - let erased = vs[erasure].clone(); - - // clear an entry - vs[erasure as usize].copy_from_slice(&[0; 16]); - - let mut blocks: Vec<_> = vs - .iter_mut() - .chain(coding_blocks.iter_mut()) - .map(Vec::as_mut_slice) - .zip(present) - .collect(); - - session - .decode_blocks(blocks.as_mut_slice()) - .expect("decoding must succeed"); - - trace!("test_coding: vs:"); - for v in &vs { - trace!("test_coding: {:?}", v); - } - assert_eq!(v_orig, vs[0]); - assert_eq!(erased, vs[erasure]); - } -} diff --git a/ledger/src/shredder.rs b/ledger/src/shredder.rs index 0fe5b68d7..ecd4b4596 100644 --- a/ledger/src/shredder.rs +++ b/ledger/src/shredder.rs @@ -1,11 +1,13 @@ use { crate::{ - erasure::Session, shred::{Error, Shred, MAX_DATA_SHREDS_PER_FEC_BLOCK, SIZE_OF_DATA_SHRED_PAYLOAD}, shred_stats::ProcessShredsStats, }, rayon::{prelude::*, ThreadPool}, - reed_solomon_erasure::Error::{InvalidIndex, TooFewDataShards, TooFewShardsPresent}, + reed_solomon_erasure::{ + galois_8::Field, + Error::{InvalidIndex, TooFewDataShards, TooFewShardsPresent}, + }, solana_entry::entry::Entry, solana_measure::measure::Measure, solana_rayon_threadlimit::get_thread_count, @@ -19,6 +21,8 @@ thread_local!(static PAR_THREAD_POOL: RefCell = RefCell::new(rayon:: .build() .unwrap())); +type ReedSolomon = reed_solomon_erasure::ReedSolomon; + #[derive(Debug)] pub struct Shredder { slot: Slot, @@ -235,9 +239,9 @@ impl Shredder { let data = data.iter().map(Shred::erasure_shard_as_slice); let data: Vec<_> = data.collect::>().unwrap(); let mut parity = vec![vec![0u8; data[0].len()]; num_coding]; - Session::new(num_data, num_coding) + ReedSolomon::new(num_data, num_coding) .unwrap() - .encode(&data, &mut parity[..]) + .encode_sep(&data, &mut parity[..]) .unwrap(); let num_data = u16::try_from(num_data).unwrap(); let num_coding = u16::try_from(num_coding).unwrap(); @@ -300,7 +304,7 @@ impl Shredder { mask[index] = true; } } - Session::new(num_data_shreds, num_coding_shreds)?.decode_blocks(&mut shards)?; + ReedSolomon::new(num_data_shreds, num_coding_shreds)?.reconstruct_data(&mut shards)?; let recovered_data = mask .into_iter() .zip(shards)