aurora_evm/executor/stack/
memory.rs

1use crate::backend::{Apply, Backend, Basic, Log};
2use crate::core::utils::{U256_ONE, U256_ZERO, U64_MAX};
3use crate::executor::stack::executor::{
4    Accessed, Authorization, StackState, StackSubstateMetadata,
5};
6use crate::prelude::*;
7use crate::{ExitError, Transfer};
8use core::mem;
9use primitive_types::{H160, H256, U256};
10
11#[derive(Clone, Debug)]
12pub struct MemoryStackAccount {
13    pub basic: Basic,
14    pub code: Option<Vec<u8>>,
15    pub reset: bool,
16}
17
18#[derive(Clone, Debug)]
19pub struct MemoryStackSubstate<'config> {
20    metadata: StackSubstateMetadata<'config>,
21    parent: Option<Box<MemoryStackSubstate<'config>>>,
22    logs: Vec<Log>,
23    accounts: BTreeMap<H160, MemoryStackAccount>,
24    storages: BTreeMap<(H160, H256), H256>,
25    tstorages: BTreeMap<(H160, H256), U256>,
26    deletes: BTreeSet<H160>,
27    creates: BTreeSet<H160>,
28}
29
30impl<'config> MemoryStackSubstate<'config> {
31    #[must_use]
32    pub const fn new(metadata: StackSubstateMetadata<'config>) -> Self {
33        Self {
34            metadata,
35            parent: None::<Box<_>>,
36            logs: Vec::new(),
37            accounts: BTreeMap::new(),
38            storages: BTreeMap::new(),
39            tstorages: BTreeMap::new(),
40            deletes: BTreeSet::new(),
41            creates: BTreeSet::new(),
42        }
43    }
44
45    #[must_use]
46    #[allow(clippy::missing_const_for_fn)]
47    pub fn logs(&self) -> &[Log] {
48        &self.logs
49    }
50
51    pub const fn logs_mut(&mut self) -> &mut Vec<Log> {
52        &mut self.logs
53    }
54
55    #[must_use]
56    pub const fn metadata(&self) -> &StackSubstateMetadata<'config> {
57        &self.metadata
58    }
59
60    pub const fn metadata_mut(&mut self) -> &mut StackSubstateMetadata<'config> {
61        &mut self.metadata
62    }
63
64    /// Deconstruct the memory stack substate, return state to be applied. Panic if the
65    /// substate is not in the top-level substate.
66    ///
67    /// # Panics
68    /// Panic if parent presents
69    #[must_use]
70    pub fn deconstruct<B: Backend>(
71        mut self,
72        backend: &B,
73    ) -> (
74        impl IntoIterator<Item = Apply<impl IntoIterator<Item = (H256, H256)>>>,
75        impl IntoIterator<Item = Log>,
76    ) {
77        assert!(self.parent.is_none());
78
79        let mut applies = Vec::<Apply<BTreeMap<H256, H256>>>::new();
80
81        let mut addresses = BTreeSet::new();
82
83        for address in self.accounts.keys() {
84            addresses.insert(*address);
85        }
86
87        for (address, _) in self.storages.keys() {
88            addresses.insert(*address);
89        }
90
91        for address in addresses {
92            if self.deletes.contains(&address) {
93                continue;
94            }
95
96            let mut storage = BTreeMap::new();
97            for ((oa, ok), ov) in &self.storages {
98                if *oa == address {
99                    storage.insert(*ok, *ov);
100                }
101            }
102
103            let apply = {
104                let account = if self.is_created(address) {
105                    let account = self
106                        .accounts
107                        .get_mut(&address)
108                        .expect("New account was just inserted");
109                    // Reset storage for CREATE call as initially it's always should be empty.
110                    // NOTE: related to `ethereum-tests`: `stSStoreTest/InitCollisionParis.json`
111                    account.reset = true;
112                    account
113                } else {
114                    self.account_mut(address, backend)
115                };
116
117                Apply::Modify {
118                    address,
119                    basic: account.basic.clone(),
120                    code: account.code.clone(),
121                    storage,
122                    reset_storage: account.reset,
123                }
124            };
125
126            applies.push(apply);
127        }
128
129        for address in self.deletes {
130            applies.push(Apply::Delete { address });
131        }
132
133        (applies, self.logs)
134    }
135
136    pub fn enter(&mut self, gas_limit: u64, is_static: bool) {
137        let mut entering = Self {
138            metadata: self.metadata.spit_child(gas_limit, is_static),
139            parent: None,
140            logs: Vec::new(),
141            accounts: BTreeMap::new(),
142            storages: BTreeMap::new(),
143            tstorages: BTreeMap::new(),
144            deletes: BTreeSet::new(),
145            creates: BTreeSet::new(),
146        };
147        mem::swap(&mut entering, self);
148
149        self.parent = Some(Box::new(entering));
150    }
151
152    /// Exit commit represent successful execution of the `substate`.
153    ///
154    /// It includes:
155    /// - swallow commit
156    ///   - gas recording
157    ///   - warmed accesses merging
158    /// - logs merging
159    /// - for account existed from substate with reset flag, remove storages by keys
160    /// - merge substate data: accounts, storages, tstorages, deletes, creates
161    ///
162    /// # Errors
163    /// Return `ExitError` that is thrown by gasometer gas calculation errors.
164    ///
165    /// # Panics
166    /// Cannot commit on root `substate` i.e. it forces to panic.
167    pub fn exit_commit(&mut self) -> Result<(), ExitError> {
168        let mut exited = *self.parent.take().expect("Cannot commit on root substate");
169        mem::swap(&mut exited, self);
170
171        self.metadata.swallow_commit(exited.metadata)?;
172        self.logs.append(&mut exited.logs);
173
174        let mut resets = BTreeSet::new();
175        for (address, account) in &exited.accounts {
176            if account.reset {
177                resets.insert(*address);
178            }
179        }
180        let mut reset_keys = BTreeSet::new();
181        for (address, key) in self.storages.keys() {
182            if resets.contains(address) {
183                reset_keys.insert((*address, *key));
184            }
185        }
186        for (address, key) in reset_keys {
187            self.storages.remove(&(address, key));
188        }
189
190        self.accounts.append(&mut exited.accounts);
191        self.storages.append(&mut exited.storages);
192        self.tstorages.append(&mut exited.tstorages);
193        self.deletes.append(&mut exited.deletes);
194        self.creates.append(&mut exited.creates);
195        Ok(())
196    }
197
198    /// Exit revert. Represents revert execution of the `substate`.
199    ///
200    /// # Errors
201    /// Return `ExitError`
202    ///
203    /// # Panics
204    /// Cannot discard on root substate
205    pub fn exit_revert(&mut self) -> Result<(), ExitError> {
206        let mut exited = *self.parent.take().expect("Cannot discard on root substate");
207        mem::swap(&mut exited, self);
208        self.metadata.swallow_revert(&exited.metadata)?;
209        Ok(())
210    }
211
212    /// Exit discard. Represents discard execution of the `substate`.
213    ///
214    /// # Errors
215    /// Return `ExitError`. At the momoet it's not throwing any real error.
216    ///
217    /// # Panics
218    /// Cannot discard on root substate
219    pub fn exit_discard(&mut self) -> Result<(), ExitError> {
220        let mut exited = *self.parent.take().expect("Cannot discard on root substate");
221        mem::swap(&mut exited, self);
222        self.metadata.swallow_discard(&exited.metadata);
223        Ok(())
224    }
225
226    pub fn known_account(&self, address: H160) -> Option<&MemoryStackAccount> {
227        self.accounts.get(&address).map_or_else(
228            || {
229                self.parent
230                    .as_ref()
231                    .and_then(|parent| parent.known_account(address))
232            },
233            Some,
234        )
235    }
236
237    #[must_use]
238    pub fn known_basic(&self, address: H160) -> Option<Basic> {
239        self.known_account(address).map(|acc| acc.basic.clone())
240    }
241
242    #[must_use]
243    pub fn known_code(&self, address: H160) -> Option<Vec<u8>> {
244        self.known_account(address).and_then(|acc| acc.code.clone())
245    }
246
247    #[must_use]
248    pub fn known_empty(&self, address: H160) -> Option<bool> {
249        if let Some(account) = self.known_account(address) {
250            if account.basic.balance != U256_ZERO {
251                return Some(false);
252            }
253
254            if account.basic.nonce != U256_ZERO {
255                return Some(false);
256            }
257
258            if let Some(code) = &account.code {
259                return Some(
260                    account.basic.balance == U256_ZERO
261                        && account.basic.nonce == U256_ZERO
262                        && code.is_empty(),
263                );
264            }
265        }
266
267        None
268    }
269
270    #[must_use]
271    pub fn known_storage(&self, address: H160, key: H256) -> Option<H256> {
272        if let Some(value) = self.storages.get(&(address, key)) {
273            return Some(*value);
274        }
275
276        if let Some(account) = self.accounts.get(&address) {
277            if account.reset {
278                return Some(H256::default());
279            }
280        }
281
282        if let Some(parent) = self.parent.as_ref() {
283            return parent.known_storage(address, key);
284        }
285
286        None
287    }
288
289    #[must_use]
290    pub fn known_original_storage(&self, address: H160) -> Option<H256> {
291        if let Some(account) = self.accounts.get(&address) {
292            if account.reset {
293                return Some(H256::default());
294            }
295        }
296
297        if let Some(parent) = self.parent.as_ref() {
298            return parent.known_original_storage(address);
299        }
300
301        None
302    }
303
304    #[must_use]
305    pub fn is_cold(&self, address: H160) -> bool {
306        self.recursive_is_cold(&|a| a.accessed_addresses.contains(&address))
307    }
308
309    #[must_use]
310    pub fn is_storage_cold(&self, address: H160, key: H256) -> bool {
311        self.recursive_is_cold(&|a: &Accessed| a.accessed_storage.contains(&(address, key)))
312    }
313
314    fn recursive_is_cold<F: Fn(&Accessed) -> bool>(&self, f: &F) -> bool {
315        let local_is_accessed = self.metadata.accessed().as_ref().is_some_and(f);
316        if local_is_accessed {
317            false
318        } else {
319            self.parent.as_ref().is_none_or(|p| p.recursive_is_cold(f))
320        }
321    }
322
323    #[must_use]
324    pub fn deleted(&self, address: H160) -> bool {
325        if self.deletes.contains(&address) {
326            return true;
327        }
328
329        if let Some(parent) = self.parent.as_ref() {
330            return parent.deleted(address);
331        }
332
333        false
334    }
335
336    #[allow(clippy::map_entry)]
337    fn account_mut<B: Backend>(&mut self, address: H160, backend: &B) -> &mut MemoryStackAccount {
338        if !self.accounts.contains_key(&address) {
339            let account = self.known_account(address).cloned().map_or_else(
340                || MemoryStackAccount {
341                    basic: backend.basic(address),
342                    code: None::<Vec<_>>,
343                    reset: false,
344                },
345                |mut v| {
346                    v.reset = false;
347                    v
348                },
349            );
350            self.accounts.insert(address, account);
351        }
352
353        self.accounts
354            .get_mut(&address)
355            .expect("New account was just inserted")
356    }
357
358    /// # Errors
359    /// Return `ExitError`
360    pub fn inc_nonce<B: Backend>(&mut self, address: H160, backend: &B) -> Result<(), ExitError> {
361        let nonce = &mut self.account_mut(address, backend).basic.nonce;
362        if *nonce >= U64_MAX {
363            return Err(ExitError::MaxNonce);
364        }
365        *nonce += U256_ONE;
366        Ok(())
367    }
368
369    pub fn set_storage(&mut self, address: H160, key: H256, value: H256) {
370        #[cfg(feature = "print-debug")]
371        println!("    [SSTORE {address:?}] {key:?}:{value:?}");
372        self.storages.insert((address, key), value);
373    }
374
375    pub fn reset_storage<B: Backend>(&mut self, address: H160, backend: &B) {
376        let mut removing = Vec::new();
377
378        for (oa, ok) in self.storages.keys() {
379            if *oa == address {
380                removing.push(*ok);
381            }
382        }
383
384        for ok in removing {
385            self.storages.remove(&(address, ok));
386        }
387        self.account_mut(address, backend).reset = true;
388    }
389
390    pub fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) {
391        self.logs.push(Log {
392            address,
393            topics,
394            data,
395        });
396    }
397
398    pub fn set_deleted(&mut self, address: H160) {
399        self.deletes.insert(address);
400    }
401
402    pub fn set_created(&mut self, address: H160) {
403        self.creates.insert(address);
404    }
405
406    #[must_use]
407    pub fn is_created(&self, address: H160) -> bool {
408        if self.creates.contains(&address) {
409            return true;
410        }
411
412        if let Some(parent) = self.parent.as_ref() {
413            return parent.is_created(address);
414        }
415
416        false
417    }
418
419    pub fn set_code<B: Backend>(&mut self, address: H160, code: Vec<u8>, backend: &B) {
420        self.account_mut(address, backend).code = Some(code);
421    }
422
423    /// # Errors
424    /// Return `ExitError`
425    pub fn transfer<B: Backend>(
426        &mut self,
427        transfer: &Transfer,
428        backend: &B,
429    ) -> Result<(), ExitError> {
430        {
431            let source = self.account_mut(transfer.source, backend);
432            if source.basic.balance < transfer.value {
433                return Err(ExitError::OutOfFund);
434            }
435            source.basic.balance -= transfer.value;
436        }
437
438        {
439            let target = self.account_mut(transfer.target, backend);
440            target.basic.balance = target.basic.balance.saturating_add(transfer.value);
441        }
442
443        Ok(())
444    }
445
446    /// Only needed for jsontests.
447    /// # Errors
448    /// Return `ExitError`
449    pub fn withdraw<B: Backend>(
450        &mut self,
451        address: H160,
452        value: U256,
453        backend: &B,
454    ) -> Result<(), ExitError> {
455        let source = self.account_mut(address, backend);
456        if source.basic.balance < value {
457            return Err(ExitError::OutOfFund);
458        }
459        source.basic.balance -= value;
460
461        Ok(())
462    }
463
464    // Only needed for jsontests.
465    pub fn deposit<B: Backend>(&mut self, address: H160, value: U256, backend: &B) {
466        let target = self.account_mut(address, backend);
467        target.basic.balance = target.basic.balance.saturating_add(value);
468    }
469
470    pub fn reset_balance<B: Backend>(&mut self, address: H160, backend: &B) {
471        self.account_mut(address, backend).basic.balance = U256_ZERO;
472    }
473
474    pub fn touch<B: Backend>(&mut self, address: H160, backend: &B) {
475        self.account_mut(address, backend);
476    }
477
478    #[must_use]
479    pub fn get_tstorage(&self, address: H160, key: H256) -> U256 {
480        self.known_tstorage(address, key).unwrap_or_default()
481    }
482
483    #[must_use]
484    pub fn known_tstorage(&self, address: H160, key: H256) -> Option<U256> {
485        if let Some(value) = self.tstorages.get(&(address, key)) {
486            return Some(*value);
487        }
488        if let Some(parent) = self.parent.as_ref() {
489            return parent.known_tstorage(address, key);
490        }
491        None
492    }
493
494    pub fn set_tstorage(&mut self, address: H160, key: H256, value: U256) {
495        self.tstorages.insert((address, key), value);
496    }
497
498    /// Get authority target from the current state. If it's `None` just take a look
499    /// recursively in the parent state.
500    fn get_authority_target_recursive(&self, authority: H160) -> Option<H160> {
501        if let Some(target) = self
502            .metadata
503            .accessed()
504            .as_ref()
505            .and_then(|accessed| accessed.get_authority_target(authority))
506        {
507            return Some(target);
508        }
509        self.parent
510            .as_ref()
511            .and_then(|p| p.get_authority_target_recursive(authority))
512    }
513}
514
515#[derive(Clone, Debug)]
516pub struct MemoryStackState<'backend, 'config, B> {
517    backend: &'backend B,
518    substate: MemoryStackSubstate<'config>,
519}
520
521impl<B: Backend> Backend for MemoryStackState<'_, '_, B> {
522    fn gas_price(&self) -> U256 {
523        self.backend.gas_price()
524    }
525    fn origin(&self) -> H160 {
526        self.backend.origin()
527    }
528    fn block_hash(&self, number: U256) -> H256 {
529        self.backend.block_hash(number)
530    }
531    fn block_number(&self) -> U256 {
532        self.backend.block_number()
533    }
534    fn block_coinbase(&self) -> H160 {
535        self.backend.block_coinbase()
536    }
537    fn block_timestamp(&self) -> U256 {
538        self.backend.block_timestamp()
539    }
540    fn block_difficulty(&self) -> U256 {
541        self.backend.block_difficulty()
542    }
543    fn block_randomness(&self) -> Option<H256> {
544        self.backend.block_randomness()
545    }
546    fn block_gas_limit(&self) -> U256 {
547        self.backend.block_gas_limit()
548    }
549    fn block_base_fee_per_gas(&self) -> U256 {
550        self.backend.block_base_fee_per_gas()
551    }
552
553    fn chain_id(&self) -> U256 {
554        self.backend.chain_id()
555    }
556
557    fn exists(&self, address: H160) -> bool {
558        self.substate.known_account(address).is_some() || self.backend.exists(address)
559    }
560
561    fn basic(&self, address: H160) -> Basic {
562        self.substate
563            .known_basic(address)
564            .unwrap_or_else(|| self.backend.basic(address))
565    }
566
567    fn code(&self, address: H160) -> Vec<u8> {
568        self.substate
569            .known_code(address)
570            .unwrap_or_else(|| self.backend.code(address))
571    }
572
573    fn storage(&self, address: H160, key: H256) -> H256 {
574        self.substate
575            .known_storage(address, key)
576            .unwrap_or_else(|| self.backend.storage(address, key))
577    }
578
579    fn is_empty_storage(&self, address: H160) -> bool {
580        self.backend.is_empty_storage(address)
581    }
582
583    fn original_storage(&self, address: H160, key: H256) -> Option<H256> {
584        if let Some(value) = self.substate.known_original_storage(address) {
585            return Some(value);
586        }
587
588        self.backend.original_storage(address, key)
589    }
590    fn blob_gas_price(&self) -> Option<u128> {
591        self.backend.blob_gas_price()
592    }
593    fn get_blob_hash(&self, index: usize) -> Option<U256> {
594        self.backend.get_blob_hash(index)
595    }
596}
597
598impl<'config, B: Backend> StackState<'config> for MemoryStackState<'_, 'config, B> {
599    fn metadata(&self) -> &StackSubstateMetadata<'config> {
600        self.substate.metadata()
601    }
602
603    fn metadata_mut(&mut self) -> &mut StackSubstateMetadata<'config> {
604        self.substate.metadata_mut()
605    }
606
607    fn enter(&mut self, gas_limit: u64, is_static: bool) {
608        self.substate.enter(gas_limit, is_static);
609    }
610
611    fn exit_commit(&mut self) -> Result<(), ExitError> {
612        self.substate.exit_commit()
613    }
614
615    fn exit_revert(&mut self) -> Result<(), ExitError> {
616        self.substate.exit_revert()
617    }
618
619    fn exit_discard(&mut self) -> Result<(), ExitError> {
620        self.substate.exit_discard()
621    }
622
623    fn is_empty(&self, address: H160) -> bool {
624        if let Some(known_empty) = self.substate.known_empty(address) {
625            return known_empty;
626        }
627
628        self.backend.basic(address).balance == U256_ZERO
629            && self.backend.basic(address).nonce == U256_ZERO
630            && self.backend.code(address).is_empty()
631    }
632
633    fn deleted(&self, address: H160) -> bool {
634        self.substate.deleted(address)
635    }
636
637    fn is_cold(&self, address: H160) -> bool {
638        self.substate.is_cold(address)
639    }
640
641    fn is_storage_cold(&self, address: H160, key: H256) -> bool {
642        self.substate.is_storage_cold(address, key)
643    }
644
645    fn inc_nonce(&mut self, address: H160) -> Result<(), ExitError> {
646        self.substate.inc_nonce(address, self.backend)
647    }
648
649    fn set_storage(&mut self, address: H160, key: H256, value: H256) {
650        self.substate.set_storage(address, key, value);
651    }
652
653    fn reset_storage(&mut self, address: H160) {
654        self.substate.reset_storage(address, self.backend);
655    }
656
657    fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) {
658        self.substate.log(address, topics, data);
659    }
660
661    fn set_deleted(&mut self, address: H160) {
662        self.substate.set_deleted(address);
663    }
664
665    fn set_created(&mut self, address: H160) {
666        self.substate.set_created(address);
667    }
668
669    fn is_created(&self, address: H160) -> bool {
670        self.substate.is_created(address)
671    }
672
673    fn set_code(&mut self, address: H160, code: Vec<u8>) {
674        self.substate.set_code(address, code, self.backend);
675    }
676
677    fn transfer(&mut self, transfer: Transfer) -> Result<(), ExitError> {
678        self.substate.transfer(&transfer, self.backend)
679    }
680
681    fn reset_balance(&mut self, address: H160) {
682        self.substate.reset_balance(address, self.backend);
683    }
684
685    fn touch(&mut self, address: H160) {
686        self.substate.touch(address, self.backend);
687    }
688
689    fn tload(&mut self, address: H160, index: H256) -> Result<U256, ExitError> {
690        Ok(self.substate.get_tstorage(address, index))
691    }
692
693    fn tstore(&mut self, address: H160, index: H256, value: U256) -> Result<(), ExitError> {
694        self.substate.set_tstorage(address, index, value);
695        Ok(())
696    }
697
698    /// EIP-7702 - check is authority cold.
699    fn is_authority_cold(&mut self, address: H160) -> Option<bool> {
700        self.get_authority_target(address)
701            .map(|target| self.is_cold(target))
702    }
703
704    /// Get authority target (EIP-7702) - delegated address.
705    /// First we're trying to get authority target from the cache recursively with parent state,
706    /// if it's not found we get code for the authority address and check if it's delegation
707    /// designator. If it's true, we add result to cache and return delegated target address.
708    fn get_authority_target(&mut self, authority: H160) -> Option<H160> {
709        // Read from cache
710        if let Some(target_address) = self.substate.get_authority_target_recursive(authority) {
711            Some(target_address)
712        } else {
713            // If not found in the cache
714            // Get code for delegated address
715            let authority_code = self.code(authority);
716            if let Some(target) = Authorization::get_delegated_address(&authority_code) {
717                // Add to cache
718                self.metadata_mut().add_authority(authority, target);
719                return Some(target);
720            }
721            None
722        }
723    }
724}
725
726impl<'backend, 'config, B: Backend> MemoryStackState<'backend, 'config, B> {
727    pub const fn new(metadata: StackSubstateMetadata<'config>, backend: &'backend B) -> Self {
728        Self {
729            backend,
730            substate: MemoryStackSubstate::new(metadata),
731        }
732    }
733
734    /// Returns a mutable reference to an account given its address
735    pub fn account_mut(&mut self, address: H160) -> &mut MemoryStackAccount {
736        self.substate.account_mut(address, self.backend)
737    }
738
739    #[must_use]
740    pub fn deconstruct(
741        self,
742    ) -> (
743        impl IntoIterator<Item = Apply<impl IntoIterator<Item = (H256, H256)>>>,
744        impl IntoIterator<Item = Log>,
745    ) {
746        self.substate.deconstruct(self.backend)
747    }
748
749    /// # Errors
750    /// Return `ExitError`
751    pub fn withdraw(&mut self, address: H160, value: U256) -> Result<(), ExitError> {
752        self.substate.withdraw(address, value, self.backend)
753    }
754
755    pub fn deposit(&mut self, address: H160, value: U256) {
756        self.substate.deposit(address, value, self.backend);
757    }
758}