// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity 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 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. If not, see .
extern crate ctrlc;
extern crate docopt;
extern crate rustc_serialize;
extern crate serde_json;
extern crate ethjson;
extern crate ethcore_util as util;
extern crate ethcore;
extern crate ethcore_devtools as devtools;
extern crate ethcore_rpc as rpc;
use std::collections::HashMap;
use std::sync::{Arc, Mutex, Condvar};
use std::process;
use std::fs::File;
use std::path::Path;
use docopt::Docopt;
use ctrlc::CtrlC;
use ethcore::spec::Genesis;
use ethcore::pod_state::PodState;
use ethcore::ethereum;
use ethcore::client::{BlockChainClient, Client, ClientConfig};
use devtools::RandomTempPath;
use util::IoChannel;
use rpc::v1::tests::helpers::{TestSyncProvider, Config as SyncConfig, TestMinerService, TestAccountProvider, TestAccount};
use rpc::v1::{Eth, EthClient, EthFilter, EthFilterClient};
use util::panics::MayPanic;
use util::hash::Address;
const USAGE: &'static str = r#"
Parity rpctest client.
By Wood/Paronyan/Kotewicz/Drwięga/Volf.
Copyright 2015, 2016 Ethcore (UK) Limited
Usage:
rpctest --json --name [options]
rpctest --help
Options:
--jsonrpc-addr HOST Specify the hostname portion of the JSONRPC API
server [default: 127.0.0.1].
--jsonrpc-port PORT Specify the port portion of the JSONRPC API server
[default: 8545].
"#;
#[derive(Debug, RustcDecodable)]
struct Args {
arg_test_file: String,
arg_test_name: String,
flag_jsonrpc_addr: String,
flag_jsonrpc_port: u16,
}
struct Configuration {
args: Args,
}
impl Configuration {
fn parse() -> Self {
Configuration {
args: Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit())
}
}
fn execute(&self) {
println!("file path: {:?}", self.args.arg_test_file);
println!("test name: {:?}", self.args.arg_test_name);
let path = Path::new(&self.args.arg_test_file);
let file = File::open(path).unwrap_or_else(|_| {
println!("Cannot open file.");
process::exit(1);
});
let tests: ethjson::blockchain::Test = serde_json::from_reader(file).unwrap_or_else(|err| {
println!("Invalid json file.");
println!("{:?}", err);
process::exit(2);
});
let blockchain = tests.get(&self.args.arg_test_name).unwrap_or_else(|| {
println!("Invalid test name.");
process::exit(3);
});
let genesis = Genesis::from(blockchain.genesis());
let state = PodState::from(blockchain.pre_state.clone());
let mut spec = ethereum::new_frontier_test();
spec.set_genesis_state(state);
spec.overwrite_genesis_params(genesis);
assert!(spec.is_state_root_valid());
let temp = RandomTempPath::new();
{
let client: Arc = Client::new(ClientConfig::default(), spec, temp.as_path(), IoChannel::disconnected()).unwrap();
for b in &blockchain.blocks_rlp() {
let _ = client.import_block(b.clone());
client.flush_queue();
client.import_verified_blocks(&IoChannel::disconnected());
}
let sync = Arc::new(TestSyncProvider::new(SyncConfig {
protocol_version: 65,
num_peers: 120
}));
let miner = Arc::new(TestMinerService::default());
let mut accs = HashMap::new();
accs.insert(Address::from(1), TestAccount::new("test"));
let accounts = Arc::new(TestAccountProvider::new(accs));
let server = rpc::RpcServer::new();
server.add_delegate(EthClient::new(&client, &sync, &accounts, &miner, true).to_delegate());
server.add_delegate(EthFilterClient::new(&client, &miner).to_delegate());
let url = format!("{}:{}", self.args.flag_jsonrpc_addr, self.args.flag_jsonrpc_port);
let panic_handler = server.start_http(url.as_ref(), "*", 1);
let exit = Arc::new(Condvar::new());
let e = exit.clone();
CtrlC::set_handler(move || { e.notify_all(); });
let e = exit.clone();
panic_handler.on_panic(move |_reason| { e.notify_all(); });
let mutex = Mutex::new(());
let _ = exit.wait(mutex.lock().unwrap()).unwrap();
}
}
}
fn main() {
Configuration::parse().execute();
}