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