massa_storage/
endorsement_indexes.rs

1use std::collections::hash_map::Entry;
2
3use massa_models::{
4    address::Address,
5    endorsement::{EndorsementId, SecureShareEndorsement},
6    prehash::{PreHashMap, PreHashSet},
7};
8
9/// Container for all endorsements and different indexes.
10/// Note: The structure can evolve and store more indexes.
11#[derive(Default)]
12pub struct EndorsementIndexes {
13    /// Endorsements structure container
14    endorsements: PreHashMap<EndorsementId, Box<SecureShareEndorsement>>,
15    /// Structure mapping creators with the created endorsements
16    index_by_creator: PreHashMap<Address, PreHashSet<EndorsementId>>,
17}
18
19impl EndorsementIndexes {
20    /// Insert an endorsement and populate the indexes.
21    /// Arguments:
22    /// - endorsement: the endorsement to insert
23    pub(crate) fn insert(&mut self, endorsement: SecureShareEndorsement) {
24        if let Entry::Vacant(vac) = self.endorsements.entry(endorsement.id) {
25            let endorsement = vac.insert(Box::new(endorsement));
26            // update creator index
27            self.index_by_creator
28                .entry(endorsement.content_creator_address)
29                .or_default()
30                .insert(endorsement.id);
31
32            massa_metrics::set_endorsements_counter(self.endorsements.len());
33        }
34    }
35
36    /// Remove a endorsement, remove from the indexes and made some clean-up in indexes if necessary.
37    /// Arguments:
38    /// * `endorsement_id`: the endorsement id to remove
39    pub(crate) fn remove(
40        &mut self,
41        endorsement_id: &EndorsementId,
42    ) -> Option<Box<SecureShareEndorsement>> {
43        if let Some(e) = self.endorsements.remove(endorsement_id) {
44            massa_metrics::set_endorsements_counter(self.endorsements.len());
45
46            // update creator index
47            if let Entry::Occupied(mut occ) = self.index_by_creator.entry(e.content_creator_address)
48            {
49                occ.get_mut().remove(&e.id);
50                if occ.get().is_empty() {
51                    occ.remove();
52                }
53            }
54            return Some(e);
55        }
56        None
57    }
58
59    /// Gets a reference to a stored endorsement, if any.
60    pub fn get(&self, id: &EndorsementId) -> Option<&SecureShareEndorsement> {
61        self.endorsements.get(id).map(|v| v.as_ref())
62    }
63
64    /// Checks whether an endorsement exists in global storage.
65    pub fn contains(&self, id: &EndorsementId) -> bool {
66        self.endorsements.contains_key(id)
67    }
68
69    /// Get endorsements created by an address
70    /// Arguments:
71    /// - address: the address to get the endorsements created by
72    ///
73    /// Returns:
74    /// - optional reference to a set of endorsements created by that address
75    pub fn get_endorsements_created_by(
76        &self,
77        address: &Address,
78    ) -> Option<&PreHashSet<EndorsementId>> {
79        self.index_by_creator.get(address)
80    }
81}