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)]
11pub struct AuthoritySelectionInputs {
12 pub d_parameter: DParameter,
14 pub permissioned_candidates: Vec<PermissionedCandidateData>,
16 pub registered_candidates: Vec<CandidateRegistrations>,
18 pub epoch_nonce: EpochNonce,
20}
21
22#[cfg(feature = "std")]
23#[derive(Debug, thiserror::Error)]
24pub enum AuthoritySelectionInputsCreationError {
26 #[cfg_attr(
27 feature = "std",
28 error(
29 "Failed to get Ariadne parameters for epoch: {0}, D-parameter: {1:?}, permissioned candidates: {2:?}: {3}"
30 )
31 )]
32 AriadneParametersQuery(
34 McEpochNumber,
35 PolicyId,
36 PolicyId,
37 Box<dyn std::error::Error + Send + Sync>,
38 ),
39 #[cfg_attr(
40 feature = "std",
41 error(
42 "Failed to get registered candidates for epoch: {0}, committee candidate address: {1}: {2}."
43 )
44 )]
45 GetCandidatesQuery(McEpochNumber, String, Box<dyn std::error::Error + Send + Sync>),
47 #[cfg_attr(feature = "std", error("Failed to get epoch nonce for epoch: {0}: {1}."))]
48 GetEpochNonceQuery(McEpochNumber, Box<dyn std::error::Error + Send + Sync>),
50}
51
52#[derive(Debug, Clone, PartialEq, serde::Serialize)]
53pub struct AriadneParameters {
55 pub d_parameter: DParameter,
57 pub permissioned_candidates: Option<Vec<PermissionedCandidateData>>,
60}
61
62#[cfg(feature = "std")]
64#[async_trait::async_trait]
65pub trait AuthoritySelectionDataSource {
66 async fn get_ariadne_parameters(
69 &self,
70 epoch_number: McEpochNumber,
71 d_parameter: PolicyId,
72 permissioned_candidates: PolicyId,
73 ) -> Result<AriadneParameters, Box<dyn std::error::Error + Send + Sync>>;
74
75 async fn get_candidates(
79 &self,
80 epoch: McEpochNumber,
81 committee_candidate_address: MainchainAddress,
82 ) -> Result<Vec<CandidateRegistrations>, Box<dyn std::error::Error + Send + Sync>>;
83
84 async fn get_epoch_nonce(
86 &self,
87 epoch: McEpochNumber,
88 ) -> Result<Option<EpochNonce>, Box<dyn std::error::Error + Send + Sync>>;
89
90 async fn data_epoch(
99 &self,
100 for_epoch: McEpochNumber,
101 ) -> Result<McEpochNumber, Box<dyn std::error::Error + Send + Sync>>;
102}
103
104impl AuthoritySelectionInputs {
105 #[cfg(feature = "std")]
106 pub(crate) async fn from_mc_data(
107 candidate_data_source: &(dyn AuthoritySelectionDataSource + Send + Sync),
108 for_epoch: McEpochNumber,
109 scripts: sp_session_validator_management::MainChainScripts,
110 ) -> Result<Self, AuthoritySelectionInputsCreationError> {
111 let ariadne_parameters_response = candidate_data_source
112 .get_ariadne_parameters(
113 for_epoch,
114 scripts.d_parameter_policy_id.clone(),
115 scripts.permissioned_candidates_policy_id.clone(),
116 )
117 .await
118 .map_err(|err| {
119 AuthoritySelectionInputsCreationError::AriadneParametersQuery(
120 for_epoch,
121 scripts.d_parameter_policy_id.clone(),
122 scripts.permissioned_candidates_policy_id.clone(),
123 err,
124 )
125 })?;
126
127 let d_parameter = ariadne_parameters_response.d_parameter;
128 let no_permissioned_candidates_expected = d_parameter.num_permissioned_candidates == 0;
129 let permissioned_candidates = match ariadne_parameters_response.permissioned_candidates {
130 None if no_permissioned_candidates_expected => Vec::new(),
131 None => {
132 return Err(AuthoritySelectionInputsCreationError::AriadneParametersQuery(
133 for_epoch,
134 scripts.d_parameter_policy_id,
135 scripts.permissioned_candidates_policy_id,
136 ("Expected Data Not Found: Permissioned Candidates List".to_string()).into(),
137 ));
138 },
139 Some(permissioned_candidates) => permissioned_candidates,
140 };
141
142 let registered_candidates: Vec<CandidateRegistrations> = candidate_data_source
143 .get_candidates(for_epoch, scripts.committee_candidate_address.clone())
144 .await
145 .map_err(|err| {
146 AuthoritySelectionInputsCreationError::GetCandidatesQuery(
147 for_epoch,
148 scripts.committee_candidate_address.to_string(),
149 err,
150 )
151 })?;
152 let epoch_nonce_response =
153 candidate_data_source.get_epoch_nonce(for_epoch).await.map_err(|err| {
154 AuthoritySelectionInputsCreationError::GetEpochNonceQuery(for_epoch, err)
155 })?;
156 let epoch_nonce = epoch_nonce_response.unwrap_or(EpochNonce(vec![]));
157
158 Ok(Self { d_parameter, permissioned_candidates, registered_candidates, epoch_nonce })
159 }
160}