Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Allow calling contracts in genesis state. (#9375)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomusdrw authored and ascjones committed Aug 20, 2018
1 parent b2cf5d2 commit 108590d
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 18 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion ethcore/src/ethereum/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ pub use self::denominations::*;
use machine::EthereumMachine;
use super::spec::*;

fn load<'a, T: Into<Option<SpecParams<'a>>>>(params: T, b: &[u8]) -> Spec {
/// Load chain spec from `SpecParams` and JSON.
pub fn load<'a, T: Into<Option<SpecParams<'a>>>>(params: T, b: &[u8]) -> Spec {
match params.into() {
Some(params) => Spec::load(params, b),
None => Spec::load(&::std::env::temp_dir(), b)
Expand Down
5 changes: 5 additions & 0 deletions ethcore/src/spec/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,11 @@ impl Spec {
Ok(())
}

/// Return genesis state as Plain old data.
pub fn genesis_state(&self) -> &PodState {
&self.genesis_state
}

/// Returns `false` if the memoized state root is invalid. `true` otherwise.
pub fn is_state_root_valid(&self) -> bool {
// TODO: get rid of this function and ensure state root always is valid.
Expand Down
1 change: 1 addition & 0 deletions evmbin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ path = "./src/main.rs"

[dependencies]
docopt = "0.8"
env_logger = "0.5"
ethcore = { path = "../ethcore", features = ["test-helpers", "json-tests"] }
ethjson = { path = "../json" }
parity-bytes = { git = "https://github.com/paritytech/parity-common" }
Expand Down
38 changes: 38 additions & 0 deletions evmbin/res/testchain.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "lab",
"engine": {
"Ethash": {
"params": {
"minimumDifficulty": "0x1",
"difficultyBoundDivisor": "0x800"
}
}
},
"accounts": {
"0000000000000000000000000000000000000020": {
"nonce": "0x0",
"balance": "0x64",
"code": "0x62aaaaaa60aa60aa5060aa60aa60aa60aa60aa60aa"
}
},
"params":{
"networkID": "0x42",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1",
"gasLimitBoundDivisor": "0x400"
},
"genesis": {
"gasLimit": "0x8000000",
"seal": {
"ethereum": {
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000042"
}
},
"difficulty": "0x400",
"extraData": "0x0",
"author": "0x3333333333333333333333333333333333333333",
"timestamp": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
}
6 changes: 3 additions & 3 deletions evmbin/src/display/std_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,13 @@ impl<T: Writer> trace::VMTracer for Informant<T> {
}

#[cfg(test)]
mod tests {
pub mod tests {
use std::sync::{Arc, Mutex};
use super::*;
use info::tests::run_test;

#[derive(Debug, Clone, Default)]
struct TestWriter(pub Arc<Mutex<Vec<u8>>>);
pub struct TestWriter(pub Arc<Mutex<Vec<u8>>>);

impl Writer for TestWriter {
fn clone(&self) -> Self { Clone::clone(self) }
Expand All @@ -189,7 +189,7 @@ mod tests {
}
}

fn informant() -> (Informant<TestWriter>, Arc<Mutex<Vec<u8>>>) {
pub fn informant() -> (Informant<TestWriter>, Arc<Mutex<Vec<u8>>>) {
let writer = TestWriter::default();
let res = writer.0.clone();
(Informant::new(writer), res)
Expand Down
60 changes: 46 additions & 14 deletions evmbin/src/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,19 @@ pub type RunResult<T> = Result<Success<T>, Failure<T>>;
/// Execute given `ActionParams` and return the result.
pub fn run_action<T: Informant>(
spec: &spec::Spec,
params: ActionParams,
mut params: ActionParams,
mut informant: T,
) -> RunResult<T::Output> {
informant.set_gas(params.gas);
run(spec, params.gas, None, |mut client| {

// if the code is not overwritten from CLI, use code from spec file.
if params.code.is_none() {
if let Some(acc) = spec.genesis_state().get().get(&params.code_address) {
params.code = acc.code.clone().map(::std::sync::Arc::new);
params.code_hash = None;
}
}
run(spec, params.gas, spec.genesis_state(), |mut client| {
let result = client
.call(params, &mut trace::NoopTracer, &mut informant)
.map(|r| (0.into(), r.gas_left, r.return_data.to_vec()));
Expand Down Expand Up @@ -130,24 +138,21 @@ pub fn run_transaction<T: Informant>(
}

/// Execute VM with given `ActionParams`
pub fn run<'a, F, T, X>(
pub fn run<'a, F, X>(
spec: &'a spec::Spec,
initial_gas: U256,
pre_state: T,
pre_state: &'a pod_state::PodState,
run: F,
) -> RunResult<X> where
F: FnOnce(EvmTestClient) -> (Result<(H256, U256, Vec<u8>), EvmTestError>, Option<X>),
T: Into<Option<&'a pod_state::PodState>>,
{
let test_client = match pre_state.into() {
Some(pre_state) => EvmTestClient::from_pod_state(spec, pre_state.clone()),
None => EvmTestClient::new(spec),
}.map_err(|error| Failure {
gas_used: 0.into(),
error,
time: Duration::from_secs(0),
traces: None,
})?;
let test_client = EvmTestClient::from_pod_state(spec, pre_state.clone())
.map_err(|error| Failure {
gas_used: 0.into(),
error,
time: Duration::from_secs(0),
traces: None,
})?;

let start = Instant::now();
let result = run(test_client);
Expand Down Expand Up @@ -204,4 +209,31 @@ pub mod tests {
},
}
}

#[test]
fn should_call_account_from_spec() {
use display::std_json::tests::informant;

let (inf, res) = informant();
let mut params = ActionParams::default();
params.code_address = 0x20.into();
params.gas = 0xffff.into();

let spec = ::ethcore::ethereum::load(None, include_bytes!("../res/testchain.json"));
let _result = run_action(&spec, params, inf);

assert_eq!(
&String::from_utf8_lossy(&**res.lock().unwrap()),
r#"{"pc":0,"op":98,"opName":"PUSH3","gas":"0xffff","stack":[],"storage":{},"depth":1}
{"pc":4,"op":96,"opName":"PUSH1","gas":"0xfffc","stack":["0xaaaaaa"],"storage":{},"depth":1}
{"pc":6,"op":96,"opName":"PUSH1","gas":"0xfff9","stack":["0xaaaaaa","0xaa"],"storage":{},"depth":1}
{"pc":8,"op":80,"opName":"POP","gas":"0xfff6","stack":["0xaaaaaa","0xaa","0xaa"],"storage":{},"depth":1}
{"pc":9,"op":96,"opName":"PUSH1","gas":"0xfff4","stack":["0xaaaaaa","0xaa"],"storage":{},"depth":1}
{"pc":11,"op":96,"opName":"PUSH1","gas":"0xfff1","stack":["0xaaaaaa","0xaa","0xaa"],"storage":{},"depth":1}
{"pc":13,"op":96,"opName":"PUSH1","gas":"0xffee","stack":["0xaaaaaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
{"pc":15,"op":96,"opName":"PUSH1","gas":"0xffeb","stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
{"pc":17,"op":96,"opName":"PUSH1","gas":"0xffe8","stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
{"pc":19,"op":96,"opName":"PUSH1","gas":"0xffe5","stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
"#);
}
}
2 changes: 2 additions & 0 deletions evmbin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ extern crate ethereum_types;
extern crate vm;
extern crate evm;
extern crate panic_hook;
extern crate env_logger;

#[cfg(test)]
#[macro_use]
Expand Down Expand Up @@ -92,6 +93,7 @@ General options:

fn main() {
panic_hook::set_abort();
env_logger::init();

let args: Args = Docopt::new(USAGE).and_then(|d| d.deserialize()).unwrap_or_else(|e| e.exit());

Expand Down

0 comments on commit 108590d

Please sign in to comment.