Skip to main content

openrank_common/runners/
compute_runner.rs

1use crate::{
2    algos::et::positive_run,
3    merkle::{self, fixed::DenseMerkleTree, hash_leaf, Hash},
4    tx::trust::{ScoreEntry, TrustEntry},
5    Domain, DomainHash,
6};
7use getset::Getters;
8use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
9use sha3::Keccak256;
10use std::collections::HashMap;
11use tracing::info;
12
13use super::{BaseRunner, Error as BaseError};
14
15#[derive(Getters)]
16#[getset(get = "pub")]
17/// Struct containing the state of the computer compute runner.
18pub struct ComputeRunner {
19    base: BaseRunner,
20    compute_results: HashMap<DomainHash, Vec<(u64, f32)>>,
21    compute_tree: HashMap<DomainHash, DenseMerkleTree<Keccak256>>,
22}
23
24impl ComputeRunner {
25    pub fn new(domains: &[Domain]) -> Self {
26        let base = BaseRunner::new(domains);
27        let mut compute_results = HashMap::new();
28        for domain in domains {
29            let domain_hash = domain.to_hash();
30            compute_results.insert(domain_hash, Vec::<(u64, f32)>::new());
31        }
32        Self {
33            base,
34            compute_results,
35            compute_tree: HashMap::new(),
36        }
37    }
38
39    /// Update the state of trees for certain domain, with the given trust entries.
40    pub fn update_trust(
41        &mut self,
42        domain: Domain,
43        trust_entries: Vec<TrustEntry>,
44    ) -> Result<(), Error> {
45        self.base
46            .update_trust(domain, trust_entries)
47            .map_err(Error::Base)
48    }
49
50    pub fn update_trust_map(
51        &mut self,
52        domain: Domain,
53        trust_entries: Vec<TrustEntry>,
54    ) -> Result<(), Error> {
55        self.base
56            .update_trust_map(domain, trust_entries)
57            .map_err(Error::Base)
58    }
59
60    /// Update the state of trees for certain domain, with the given seed entries.
61    pub fn update_seed(
62        &mut self,
63        domain: Domain,
64        seed_entries: Vec<ScoreEntry>,
65    ) -> Result<(), Error> {
66        self.base
67            .update_seed(domain, seed_entries)
68            .map_err(Error::Base)
69    }
70
71    pub fn update_seed_map(
72        &mut self,
73        domain: Domain,
74        seed_entries: Vec<ScoreEntry>,
75    ) -> Result<(), Error> {
76        self.base
77            .update_seed_map(domain, seed_entries)
78            .map_err(Error::Base)
79    }
80
81    /// Compute the EigenTrust scores for certain domain.
82    pub fn compute(&mut self, domain: Domain) -> Result<(), Error> {
83        info!("COMPUTE_RUN: {}", domain.to_hash());
84        let lt = self
85            .base
86            .local_trust
87            .get(&domain.trust_namespace())
88            .ok_or::<Error>(BaseError::LocalTrustNotFound(domain.trust_namespace()).into())?;
89        let seed = self
90            .base
91            .seed_trust
92            .get(&domain.seed_namespace())
93            .ok_or::<Error>(BaseError::SeedTrustNotFound(domain.seed_namespace()).into())?;
94        let count = self
95            .base
96            .count
97            .get(&domain.to_hash())
98            .ok_or::<Error>(BaseError::CountNotFound(domain.to_hash()).into())?;
99        let res = positive_run(lt.clone(), seed.clone(), *count);
100        self.compute_results.insert(domain.to_hash(), res);
101        Ok(())
102    }
103
104    /// Create the compute tree for certain domain.
105    pub fn create_compute_tree(&mut self, domain: Domain) -> Result<(), Error> {
106        info!("CREATE_COMPUTE_TREE: {}", domain.to_hash());
107        let scores = self
108            .compute_results
109            .get(&domain.to_hash())
110            .ok_or(Error::ComputeResultsNotFound(domain.to_hash()))?;
111        let score_hashes: Vec<Hash> = scores
112            .par_iter()
113            .map(|(_, x)| hash_leaf::<Keccak256>(x.to_be_bytes().to_vec()))
114            .collect();
115        let compute_tree =
116            DenseMerkleTree::<Keccak256>::new(score_hashes).map_err(Error::Merkle)?;
117        info!(
118            "COMPUTE_TREE_ROOT_HASH: {}",
119            compute_tree.root().map_err(Error::Merkle)?
120        );
121        self.compute_tree.insert(domain.to_hash(), compute_tree);
122        Ok(())
123    }
124
125    /// Get the compute scores for certain domain.
126    pub fn get_compute_scores(&self, domain: Domain) -> Result<Vec<ScoreEntry>, Error> {
127        let domain_indices = self
128            .base
129            .indices
130            .get(&domain.to_hash())
131            .ok_or::<Error>(BaseError::IndicesNotFound(domain.to_hash()).into())?;
132        let scores = self
133            .compute_results
134            .get(&domain.to_hash())
135            .ok_or(Error::ComputeResultsNotFound(domain.to_hash()))?;
136        let index_to_address: HashMap<&u64, &String> =
137            domain_indices.iter().map(|(k, v)| (v, k)).collect();
138
139        let mut entries = Vec::new();
140        for (index, val) in scores {
141            let address = index_to_address
142                .get(&index)
143                .ok_or(Error::IndexToAddressNotFound(*index))?;
144            let score_entry = ScoreEntry::new((*address).clone(), *val);
145            entries.push(score_entry);
146        }
147        Ok(entries)
148    }
149
150    /// Get the local trust root hash and compute tree root hash for certain domain.
151    pub fn get_root_hashes(&self, domain: Domain) -> Result<(Hash, Hash), Error> {
152        let tree_roots = self.base.get_base_root_hashes(&domain)?;
153
154        let compute_tree = self
155            .compute_tree
156            .get(&domain.to_hash())
157            .ok_or(Error::ComputeTreeNotFound(domain.to_hash()))?;
158        let ct_tree_root = compute_tree.root().map_err(Error::Merkle)?;
159
160        Ok((tree_roots, ct_tree_root))
161    }
162}
163
164#[derive(thiserror::Error, Debug)]
165/// Errors that can arise while using the compute runner.
166pub enum Error {
167    #[error("Base Error: {0}")]
168    Base(BaseError),
169    /// The compute results for the domain are not found.
170    #[error("ComputeResultsNotFound Error: {0}")]
171    ComputeResultsNotFound(DomainHash),
172    /// The index to address mapping for the domain are not found.
173    #[error("IndexToAddressNotFound Error: {0}")]
174    IndexToAddressNotFound(u64),
175    /// The compute tree for the domain are not found.
176    #[error("ComputeTreeNotFound Error: {0}")]
177    ComputeTreeNotFound(DomainHash),
178    /// The compute merkle tree error.
179    #[error("Merkle Error: {0}")]
180    Merkle(merkle::Error),
181}
182
183impl From<BaseError> for Error {
184    fn from(err: BaseError) -> Self {
185        Self::Base(err)
186    }
187}