1use crate::{External, ValuePtr};
2use near_primitives_core::types::{AccountId, Balance, Gas};
3use near_vm_errors::HostError;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Default, Clone)]
8pub struct MockedExternal {
10 pub fake_trie: HashMap<Vec<u8>, Vec<u8>>,
11 receipts: Vec<Receipt>,
12 pub validators: HashMap<AccountId, Balance>,
13}
14
15pub struct MockedValuePtr {
16 value: Vec<u8>,
17}
18
19impl MockedValuePtr {
20 pub fn new<T>(value: T) -> Self
21 where
22 T: AsRef<[u8]>,
23 {
24 MockedValuePtr { value: value.as_ref().to_vec() }
25 }
26}
27
28impl ValuePtr for MockedValuePtr {
29 fn len(&self) -> u32 {
30 self.value.len() as u32
31 }
32
33 fn deref(&self) -> crate::dependencies::Result<Vec<u8>> {
34 Ok(self.value.clone())
35 }
36}
37
38impl MockedExternal {
39 pub fn new() -> Self {
40 Self::default()
41 }
42
43 pub fn get_receipt_create_calls(&self) -> &Vec<Receipt> {
45 &self.receipts
46 }
47}
48
49use crate::dependencies::Result;
50use crate::types::PublicKey;
51
52impl External for MockedExternal {
53 fn storage_set(&mut self, key: &[u8], value: &[u8]) -> Result<()> {
54 self.fake_trie.insert(key.to_vec(), value.to_vec());
55 Ok(())
56 }
57
58 fn storage_get(&self, key: &[u8]) -> Result<Option<Box<dyn ValuePtr>>> {
59 Ok(self
60 .fake_trie
61 .get(key)
62 .map(|value| Box::new(MockedValuePtr { value: value.clone() }) as Box<_>))
63 }
64
65 fn storage_remove(&mut self, key: &[u8]) -> Result<()> {
66 self.fake_trie.remove(key);
67 Ok(())
68 }
69
70 fn storage_remove_subtree(&mut self, prefix: &[u8]) -> Result<()> {
71 let keys: Vec<_> = self
72 .fake_trie
73 .iter()
74 .filter_map(|(key, _)| if key.starts_with(prefix) { Some(key.clone()) } else { None })
75 .collect();
76 for key in keys {
77 self.fake_trie.remove(&key);
78 }
79 Ok(())
80 }
81
82 fn storage_has_key(&mut self, key: &[u8]) -> Result<bool> {
83 Ok(self.fake_trie.contains_key(key))
84 }
85
86 fn create_receipt(&mut self, receipt_indices: Vec<u64>, receiver_id: String) -> Result<u64> {
87 if let Some(index) = receipt_indices.iter().find(|&&el| el >= self.receipts.len() as u64) {
88 return Err(HostError::InvalidReceiptIndex { receipt_index: *index }.into());
89 }
90 let res = self.receipts.len() as u64;
91 self.receipts.push(Receipt { receipt_indices, receiver_id, actions: vec![] });
92 Ok(res)
93 }
94
95 fn append_action_create_account(&mut self, receipt_index: u64) -> Result<()> {
96 self.receipts.get_mut(receipt_index as usize).unwrap().actions.push(Action::CreateAccount);
97 Ok(())
98 }
99
100 fn append_action_deploy_contract(&mut self, receipt_index: u64, code: Vec<u8>) -> Result<()> {
101 self.receipts
102 .get_mut(receipt_index as usize)
103 .unwrap()
104 .actions
105 .push(Action::DeployContract(DeployContractAction { code }));
106 Ok(())
107 }
108
109 fn append_action_function_call(
110 &mut self,
111 receipt_index: u64,
112 method_name: Vec<u8>,
113 arguments: Vec<u8>,
114 attached_deposit: u128,
115 prepaid_gas: u64,
116 ) -> Result<()> {
117 self.receipts.get_mut(receipt_index as usize).unwrap().actions.push(Action::FunctionCall(
118 FunctionCallAction {
119 method_name,
120 args: arguments,
121 deposit: attached_deposit,
122 gas: prepaid_gas,
123 },
124 ));
125 Ok(())
126 }
127
128 fn append_action_transfer(&mut self, receipt_index: u64, amount: u128) -> Result<()> {
129 self.receipts
130 .get_mut(receipt_index as usize)
131 .unwrap()
132 .actions
133 .push(Action::Transfer(TransferAction { deposit: amount }));
134 Ok(())
135 }
136
137 fn append_action_stake(
138 &mut self,
139 receipt_index: u64,
140 stake: u128,
141 public_key: Vec<u8>,
142 ) -> Result<()> {
143 self.receipts
144 .get_mut(receipt_index as usize)
145 .unwrap()
146 .actions
147 .push(Action::Stake(StakeAction { stake, public_key }));
148 Ok(())
149 }
150
151 fn append_action_add_key_with_full_access(
152 &mut self,
153 receipt_index: u64,
154 public_key: Vec<u8>,
155 nonce: u64,
156 ) -> Result<()> {
157 self.receipts
158 .get_mut(receipt_index as usize)
159 .unwrap()
160 .actions
161 .push(Action::AddKeyWithFullAccess(AddKeyWithFullAccessAction { public_key, nonce }));
162 Ok(())
163 }
164
165 fn append_action_add_key_with_function_call(
166 &mut self,
167 receipt_index: u64,
168 public_key: Vec<u8>,
169 nonce: u64,
170 allowance: Option<u128>,
171 receiver_id: String,
172 method_names: Vec<Vec<u8>>,
173 ) -> Result<()> {
174 self.receipts.get_mut(receipt_index as usize).unwrap().actions.push(
175 Action::AddKeyWithFunctionCall(AddKeyWithFunctionCallAction {
176 public_key,
177 nonce,
178 allowance,
179 receiver_id,
180 method_names,
181 }),
182 );
183 Ok(())
184 }
185
186 fn append_action_delete_key(&mut self, receipt_index: u64, public_key: Vec<u8>) -> Result<()> {
187 self.receipts
188 .get_mut(receipt_index as usize)
189 .unwrap()
190 .actions
191 .push(Action::DeleteKey(DeleteKeyAction { public_key }));
192 Ok(())
193 }
194
195 fn append_action_delete_account(
196 &mut self,
197 receipt_index: u64,
198 beneficiary_id: String,
199 ) -> Result<()> {
200 self.receipts
201 .get_mut(receipt_index as usize)
202 .unwrap()
203 .actions
204 .push(Action::DeleteAccount(DeleteAccountAction { beneficiary_id }));
205 Ok(())
206 }
207
208 fn get_touched_nodes_count(&self) -> u64 {
209 0
210 }
211
212 fn reset_touched_nodes_counter(&mut self) {}
213
214 fn validator_stake(&self, account_id: &AccountId) -> Result<Option<Balance>> {
215 Ok(self.validators.get(account_id).cloned())
216 }
217
218 fn validator_total_stake(&self) -> Result<Balance> {
219 Ok(self.validators.values().sum())
220 }
221}
222
223#[derive(Serialize, Deserialize, Clone, Debug)]
224pub struct Receipt {
225 receipt_indices: Vec<u64>,
226 receiver_id: String,
227 actions: Vec<Action>,
228}
229
230#[derive(Serialize, Deserialize, Clone, Debug)]
231pub enum Action {
232 CreateAccount,
233 DeployContract(DeployContractAction),
234 FunctionCall(FunctionCallAction),
235 Transfer(TransferAction),
236 Stake(StakeAction),
237 AddKeyWithFullAccess(AddKeyWithFullAccessAction),
238 AddKeyWithFunctionCall(AddKeyWithFunctionCallAction),
239 DeleteKey(DeleteKeyAction),
240 DeleteAccount(DeleteAccountAction),
241}
242
243#[derive(Serialize, Deserialize, Clone, Debug)]
244pub struct DeployContractAction {
245 pub code: Vec<u8>,
246}
247
248#[derive(Serialize, Deserialize, Clone, Debug)]
249pub struct FunctionCallAction {
250 #[serde(with = "crate::serde_with::bytes_as_str")]
251 method_name: Vec<u8>,
252 #[serde(with = "crate::serde_with::bytes_as_str")]
257 args: Vec<u8>,
258 gas: Gas,
259 deposit: Balance,
260}
261
262#[derive(Serialize, Deserialize, Clone, Debug)]
263pub struct TransferAction {
264 deposit: Balance,
265}
266
267#[derive(Serialize, Deserialize, Clone, Debug)]
268pub struct StakeAction {
269 stake: Balance,
270 #[serde(with = "crate::serde_with::bytes_as_base58")]
271 public_key: PublicKey,
272}
273
274#[derive(Serialize, Deserialize, Clone, Debug)]
275pub struct AddKeyWithFullAccessAction {
276 #[serde(with = "crate::serde_with::bytes_as_base58")]
277 public_key: PublicKey,
278 nonce: u64,
279}
280
281#[derive(Serialize, Deserialize, Clone, Debug)]
282pub struct AddKeyWithFunctionCallAction {
283 #[serde(with = "crate::serde_with::bytes_as_base58")]
284 public_key: PublicKey,
285 nonce: u64,
286 allowance: Option<Balance>,
287 receiver_id: AccountId,
288 #[serde(with = "crate::serde_with::vec_bytes_as_str")]
289 method_names: Vec<Vec<u8>>,
290}
291
292#[derive(Serialize, Deserialize, Clone, Debug)]
293pub struct DeleteKeyAction {
294 #[serde(with = "crate::serde_with::bytes_as_base58")]
295 public_key: PublicKey,
296}
297
298#[derive(Serialize, Deserialize, Clone, Debug)]
299pub struct DeleteAccountAction {
300 beneficiary_id: AccountId,
301}