EIP2929 with journaling + Yolov3 (#79)
This commit is contained in:
@@ -108,6 +108,7 @@ impl<'a> EvmTestClient<'a> {
|
||||
Some(ethereum::new_byzantium_to_constantinoplefixat5_test())
|
||||
}
|
||||
ForkSpec::Berlin => Some(ethereum::new_berlin_test()),
|
||||
ForkSpec::Yolo3 => Some(ethereum::new_yolo3_test()),
|
||||
ForkSpec::FrontierToHomesteadAt5
|
||||
| ForkSpec::HomesteadToDaoAt5
|
||||
| ForkSpec::HomesteadToEIP150At5
|
||||
|
||||
@@ -252,6 +252,11 @@ pub fn new_berlin_test() -> Spec {
|
||||
load(None, include_bytes!("../../res/ethereum/berlin_test.json"))
|
||||
}
|
||||
|
||||
/// Create a new YOLO spec
|
||||
pub fn new_yolo3_test() -> Spec {
|
||||
load(None, include_bytes!("../../res/ethereum/yolo3_test.json"))
|
||||
}
|
||||
|
||||
/// Create a new Musicoin-MCIP3-era spec.
|
||||
pub fn new_mcip3_test() -> Spec {
|
||||
load(None, include_bytes!("../../res/ethereum/mcip3_test.json"))
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
//! Transaction Execution environment.
|
||||
use bytes::{Bytes, BytesRef};
|
||||
use crossbeam_utils::thread;
|
||||
use ethereum_types::{Address, H256, U256, U512};
|
||||
use evm::{CallType, FinalizationResult, Finalize};
|
||||
use executed::ExecutionError;
|
||||
@@ -31,26 +30,10 @@ use trace::{self, Tracer, VMTracer};
|
||||
use transaction_ext::Transaction;
|
||||
use types::transaction::{Action, SignedTransaction};
|
||||
use vm::{
|
||||
self, ActionParams, ActionValue, CleanDustMode, CreateContractAddress, EnvInfo, ResumeCall,
|
||||
ResumeCreate, ReturnData, Schedule, TrapError,
|
||||
self, AccessList, ActionParams, ActionValue, CleanDustMode, CreateContractAddress, EnvInfo,
|
||||
ResumeCall, ResumeCreate, ReturnData, Schedule, TrapError,
|
||||
};
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
/// Roughly estimate what stack size each level of evm depth will use. (Debug build)
|
||||
const STACK_SIZE_PER_DEPTH: usize = 128 * 1024;
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
/// Roughly estimate what stack size each level of evm depth will use.
|
||||
const STACK_SIZE_PER_DEPTH: usize = 24 * 1024;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
/// Entry stack overhead prior to execution. (Debug build)
|
||||
const STACK_SIZE_ENTRY_OVERHEAD: usize = 100 * 1024;
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
/// Entry stack overhead prior to execution.
|
||||
const STACK_SIZE_ENTRY_OVERHEAD: usize = 20 * 1024;
|
||||
|
||||
#[cfg(any(test, feature = "test-helpers"))]
|
||||
/// Precompile that can never be prunned from state trie (0x3, only in tests)
|
||||
const UNPRUNABLE_PRECOMPILE_ADDRESS: Option<Address> = Some(ethereum_types::H160([
|
||||
@@ -252,6 +235,18 @@ pub struct CallCreateExecutive<'a> {
|
||||
}
|
||||
|
||||
impl<'a> CallCreateExecutive<'a> {
|
||||
/// Create new state with access list.
|
||||
pub fn new_substate(params: &ActionParams, schedule: &'a Schedule) -> Substate {
|
||||
if schedule.eip2929 {
|
||||
let mut substate = Substate::from_access_list(¶ms.access_list);
|
||||
substate.access_list.insert_address(params.address);
|
||||
substate.access_list.insert_address(params.sender);
|
||||
substate
|
||||
} else {
|
||||
Substate::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new call executive using raw data.
|
||||
pub fn new_call_raw(
|
||||
params: ActionParams,
|
||||
@@ -287,7 +282,8 @@ impl<'a> CallCreateExecutive<'a> {
|
||||
CallCreateExecutiveKind::CallBuiltin(params)
|
||||
} else {
|
||||
if params.code.is_some() {
|
||||
CallCreateExecutiveKind::ExecCall(params, Substate::new())
|
||||
let substate = Self::new_substate(¶ms, schedule);
|
||||
CallCreateExecutiveKind::ExecCall(params, substate)
|
||||
} else {
|
||||
CallCreateExecutiveKind::Transfer(params)
|
||||
}
|
||||
@@ -327,7 +323,8 @@ impl<'a> CallCreateExecutive<'a> {
|
||||
|
||||
let gas = params.gas;
|
||||
|
||||
let kind = CallCreateExecutiveKind::ExecCreate(params, Substate::new());
|
||||
let substate = Self::new_substate(¶ms, schedule);
|
||||
let kind = CallCreateExecutiveKind::ExecCreate(params, substate);
|
||||
|
||||
Self {
|
||||
info,
|
||||
@@ -457,6 +454,7 @@ impl<'a> CallCreateExecutive<'a> {
|
||||
}
|
||||
}
|
||||
state.revert_to_checkpoint();
|
||||
un_substate.access_list.rollback();
|
||||
}
|
||||
Ok(_) | Err(vm::Error::Internal(_)) => {
|
||||
state.discard_checkpoint();
|
||||
@@ -1188,7 +1186,14 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
});
|
||||
}
|
||||
|
||||
let mut substate = Substate::new();
|
||||
let mut access_list = AccessList::new(schedule.eip2929);
|
||||
if schedule.eip2929 {
|
||||
for (address, _) in self.machine.builtins() {
|
||||
access_list.insert_address(*address);
|
||||
}
|
||||
}
|
||||
|
||||
let mut substate = Substate::from_access_list(&access_list);
|
||||
|
||||
// NOTE: there can be no invalid transactions from this point.
|
||||
if !schedule.keep_unsigned_nonce || !t.is_unsigned() {
|
||||
@@ -1221,6 +1226,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
data: None,
|
||||
call_type: CallType::None,
|
||||
params_type: vm::ParamsType::Embedded,
|
||||
access_list: access_list,
|
||||
};
|
||||
let res = self.create(params, &mut substate, &mut tracer, &mut vm_tracer);
|
||||
let out = match &res {
|
||||
@@ -1243,6 +1249,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
data: Some(t.data.clone()),
|
||||
call_type: CallType::Call,
|
||||
params_type: vm::ParamsType::Separate,
|
||||
access_list: access_list,
|
||||
};
|
||||
let res = self.call(params, &mut substate, &mut tracer, &mut vm_tracer);
|
||||
let out = match &res {
|
||||
@@ -1325,48 +1332,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
result
|
||||
}
|
||||
|
||||
/// Calls contract function with given contract params, if the stack depth is above a threshold, create a new thread
|
||||
/// to execute it.
|
||||
pub fn call_with_crossbeam<T, V>(
|
||||
&mut self,
|
||||
params: ActionParams,
|
||||
substate: &mut Substate,
|
||||
stack_depth: usize,
|
||||
tracer: &mut T,
|
||||
vm_tracer: &mut V,
|
||||
) -> vm::Result<FinalizationResult>
|
||||
where
|
||||
T: Tracer,
|
||||
V: VMTracer,
|
||||
{
|
||||
let local_stack_size = ::io::LOCAL_STACK_SIZE.with(|sz| sz.get());
|
||||
let depth_threshold =
|
||||
local_stack_size.saturating_sub(STACK_SIZE_ENTRY_OVERHEAD) / STACK_SIZE_PER_DEPTH;
|
||||
|
||||
if stack_depth != depth_threshold {
|
||||
self.call_with_stack_depth(params, substate, stack_depth, tracer, vm_tracer)
|
||||
} else {
|
||||
thread::scope(|scope| {
|
||||
let stack_size = cmp::max(
|
||||
self.schedule.max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH,
|
||||
local_stack_size,
|
||||
);
|
||||
scope
|
||||
.builder()
|
||||
.stack_size(stack_size)
|
||||
.spawn(|_| {
|
||||
self.call_with_stack_depth(params, substate, stack_depth, tracer, vm_tracer)
|
||||
})
|
||||
.expect(
|
||||
"Sub-thread creation cannot fail; the host might run out of resources; qed",
|
||||
)
|
||||
.join()
|
||||
})
|
||||
.expect("Sub-thread never panics; qed")
|
||||
.expect("Sub-thread never panics; qed")
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls contract function with given contract params.
|
||||
pub fn call<T, V>(
|
||||
&mut self,
|
||||
@@ -1437,54 +1402,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
result
|
||||
}
|
||||
|
||||
/// Creates contract with given contract params, if the stack depth is above a threshold, create a new thread to
|
||||
/// execute it.
|
||||
pub fn create_with_crossbeam<T, V>(
|
||||
&mut self,
|
||||
params: ActionParams,
|
||||
substate: &mut Substate,
|
||||
stack_depth: usize,
|
||||
tracer: &mut T,
|
||||
vm_tracer: &mut V,
|
||||
) -> vm::Result<FinalizationResult>
|
||||
where
|
||||
T: Tracer,
|
||||
V: VMTracer,
|
||||
{
|
||||
let local_stack_size = ::io::LOCAL_STACK_SIZE.with(|sz| sz.get());
|
||||
let depth_threshold =
|
||||
local_stack_size.saturating_sub(STACK_SIZE_ENTRY_OVERHEAD) / STACK_SIZE_PER_DEPTH;
|
||||
|
||||
if stack_depth != depth_threshold {
|
||||
self.create_with_stack_depth(params, substate, stack_depth, tracer, vm_tracer)
|
||||
} else {
|
||||
thread::scope(|scope| {
|
||||
let stack_size = cmp::max(
|
||||
self.schedule.max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH,
|
||||
local_stack_size,
|
||||
);
|
||||
scope
|
||||
.builder()
|
||||
.stack_size(stack_size)
|
||||
.spawn(|_| {
|
||||
self.create_with_stack_depth(
|
||||
params,
|
||||
substate,
|
||||
stack_depth,
|
||||
tracer,
|
||||
vm_tracer,
|
||||
)
|
||||
})
|
||||
.expect(
|
||||
"Sub-thread creation cannot fail; the host might run out of resources; qed",
|
||||
)
|
||||
.join()
|
||||
})
|
||||
.expect("Sub-thread never panics; qed")
|
||||
.expect("Sub-thread never panics; qed")
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates contract with given contract params.
|
||||
pub fn create<T, V>(
|
||||
&mut self,
|
||||
|
||||
@@ -24,8 +24,8 @@ use std::{cmp, sync::Arc};
|
||||
use trace::{Tracer, VMTracer};
|
||||
use types::transaction::UNSIGNED_SENDER;
|
||||
use vm::{
|
||||
self, ActionParams, ActionValue, CallType, ContractCreateResult, CreateContractAddress,
|
||||
EnvInfo, Ext, MessageCallResult, ReturnData, Schedule, TrapKind,
|
||||
self, AccessList, ActionParams, ActionValue, CallType, ContractCreateResult,
|
||||
CreateContractAddress, EnvInfo, Ext, MessageCallResult, ReturnData, Schedule, TrapKind,
|
||||
};
|
||||
|
||||
/// Policy for handling output data on `RETURN` opcode.
|
||||
@@ -200,10 +200,11 @@ where
|
||||
data: Some(H256::from(number).to_vec()),
|
||||
call_type: CallType::Call,
|
||||
params_type: vm::ParamsType::Separate,
|
||||
access_list: AccessList::default(),
|
||||
};
|
||||
|
||||
let mut ex = Executive::new(self.state, self.env_info, self.machine, self.schedule);
|
||||
let r = ex.call_with_crossbeam(
|
||||
let r = ex.call_with_stack_depth(
|
||||
params,
|
||||
self.substate,
|
||||
self.stack_depth + 1,
|
||||
@@ -288,6 +289,7 @@ where
|
||||
data: None,
|
||||
call_type: CallType::None,
|
||||
params_type: vm::ParamsType::Embedded,
|
||||
access_list: self.substate.access_list.clone(),
|
||||
};
|
||||
|
||||
if !self.static_flag {
|
||||
@@ -312,7 +314,7 @@ where
|
||||
self.depth,
|
||||
self.static_flag,
|
||||
);
|
||||
let out = ex.create_with_crossbeam(
|
||||
let out = ex.create_with_stack_depth(
|
||||
params,
|
||||
self.substate,
|
||||
self.stack_depth + 1,
|
||||
@@ -322,6 +324,15 @@ where
|
||||
Ok(into_contract_create_result(out, &address, self.substate))
|
||||
}
|
||||
|
||||
fn calc_address(&self, code: &[u8], address_scheme: CreateContractAddress) -> Option<Address> {
|
||||
match self.state.nonce(&self.origin_info.address) {
|
||||
Ok(nonce) => {
|
||||
Some(contract_address(address_scheme, &self.origin_info.address, &nonce, &code).0)
|
||||
}
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn call(
|
||||
&mut self,
|
||||
gas: &U256,
|
||||
@@ -358,6 +369,7 @@ where
|
||||
data: Some(data.to_vec()),
|
||||
call_type: call_type,
|
||||
params_type: vm::ParamsType::Separate,
|
||||
access_list: self.substate.access_list.clone(),
|
||||
};
|
||||
|
||||
if let Some(value) = value {
|
||||
@@ -376,7 +388,7 @@ where
|
||||
self.depth,
|
||||
self.static_flag,
|
||||
);
|
||||
let out = ex.call_with_crossbeam(
|
||||
let out = ex.call_with_stack_depth(
|
||||
params,
|
||||
self.substate,
|
||||
self.stack_depth + 1,
|
||||
@@ -518,6 +530,26 @@ where
|
||||
fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem: &[u8]) {
|
||||
self.vm_tracer.trace_executed(gas_used, stack_push, mem)
|
||||
}
|
||||
|
||||
fn al_is_enabled(&self) -> bool {
|
||||
self.substate.access_list.is_enabled()
|
||||
}
|
||||
|
||||
fn al_contains_storage_key(&self, address: &Address, key: &H256) -> bool {
|
||||
self.substate.access_list.contains_storage_key(address, key)
|
||||
}
|
||||
|
||||
fn al_insert_storage_key(&mut self, address: Address, key: H256) {
|
||||
self.substate.access_list.insert_storage_key(address, key)
|
||||
}
|
||||
|
||||
fn al_contains_address(&self, address: &Address) -> bool {
|
||||
self.substate.access_list.contains_address(address)
|
||||
}
|
||||
|
||||
fn al_insert_address(&mut self, address: Address) {
|
||||
self.substate.access_list.insert_address(address)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -167,6 +167,10 @@ where
|
||||
Ok(ContractCreateResult::Created(contract_address, *gas))
|
||||
}
|
||||
|
||||
fn calc_address(&self, code: &[u8], address: CreateContractAddress) -> Option<Address> {
|
||||
Some(contract_address(address, &self.sender, &self.nonce, &code).0)
|
||||
}
|
||||
|
||||
fn call(
|
||||
&mut self,
|
||||
gas: &U256,
|
||||
@@ -238,6 +242,26 @@ where
|
||||
fn sub_sstore_refund(&mut self, value: usize) {
|
||||
self.ext.sub_sstore_refund(value)
|
||||
}
|
||||
|
||||
fn al_is_enabled(&self) -> bool {
|
||||
self.ext.al_is_enabled()
|
||||
}
|
||||
|
||||
fn al_contains_storage_key(&self, address: &Address, key: &H256) -> bool {
|
||||
self.ext.al_contains_storage_key(address, key)
|
||||
}
|
||||
|
||||
fn al_insert_storage_key(&mut self, address: Address, key: H256) {
|
||||
self.ext.al_insert_storage_key(address, key)
|
||||
}
|
||||
|
||||
fn al_contains_address(&self, address: &Address) -> bool {
|
||||
self.ext.al_contains_address(address)
|
||||
}
|
||||
|
||||
fn al_insert_address(&mut self, address: Address) {
|
||||
self.ext.al_insert_address(address)
|
||||
}
|
||||
}
|
||||
|
||||
/// run an json executive test
|
||||
|
||||
@@ -68,7 +68,6 @@ pub fn json_chain_test<H: FnMut(&str, HookType)>(
|
||||
let pre: PodState = test.pre_state.into();
|
||||
|
||||
for (spec_name, states) in test.post_states {
|
||||
let total = states.len();
|
||||
let spec = match EvmTestClient::spec_from_json(&spec_name) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
@@ -81,11 +80,10 @@ pub fn json_chain_test<H: FnMut(&str, HookType)>(
|
||||
|
||||
for (i, state) in states.into_iter().enumerate() {
|
||||
let info = format!(
|
||||
" - state: {} | {:?} ({}/{}) ...",
|
||||
name,
|
||||
"TestState/{}/{:?}/{}/trie",
|
||||
path.to_string_lossy(),
|
||||
spec_name,
|
||||
i + 1,
|
||||
total
|
||||
i
|
||||
);
|
||||
if skip_test(&state_test, &name, &spec.name, i + 1) {
|
||||
println!("{}: SKIPPED", info);
|
||||
@@ -112,7 +110,7 @@ pub fn json_chain_test<H: FnMut(&str, HookType)>(
|
||||
}
|
||||
Ok(Ok(TransactSuccess { state_root, .. })) if state_root != post_root => {
|
||||
println!(
|
||||
"{} !!! State mismatch (got: {}, expect: {}",
|
||||
"{}: post state root mismatch: got {:?}, want {:?}",
|
||||
info, state_root, post_root
|
||||
);
|
||||
flushln!("{} fail", info);
|
||||
@@ -124,7 +122,7 @@ pub fn json_chain_test<H: FnMut(&str, HookType)>(
|
||||
..
|
||||
})) if state_root != post_root => {
|
||||
println!(
|
||||
"{} !!! State mismatch (got: {}, expect: {}",
|
||||
"{}: post state root mismatch: got {:?}, want {:?}",
|
||||
info, state_root, post_root
|
||||
);
|
||||
println!("{} !!! Execution error: {:?}", info, error);
|
||||
|
||||
@@ -32,7 +32,8 @@ use types::{
|
||||
BlockNumber,
|
||||
};
|
||||
use vm::{
|
||||
ActionParams, ActionValue, CallType, CreateContractAddress, EnvInfo, ParamsType, Schedule,
|
||||
AccessList, ActionParams, ActionValue, CallType, CreateContractAddress, EnvInfo, ParamsType,
|
||||
Schedule,
|
||||
};
|
||||
|
||||
use block::ExecutedBlock;
|
||||
@@ -201,6 +202,7 @@ impl EthereumMachine {
|
||||
data,
|
||||
call_type: call_type.unwrap_or(CallType::Call),
|
||||
params_type: ParamsType::Separate,
|
||||
access_list: AccessList::default(),
|
||||
};
|
||||
let schedule = self.schedule(env_info.number);
|
||||
let mut ex = Executive::new(&mut state, &env_info, self, &schedule);
|
||||
|
||||
@@ -32,7 +32,7 @@ use parking_lot::RwLock;
|
||||
use rlp::{Rlp, RlpStream};
|
||||
use rustc_hex::FromHex;
|
||||
use types::{header::Header, BlockNumber};
|
||||
use vm::{ActionParams, ActionValue, CallType, EnvInfo, ParamsType};
|
||||
use vm::{AccessList, ActionParams, ActionValue, CallType, EnvInfo, ParamsType};
|
||||
|
||||
use builtin::Builtin;
|
||||
use engines::{
|
||||
@@ -135,6 +135,8 @@ pub struct CommonParams {
|
||||
pub eip2028_transition: BlockNumber,
|
||||
/// Number of first block where EIP-2315 rules begin.
|
||||
pub eip2315_transition: BlockNumber,
|
||||
/// Number of first block where EIP-2929 rules begin.
|
||||
pub eip2929_transition: BlockNumber,
|
||||
/// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin.
|
||||
pub dust_protection_transition: BlockNumber,
|
||||
/// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled.
|
||||
@@ -209,6 +211,7 @@ impl CommonParams {
|
||||
|| block_number >= self.eip1283_reenable_transition;
|
||||
schedule.eip1706 = block_number >= self.eip1706_transition;
|
||||
schedule.have_subs = block_number >= self.eip2315_transition;
|
||||
schedule.eip2929 = block_number >= self.eip2929_transition;
|
||||
|
||||
if block_number >= self.eip1884_transition {
|
||||
schedule.have_selfbalance = true;
|
||||
@@ -222,6 +225,24 @@ impl CommonParams {
|
||||
if block_number >= self.eip210_transition {
|
||||
schedule.blockhash_gas = 800;
|
||||
}
|
||||
if block_number >= self.eip2929_transition {
|
||||
schedule.eip2929 = true;
|
||||
schedule.eip1283 = true;
|
||||
|
||||
schedule.call_gas = ::vm::schedule::EIP2929_COLD_ACCOUNT_ACCESS_COST;
|
||||
schedule.balance_gas = ::vm::schedule::EIP2929_COLD_ACCOUNT_ACCESS_COST;
|
||||
schedule.extcodecopy_base_gas = ::vm::schedule::EIP2929_COLD_ACCOUNT_ACCESS_COST;
|
||||
schedule.extcodehash_gas = ::vm::schedule::EIP2929_COLD_ACCOUNT_ACCESS_COST;
|
||||
schedule.extcodesize_gas = ::vm::schedule::EIP2929_COLD_ACCOUNT_ACCESS_COST;
|
||||
|
||||
schedule.cold_sload_cost = ::vm::schedule::EIP2929_COLD_SLOAD_COST;
|
||||
schedule.cold_account_access_cost = ::vm::schedule::EIP2929_COLD_ACCOUNT_ACCESS_COST;
|
||||
schedule.warm_storage_read_cost = ::vm::schedule::EIP2929_WARM_STORAGE_READ_COST;
|
||||
|
||||
schedule.sload_gas = ::vm::schedule::EIP2929_WARM_STORAGE_READ_COST;
|
||||
schedule.sstore_reset_gas = ::vm::schedule::EIP2929_SSTORE_RESET_GAS;
|
||||
}
|
||||
|
||||
if block_number >= self.dust_protection_transition {
|
||||
schedule.kill_dust = match self.remove_dust_contracts {
|
||||
true => ::vm::CleanDustMode::WithCodeAndStorage,
|
||||
@@ -346,6 +367,9 @@ impl From<ethjson::spec::Params> for CommonParams {
|
||||
eip2315_transition: p
|
||||
.eip2315_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
eip2929_transition: p
|
||||
.eip2929_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
dust_protection_transition: p
|
||||
.dust_protection_transition
|
||||
.map_or_else(BlockNumber::max_value, Into::into),
|
||||
@@ -757,6 +781,7 @@ impl Spec {
|
||||
data: None,
|
||||
call_type: CallType::None,
|
||||
params_type: ParamsType::Embedded,
|
||||
access_list: AccessList::default(),
|
||||
};
|
||||
|
||||
let mut substate = Substate::new();
|
||||
|
||||
@@ -20,6 +20,7 @@ use ethereum_types::Address;
|
||||
use evm::{CleanDustMode, Schedule};
|
||||
use std::collections::HashSet;
|
||||
use types::log_entry::LogEntry;
|
||||
use vm::access_list::AccessList;
|
||||
|
||||
/// State changes which should be applied in finalize,
|
||||
/// after transaction is fully executed.
|
||||
@@ -39,6 +40,9 @@ pub struct Substate {
|
||||
|
||||
/// Created contracts.
|
||||
pub contracts_created: Vec<Address>,
|
||||
|
||||
/// List of accesses addresses and slots
|
||||
pub access_list: AccessList,
|
||||
}
|
||||
|
||||
impl Substate {
|
||||
@@ -46,6 +50,17 @@ impl Substate {
|
||||
pub fn new() -> Self {
|
||||
Substate::default()
|
||||
}
|
||||
/// Creates a new substate from an access list
|
||||
pub fn from_access_list(access_list: &AccessList) -> Self {
|
||||
Self {
|
||||
suicides: HashSet::default(),
|
||||
touched: HashSet::default(),
|
||||
logs: Vec::default(),
|
||||
sstore_clears_refund: 0,
|
||||
contracts_created: Vec::default(),
|
||||
access_list: access_list.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Merge secondary substate `s` into self, accruing each element correspondingly.
|
||||
pub fn accrue(&mut self, s: Substate) {
|
||||
|
||||
@@ -24,7 +24,7 @@ use std::sync::Arc;
|
||||
use test_helpers::get_temp_state_with_factory;
|
||||
use trace::{NoopTracer, NoopVMTracer};
|
||||
use types::transaction::SYSTEM_ADDRESS;
|
||||
use vm::{ActionParams, ActionValue, CallType, EnvInfo, ParamsType};
|
||||
use vm::{AccessList, ActionParams, ActionValue, CallType, EnvInfo, ParamsType};
|
||||
|
||||
use rustc_hex::FromHex;
|
||||
|
||||
@@ -62,6 +62,7 @@ fn test_blockhash_eip210(factory: Factory) {
|
||||
data: Some(H256::from(i - 1).to_vec()),
|
||||
call_type: CallType::Call,
|
||||
params_type: ParamsType::Separate,
|
||||
access_list: AccessList::default(),
|
||||
};
|
||||
let schedule = machine.schedule(env_info.number);
|
||||
let mut ex = Executive::new(&mut state, &env_info, &machine, &schedule);
|
||||
@@ -85,6 +86,7 @@ fn test_blockhash_eip210(factory: Factory) {
|
||||
data: None,
|
||||
call_type: CallType::Call,
|
||||
params_type: ParamsType::Separate,
|
||||
access_list: AccessList::default(),
|
||||
};
|
||||
let schedule = machine.schedule(env_info.number);
|
||||
let mut ex = Executive::new(&mut state, &env_info, &machine, &schedule);
|
||||
|
||||
Reference in New Issue
Block a user