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