Generalize engine trait (#6591)

* move common forks and parameters to common params

* port specs over to new format

* fix RPC tests

* parity-machine skeleton

* remove block type

* extract out ethereum-specific methods into EthereumMachine

* beginning to integrate Machine into engines. dealing with stale transitions in Ethash

* initial porting to machine

* move block reward back into engine

* abstract block reward logic

* move last hash and DAO HF logic into machine

* begin making engine function parameters generic

* abstract epoch verifier and ethash block reward logic

* instantiate special ethereummachine for ethash in spec

* optional full verification in verify_block_family

* re-instate tx_filter in a way that works for all engines

* fix warnings

* fix most tests, further generalize engine trait

* uncomment nullengine, get ethcore tests compiling

* fix warnings

* update a bunch of specs

* re-enable engine signer, validator set, and transition handler

* migrate basic_authority engine

* move last hashes into executedblock

* port tendermint

* make all ethcore tests pass

* json-tests compilation

* fix RPC tests: change in gas limit for new block changed PoW hash

* fix minor grumbles

* validate chainspecs

* fix broken import

* fix transaction verification for pre-homestead
This commit is contained in:
Robert Habermeier
2017-09-26 14:19:08 +02:00
committed by Gav Wood
parent d8af9f4e7b
commit bc167a211b
85 changed files with 2233 additions and 1923 deletions

View File

@@ -27,7 +27,7 @@ use std::sync::Arc;
use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY};
use receipt::{Receipt, TransactionOutcome};
use engines::Engine;
use machine::EthereumMachine as Machine;
use vm::EnvInfo;
use error::Error;
use executive::{Executive, TransactOptions};
@@ -196,7 +196,7 @@ pub fn check_proof(
proof: &[::util::DBValue],
root: H256,
transaction: &SignedTransaction,
engine: &Engine,
machine: &Machine,
env_info: &EnvInfo,
) -> ProvedExecution {
let backend = self::backend::ProofCheck::new(proof);
@@ -206,7 +206,7 @@ pub fn check_proof(
let res = State::from_existing(
backend,
root,
engine.account_start_nonce(env_info.number),
machine.account_start_nonce(env_info.number),
factories
);
@@ -216,7 +216,7 @@ pub fn check_proof(
};
let options = TransactOptions::with_no_tracing().save_output_from_contract();
match state.execute(env_info, engine, transaction, options, true) {
match state.execute(env_info, machine, transaction, options, true) {
Ok(executed) => ProvedExecution::Complete(executed),
Err(ExecutionError::Internal(_)) => ProvedExecution::BadProof,
Err(e) => ProvedExecution::Failed(e),
@@ -230,7 +230,7 @@ pub fn prove_transaction<H: AsHashDB + Send + Sync>(
db: H,
root: H256,
transaction: &SignedTransaction,
engine: &Engine,
machine: &Machine,
env_info: &EnvInfo,
factories: Factories,
virt: bool,
@@ -241,7 +241,7 @@ pub fn prove_transaction<H: AsHashDB + Send + Sync>(
let res = State::from_existing(
backend,
root,
engine.account_start_nonce(env_info.number),
machine.account_start_nonce(env_info.number),
factories,
);
@@ -251,7 +251,7 @@ pub fn prove_transaction<H: AsHashDB + Send + Sync>(
};
let options = TransactOptions::with_no_tracing().dont_check_nonce().save_output_from_contract();
match state.execute(env_info, engine, transaction, options, virt) {
match state.execute(env_info, machine, transaction, options, virt) {
Err(ExecutionError::Internal(_)) => None,
Err(e) => {
trace!(target: "state", "Proved call failed: {}", e);
@@ -668,13 +668,13 @@ impl<B: Backend> State<B> {
/// Execute a given transaction, producing a receipt and an optional trace.
/// This will change the state accordingly.
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &SignedTransaction, tracing: bool) -> ApplyResult {
pub fn apply(&mut self, env_info: &EnvInfo, machine: &Machine, t: &SignedTransaction, tracing: bool) -> ApplyResult {
if tracing {
let options = TransactOptions::with_tracing();
self.apply_with_tracing(env_info, engine, t, options.tracer, options.vm_tracer)
self.apply_with_tracing(env_info, machine, t, options.tracer, options.vm_tracer)
} else {
let options = TransactOptions::with_no_tracing();
self.apply_with_tracing(env_info, engine, t, options.tracer, options.vm_tracer)
self.apply_with_tracing(env_info, machine, t, options.tracer, options.vm_tracer)
}
}
@@ -683,7 +683,7 @@ impl<B: Backend> State<B> {
pub fn apply_with_tracing<V, T>(
&mut self,
env_info: &EnvInfo,
engine: &Engine,
machine: &Machine,
t: &SignedTransaction,
tracer: T,
vm_tracer: V,
@@ -692,12 +692,13 @@ impl<B: Backend> State<B> {
V: trace::VMTracer,
{
let options = TransactOptions::new(tracer, vm_tracer);
let e = self.execute(env_info, engine, t, options, false)?;
let e = self.execute(env_info, machine, t, options, false)?;
let params = machine.params();
let eip658 = env_info.number >= engine.params().eip658_transition;
let eip658 = env_info.number >= params.eip658_transition;
let no_intermediate_commits =
eip658 ||
(env_info.number >= engine.params().eip98_transition && env_info.number >= engine.params().validate_receipts_transition);
(env_info.number >= params.eip98_transition && env_info.number >= params.validate_receipts_transition);
let outcome = if no_intermediate_commits {
if eip658 {
@@ -726,10 +727,10 @@ impl<B: Backend> State<B> {
//
// `virt` signals that we are executing outside of a block set and restrictions like
// gas limits and gas costs should be lifted.
fn execute<T, V>(&mut self, env_info: &EnvInfo, engine: &Engine, t: &SignedTransaction, options: TransactOptions<T, V>, virt: bool)
fn execute<T, V>(&mut self, env_info: &EnvInfo, machine: &Machine, t: &SignedTransaction, options: TransactOptions<T, V>, virt: bool)
-> Result<Executed, ExecutionError> where T: trace::Tracer, V: trace::VMTracer,
{
let mut e = Executive::new(self, env_info, engine);
let mut e = Executive::new(self, env_info, machine);
match virt {
true => e.transact_virtual(t, options),
@@ -1071,6 +1072,7 @@ mod tests {
use bigint::hash::H256;
use util::Address;
use tests::helpers::*;
use machine::EthereumMachine;
use vm::EnvInfo;
use spec::*;
use transaction::*;
@@ -1082,6 +1084,12 @@ mod tests {
keccak("").into()
}
fn make_frontier_machine(max_depth: usize) -> EthereumMachine {
let mut machine = ::ethereum::new_frontier_test_machine();
machine.set_schedule_creation_rules(Box::new(move |s, _| s.max_depth = max_depth));
machine
}
#[test]
fn should_apply_create_transaction() {
init_log();
@@ -1090,7 +1098,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
let engine = TestEngine::new(5);
let machine = make_frontier_machine(5);
let t = Transaction {
nonce: 0.into(),
@@ -1102,7 +1110,7 @@ mod tests {
}.sign(&secret(), None);
state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap();
let result = state.apply(&info, &engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
subtraces: 0,
@@ -1148,7 +1156,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
let engine = TestEngine::new(5);
let machine = make_frontier_machine(5);
let t = Transaction {
nonce: 0.into(),
@@ -1160,7 +1168,7 @@ mod tests {
}.sign(&secret(), None);
state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap();
let result = state.apply(&info, &engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
action: trace::Action::Create(trace::Create {
@@ -1184,7 +1192,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
let engine = TestEngine::new(5);
let machine = make_frontier_machine(5);
let t = Transaction {
nonce: 0.into(),
@@ -1197,7 +1205,7 @@ mod tests {
state.init_code(&0xa.into(), FromHex::from_hex("6000").unwrap()).unwrap();
state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap();
let result = state.apply(&info, &engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
action: trace::Action::Call(trace::Call {
@@ -1226,7 +1234,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
let engine = TestEngine::new(5);
let machine = make_frontier_machine(5);
let t = Transaction {
nonce: 0.into(),
@@ -1238,7 +1246,7 @@ mod tests {
}.sign(&secret(), None);
state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap();
let result = state.apply(&info, &engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
action: trace::Action::Call(trace::Call {
@@ -1267,7 +1275,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
let engine = &*Spec::new_test().engine;
let machine = Spec::new_test_machine();
let t = Transaction {
nonce: 0.into(),
@@ -1278,7 +1286,7 @@ mod tests {
data: vec![],
}.sign(&secret(), None);
let result = state.apply(&info, engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
@@ -1308,7 +1316,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
let engine = &*Spec::new_test().engine;
let machine = Spec::new_test_machine();
let t = Transaction {
nonce: 0.into(),
@@ -1320,7 +1328,7 @@ mod tests {
}.sign(&secret(), None);
state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060006001610be0f1").unwrap()).unwrap();
let result = state.apply(&info, engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
@@ -1333,7 +1341,7 @@ mod tests {
call_type: CallType::Call,
}),
result: trace::Res::Call(trace::CallResult {
gas_used: U256::from(28_061),
gas_used: U256::from(3_721), // in post-eip150
output: vec![]
}),
subtraces: 0,
@@ -1350,7 +1358,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
let engine = &*Spec::new_test().engine;
let machine = Spec::new_test_machine();
let t = Transaction {
nonce: 0.into(),
@@ -1363,7 +1371,7 @@ mod tests {
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b611000f2").unwrap()).unwrap();
state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()).unwrap();
let result = state.apply(&info, engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
@@ -1377,7 +1385,7 @@ mod tests {
call_type: CallType::Call,
}),
result: trace::Res::Call(trace::CallResult {
gas_used: 64.into(),
gas_used: 724.into(), // in post-eip150
output: vec![]
}),
}, FlatTrace {
@@ -1409,9 +1417,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
info.number = 0x789b0;
let engine = &*Spec::new_test().engine;
println!("schedule.have_delegate_call: {:?}", engine.schedule(info.number).have_delegate_call);
let machine = Spec::new_test_machine();
let t = Transaction {
nonce: 0.into(),
@@ -1424,7 +1430,7 @@ mod tests {
state.init_code(&0xa.into(), FromHex::from_hex("6000600060006000600b618000f4").unwrap()).unwrap();
state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()).unwrap();
let result = state.apply(&info, engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
@@ -1438,7 +1444,7 @@ mod tests {
call_type: CallType::Call,
}),
result: trace::Res::Call(trace::CallResult {
gas_used: U256::from(61),
gas_used: U256::from(721), // in post-eip150
output: vec![]
}),
}, FlatTrace {
@@ -1469,7 +1475,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
let engine = TestEngine::new(5);
let machine = make_frontier_machine(5);
let t = Transaction {
nonce: 0.into(),
@@ -1482,7 +1488,7 @@ mod tests {
state.init_code(&0xa.into(), FromHex::from_hex("5b600056").unwrap()).unwrap();
state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap();
let result = state.apply(&info, &engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
action: trace::Action::Call(trace::Call {
@@ -1508,7 +1514,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
let engine = TestEngine::new(5);
let machine = make_frontier_machine(5);
let t = Transaction {
nonce: 0.into(),
@@ -1522,7 +1528,7 @@ mod tests {
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()).unwrap();
state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()).unwrap();
state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap();
let result = state.apply(&info, &engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
@@ -1567,7 +1573,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
let engine = TestEngine::new(5);
let machine = make_frontier_machine(5);
let t = Transaction {
nonce: 0.into(),
@@ -1580,7 +1586,7 @@ mod tests {
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006045600b6000f1").unwrap()).unwrap();
state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap();
let result = state.apply(&info, &engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
subtraces: 1,
@@ -1621,7 +1627,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
let engine = TestEngine::new(5);
let machine = make_frontier_machine(5);
let t = Transaction {
nonce: 0.into(),
@@ -1634,7 +1640,7 @@ mod tests {
state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060ff600b6000f1").unwrap()).unwrap(); // not enough funds.
state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap();
let result = state.apply(&info, &engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
subtraces: 0,
@@ -1663,7 +1669,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
let engine = TestEngine::new(5);
let machine = make_frontier_machine(5);
let t = Transaction {
nonce: 0.into(),
@@ -1677,7 +1683,7 @@ mod tests {
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()).unwrap();
state.init_code(&0xb.into(), FromHex::from_hex("5b600056").unwrap()).unwrap();
state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap();
let result = state.apply(&info, &engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
subtraces: 1,
@@ -1718,7 +1724,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
let engine = TestEngine::new(5);
let machine = make_frontier_machine(5);
let t = Transaction {
nonce: 0.into(),
@@ -1733,7 +1739,7 @@ mod tests {
state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1").unwrap()).unwrap();
state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap()).unwrap();
state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap();
let result = state.apply(&info, &engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
subtraces: 1,
@@ -1792,7 +1798,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
let engine = TestEngine::new(5);
let machine = make_frontier_machine(5);
let t = Transaction {
nonce: 0.into(),
@@ -1807,7 +1813,7 @@ mod tests {
state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1505b601256").unwrap()).unwrap();
state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap()).unwrap();
state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap();
let result = state.apply(&info, &engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
@@ -1864,7 +1870,7 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = 1_000_000.into();
let engine = TestEngine::new(5);
let machine = make_frontier_machine(5);
let t = Transaction {
nonce: 0.into(),
@@ -1878,7 +1884,7 @@ mod tests {
state.init_code(&0xa.into(), FromHex::from_hex("73000000000000000000000000000000000000000bff").unwrap()).unwrap();
state.add_balance(&0xa.into(), &50.into(), CleanupMode::NoEmpty).unwrap();
state.add_balance(&t.sender(), &100.into(), CleanupMode::NoEmpty).unwrap();
let result = state.apply(&info, &engine, &t, true).unwrap();
let result = state.apply(&info, &machine, &t, true).unwrap();
let expected_trace = vec![FlatTrace {
trace_address: Default::default(),
subtraces: 1,