1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use super::{AccountEntry, OverlayAccount};
use cfx_rpc_eth_types::{AccountOverride, AccountStateOverrideMode};
use cfx_types::{AddressWithSpace, Space, H256, U256};
use primitives::{Account, StorageValue};
use std::{collections::HashMap, sync::Arc};

impl AccountEntry {
    pub fn from_loaded_with_override(
        address: &AddressWithSpace, account: Option<Account>,
        acc_overrides: &AccountOverride,
    ) -> Self {
        let acc = account.unwrap_or_else(|| Account::new_empty(address));
        AccountEntry::Cached(
            OverlayAccount::from_loaded_with_override(
                address,
                acc,
                acc_overrides,
            ),
            true,
        )
    }
}

impl OverlayAccount {
    pub fn from_loaded_with_override(
        address: &AddressWithSpace, account: Account,
        acc_overrides: &AccountOverride,
    ) -> Self {
        let mut acc = Self::from_loaded(address, account);

        if let Some(balance) = acc_overrides.balance {
            let curr_balance = *acc.balance();
            if curr_balance > U256::zero() {
                acc.sub_balance(&curr_balance);
            }
            acc.add_balance(&balance);
        }

        if let Some(nonce) = acc_overrides.nonce {
            acc.set_nonce(&U256::from(nonce));
        }

        if let Some(code) = acc_overrides.code.as_ref() {
            acc.init_code(code.clone(), address.address);
        }

        match &acc_overrides.state {
            AccountStateOverrideMode::State(state_override) => {
                acc.override_storage_read_cache(state_override, true);
            }
            AccountStateOverrideMode::Diff(diff) => {
                acc.override_storage_read_cache(diff, false);
            }
            AccountStateOverrideMode::None => {}
        }

        if acc_overrides.move_precompile_to.is_some() {
            // TODO: impl move precompile to logic
        }

        acc
    }

    fn override_storage_read_cache(
        &mut self, account_storage: &HashMap<H256, H256>,
        complete_override: bool,
    ) {
        assert!(self.storage_write_checkpoint.is_none());

        self.storage_overrided = complete_override;

        let read_cache = Arc::get_mut(&mut self.storage_read_cache)
            .expect("override should happen when no checkpoint")
            .get_mut();
        for (key, value) in account_storage {
            let key = key.as_bytes().to_vec();
            let value = U256::from_big_endian(value.as_bytes());
            let owner = if self.address.space == Space::Native {
                Some(self.address.address)
            } else {
                None
            };
            let storage_value = StorageValue { owner, value };
            read_cache.insert(key, storage_value);
        }
    }
}