subspace_rpc_primitives/
lib.rs

1//! Primitives for Subspace RPC.
2
3use parity_scale_codec::{Decode, Encode, EncodeLike, Input, Output};
4use serde::{Deserialize, Serialize};
5use std::time::Duration;
6use subspace_core_primitives::hashes::Blake3Hash;
7use subspace_core_primitives::objects::GlobalObjectMapping;
8use subspace_core_primitives::solutions::{RewardSignature, Solution, SolutionRange};
9use subspace_core_primitives::{BlockNumber, PublicKey, SlotNumber};
10use subspace_farmer_components::FarmerProtocolInfo;
11use subspace_networking::libp2p::Multiaddr;
12
13/// Defines a limit for number of segments that can be requested over RPC
14pub const MAX_SEGMENT_HEADERS_PER_REQUEST: usize = 1000;
15
16/// Information necessary for farmer application
17#[derive(Debug, Clone, Serialize, Deserialize)]
18#[serde(rename_all = "camelCase")]
19pub struct FarmerAppInfo {
20    /// Genesis hash of the chain
21    #[serde(with = "hex")]
22    pub genesis_hash: [u8; 32],
23    /// Bootstrap nodes for DSN
24    pub dsn_bootstrap_nodes: Vec<Multiaddr>,
25    /// Whether node is syncing right now
26    pub syncing: bool,
27    /// How much time farmer has to audit sectors and generate a solution
28    pub farming_timeout: Duration,
29    /// Protocol info for farmer
30    pub protocol_info: FarmerProtocolInfo,
31}
32
33impl Encode for FarmerAppInfo {
34    fn size_hint(&self) -> usize {
35        0_usize
36            .saturating_add(Encode::size_hint(&self.genesis_hash))
37            .saturating_add(Encode::size_hint(
38                &self
39                    .dsn_bootstrap_nodes
40                    .iter()
41                    .map(|addr| addr.as_ref())
42                    .collect::<Vec<_>>(),
43            ))
44            .saturating_add(Encode::size_hint(&self.syncing))
45            .saturating_add(Encode::size_hint(&self.farming_timeout))
46            .saturating_add(Encode::size_hint(&self.protocol_info))
47    }
48
49    fn encode_to<O: Output + ?Sized>(&self, output: &mut O) {
50        Encode::encode_to(&self.genesis_hash, output);
51        Encode::encode_to(
52            &self
53                .dsn_bootstrap_nodes
54                .iter()
55                .map(|addr| addr.as_ref())
56                .collect::<Vec<_>>(),
57            output,
58        );
59        Encode::encode_to(&self.syncing, output);
60        Encode::encode_to(&self.farming_timeout, output);
61        Encode::encode_to(&self.protocol_info, output);
62    }
63}
64
65impl EncodeLike for FarmerAppInfo {}
66
67impl Decode for FarmerAppInfo {
68    fn decode<I: Input>(input: &mut I) -> Result<Self, parity_scale_codec::Error> {
69        Ok(FarmerAppInfo {
70            genesis_hash: <[u8; 32]>::decode(input)
71                .map_err(|error| error.chain("Could not decode `FarmerAppInfo::genesis_hash`"))?,
72            dsn_bootstrap_nodes: Vec::<Vec<u8>>::decode(input)
73                .map_err(|error| {
74                    error.chain("Could not decode `FarmerAppInfo::dsn_bootstrap_nodes`")
75                })?
76                .into_iter()
77                .map(Multiaddr::try_from)
78                .collect::<Result<Vec<_>, _>>()
79                .map_err(|error| {
80                    parity_scale_codec::Error::from("Failed to decode bytes as Multiaddr")
81                        .chain(error.to_string())
82                        .chain("Could not decode `FarmerAppInfo::dsn_bootstrap_nodes`")
83                })?,
84            syncing: bool::decode(input)
85                .map_err(|error| error.chain("Could not decode `FarmerAppInfo::syncing`"))?,
86            farming_timeout: Duration::decode(input).map_err(|error| {
87                error.chain("Could not decode `FarmerAppInfo::farming_timeout`")
88            })?,
89            protocol_info: FarmerProtocolInfo::decode(input)
90                .map_err(|error| error.chain("Could not decode `FarmerAppInfo::protocol_info`"))?,
91        })
92    }
93}
94
95/// Information about new slot that just arrived
96#[derive(Debug, Copy, Clone, Eq, PartialEq, Encode, Decode, Serialize, Deserialize)]
97#[serde(rename_all = "camelCase")]
98pub struct SlotInfo {
99    /// Slot number
100    pub slot_number: SlotNumber,
101    /// Global slot challenge
102    pub global_challenge: Blake3Hash,
103    /// Acceptable solution range for block authoring
104    pub solution_range: SolutionRange,
105    /// Acceptable solution range for voting
106    pub voting_solution_range: SolutionRange,
107}
108
109/// Response of a slot challenge consisting of an optional solution and
110/// the submitter(farmer)'s secret key for block signing.
111#[derive(Clone, Debug, Encode, Decode, Serialize, Deserialize)]
112#[serde(rename_all = "camelCase")]
113pub struct SolutionResponse {
114    /// Slot number.
115    pub slot_number: SlotNumber,
116    /// Solution farmer has for the challenge.
117    ///
118    /// Corresponds to `slot_number` above.
119    pub solution: Solution<PublicKey>,
120}
121
122/// Reward info that needs to be signed.
123#[derive(Clone, Copy, Debug, Encode, Decode, Serialize, Deserialize)]
124#[serde(rename_all = "camelCase")]
125pub struct RewardSigningInfo {
126    /// Hash to be signed.
127    #[serde(with = "hex")]
128    pub hash: [u8; 32],
129    /// Public key of the plot identity that should create signature.
130    pub public_key: PublicKey,
131}
132
133/// Signature in response to reward hash signing request.
134#[derive(Clone, Copy, Debug, Encode, Decode, Serialize, Deserialize)]
135#[serde(rename_all = "camelCase")]
136pub struct RewardSignatureResponse {
137    /// Hash that was signed.
138    #[serde(with = "hex")]
139    pub hash: [u8; 32],
140    /// Pre-header or vote hash signature.
141    pub signature: Option<RewardSignature>,
142}
143
144/// Response to object mapping subscription, including a block height.
145/// Large responses are batched, so the block height can be repeated in different responses.
146#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize)]
147#[serde(rename_all = "camelCase")]
148pub struct ObjectMappingResponse {
149    /// The block number that the object mapping is from.
150    pub block_number: BlockNumber,
151
152    /// The object mappings.
153    #[serde(flatten)]
154    pub objects: GlobalObjectMapping,
155}