use std::sync::Arc;
use core_primitives::{
AccountId, PhronSessionApi, AuraId, BlockHash, BlockNumber,
};
use sc_client_api::Backend;
use sp_consensus_aura::AuraApi;
use sp_runtime::traits::{Block, Header};
use crate::{
abft::NodeIndex,
runtime_api::RuntimeApi,
session::{SessionBoundaryInfo, SessionId},
session_map::{AuthorityProvider, AuthorityProviderImpl},
ClientForPhron,
};
pub trait ValidatorIndexToAccountIdConverter {
fn account(&self, session: SessionId, validator_index: NodeIndex) -> Option<AccountId>;
}
pub struct ValidatorIndexToAccountIdConverterImpl<C, B, BE, RA>
where
C: ClientForPhron<B, BE> + Send + Sync + 'static,
C::Api: crate::phron_primitives::PhronSessionApi<B> + AuraApi<B, AuraId>,
B: Block<Hash = BlockHash>,
BE: Backend<B> + 'static,
RA: RuntimeApi,
{
client: Arc<C>,
session_boundary_info: SessionBoundaryInfo,
authority_provider: AuthorityProviderImpl<C, B, BE, RA>,
}
impl<C, B, BE, RA> ValidatorIndexToAccountIdConverterImpl<C, B, BE, RA>
where
C: ClientForPhron<B, BE> + Send + Sync + 'static,
C::Api: crate::phron_primitives::PhronSessionApi<B> + AuraApi<B, AuraId>,
B: Block<Hash = BlockHash>,
B::Header: Header<Number = BlockNumber>,
BE: Backend<B> + 'static,
RA: RuntimeApi,
{
pub fn new(client: Arc<C>, session_boundary_info: SessionBoundaryInfo, api: RA) -> Self {
Self {
client: client.clone(),
session_boundary_info,
authority_provider: AuthorityProviderImpl::new(client, api),
}
}
}
impl<C, B, BE, RA> ValidatorIndexToAccountIdConverter
for ValidatorIndexToAccountIdConverterImpl<C, B, BE, RA>
where
C: ClientForPhron<B, BE> + Send + Sync + 'static,
C::Api: crate::phron_primitives::PhronSessionApi<B> + AuraApi<B, AuraId>,
B: Block<Hash = BlockHash>,
B::Header: Header<Number = BlockNumber>,
BE: Backend<B> + 'static,
RA: RuntimeApi,
{
fn account(&self, session: SessionId, validator_index: NodeIndex) -> Option<AccountId> {
let block_number = self
.session_boundary_info
.boundaries_for_session(session)
.first_block();
let block_hash = self.client.block_hash(block_number).ok()??;
let authority_data = self.authority_provider.authority_data(block_number)?;
let aleph_key = authority_data.authorities()[validator_index.0].clone();
self.client
.runtime_api()
.key_owner(block_hash, aleph_key)
.ok()?
}
}
#[cfg(test)]
pub struct MockConverter;
#[cfg(test)]
impl ValidatorIndexToAccountIdConverter for MockConverter {
fn account(&self, _: SessionId, _: NodeIndex) -> Option<AccountId> {
None
}
}