authority_selection_inherents/
authority_selection_inputs.rs1use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode};
3use plutus::*;
4use scale_info::TypeInfo;
5use sidechain_domain::*;
6
7#[derive(Clone, Debug, Encode, Decode, DecodeWithMemTracking, TypeInfo, PartialEq, Eq)]
10pub struct AuthoritySelectionInputs {
11 pub d_parameter: DParameter,
13 pub permissioned_candidates: Vec<PermissionedCandidateData>,
15 pub registered_candidates: Vec<CandidateRegistrations>,
17 pub epoch_nonce: EpochNonce,
19}
20
21#[cfg(feature = "std")]
22#[derive(Debug, thiserror::Error)]
23pub enum AuthoritySelectionInputsCreationError {
25 #[cfg_attr(
26 feature = "std",
27 error(
28 "Failed to get Ariadne parameters for epoch: {0}, D-parameter: {1:?}, permissioned candidates: {2:?}: {3}"
29 )
30 )]
31 AriadneParametersQuery(
33 McEpochNumber,
34 PolicyId,
35 PolicyId,
36 Box<dyn std::error::Error + Send + Sync>,
37 ),
38 #[cfg_attr(
39 feature = "std",
40 error(
41 "Failed to get registered candidates for epoch: {0}, committee candidate address: {1}: {2}."
42 )
43 )]
44 GetCandidatesQuery(McEpochNumber, String, Box<dyn std::error::Error + Send + Sync>),
46 #[cfg_attr(feature = "std", error("Failed to get epoch nonce for epoch: {0}: {1}."))]
47 GetEpochNonceQuery(McEpochNumber, Box<dyn std::error::Error + Send + Sync>),
49}
50
51#[derive(Debug, Clone, PartialEq, serde::Serialize)]
52pub struct RawPermissionedCandidateData {
54 pub sidechain_public_key: SidechainPublicKey,
56 pub aura_public_key: AuraPublicKey,
58 pub grandpa_public_key: GrandpaPublicKey,
60}
61
62#[derive(Debug, Clone, PartialEq, serde::Serialize)]
63pub struct AriadneParameters {
65 pub d_parameter: DParameter,
67 pub permissioned_candidates: Option<Vec<RawPermissionedCandidateData>>,
70}
71
72#[cfg(feature = "std")]
74#[async_trait::async_trait]
75pub trait AuthoritySelectionDataSource {
76 async fn get_ariadne_parameters(
79 &self,
80 epoch_number: McEpochNumber,
81 d_parameter: PolicyId,
82 permissioned_candidates: PolicyId,
83 ) -> Result<AriadneParameters, Box<dyn std::error::Error + Send + Sync>>;
84
85 async fn get_candidates(
89 &self,
90 epoch: McEpochNumber,
91 committee_candidate_address: MainchainAddress,
92 ) -> Result<Vec<CandidateRegistrations>, Box<dyn std::error::Error + Send + Sync>>;
93
94 async fn get_epoch_nonce(
96 &self,
97 epoch: McEpochNumber,
98 ) -> Result<Option<EpochNonce>, Box<dyn std::error::Error + Send + Sync>>;
99
100 async fn data_epoch(
109 &self,
110 for_epoch: McEpochNumber,
111 ) -> Result<McEpochNumber, Box<dyn std::error::Error + Send + Sync>>;
112}
113
114impl AuthoritySelectionInputs {
115 #[cfg(feature = "std")]
116 pub(crate) async fn from_mc_data(
117 candidate_data_source: &(dyn AuthoritySelectionDataSource + Send + Sync),
118 for_epoch: McEpochNumber,
119 scripts: sp_session_validator_management::MainChainScripts,
120 ) -> Result<Self, AuthoritySelectionInputsCreationError> {
121 let ariadne_parameters_response = candidate_data_source
122 .get_ariadne_parameters(
123 for_epoch,
124 scripts.d_parameter_policy_id.clone(),
125 scripts.permissioned_candidates_policy_id.clone(),
126 )
127 .await
128 .map_err(|err| {
129 AuthoritySelectionInputsCreationError::AriadneParametersQuery(
130 for_epoch,
131 scripts.d_parameter_policy_id.clone(),
132 scripts.permissioned_candidates_policy_id.clone(),
133 err,
134 )
135 })?;
136
137 let d_parameter = ariadne_parameters_response.d_parameter;
138 let no_permissioned_candidates_expected = d_parameter.num_permissioned_candidates == 0;
139 let permissioned_candidates = match ariadne_parameters_response.permissioned_candidates {
140 None if no_permissioned_candidates_expected => Vec::new(),
141 None => {
142 return Err(AuthoritySelectionInputsCreationError::AriadneParametersQuery(
143 for_epoch,
144 scripts.d_parameter_policy_id,
145 scripts.permissioned_candidates_policy_id,
146 ("Expected Data Not Found: Permissioned Candidates List".to_string()).into(),
147 ));
148 },
149 Some(permissioned_candidates) => permissioned_candidates
150 .into_iter()
151 .map(|candidate| PermissionedCandidateData {
152 sidechain_public_key: candidate.sidechain_public_key,
153 aura_public_key: candidate.aura_public_key,
154 grandpa_public_key: candidate.grandpa_public_key,
155 })
156 .collect::<Vec<PermissionedCandidateData>>(),
157 };
158
159 let registered_candidates: Vec<CandidateRegistrations> = candidate_data_source
160 .get_candidates(for_epoch, scripts.committee_candidate_address.clone())
161 .await
162 .map_err(|err| {
163 AuthoritySelectionInputsCreationError::GetCandidatesQuery(
164 for_epoch,
165 scripts.committee_candidate_address.to_string(),
166 err,
167 )
168 })?;
169 let epoch_nonce_response =
170 candidate_data_source.get_epoch_nonce(for_epoch).await.map_err(|err| {
171 AuthoritySelectionInputsCreationError::GetEpochNonceQuery(for_epoch, err)
172 })?;
173 let epoch_nonce = epoch_nonce_response.unwrap_or(EpochNonce(vec![]));
174
175 Ok(Self { d_parameter, permissioned_candidates, registered_candidates, epoch_nonce })
176 }
177}