cfx_vm_types/context.rs
1// Copyright 2015-2018 Parity Technologies (UK) Ltd.
2// This file is part of Parity.
3
4// Parity is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity. If not, see <http://www.gnu.org/licenses/>.
16
17// Copyright 2019 Conflux Foundation. All rights reserved.
18// Conflux is free software and distributed under GNU General Public License.
19// See http://www.gnu.org/licenses/
20
21//! Interface for Evm externalities.
22
23use super::{
24 call_create_type::CallType,
25 env::Env,
26 error::{Result, TrapKind},
27 return_data::ReturnData,
28 spec::Spec,
29 Error, InterpreterInfo,
30};
31use cfx_bytes::Bytes;
32use cfx_db_errors::statedb::Result as DbResult;
33pub use cfx_types::{
34 cal_contract_address as contract_address,
35 CreateContractAddressType as CreateContractAddress,
36};
37use cfx_types::{Address, Space, H256, U256};
38use std::sync::Arc;
39
40#[derive(Debug)]
41/// Result of externalities create function.
42pub enum ContractCreateResult {
43 /// Returned when creation was successful.
44 /// Contains an address of newly created contract and gas left.
45 Created(Address, U256),
46 /// Returned when contract creation failed.
47 /// Returns the reason so block trace can record it.
48 Failed(Error),
49 /// Reverted with REVERT.
50 Reverted(U256, ReturnData),
51}
52
53#[derive(Debug)]
54/// Result of externalities call function.
55pub enum MessageCallResult {
56 /// Returned when message call was successful.
57 /// Contains gas left and output data.
58 Success(U256, ReturnData),
59 /// Returned when message call failed.
60 /// Returns the reason so block trace can record it.
61 Failed(Error),
62 /// Returned when message call was reverted.
63 /// Contains gas left and output data.
64 Reverted(U256, ReturnData),
65}
66
67#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
68pub enum BlockHashSource {
69 /// Before CIP-133, block hash is read from `Env`, same as the Ethereum
70 Env,
71 /// After CIP-133, block hash is read from `State`
72 State,
73}
74
75/// Context for VMs
76pub trait Context {
77 /// Returns a value for given key.
78 fn storage_at(&self, key: &[u8]) -> Result<U256>;
79
80 /// Returns a value for given key.
81 fn origin_storage_at(&self, key: &[u8]) -> Result<Option<U256>>;
82
83 /// Stores a value for given key.
84 fn set_storage(&mut self, key: Vec<u8>, value: U256) -> Result<()>;
85
86 /// Returns a value for given key.
87 fn transient_storage_at(&self, key: &Vec<u8>) -> Result<U256>;
88
89 /// Stores a value for given key.
90 fn transient_set_storage(
91 &mut self, key: Vec<u8>, value: U256,
92 ) -> Result<()>;
93
94 /// Determine whether an account exists.
95 fn exists(&self, address: &Address) -> Result<bool>;
96
97 /// Determine whether an account exists and is not null (zero
98 /// balance/nonce, no code).
99 fn exists_and_not_null(&self, address: &Address) -> Result<bool>;
100
101 /// Balance of the origin account.
102 fn origin_balance(&self) -> Result<U256>;
103
104 /// Returns address balance.
105 fn balance(&self, address: &Address) -> Result<U256>;
106
107 /// Returns the hash of one of the 256 most recent complete blocks.
108 fn blockhash(&mut self, number: &U256) -> Result<H256>;
109
110 /// Creates new contract.
111 ///
112 /// Returns gas_left and contract address if contract creation was
113 /// succesfull.
114 fn create(
115 &mut self, gas: &U256, value: &U256, code: &[u8],
116 address: CreateContractAddress,
117 ) -> DbResult<::std::result::Result<ContractCreateResult, TrapKind>>;
118
119 /// Message call.
120 ///
121 /// Returns Err, if we run out of gas.
122 /// Otherwise returns call_result which contains gas left
123 /// and true if subcall was successful.
124 fn call(
125 &mut self, gas: &U256, sender_address: &Address,
126 receive_address: &Address, value: Option<U256>, data: &[u8],
127 code_address: &Address, call_type: CallType,
128 ) -> DbResult<::std::result::Result<MessageCallResult, TrapKind>>;
129
130 /// Returns code at given address
131 fn extcode(&self, address: &Address) -> Result<Option<Arc<Bytes>>>;
132
133 /// Returns code hash at given address
134 fn extcodehash(&self, address: &Address) -> Result<H256>;
135
136 /// Returns code size at given address
137 fn extcodesize(&self, address: &Address) -> Result<usize>;
138
139 /// Creates log entry with given topics and data
140 fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> Result<()>;
141
142 fn refund(&mut self, refund_gas: i64);
143
144 /// Should be called when transaction calls `RETURN` opcode.
145 /// Returns gas_left if cost of returning the data is not too high.
146 fn ret(
147 self, gas: &U256, data: &ReturnData, apply_state: bool,
148 ) -> Result<U256>;
149
150 /// Should be called when contract commits suicide.
151 /// Address to which funds should be refunded.
152 fn suicide(&mut self, refund_address: &Address) -> Result<()>;
153
154 /// Returns specification.
155 fn spec(&self) -> &Spec;
156
157 /// Returns environment.
158 fn env(&self) -> &Env;
159
160 /// Returns the chain ID of the blockchain
161 fn chain_id(&self) -> u64;
162
163 /// Returns the space of the blockchain
164 fn space(&self) -> Space;
165
166 /// Returns current depth of execution.
167 ///
168 /// If contract A calls contract B, and contract B calls C,
169 /// then A depth is 0, B is 1, C is 2 and so on.
170 fn depth(&self) -> usize;
171
172 fn is_warm_account(&self, account: Address) -> bool;
173
174 fn is_warm_storage_entry(&self, key: &H256) -> Result<bool>;
175
176 fn trace_step(&mut self, interpreter: &dyn InterpreterInfo) {
177 let _ = interpreter;
178 }
179
180 fn trace_step_end(&mut self, interpreter: &dyn InterpreterInfo) {
181 let _ = interpreter;
182 }
183
184 fn opcode_trace_enabled(&self) -> bool { false }
185
186 /// Check if running in static context.
187 fn is_static(&self) -> bool;
188
189 /// Check if running in static context or reentrancy context
190 fn is_static_or_reentrancy(&self) -> bool;
191
192 fn blockhash_source(&self) -> BlockHashSource;
193}