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