subspace_farmer_components/
segment_reconstruction.rs

1use subspace_archiving::piece_reconstructor::{PiecesReconstructor, ReconstructorError};
2use subspace_core_primitives::pieces::{Piece, PieceIndex};
3use subspace_data_retrieval::piece_getter::PieceGetter;
4use subspace_data_retrieval::segment_downloading::{
5    SegmentDownloadingError, download_segment_pieces,
6};
7use subspace_erasure_coding::ErasureCoding;
8use subspace_kzg::Kzg;
9use thiserror::Error;
10use tokio::task::JoinError;
11use tracing::{error, info};
12
13#[derive(Debug, Error)]
14pub(crate) enum SegmentReconstructionError {
15    /// Segment downloading failed
16    #[error("Segment downloading failed: {0}")]
17    SegmentDownloadingFailed(#[from] SegmentDownloadingError),
18
19    /// Internal piece retrieval process failed
20    #[error("Piece reconstruction failed: {0}")]
21    ReconstructionFailed(#[from] ReconstructorError),
22
23    /// Join error
24    #[error("Join error: {0}")]
25    JoinError(#[from] JoinError),
26}
27
28pub(crate) async fn recover_missing_piece<PG>(
29    piece_getter: &PG,
30    kzg: Kzg,
31    erasure_coding: ErasureCoding,
32    missing_piece_index: PieceIndex,
33) -> Result<Piece, SegmentReconstructionError>
34where
35    PG: PieceGetter + Send + Sync,
36{
37    info!(%missing_piece_index, "Recovering missing piece...");
38    let segment_index = missing_piece_index.segment_index();
39    let position = missing_piece_index.position();
40
41    let segment_pieces = download_segment_pieces(segment_index, piece_getter).await?;
42
43    let result = tokio::task::spawn_blocking(move || {
44        let reconstructor = PiecesReconstructor::new(kzg, erasure_coding);
45
46        reconstructor.reconstruct_piece(&segment_pieces, position as usize)
47    })
48    .await??;
49
50    info!(%missing_piece_index, "Recovering missing piece succeeded.");
51
52    Ok(result)
53}