solana_sdk/
keyed_account.rs

1#![deprecated(
2    since = "1.11.0",
3    note = "Please use BorrowedAccount instead of KeyedAccount"
4)]
5#![allow(deprecated)]
6use {
7    crate::{
8        account::{AccountSharedData, ReadableAccount},
9        account_utils::{State, StateMut},
10    },
11    solana_program::{clock::Epoch, instruction::InstructionError, pubkey::Pubkey},
12    std::{
13        cell::{Ref, RefCell, RefMut},
14        iter::FromIterator,
15        rc::Rc,
16    },
17};
18
19#[repr(C)]
20#[derive(Debug, Clone)]
21pub struct KeyedAccount<'a> {
22    is_signer: bool, // Transaction was signed by this account's key
23    is_writable: bool,
24    key: &'a Pubkey,
25    pub account: &'a RefCell<AccountSharedData>,
26}
27
28impl<'a> KeyedAccount<'a> {
29    pub fn signer_key(&self) -> Option<&Pubkey> {
30        if self.is_signer {
31            Some(self.key)
32        } else {
33            None
34        }
35    }
36
37    pub fn unsigned_key(&self) -> &Pubkey {
38        self.key
39    }
40
41    pub fn is_writable(&self) -> bool {
42        self.is_writable
43    }
44
45    pub fn lamports(&self) -> Result<u64, InstructionError> {
46        Ok(self.try_borrow()?.lamports())
47    }
48
49    pub fn data_len(&self) -> Result<usize, InstructionError> {
50        Ok(self.try_borrow()?.data().len())
51    }
52
53    pub fn data_is_empty(&self) -> Result<bool, InstructionError> {
54        Ok(self.try_borrow()?.data().is_empty())
55    }
56
57    pub fn owner(&self) -> Result<Pubkey, InstructionError> {
58        Ok(*self.try_borrow()?.owner())
59    }
60
61    pub fn executable(&self) -> Result<bool, InstructionError> {
62        Ok(self.try_borrow()?.executable())
63    }
64
65    pub fn rent_epoch(&self) -> Result<Epoch, InstructionError> {
66        Ok(self.try_borrow()?.rent_epoch())
67    }
68
69    pub fn try_account_ref(&'a self) -> Result<Ref<AccountSharedData>, InstructionError> {
70        self.try_borrow()
71    }
72
73    pub fn try_account_ref_mut(&'a self) -> Result<RefMut<AccountSharedData>, InstructionError> {
74        self.try_borrow_mut()
75    }
76
77    fn try_borrow(&self) -> Result<Ref<AccountSharedData>, InstructionError> {
78        self.account
79            .try_borrow()
80            .map_err(|_| InstructionError::AccountBorrowFailed)
81    }
82    fn try_borrow_mut(&self) -> Result<RefMut<AccountSharedData>, InstructionError> {
83        self.account
84            .try_borrow_mut()
85            .map_err(|_| InstructionError::AccountBorrowFailed)
86    }
87
88    pub fn new(key: &'a Pubkey, is_signer: bool, account: &'a RefCell<AccountSharedData>) -> Self {
89        Self {
90            is_signer,
91            is_writable: true,
92            key,
93            account,
94        }
95    }
96
97    pub fn new_readonly(
98        key: &'a Pubkey,
99        is_signer: bool,
100        account: &'a RefCell<AccountSharedData>,
101    ) -> Self {
102        Self {
103            is_signer,
104            is_writable: false,
105            key,
106            account,
107        }
108    }
109}
110
111impl<'a> PartialEq for KeyedAccount<'a> {
112    fn eq(&self, other: &Self) -> bool {
113        self.key == other.key
114    }
115}
116
117impl<'a> From<(&'a Pubkey, &'a RefCell<AccountSharedData>)> for KeyedAccount<'a> {
118    fn from((key, account): (&'a Pubkey, &'a RefCell<AccountSharedData>)) -> Self {
119        Self {
120            is_signer: false,
121            is_writable: true,
122            key,
123            account,
124        }
125    }
126}
127
128impl<'a> From<(&'a Pubkey, bool, &'a RefCell<AccountSharedData>)> for KeyedAccount<'a> {
129    fn from((key, is_signer, account): (&'a Pubkey, bool, &'a RefCell<AccountSharedData>)) -> Self {
130        Self {
131            is_signer,
132            is_writable: true,
133            key,
134            account,
135        }
136    }
137}
138
139impl<'a> From<&'a (&'a Pubkey, &'a RefCell<AccountSharedData>)> for KeyedAccount<'a> {
140    fn from((key, account): &'a (&'a Pubkey, &'a RefCell<AccountSharedData>)) -> Self {
141        Self {
142            is_signer: false,
143            is_writable: true,
144            key,
145            account,
146        }
147    }
148}
149
150pub fn create_keyed_accounts<'a>(
151    accounts: &'a [(&'a Pubkey, &'a RefCell<AccountSharedData>)],
152) -> Vec<KeyedAccount<'a>> {
153    accounts.iter().map(Into::into).collect()
154}
155
156#[deprecated(
157    since = "1.7.0",
158    note = "Please use create_keyed_accounts_unified instead"
159)]
160pub fn create_keyed_is_signer_accounts<'a>(
161    accounts: &'a [(&'a Pubkey, bool, &'a RefCell<AccountSharedData>)],
162) -> Vec<KeyedAccount<'a>> {
163    accounts
164        .iter()
165        .map(|(key, is_signer, account)| KeyedAccount {
166            is_signer: *is_signer,
167            is_writable: false,
168            key,
169            account,
170        })
171        .collect()
172}
173
174#[deprecated(
175    since = "1.7.0",
176    note = "Please use create_keyed_accounts_unified instead"
177)]
178pub fn create_keyed_readonly_accounts(
179    accounts: &[(Pubkey, Rc<RefCell<AccountSharedData>>)],
180) -> Vec<KeyedAccount> {
181    accounts
182        .iter()
183        .map(|(key, account)| KeyedAccount {
184            is_signer: false,
185            is_writable: false,
186            key,
187            account,
188        })
189        .collect()
190}
191
192pub fn create_keyed_accounts_unified<'a>(
193    accounts: &[(bool, bool, &'a Pubkey, &'a RefCell<AccountSharedData>)],
194) -> Vec<KeyedAccount<'a>> {
195    accounts
196        .iter()
197        .map(|(is_signer, is_writable, key, account)| KeyedAccount {
198            is_signer: *is_signer,
199            is_writable: *is_writable,
200            key,
201            account,
202        })
203        .collect()
204}
205
206#[deprecated(
207    since = "1.11.0",
208    note = "Please use InstructionContext::get_signers() instead"
209)]
210/// Return all the signers from a set of KeyedAccounts
211pub fn get_signers<A>(keyed_accounts: &[KeyedAccount]) -> A
212where
213    A: FromIterator<Pubkey>,
214{
215    keyed_accounts
216        .iter()
217        .filter_map(|keyed_account| keyed_account.signer_key())
218        .cloned()
219        .collect::<A>()
220}
221
222#[deprecated(since = "1.7.0", note = "Please use keyed_account_at_index instead")]
223/// Return the next KeyedAccount or a NotEnoughAccountKeys error
224pub fn next_keyed_account<'a, 'b, I: Iterator<Item = &'a KeyedAccount<'b>>>(
225    iter: &mut I,
226) -> Result<I::Item, InstructionError> {
227    iter.next().ok_or(InstructionError::NotEnoughAccountKeys)
228}
229
230/// Return the KeyedAccount at the specified index or a NotEnoughAccountKeys error
231///
232/// Index zero starts at the chain of program accounts, followed by the instruction accounts.
233pub fn keyed_account_at_index<'a>(
234    keyed_accounts: &'a [KeyedAccount],
235    index: usize,
236) -> Result<&'a KeyedAccount<'a>, InstructionError> {
237    keyed_accounts
238        .get(index)
239        .ok_or(InstructionError::NotEnoughAccountKeys)
240}
241
242/// Return true if the first keyed_account is executable, used to determine if
243/// the loader should call a program's 'main'
244pub fn is_executable(keyed_accounts: &[KeyedAccount]) -> Result<bool, InstructionError> {
245    Ok(!keyed_accounts.is_empty() && keyed_accounts[0].executable()?)
246}
247
248impl<'a, T> State<T> for crate::keyed_account::KeyedAccount<'a>
249where
250    T: serde::Serialize + serde::de::DeserializeOwned,
251{
252    fn state(&self) -> Result<T, InstructionError> {
253        self.try_account_ref()?.state()
254    }
255    fn set_state(&self, state: &T) -> Result<(), InstructionError> {
256        self.try_account_ref_mut()?.set_state(state)
257    }
258}