subspace_data_retrieval/
piece_fetcher.rs

1//! Fetching pieces of the archived history of Subspace Network.
2
3use crate::object_fetcher::Error;
4use crate::piece_getter::PieceGetter;
5use futures::StreamExt;
6use std::sync::Arc;
7use subspace_core_primitives::pieces::{Piece, PieceIndex};
8use tracing::{debug, trace};
9
10/// Concurrently downloads the exact pieces in `piece_indexes`, returning them in that order.
11/// Each piece index must be unique.
12///
13/// If any piece can't be downloaded, returns an error.
14// This code was copied and modified from subspace_service::sync_from_dsn::download_and_reconstruct_blocks():
15// <https://github.com/autonomys/subspace/blob/d71ca47e45e1b53cd2e472413caa23472a91cd74/crates/subspace-service/src/sync_from_dsn/import_blocks.rs#L236-L322>
16pub async fn download_pieces<PG>(
17    piece_indexes: Arc<[PieceIndex]>,
18    piece_getter: &PG,
19) -> anyhow::Result<Vec<Piece>>
20where
21    PG: PieceGetter,
22{
23    debug!(
24        count = piece_indexes.len(),
25        ?piece_indexes,
26        "Retrieving exact pieces"
27    );
28
29    // TODO:
30    // - if we're close to the number of pieces in a segment, or we can't find a piece, use segment downloading and piece
31    //   reconstruction instead
32    // Currently most objects are limited to 4-6 pieces, so this isn't needed yet.
33    let mut received_pieces = piece_getter.get_pieces(piece_indexes.to_vec()).await?;
34
35    let mut pieces = Vec::new();
36    pieces.resize(piece_indexes.len(), Piece::default());
37
38    while let Some((piece_index, maybe_piece)) = received_pieces.next().await {
39        // We want exact pieces, so any errors are fatal.
40        let piece = maybe_piece?.ok_or(Error::PieceNotFound { piece_index })?;
41        let index_position = piece_indexes
42            .iter()
43            .position(|i| *i == piece_index)
44            .expect("get_pieces only returns indexes it was supplied; qed");
45        pieces[index_position] = piece;
46    }
47
48    trace!(
49        count = piece_indexes.len(),
50        ?piece_indexes,
51        "Successfully retrieved exact pieces"
52    );
53
54    Ok(pieces)
55}