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