1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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();

        // match self.client.runtime_api().key_owner(block_hash, aleph_key) {
        //     Ok(Some(account_id)) => Some(primitives::HashedConversion::convert_account_id(
        //         account_id.into(),
        //     )),
        //     Ok(None) => None,
        //     Err(_) => None,
        // }

        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
    }
}