solana_message/versions/v1/
cached.rs1use {
2 crate::{v1::Message, AccountKeys},
3 solana_address::Address,
4 std::{borrow::Cow, collections::HashSet},
5};
6
7#[derive(Debug, Clone, Eq, PartialEq)]
8pub struct CachedMessage<'a> {
9 pub message: Cow<'a, Message>,
11 pub is_writable_account_cache: Vec<bool>,
14}
15
16impl CachedMessage<'_> {
17 pub fn new(message: Message, reserved_account_keys: &HashSet<Address>) -> Self {
18 let is_writable_account_cache = message
19 .account_keys
20 .iter()
21 .enumerate()
22 .map(|(i, key)| {
23 message.is_writable_index(i)
24 && !reserved_account_keys.contains(key)
25 && !message.demote_program_id(i)
26 })
27 .collect::<Vec<_>>();
28 Self {
29 message: Cow::Owned(message),
30 is_writable_account_cache,
31 }
32 }
33
34 pub fn has_duplicates(&self) -> bool {
36 let mut uniq = HashSet::with_capacity(self.account_keys().len());
37 self.account_keys().iter().any(|x| !uniq.insert(x))
38 }
39
40 pub fn is_key_called_as_program(&self, key_index: usize) -> bool {
41 self.message.is_key_called_as_program(key_index)
42 }
43
44 pub fn is_upgradeable_loader_present(&self) -> bool {
46 self.message.is_upgradeable_loader_present()
47 }
48
49 pub fn account_keys(&self) -> AccountKeys<'_> {
51 AccountKeys::new(&self.message.account_keys, None)
52 }
53
54 pub fn is_writable(&self, index: usize) -> bool {
55 *self.is_writable_account_cache.get(index).unwrap_or(&false)
56 }
57
58 pub fn demote_program_id(&self, i: usize) -> bool {
59 self.is_key_called_as_program(i) && !self.is_upgradeable_loader_present()
60 }
61}