light_token_interface/
hash_cache.rs

1use light_array_map::ArrayMap;
2use light_compressed_account::hash_to_bn254_field_size_be;
3use pinocchio::pubkey::{pubkey_eq, Pubkey};
4
5use crate::error::TokenError;
6/// Context for caching hashed values to avoid recomputation
7pub struct HashCache {
8    /// Cache for mint hashes: (mint_pubkey, hashed_mint)
9    pub hashed_mints: ArrayMap<Pubkey, [u8; 32], 5>,
10    /// Cache for pubkey hashes: (pubkey, hashed_pubkey)
11    pub hashed_pubkeys: Vec<(Pubkey, [u8; 32])>,
12}
13
14impl HashCache {
15    /// Create a new empty context
16    pub fn new() -> Self {
17        Self {
18            hashed_mints: ArrayMap::new(),
19            hashed_pubkeys: Vec::new(),
20        }
21    }
22
23    /// Get or compute hash for a mint pubkey
24    pub fn get_or_hash_mint(&mut self, mint: &Pubkey) -> Result<[u8; 32], TokenError> {
25        if let Some(hash) = self.hashed_mints.get_by_key(mint) {
26            return Ok(*hash);
27        }
28
29        let hashed_mint = hash_to_bn254_field_size_be(mint);
30        self.hashed_mints
31            .insert(*mint, hashed_mint, TokenError::InvalidAccountData)?;
32        Ok(hashed_mint)
33    }
34
35    /// Get or compute hash for a pubkey (owner, delegate, etc.)
36    pub fn get_or_hash_pubkey(&mut self, pubkey: &Pubkey) -> [u8; 32] {
37        let hashed_pubkey = self
38            .hashed_pubkeys
39            .iter()
40            .find(|a| pubkey_eq(&a.0, pubkey))
41            .map(|a| a.1);
42        match hashed_pubkey {
43            Some(hashed_pubkey) => hashed_pubkey,
44            None => {
45                let hashed_pubkey = hash_to_bn254_field_size_be(pubkey);
46                self.hashed_pubkeys.push((*pubkey, hashed_pubkey));
47                hashed_pubkey
48            }
49        }
50    }
51}
52
53impl Default for HashCache {
54    fn default() -> Self {
55        Self::new()
56    }
57}