evm_nogas/executor/stack/
memory.rs

1use crate::backend::{Apply, Backend, Basic, Log};
2use crate::executor::stack::executor::{Accessed, StackState, StackSubstateMetadata};
3use crate::{ExitError, Transfer};
4use alloc::{
5    boxed::Box,
6    collections::{BTreeMap, BTreeSet},
7    vec::Vec,
8};
9use core::mem;
10use primitive_types::{H160, H256, U256};
11
12#[derive(Clone, Debug)]
13pub struct MemoryStackAccount {
14    pub basic: Basic,
15    pub code: Option<Vec<u8>>,
16    pub reset: bool,
17}
18
19#[derive(Clone, Debug)]
20pub struct MemoryStackSubstate {
21    metadata: StackSubstateMetadata,
22    parent: Option<Box<MemoryStackSubstate>>,
23    logs: Vec<Log>,
24    accounts: BTreeMap<H160, MemoryStackAccount>,
25    storages: BTreeMap<(H160, H256), H256>,
26    deletes: BTreeSet<H160>,
27}
28
29impl MemoryStackSubstate {
30    pub fn new(metadata: StackSubstateMetadata) -> Self {
31        Self {
32            metadata,
33            parent: None,
34            logs: Vec::new(),
35            accounts: BTreeMap::new(),
36            storages: BTreeMap::new(),
37            deletes: BTreeSet::new(),
38        }
39    }
40
41    pub fn logs(&self) -> &[Log] {
42        &self.logs
43    }
44
45    pub fn logs_mut(&mut self) -> &mut Vec<Log> {
46        &mut self.logs
47    }
48
49    pub fn metadata(&self) -> &StackSubstateMetadata {
50        &self.metadata
51    }
52
53    pub fn metadata_mut(&mut self) -> &mut StackSubstateMetadata {
54        &mut self.metadata
55    }
56
57    /// Deconstruct the executor, return state to be applied. Panic if the
58    /// executor is not in the top-level substate.
59    #[must_use]
60    pub fn deconstruct<B: Backend>(
61        mut self,
62        backend: &B,
63    ) -> (
64        impl IntoIterator<Item = Apply<impl IntoIterator<Item = (H256, H256)>>>,
65        impl IntoIterator<Item = Log>,
66    ) {
67        assert!(self.parent.is_none());
68
69        let mut applies = Vec::<Apply<BTreeMap<H256, H256>>>::new();
70
71        let mut addresses = BTreeSet::new();
72
73        for address in self.accounts.keys() {
74            addresses.insert(*address);
75        }
76
77        for (address, _) in self.storages.keys() {
78            addresses.insert(*address);
79        }
80
81        for address in addresses {
82            if self.deletes.contains(&address) {
83                continue;
84            }
85
86            let mut storage = BTreeMap::new();
87            for ((oa, ok), ov) in &self.storages {
88                if *oa == address {
89                    storage.insert(*ok, *ov);
90                }
91            }
92
93            let apply = {
94                let account = self.account_mut(address, backend);
95
96                Apply::Modify {
97                    address,
98                    basic: account.basic.clone(),
99                    code: account.code.clone(),
100                    storage,
101                    reset_storage: account.reset,
102                }
103            };
104
105            applies.push(apply);
106        }
107
108        for address in self.deletes {
109            applies.push(Apply::Delete { address });
110        }
111
112        (applies, self.logs)
113    }
114
115    pub fn enter(&mut self, is_static: bool) {
116        let mut entering = Self {
117            metadata: self.metadata.spit_child(is_static),
118            parent: None,
119            logs: Vec::new(),
120            accounts: BTreeMap::new(),
121            storages: BTreeMap::new(),
122            deletes: BTreeSet::new(),
123        };
124        mem::swap(&mut entering, self);
125
126        self.parent = Some(Box::new(entering));
127    }
128
129    pub fn exit_commit(&mut self) -> Result<(), ExitError> {
130        let mut exited = *self.parent.take().expect("Cannot commit on root substate");
131        mem::swap(&mut exited, self);
132
133        self.metadata.swallow_commit(exited.metadata)?;
134        self.logs.append(&mut exited.logs);
135
136        let mut resets = BTreeSet::new();
137        for (address, account) in &exited.accounts {
138            if account.reset {
139                resets.insert(*address);
140            }
141        }
142        let mut reset_keys = BTreeSet::new();
143        for (address, key) in self.storages.keys() {
144            if resets.contains(address) {
145                reset_keys.insert((*address, *key));
146            }
147        }
148        for (address, key) in reset_keys {
149            self.storages.remove(&(address, key));
150        }
151
152        self.accounts.append(&mut exited.accounts);
153        self.storages.append(&mut exited.storages);
154        self.deletes.append(&mut exited.deletes);
155
156        Ok(())
157    }
158
159    pub fn exit_revert(&mut self) -> Result<(), ExitError> {
160        let mut exited = *self.parent.take().expect("Cannot discard on root substate");
161        mem::swap(&mut exited, self);
162
163        self.metadata.swallow_revert(exited.metadata)?;
164
165        Ok(())
166    }
167
168    pub fn exit_discard(&mut self) -> Result<(), ExitError> {
169        let mut exited = *self.parent.take().expect("Cannot discard on root substate");
170        mem::swap(&mut exited, self);
171
172        self.metadata.swallow_discard(exited.metadata)?;
173
174        Ok(())
175    }
176
177    pub fn known_account(&self, address: H160) -> Option<&MemoryStackAccount> {
178        if let Some(account) = self.accounts.get(&address) {
179            Some(account)
180        } else if let Some(parent) = self.parent.as_ref() {
181            parent.known_account(address)
182        } else {
183            None
184        }
185    }
186
187    pub fn known_basic(&self, address: H160) -> Option<Basic> {
188        self.known_account(address).map(|acc| acc.basic.clone())
189    }
190
191    pub fn known_code(&self, address: H160) -> Option<Vec<u8>> {
192        self.known_account(address).and_then(|acc| acc.code.clone())
193    }
194
195    pub fn known_empty(&self, address: H160) -> Option<bool> {
196        if let Some(account) = self.known_account(address) {
197            if account.basic.balance != U256::zero() {
198                return Some(false);
199            }
200
201            if account.basic.nonce != U256::zero() {
202                return Some(false);
203            }
204
205            if let Some(code) = &account.code {
206                return Some(
207                    account.basic.balance == U256::zero()
208                        && account.basic.nonce == U256::zero()
209                        && code.is_empty(),
210                );
211            }
212        }
213
214        None
215    }
216
217    pub fn known_storage(&self, address: H160, key: H256) -> Option<H256> {
218        if let Some(value) = self.storages.get(&(address, key)) {
219            return Some(*value);
220        }
221
222        if let Some(account) = self.accounts.get(&address) {
223            if account.reset {
224                return Some(H256::default());
225            }
226        }
227
228        if let Some(parent) = self.parent.as_ref() {
229            return parent.known_storage(address, key);
230        }
231
232        None
233    }
234
235    pub fn known_original_storage(&self, address: H160, key: H256) -> Option<H256> {
236        if let Some(account) = self.accounts.get(&address) {
237            if account.reset {
238                return Some(H256::default());
239            }
240        }
241
242        if let Some(parent) = self.parent.as_ref() {
243            return parent.known_original_storage(address, key);
244        }
245
246        None
247    }
248
249    pub fn is_cold(&self, address: H160) -> bool {
250        self.recursive_is_cold(&|a| a.accessed_addresses.contains(&address))
251    }
252
253    pub fn is_storage_cold(&self, address: H160, key: H256) -> bool {
254        self.recursive_is_cold(&|a: &Accessed| a.accessed_storage.contains(&(address, key)))
255    }
256
257    fn recursive_is_cold<F: Fn(&Accessed) -> bool>(&self, f: &F) -> bool {
258        let local_is_accessed = self.metadata.accessed().as_ref().map(f).unwrap_or(false);
259        if local_is_accessed {
260            false
261        } else {
262            self.parent
263                .as_ref()
264                .map(|p| p.recursive_is_cold(f))
265                .unwrap_or(true)
266        }
267    }
268
269    pub fn deleted(&self, address: H160) -> bool {
270        if self.deletes.contains(&address) {
271            return true;
272        }
273
274        if let Some(parent) = self.parent.as_ref() {
275            return parent.deleted(address);
276        }
277
278        false
279    }
280
281    #[allow(clippy::map_entry)]
282    fn account_mut<B: Backend>(&mut self, address: H160, backend: &B) -> &mut MemoryStackAccount {
283        if !self.accounts.contains_key(&address) {
284            let account = self
285                .known_account(address)
286                .cloned()
287                .map(|mut v| {
288                    v.reset = false;
289                    v
290                })
291                .unwrap_or_else(|| MemoryStackAccount {
292                    basic: backend.basic(address),
293                    code: None,
294                    reset: false,
295                });
296            self.accounts.insert(address, account);
297        }
298
299        self.accounts
300            .get_mut(&address)
301            .expect("New account was just inserted")
302    }
303
304    pub fn inc_nonce<B: Backend>(&mut self, address: H160, backend: &B) {
305        self.account_mut(address, backend).basic.nonce += U256::one();
306    }
307
308    pub fn set_storage(&mut self, address: H160, key: H256, value: H256) {
309        self.storages.insert((address, key), value);
310    }
311
312    pub fn reset_storage<B: Backend>(&mut self, address: H160, backend: &B) {
313        let mut removing = Vec::new();
314
315        for (oa, ok) in self.storages.keys() {
316            if *oa == address {
317                removing.push(*ok);
318            }
319        }
320
321        for ok in removing {
322            self.storages.remove(&(address, ok));
323        }
324
325        self.account_mut(address, backend).reset = true;
326    }
327
328    pub fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) {
329        self.logs.push(Log {
330            address,
331            topics,
332            data,
333        });
334    }
335
336    pub fn set_deleted(&mut self, address: H160) {
337        self.deletes.insert(address);
338    }
339
340    pub fn set_code<B: Backend>(&mut self, address: H160, code: Vec<u8>, backend: &B) {
341        self.account_mut(address, backend).code = Some(code);
342    }
343
344    pub fn transfer<B: Backend>(
345        &mut self,
346        transfer: Transfer,
347        backend: &B,
348    ) -> Result<(), ExitError> {
349        {
350            let source = self.account_mut(transfer.source, backend);
351            if source.basic.balance < transfer.value {
352                return Err(ExitError::OutOfFund);
353            }
354            source.basic.balance -= transfer.value;
355        }
356
357        {
358            let target = self.account_mut(transfer.target, backend);
359            target.basic.balance = target.basic.balance.saturating_add(transfer.value);
360        }
361
362        Ok(())
363    }
364
365    // Only needed for jsontests.
366    pub fn withdraw<B: Backend>(
367        &mut self,
368        address: H160,
369        value: U256,
370        backend: &B,
371    ) -> Result<(), ExitError> {
372        let source = self.account_mut(address, backend);
373        if source.basic.balance < value {
374            return Err(ExitError::OutOfFund);
375        }
376        source.basic.balance -= value;
377
378        Ok(())
379    }
380
381    // Only needed for jsontests.
382    pub fn deposit<B: Backend>(&mut self, address: H160, value: U256, backend: &B) {
383        let target = self.account_mut(address, backend);
384        target.basic.balance = target.basic.balance.saturating_add(value);
385    }
386
387    pub fn reset_balance<B: Backend>(&mut self, address: H160, backend: &B) {
388        self.account_mut(address, backend).basic.balance = U256::zero();
389    }
390
391    pub fn touch<B: Backend>(&mut self, address: H160, backend: &B) {
392        self.account_mut(address, backend);
393    }
394}
395
396#[derive(Clone, Debug)]
397pub struct MemoryStackState<'backend, B> {
398    backend: &'backend B,
399    substate: MemoryStackSubstate,
400}
401
402impl<'backend, B: Backend> Backend for MemoryStackState<'backend, B> {
403    fn gas_price(&self) -> U256 {
404        self.backend.gas_price()
405    }
406    fn origin(&self) -> H160 {
407        self.backend.origin()
408    }
409    fn block_hash(&self, number: U256) -> H256 {
410        self.backend.block_hash(number)
411    }
412    fn block_number(&self) -> U256 {
413        self.backend.block_number()
414    }
415    fn block_coinbase(&self) -> H160 {
416        self.backend.block_coinbase()
417    }
418    fn block_timestamp(&self) -> U256 {
419        self.backend.block_timestamp()
420    }
421    fn block_difficulty(&self) -> U256 {
422        self.backend.block_difficulty()
423    }
424    fn block_gas_limit(&self) -> U256 {
425        self.backend.block_gas_limit()
426    }
427    fn block_base_fee_per_gas(&self) -> U256 {
428        self.backend.block_base_fee_per_gas()
429    }
430
431    fn gas_left(&self) -> U256 {
432        self.backend.gas_left()
433    }
434
435    fn chain_id(&self) -> U256 {
436        self.backend.chain_id()
437    }
438
439    fn exists(&self, address: H160) -> bool {
440        self.substate.known_account(address).is_some() || self.backend.exists(address)
441    }
442
443    fn basic(&self, address: H160) -> Basic {
444        self.substate
445            .known_basic(address)
446            .unwrap_or_else(|| self.backend.basic(address))
447    }
448
449    fn code(&self, address: H160) -> Vec<u8> {
450        self.substate
451            .known_code(address)
452            .unwrap_or_else(|| self.backend.code(address))
453    }
454
455    fn storage(&self, address: H160, key: H256) -> H256 {
456        self.substate
457            .known_storage(address, key)
458            .unwrap_or_else(|| self.backend.storage(address, key))
459    }
460
461    fn original_storage(&self, address: H160, key: H256) -> Option<H256> {
462        if let Some(value) = self.substate.known_original_storage(address, key) {
463            return Some(value);
464        }
465
466        self.backend.original_storage(address, key)
467    }
468}
469
470impl<'backend, B: Backend> StackState for MemoryStackState<'backend, B> {
471    fn metadata(&self) -> &StackSubstateMetadata {
472        self.substate.metadata()
473    }
474
475    fn metadata_mut(&mut self) -> &mut StackSubstateMetadata {
476        self.substate.metadata_mut()
477    }
478
479    fn enter(&mut self, is_static: bool) {
480        self.substate.enter(is_static)
481    }
482
483    fn exit_commit(&mut self) -> Result<(), ExitError> {
484        self.substate.exit_commit()
485    }
486
487    fn exit_revert(&mut self) -> Result<(), ExitError> {
488        self.substate.exit_revert()
489    }
490
491    fn exit_discard(&mut self) -> Result<(), ExitError> {
492        self.substate.exit_discard()
493    }
494
495    fn is_empty(&self, address: H160) -> bool {
496        if let Some(known_empty) = self.substate.known_empty(address) {
497            return known_empty;
498        }
499
500        self.backend.basic(address).balance == U256::zero()
501            && self.backend.basic(address).nonce == U256::zero()
502            && self.backend.code(address).len() == 0
503    }
504
505    fn deleted(&self, address: H160) -> bool {
506        self.substate.deleted(address)
507    }
508
509    fn is_cold(&self, address: H160) -> bool {
510        self.substate.is_cold(address)
511    }
512
513    fn is_storage_cold(&self, address: H160, key: H256) -> bool {
514        self.substate.is_storage_cold(address, key)
515    }
516
517    fn inc_nonce(&mut self, address: H160) {
518        self.substate.inc_nonce(address, self.backend);
519    }
520
521    fn set_storage(&mut self, address: H160, key: H256, value: H256) {
522        self.substate.set_storage(address, key, value)
523    }
524
525    fn reset_storage(&mut self, address: H160) {
526        self.substate.reset_storage(address, self.backend);
527    }
528
529    fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) {
530        self.substate.log(address, topics, data);
531    }
532
533    fn set_deleted(&mut self, address: H160) {
534        self.substate.set_deleted(address)
535    }
536
537    fn set_code(&mut self, address: H160, code: Vec<u8>) {
538        self.substate.set_code(address, code, self.backend)
539    }
540
541    fn transfer(&mut self, transfer: Transfer) -> Result<(), ExitError> {
542        self.substate.transfer(transfer, self.backend)
543    }
544
545    fn reset_balance(&mut self, address: H160) {
546        self.substate.reset_balance(address, self.backend)
547    }
548
549    fn touch(&mut self, address: H160) {
550        self.substate.touch(address, self.backend)
551    }
552}
553
554impl<'backend, B: Backend> MemoryStackState<'backend, B> {
555    pub fn new(metadata: StackSubstateMetadata, backend: &'backend B) -> Self {
556        Self {
557            backend,
558            substate: MemoryStackSubstate::new(metadata),
559        }
560    }
561
562    /// Returns a mutable reference to an account given its address
563    pub fn account_mut(&mut self, address: H160) -> &mut MemoryStackAccount {
564        self.substate.account_mut(address, self.backend)
565    }
566
567    #[must_use]
568    pub fn deconstruct(
569        self,
570    ) -> (
571        impl IntoIterator<Item = Apply<impl IntoIterator<Item = (H256, H256)>>>,
572        impl IntoIterator<Item = Log>,
573    ) {
574        self.substate.deconstruct(self.backend)
575    }
576
577    pub fn withdraw(&mut self, address: H160, value: U256) -> Result<(), ExitError> {
578        self.substate.withdraw(address, value, self.backend)
579    }
580
581    pub fn deposit(&mut self, address: H160, value: U256) {
582        self.substate.deposit(address, value, self.backend)
583    }
584}