sp_session_validator_management_query/
get_registrations.rs1use crate::*;
3use authority_selection_inherents::{CandidateValidationApi, RegistrationDataError, StakeError};
4use sidechain_domain::{
5 CandidateRegistrations, MainchainAddress, McEpochNumber, RegistrationData, StakeDelegation,
6};
7use sp_core::bytes::to_hex;
8use sp_sidechain::GetGenesisUtxo;
9
10impl<
11 C,
12 Block,
13 AuthorityId: parity_scale_codec::Decode + Send + Sync + 'static,
14 SessionKeys: parity_scale_codec::Decode + Send + Sync + 'static,
15> SessionValidatorManagementQuery<C, Block, AuthorityId, SessionKeys>
16where
17 Block: BlockT,
18 C: HeaderBackend<Block>,
19 C: 'static + ProvideRuntimeApi<Block> + Send + Sync,
20 C::Api: GetGenesisUtxo<Block>,
21 C::Api: CandidateValidationApi<Block>,
22{
23 async fn registrations_to_rpc_response(
24 &self,
25 candidate_registrations: Vec<CandidateRegistrations>,
26 ) -> Result<GetRegistrationsResponseMap, String> {
27 let api = self.client.runtime_api();
28 let best_block = self.client.info().best_hash;
29
30 let registration_data_validation =
31 |pub_key: &StakePoolPublicKey, registration_data: &RegistrationData| {
32 api.validate_registered_candidate_data(best_block, pub_key, registration_data)
33 };
34 let stake_validation = |stake_delegation: &Option<StakeDelegation>| {
35 api.validate_stake(best_block, *stake_delegation)
36 };
37 get_registrations_response_map(
38 candidate_registrations,
39 registration_data_validation,
40 stake_validation,
41 )
42 .map_err(|err| format!("{err:?}"))
43 }
44
45 pub(crate) async fn candidates_registrations_for_epoch(
46 &self,
47 mc_epoch_number: McEpochNumber,
48 committee_candidate_address: MainchainAddress,
49 ) -> Result<GetRegistrationsResponseMap, String> {
50 let candidates = get_candidates_for_epoch(
51 mc_epoch_number,
52 self.candidate_data_source.as_ref(),
53 committee_candidate_address,
54 )
55 .await?;
56 self.registrations_to_rpc_response(candidates).await
57 }
58}
59
60fn get_registrations_response_map(
62 candidates: Vec<CandidateRegistrations>,
63 validate_registration_data: impl Fn(
64 &StakePoolPublicKey,
65 &RegistrationData,
66 ) -> Result<Option<RegistrationDataError>, sp_api::ApiError>,
67 validate_stake: impl Fn(&Option<StakeDelegation>) -> Result<Option<StakeError>, sp_api::ApiError>,
68) -> Result<GetRegistrationsResponseMap, sp_api::ApiError> {
69 let mut map = GetRegistrationsResponseMap::new();
70
71 for candidate in candidates {
72 let mainchain_pub_key = candidate.mainchain_pub_key().clone();
73
74 let mut registration_entries: Vec<CandidateRegistrationEntry> = candidate
75 .registrations
76 .iter()
77 .map(|registration_data| {
78 let registration_data_validation_result =
79 validate_registration_data(&mainchain_pub_key, registration_data)?;
80 Ok::<CandidateRegistrationEntry, sp_api::ApiError>(CandidateRegistrationEntry::new(
81 registration_data.clone(),
82 mainchain_pub_key.clone(),
83 candidate.stake_delegation,
84 registration_data_validation_result,
85 ))
86 })
87 .collect::<Result<Vec<_>, _>>()?;
88
89 registration_entries.sort_by_key(|entry| entry.utxo.ordering_key());
90 let latest_valid_or_zero = registration_entries
91 .iter()
92 .rposition(|registration| registration.is_valid)
93 .unwrap_or(0);
94
95 registration_entries.drain(..latest_valid_or_zero);
96 if let Some(err) = validate_stake(&candidate.stake_delegation)? {
97 if let Some(first) = registration_entries.first_mut() {
98 if first.is_valid {
99 first.is_valid = false;
100 first.invalid_reasons = Some(err.into());
101 }
102 }
103 }
104
105 map.insert(to_hex(&mainchain_pub_key.0, false), registration_entries);
106 }
107
108 Ok(map)
109}
110
111pub(crate) async fn get_candidates_for_epoch(
112 mainchain_epoch: McEpochNumber,
113 candidate_data_source: &(dyn AuthoritySelectionDataSource + Send + Sync),
114 committee_candidate_address: MainchainAddress,
115) -> Result<Vec<CandidateRegistrations>, String> {
116 candidate_data_source
117 .get_candidates(mainchain_epoch, committee_candidate_address)
118 .await
119 .map_err(|err| format!("{err:?}"))
120}