Move the substate module into ethcore/executive (#10867)

* substate is not a part of account-state

* fn cleanup_mode is a part of executive.rs

* test_cleanup_mode
This commit is contained in:
Marek Kotewicz
2019-07-10 10:55:37 +02:00
committed by Andronik Ordian
parent f53c3e582c
commit 34cdeac2a6
17 changed files with 67 additions and 43 deletions

View File

@@ -28,7 +28,8 @@ use trie_vm_factories::Factories;
use evm::{VMType, FinalizationResult};
use vm::{self, ActionParams};
use ethtrie;
use account_state::{CleanupMode, Substate, State};
use account_state::{CleanupMode, State};
use substate::Substate;
use executive_state::ExecutiveState;

View File

@@ -21,7 +21,8 @@ use std::sync::Arc;
use hash::keccak;
use ethereum_types::{H256, U256, U512, Address};
use bytes::{Bytes, BytesRef};
use account_state::{Backend as StateBackend, State, Substate, CleanupMode};
use account_state::{Backend as StateBackend, State, CleanupMode};
use substate::Substate;
use executed::ExecutionError;
use machine::Machine;
use evm::{CallType, Finalize, FinalizationResult};
@@ -106,6 +107,15 @@ pub fn into_contract_create_result(result: vm::Result<FinalizationResult>, addre
}
}
/// Get the cleanup mode object from this.
pub fn cleanup_mode<'a>(substate: &'a mut Substate, schedule: &Schedule) -> CleanupMode<'a> {
match (schedule.kill_dust != CleanDustMode::Off, schedule.no_empty, schedule.kill_empty) {
(false, false, _) => CleanupMode::ForceCreate,
(false, true, false) => CleanupMode::NoEmpty,
(false, true, true) | (true, _, _,) => CleanupMode::TrackTouched(&mut substate.touched),
}
}
/// Transaction execution options.
#[derive(Copy, Clone, PartialEq)]
pub struct TransactOptions<T, V> {
@@ -302,7 +312,7 @@ impl<'a> CallCreateExecutive<'a> {
fn transfer_exec_balance<B: 'a + StateBackend>(params: &ActionParams, schedule: &Schedule, state: &mut State<B>, substate: &mut Substate) -> vm::Result<()> {
if let ActionValue::Transfer(val) = params.value {
state.transfer_balance(&params.sender, &params.address, &val, substate.to_cleanup_mode(&schedule))?;
state.transfer_balance(&params.sender, &params.address, &val, cleanup_mode(substate, &schedule))?;
}
Ok(())
@@ -312,7 +322,7 @@ impl<'a> CallCreateExecutive<'a> {
let nonce_offset = if schedule.no_empty { 1 } else { 0 }.into();
let prev_bal = state.balance(&params.address)?;
if let ActionValue::Transfer(val) = params.value {
state.sub_balance(&params.sender, &val, &mut substate.to_cleanup_mode(&schedule))?;
state.sub_balance(&params.sender, &val, &mut cleanup_mode(substate, &schedule))?;
state.new_contract(&params.address, val.saturating_add(prev_bal), nonce_offset, params.code_version)?;
} else {
state.new_contract(&params.address, prev_bal, nonce_offset, params.code_version)?;
@@ -865,7 +875,11 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
if !schedule.keep_unsigned_nonce || !t.is_unsigned() {
self.state.inc_nonce(&sender)?;
}
self.state.sub_balance(&sender, &U256::try_from(gas_cost).expect("Total cost (value + gas_cost) is lower than max allowed balance (U256); gas_cost has to fit U256; qed"), &mut substate.to_cleanup_mode(&schedule))?;
self.state.sub_balance(
&sender,
&U256::try_from(gas_cost).expect("Total cost (value + gas_cost) is lower than max allowed balance (U256); gas_cost has to fit U256; qed"),
&mut cleanup_mode(&mut substate, &schedule)
)?;
let (result, output) = match t.action {
Action::Create => {
@@ -1142,7 +1156,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
// Below: NoEmpty is safe since the sender must already be non-null to have sent this transaction
self.state.add_balance(&sender, &refund_value, CleanupMode::NoEmpty)?;
trace!("exec::finalize: Compensating author: fees_value={}, author={}\n", fees_value, &self.info.author);
self.state.add_balance(&self.info.author, &fees_value, substate.to_cleanup_mode(&schedule))?;
self.state.add_balance(&self.info.author, &fees_value, cleanup_mode(&mut substate, &schedule))?;
// perform suicides
for address in &substate.suicides {
@@ -1194,6 +1208,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
mod tests {
use std::sync::Arc;
use std::str::FromStr;
use std::collections::HashSet;
use rustc_hex::FromHex;
use ethkey::{Generator, Random};
use super::*;
@@ -1202,7 +1217,8 @@ mod tests {
use evm::{Factory, VMType};
use error::ExecutionError;
use machine::Machine;
use account_state::{Substate, CleanupMode};
use account_state::CleanupMode;
use substate::Substate;
use test_helpers::{get_temp_state_with_factory, get_temp_state};
use trace::trace;
use trace::{FlatTrace, Tracer, NoopTracer, ExecutiveTracer};
@@ -1221,6 +1237,33 @@ mod tests {
machine
}
#[test]
fn test_cleanup_mode() {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let mut touched = HashSet::new();
touched.insert(address);
let mut substate = Substate::default();
substate.touched = touched.clone();
assert_eq!(CleanupMode::ForceCreate, cleanup_mode(&mut substate, &Schedule::new_frontier()));
assert_eq!(CleanupMode::ForceCreate, cleanup_mode(&mut substate, &Schedule::new_homestead()));
assert_eq!(CleanupMode::TrackTouched(&mut touched), cleanup_mode(&mut substate, &Schedule::new_byzantium()));
assert_eq!(CleanupMode::TrackTouched(&mut touched), cleanup_mode(&mut substate, &Schedule::new_constantinople()));
assert_eq!(CleanupMode::TrackTouched(&mut touched), cleanup_mode(&mut substate, &{
let mut schedule = Schedule::new_homestead();
schedule.kill_dust = CleanDustMode::BasicOnly;
schedule
}));
assert_eq!(CleanupMode::NoEmpty, cleanup_mode(&mut substate, &{
let mut schedule = Schedule::new_homestead();
schedule.no_empty = true;
schedule
}));
}
#[test]
fn test_contract_address() {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();

View File

@@ -19,7 +19,8 @@ use std::cmp;
use std::sync::Arc;
use ethereum_types::{H256, U256, Address, BigEndianHash};
use bytes::Bytes;
use account_state::{Backend as StateBackend, State, Substate, CleanupMode};
use account_state::{Backend as StateBackend, State, CleanupMode};
use substate::Substate;
use machine::Machine;
use executive::*;
use vm::{
@@ -388,7 +389,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
&address,
refund_address,
&balance,
self.substate.to_cleanup_mode(&self.schedule)
cleanup_mode(&mut self.substate, &self.schedule)
)?;
}
@@ -435,7 +436,8 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
mod tests {
use ethereum_types::{U256, Address};
use evm::{EnvInfo, Ext, CallType};
use account_state::{State, Substate};
use account_state::State;
use substate::Substate;
use test_helpers::get_temp_state;
use super::*;
use trace::{NoopTracer, NoopVMTracer};

View File

@@ -17,7 +17,8 @@
use std::path::Path;
use std::sync::Arc;
use super::test_common::*;
use account_state::{Backend as StateBackend, State, Substate};
use account_state::{Backend as StateBackend, State};
use substate::Substate;
use executive::*;
use evm::{VMType, Finalize};
use vm::{

View File

@@ -164,6 +164,7 @@ pub mod spec;
pub mod verification;
mod externalities;
mod substate;
mod transaction_ext;
mod tx_filter;

View File

@@ -35,7 +35,8 @@ use client::BlockInfo;
use error::Error;
use executive::Executive;
use spec::CommonParams;
use account_state::{CleanupMode, Substate};
use account_state::CleanupMode;
use substate::Substate;
use trace::{NoopTracer, NoopVMTracer};
use tx_filter::TransactionFilter;

View File

@@ -45,7 +45,8 @@ use machine::Machine;
use pod::PodState;
use spec::Genesis;
use spec::seal::Generic as GenericSeal;
use account_state::{Backend, State, Substate, backend::Basic as BasicBackend};
use account_state::{Backend, State, backend::Basic as BasicBackend};
use substate::Substate;
use trace::{NoopTracer, NoopVMTracer};
pub use ethash::OptimizeFor;

96
ethcore/src/substate.rs Normal file
View File

@@ -0,0 +1,96 @@
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Execution environment substate.
use std::collections::HashSet;
use ethereum_types::Address;
use types::log_entry::LogEntry;
/// State changes which should be applied in finalize,
/// after transaction is fully executed.
#[derive(Debug, Default)]
pub struct Substate {
/// Any accounts that have suicided.
pub suicides: HashSet<Address>,
/// Any accounts that are touched.
pub touched: HashSet<Address>,
/// Any logs.
pub logs: Vec<LogEntry>,
/// Refund counter of SSTORE.
pub sstore_clears_refund: i128,
/// Created contracts.
pub contracts_created: Vec<Address>,
}
impl Substate {
/// Creates new substate.
pub fn new() -> Self {
Substate::default()
}
/// Merge secondary substate `s` into self, accruing each element correspondingly.
pub fn accrue(&mut self, s: Substate) {
self.suicides.extend(s.suicides);
self.touched.extend(s.touched);
self.logs.extend(s.logs);
self.sstore_clears_refund += s.sstore_clears_refund;
self.contracts_created.extend(s.contracts_created);
}
}
#[cfg(test)]
mod tests {
use ethereum_types::Address;
use types::log_entry::LogEntry;
use super::Substate;
#[test]
fn created() {
let sub_state = Substate::new();
assert_eq!(sub_state.suicides.len(), 0);
}
#[test]
fn accrue() {
let mut sub_state = Substate::new();
sub_state.contracts_created.push(Address::from_low_u64_be(1));
sub_state.logs.push(LogEntry {
address: Address::from_low_u64_be(1),
topics: vec![],
data: vec![]
});
sub_state.sstore_clears_refund = (15000 * 5).into();
sub_state.suicides.insert(Address::from_low_u64_be(10));
let mut sub_state_2 = Substate::new();
sub_state_2.contracts_created.push(Address::from_low_u64_be(2u64));
sub_state_2.logs.push(LogEntry {
address: Address::from_low_u64_be(1),
topics: vec![],
data: vec![]
});
sub_state_2.sstore_clears_refund = (15000 * 7).into();
sub_state.accrue(sub_state_2);
assert_eq!(sub_state.contracts_created.len(), 2);
assert_eq!(sub_state.sstore_clears_refund, (15000 * 12).into());
assert_eq!(sub_state.suicides.len(), 1);
}
}

View File

@@ -21,7 +21,7 @@ use hash::keccak;
use vm::{EnvInfo, ActionParams, ActionValue, CallType, ParamsType};
use evm::{Factory, VMType};
use executive::Executive;
use account_state::Substate;
use substate::Substate;
use test_helpers::get_temp_state_with_factory;
use trace::{NoopVMTracer, NoopTracer};
use types::transaction::SYSTEM_ADDRESS;