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;
33use cfx_types::{Address, CreateContractAddressType, Space, H256, U256};
34use std::sync::Arc;
35
36#[derive(Debug)]
37/// Result of externalities create function.
38pub enum ContractCreateResult {
39 /// Returned when creation was successful.
40 /// Contains an address of newly created contract and gas left.
41 Created(Address, U256),
42 /// Returned when contract creation failed.
43 /// Returns the reason so block trace can record it.
44 Failed(Error),
45 /// Reverted with REVERT.
46 Reverted(U256, ReturnData),
47}
48
49#[derive(Debug)]
50/// Result of externalities call function.
51pub enum MessageCallResult {
52 /// Returned when message call was successful.
53 /// Contains gas left and output data.
54 Success(U256, ReturnData),
55 /// Returned when message call failed.
56 /// Returns the reason so block trace can record it.
57 Failed(Error),
58 /// Returned when message call was reverted.
59 /// Contains gas left and output data.
60 Reverted(U256, ReturnData),
61}
62
63#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
64pub enum BlockHashSource {
65 /// Before CIP-133, block hash is read from `Env`, same as the Ethereum
66 Env,
67 /// After CIP-133, block hash is read from `State`
68 State,
69}
70
71/// Context for VMs
72pub trait Context {
73 /// Returns a value for given key.
74 fn storage_at(&self, key: &[u8]) -> Result<U256>;
75
76 /// Returns a value for given key.
77 fn origin_storage_at(&self, key: &[u8]) -> Result<Option<U256>>;
78
79 /// Stores a value for given key.
80 fn set_storage(&mut self, key: Vec<u8>, value: U256) -> Result<()>;
81
82 /// Returns a value for given key.
83 fn transient_storage_at(&self, key: &Vec<u8>) -> Result<U256>;
84
85 /// Stores a value for given key.
86 fn transient_set_storage(
87 &mut self, key: Vec<u8>, value: U256,
88 ) -> Result<()>;
89
90 /// Determine whether an account exists.
91 fn exists(&self, address: &Address) -> Result<bool>;
92
93 /// Determine whether an account exists and is not null (zero
94 /// balance/nonce, no code).
95 fn exists_and_not_null(&self, address: &Address) -> Result<bool>;
96
97 /// Balance of the origin account.
98 fn origin_balance(&self) -> Result<U256>;
99
100 /// Returns address balance.
101 fn balance(&self, address: &Address) -> Result<U256>;
102
103 /// Returns the hash of one of the 256 most recent complete blocks.
104 fn blockhash(&mut self, number: &U256) -> Result<H256>;
105
106 /// Creates new contract.
107 ///
108 /// Returns gas_left and contract address if contract creation was
109 /// succesfull.
110 fn create(
111 &mut self, gas: &U256, value: &U256, code: &[u8],
112 address: CreateContractAddressType,
113 ) -> DbResult<::std::result::Result<ContractCreateResult, TrapKind>>;
114
115 /// Message call.
116 ///
117 /// Returns Err, if we run out of gas.
118 /// Otherwise returns call_result which contains gas left
119 /// and true if subcall was successful.
120 fn call(
121 &mut self, gas: &U256, sender_address: &Address,
122 receive_address: &Address, value: Option<U256>, data: &[u8],
123 code_address: &Address, call_type: CallType,
124 ) -> DbResult<::std::result::Result<MessageCallResult, TrapKind>>;
125
126 /// Returns code at given address
127 fn extcode(&self, address: &Address) -> Result<Option<Arc<Bytes>>>;
128
129 /// Returns code hash at given address
130 fn extcodehash(&self, address: &Address) -> Result<H256>;
131
132 /// Returns code size at given address
133 fn extcodesize(&self, address: &Address) -> Result<usize>;
134
135 /// Creates log entry with given topics and data
136 fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> Result<()>;
137
138 fn refund(&mut self, refund_gas: i64);
139
140 /// Should be called when transaction calls `RETURN` opcode.
141 /// Returns gas_left if cost of returning the data is not too high.
142 fn ret(
143 self, gas: &U256, data: &ReturnData, apply_state: bool,
144 ) -> Result<U256>;
145
146 /// Should be called when contract commits suicide.
147 /// Address to which funds should be refunded.
148 fn suicide(&mut self, refund_address: &Address) -> Result<()>;
149
150 /// Returns specification.
151 fn spec(&self) -> &Spec;
152
153 /// Returns environment.
154 fn env(&self) -> &Env;
155
156 /// Returns the chain ID of the blockchain
157 fn chain_id(&self) -> u64;
158
159 /// Returns the space of the blockchain
160 fn space(&self) -> Space;
161
162 /// Returns current depth of execution.
163 ///
164 /// If contract A calls contract B, and contract B calls C,
165 /// then A depth is 0, B is 1, C is 2 and so on.
166 fn depth(&self) -> usize;
167
168 fn is_warm_account(&self, account: Address) -> bool;
169
170 fn is_warm_storage_entry(&self, key: &H256) -> Result<bool>;
171
172 fn trace_step(&mut self, interpreter: &dyn InterpreterInfo) {
173 let _ = interpreter;
174 }
175
176 fn trace_step_end(&mut self, interpreter: &dyn InterpreterInfo) {
177 let _ = interpreter;
178 }
179
180 fn opcode_trace_enabled(&self) -> bool { false }
181
182 /// Check if running in static context.
183 fn is_static(&self) -> bool;
184
185 /// Check if running in static context or reentrancy context
186 fn is_static_or_reentrancy(&self) -> bool;
187
188 fn blockhash_source(&self) -> BlockHashSource;
189}