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}