cita_evm/
extmock.rs

1use super::err;
2use super::ext;
3use super::interpreter;
4use super::opcodes;
5use ethereum_types::{Address, H256, U256};
6use keccak_hash;
7use std::collections::BTreeMap;
8
9#[derive(Clone, Default)]
10pub struct Account {
11    pub balance: U256,
12    pub code: Vec<u8>,
13    pub nonce: U256,
14    pub storage: BTreeMap<H256, H256>,
15}
16
17#[derive(Default)]
18pub struct DataProviderMock {
19    pub db: BTreeMap<Address, Account>,
20    pub db_origin: BTreeMap<Address, Account>,
21    pub refund: BTreeMap<Address, u64>,
22}
23
24impl ext::DataProvider for DataProviderMock {
25    fn get_balance(&self, address: &Address) -> U256 {
26        self.db.get(address).map_or(U256::zero(), |v| v.balance)
27    }
28
29    fn add_refund(&mut self, address: &Address, n: u64) {
30        self.refund.entry(*address).and_modify(|v| *v += n).or_insert(n);
31    }
32
33    fn sub_refund(&mut self, address: &Address, n: u64) {
34        self.refund.entry(*address).and_modify(|v| *v -= n).or_insert(n);
35    }
36
37    fn get_refund(&self, address: &Address) -> u64 {
38        self.refund.get(address).map_or(0, |v| *v)
39    }
40
41    fn get_code_size(&self, address: &Address) -> u64 {
42        self.db.get(address).map_or(0, |v| v.code.len() as u64)
43    }
44
45    fn get_code(&self, address: &Address) -> Vec<u8> {
46        self.db.get(address).map_or(vec![], |v| v.code.clone())
47    }
48
49    fn get_code_hash(&self, address: &Address) -> H256 {
50        self.db
51            .get(address)
52            .map_or(H256::zero(), |v| self.sha3(v.code.as_slice()))
53    }
54
55    fn get_block_hash(&self, _: &U256) -> H256 {
56        H256::zero()
57    }
58
59    fn get_storage(&self, address: &Address, key: &H256) -> H256 {
60        self.db
61            .get(address)
62            .map_or(H256::zero(), |v| v.storage.get(key).map_or(H256::zero(), |&v| v))
63    }
64
65    fn set_storage(&mut self, address: &Address, key: H256, value: H256) {
66        self.db
67            .entry(*address)
68            .or_insert_with(Account::default)
69            .storage
70            .insert(key, value);
71    }
72
73    fn get_storage_origin(&self, address: &Address, key: &H256) -> H256 {
74        self.db_origin
75            .get(address)
76            .map_or(H256::zero(), |v| v.storage.get(key).map_or(H256::zero(), |&v| v))
77    }
78
79    fn set_storage_origin(&mut self, address: &Address, key: H256, value: H256) {
80        self.db_origin
81            .entry(*address)
82            .or_insert_with(Account::default)
83            .storage
84            .insert(key, value);
85    }
86
87    fn selfdestruct(&mut self, address: &Address, _: &Address) -> bool {
88        self.db.remove(address);
89        true
90    }
91
92    fn sha3(&self, data: &[u8]) -> H256 {
93        keccak_hash::keccak(data)
94    }
95
96    fn is_empty(&self, address: &Address) -> bool {
97        self.db.get(address).is_none()
98    }
99
100    fn call(
101        &self,
102        opcode: opcodes::OpCode,
103        params: interpreter::InterpreterParams,
104    ) -> (Result<interpreter::InterpreterResult, err::Error>) {
105        match opcode {
106            opcodes::OpCode::CALL => {
107                let mut it = interpreter::Interpreter::new(
108                    interpreter::Context::default(),
109                    interpreter::InterpreterConf::default(),
110                    Box::new(DataProviderMock::default()),
111                    params,
112                );
113                let mut data_provider = DataProviderMock::default();
114                data_provider.db = self.db.clone();
115                it.data_provider = Box::new(data_provider);
116                it.run()
117            }
118            _ => unimplemented!(),
119        }
120    }
121}