subspace_farmer_components/
lib.rs

1//! Components of the reference implementation of Subspace Farmer for Subspace Network Blockchain.
2//!
3//! These components are used to implement farmer itself, but can also be used independently if necessary.
4
5#![feature(
6    const_trait_impl,
7    exact_size_is_empty,
8    int_roundings,
9    iter_collect_into,
10    never_type,
11    portable_simd,
12    try_blocks
13)]
14#![warn(rust_2018_idioms, missing_debug_implementations, missing_docs)]
15
16pub mod auditing;
17pub mod file_ext;
18pub mod plotting;
19pub mod proving;
20pub mod reading;
21pub mod sector;
22mod segment_reconstruction;
23
24use crate::file_ext::FileExt;
25use parity_scale_codec::{Decode, Encode};
26use serde::{Deserialize, Serialize};
27use static_assertions::const_assert;
28use std::fs::File;
29use std::future::Future;
30use std::io;
31use subspace_core_primitives::segments::HistorySize;
32
33/// Enum to encapsulate the selection between [`ReadAtSync`] and [`ReadAtAsync]` variants
34#[derive(Debug, Copy, Clone)]
35pub enum ReadAt<S, A>
36where
37    S: ReadAtSync,
38    A: ReadAtAsync,
39{
40    /// Sync variant
41    Sync(S),
42    /// Async variant
43    Async(A),
44}
45
46impl<S> ReadAt<S, !>
47where
48    S: ReadAtSync,
49{
50    /// Instantiate [`ReadAt`] from some [`ReadAtSync`] implementation
51    pub fn from_sync(value: S) -> Self {
52        Self::Sync(value)
53    }
54}
55
56impl<A> ReadAt<!, A>
57where
58    A: ReadAtAsync,
59{
60    /// Instantiate [`ReadAt`] from some [`ReadAtAsync`] implementation
61    pub fn from_async(value: A) -> Self {
62        Self::Async(value)
63    }
64}
65
66/// Sync version of [`ReadAt`], it is both [`Send`] and [`Sync`] and is supposed to be used with a
67/// thread pool
68pub trait ReadAtSync: Send + Sync {
69    /// Get implementation of [`ReadAtSync`] that add specified offset to all attempted reads
70    fn offset(&self, offset: u64) -> ReadAtOffset<'_, Self>
71    where
72        Self: Sized,
73    {
74        ReadAtOffset {
75            inner: self,
76            offset,
77        }
78    }
79
80    /// Fill the buffer by reading bytes at a specific offset
81    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()>;
82}
83
84impl ReadAtSync for ! {
85    fn read_at(&self, _buf: &mut [u8], _offset: u64) -> io::Result<()> {
86        unreachable!("Is never called")
87    }
88}
89
90/// Container or asynchronously reading bytes using in [`ReadAtAsync`]
91#[repr(transparent)]
92#[derive(Debug)]
93pub struct AsyncReadBytes<B>(B)
94where
95    B: AsMut<[u8]> + Unpin + 'static;
96
97impl From<Vec<u8>> for AsyncReadBytes<Vec<u8>> {
98    fn from(value: Vec<u8>) -> Self {
99        Self(value)
100    }
101}
102
103impl From<Box<[u8]>> for AsyncReadBytes<Box<[u8]>> {
104    fn from(value: Box<[u8]>) -> Self {
105        Self(value)
106    }
107}
108
109impl<B> AsMut<[u8]> for AsyncReadBytes<B>
110where
111    B: AsMut<[u8]> + Unpin + 'static,
112{
113    fn as_mut(&mut self) -> &mut [u8] {
114        self.0.as_mut()
115    }
116}
117
118impl<B> AsyncReadBytes<B>
119where
120    B: AsMut<[u8]> + Unpin + 'static,
121{
122    /// Extract inner value
123    pub fn into_inner(self) -> B {
124        self.0
125    }
126}
127
128/// Async version of [`ReadAt`], it is neither [`Send`] nor [`Sync`] and is supposed to be used with
129/// concurrent async combinators
130pub trait ReadAtAsync {
131    /// Get implementation of [`ReadAtAsync`] that add specified offset to all attempted reads
132    fn offset(&self, offset: u64) -> ReadAtOffset<'_, Self>
133    where
134        Self: Sized,
135    {
136        ReadAtOffset {
137            inner: self,
138            offset,
139        }
140    }
141
142    /// Fill the buffer by reading bytes at a specific offset and return the buffer back
143    fn read_at<B>(&self, buf: B, offset: u64) -> impl Future<Output = io::Result<B>>
144    where
145        AsyncReadBytes<B>: From<B>,
146        B: AsMut<[u8]> + Unpin + 'static;
147}
148
149impl ReadAtAsync for ! {
150    async fn read_at<B>(&self, _buf: B, _offset: u64) -> io::Result<B>
151    where
152        AsyncReadBytes<B>: From<B>,
153        B: AsMut<[u8]> + Unpin + 'static,
154    {
155        unreachable!("Is never called")
156    }
157}
158
159impl ReadAtSync for [u8] {
160    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
161        if buf.len() as u64 + offset > self.len() as u64 {
162            return Err(io::Error::new(
163                io::ErrorKind::InvalidInput,
164                "Buffer length with offset exceeds own length",
165            ));
166        }
167
168        buf.copy_from_slice(&self[offset as usize..][..buf.len()]);
169
170        Ok(())
171    }
172}
173
174impl ReadAtSync for &[u8] {
175    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
176        if buf.len() as u64 + offset > self.len() as u64 {
177            return Err(io::Error::new(
178                io::ErrorKind::InvalidInput,
179                "Buffer length with offset exceeds own length",
180            ));
181        }
182
183        buf.copy_from_slice(&self[offset as usize..][..buf.len()]);
184
185        Ok(())
186    }
187}
188
189impl ReadAtSync for Vec<u8> {
190    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
191        self.as_slice().read_at(buf, offset)
192    }
193}
194
195impl ReadAtSync for &Vec<u8> {
196    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
197        self.as_slice().read_at(buf, offset)
198    }
199}
200
201impl ReadAtSync for File {
202    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
203        self.read_exact_at(buf, offset)
204    }
205}
206
207impl ReadAtSync for &File {
208    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
209        self.read_exact_at(buf, offset)
210    }
211}
212
213/// Reader with fixed offset added to all attempted reads
214#[derive(Debug, Copy, Clone)]
215pub struct ReadAtOffset<'a, T> {
216    inner: &'a T,
217    offset: u64,
218}
219
220impl<T> ReadAtSync for ReadAtOffset<'_, T>
221where
222    T: ReadAtSync,
223{
224    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
225        self.inner.read_at(buf, offset + self.offset)
226    }
227}
228
229impl<T> ReadAtSync for &ReadAtOffset<'_, T>
230where
231    T: ReadAtSync,
232{
233    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
234        self.inner.read_at(buf, offset + self.offset)
235    }
236}
237
238impl<T> ReadAtAsync for ReadAtOffset<'_, T>
239where
240    T: ReadAtAsync,
241{
242    async fn read_at<B>(&self, buf: B, offset: u64) -> io::Result<B>
243    where
244        AsyncReadBytes<B>: From<B>,
245        B: AsMut<[u8]> + Unpin + 'static,
246    {
247        self.inner.read_at(buf, offset + self.offset).await
248    }
249}
250
251impl<T> ReadAtAsync for &ReadAtOffset<'_, T>
252where
253    T: ReadAtAsync,
254{
255    async fn read_at<B>(&self, buf: B, offset: u64) -> io::Result<B>
256    where
257        AsyncReadBytes<B>: From<B>,
258        B: AsMut<[u8]> + Unpin + 'static,
259    {
260        self.inner.read_at(buf, offset + self.offset).await
261    }
262}
263
264// Refuse to compile on non-64-bit platforms, offsets may fail on those when converting from u64 to
265// usize depending on chain parameters
266const_assert!(std::mem::size_of::<usize>() >= std::mem::size_of::<u64>());
267
268/// Information about the protocol necessary for farmer operation
269#[derive(Debug, Copy, Clone, Encode, Decode, Serialize, Deserialize)]
270#[serde(rename_all = "camelCase")]
271pub struct FarmerProtocolInfo {
272    /// Size of the blockchain history
273    pub history_size: HistorySize,
274    /// How many pieces one sector is supposed to contain (max)
275    pub max_pieces_in_sector: u16,
276    /// Number of latest archived segments that are considered "recent history".
277    pub recent_segments: HistorySize,
278    /// Fraction of pieces from the "recent history" (`recent_segments`) in each sector.
279    pub recent_history_fraction: (HistorySize, HistorySize),
280    /// Minimum lifetime of a plotted sector, measured in archived segment
281    pub min_sector_lifetime: HistorySize,
282}