miner and client take spec reference (#1853)

* miner and client take spec reference

* fix tests
This commit is contained in:
Robert Habermeier 2016-08-05 23:33:55 +02:00 committed by Gav Wood
parent 2f52425387
commit e72fc5398a
15 changed files with 67 additions and 69 deletions

View File

@ -193,6 +193,7 @@ impl Client {
} }
let engine = spec.engine.clone(); let engine = spec.engine.clone();
let block_queue = BlockQueue::new(config.queue, engine.clone(), message_channel.clone()); let block_queue = BlockQueue::new(config.queue, engine.clone(), message_channel.clone());
let panic_handler = PanicHandler::new_in_arc(); let panic_handler = PanicHandler::new_in_arc();
panic_handler.forward_from(&block_queue); panic_handler.forward_from(&block_queue);

View File

@ -96,7 +96,7 @@ impl Default for TestBlockChainClient {
impl TestBlockChainClient { impl TestBlockChainClient {
/// Creates new test client. /// Creates new test client.
pub fn new() -> Self { pub fn new() -> Self {
let spec = Spec::new_test();
let mut client = TestBlockChainClient { let mut client = TestBlockChainClient {
blocks: RwLock::new(HashMap::new()), blocks: RwLock::new(HashMap::new()),
numbers: RwLock::new(HashMap::new()), numbers: RwLock::new(HashMap::new()),
@ -110,8 +110,8 @@ impl TestBlockChainClient {
execution_result: RwLock::new(None), execution_result: RwLock::new(None),
receipts: RwLock::new(HashMap::new()), receipts: RwLock::new(HashMap::new()),
queue_size: AtomicUsize::new(0), queue_size: AtomicUsize::new(0),
miner: Arc::new(Miner::with_spec(Spec::new_test())), miner: Arc::new(Miner::with_spec(&spec)),
spec: Spec::new_test(), spec: spec,
vm_factory: EvmFactory::new(VMType::Interpreter), vm_factory: EvmFactory::new(VMType::Interpreter),
}; };
client.add_blocks(1, EachBlockWith::Nothing); // add genesis block client.add_blocks(1, EachBlockWith::Nothing); // add genesis block

View File

@ -22,7 +22,6 @@ use tests::helpers::*;
use devtools::*; use devtools::*;
use spec::Genesis; use spec::Genesis;
use ethjson; use ethjson;
use ethjson::blockchain::BlockChain;
use miner::Miner; use miner::Miner;
use io::IoChannel; use io::IoChannel;
@ -43,7 +42,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
flush!(" - {}...", name); flush!(" - {}...", name);
let spec = |blockchain: &BlockChain| { let spec = {
let genesis = Genesis::from(blockchain.genesis()); let genesis = Genesis::from(blockchain.genesis());
let state = From::from(blockchain.pre_state.clone()); let state = From::from(blockchain.pre_state.clone());
let mut spec = match era { let mut spec = match era {
@ -61,9 +60,9 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
{ {
let client = Client::new( let client = Client::new(
ClientConfig::default(), ClientConfig::default(),
&spec(&blockchain), &spec,
temp.as_path(), temp.as_path(),
Arc::new(Miner::with_spec(spec(&blockchain))), Arc::new(Miner::with_spec(&spec)),
IoChannel::disconnected() IoChannel::disconnected()
).unwrap(); ).unwrap();
for b in &blockchain.blocks_rlp() { for b in &blockchain.blocks_rlp() {

View File

@ -177,7 +177,7 @@ pub struct Miner {
gas_range_target: RwLock<(U256, U256)>, gas_range_target: RwLock<(U256, U256)>,
author: RwLock<Address>, author: RwLock<Address>,
extra_data: RwLock<Bytes>, extra_data: RwLock<Bytes>,
spec: Spec, engine: Arc<Engine>,
accounts: Option<Arc<AccountProvider>>, accounts: Option<Arc<AccountProvider>>,
work_poster: Option<WorkPoster>, work_poster: Option<WorkPoster>,
@ -186,7 +186,7 @@ pub struct Miner {
impl Miner { impl Miner {
/// Creates new instance of miner without accounts, but with given spec. /// Creates new instance of miner without accounts, but with given spec.
pub fn with_spec(spec: Spec) -> Miner { pub fn with_spec(spec: &Spec) -> Miner {
Miner { Miner {
transaction_queue: Arc::new(Mutex::new(TransactionQueue::new())), transaction_queue: Arc::new(Mutex::new(TransactionQueue::new())),
options: Default::default(), options: Default::default(),
@ -197,14 +197,14 @@ impl Miner {
author: RwLock::new(Address::default()), author: RwLock::new(Address::default()),
extra_data: RwLock::new(Vec::new()), extra_data: RwLock::new(Vec::new()),
accounts: None, accounts: None,
spec: spec, engine: spec.engine.clone(),
work_poster: None, work_poster: None,
gas_pricer: Mutex::new(GasPricer::new_fixed(20_000_000_000u64.into())), gas_pricer: Mutex::new(GasPricer::new_fixed(20_000_000_000u64.into())),
} }
} }
/// Creates new instance of miner /// Creates new instance of miner
pub fn new(options: MinerOptions, gas_pricer: GasPricer, spec: Spec, accounts: Option<Arc<AccountProvider>>) -> Arc<Miner> { pub fn new(options: MinerOptions, gas_pricer: GasPricer, spec: &Spec, accounts: Option<Arc<AccountProvider>>) -> Arc<Miner> {
let work_poster = if !options.new_work_notify.is_empty() { Some(WorkPoster::new(&options.new_work_notify)) } else { None }; let work_poster = if !options.new_work_notify.is_empty() { Some(WorkPoster::new(&options.new_work_notify)) } else { None };
let txq = Arc::new(Mutex::new(TransactionQueue::with_limits(options.tx_queue_size, options.tx_gas_limit))); let txq = Arc::new(Mutex::new(TransactionQueue::with_limits(options.tx_queue_size, options.tx_gas_limit)));
Arc::new(Miner { Arc::new(Miner {
@ -217,16 +217,12 @@ impl Miner {
extra_data: RwLock::new(Vec::new()), extra_data: RwLock::new(Vec::new()),
options: options, options: options,
accounts: accounts, accounts: accounts,
spec: spec, engine: spec.engine.clone(),
work_poster: work_poster, work_poster: work_poster,
gas_pricer: Mutex::new(gas_pricer), gas_pricer: Mutex::new(gas_pricer),
}) })
} }
fn engine(&self) -> &Engine {
self.spec.engine.deref()
}
fn forced_sealing(&self) -> bool { fn forced_sealing(&self) -> bool {
self.options.force_sealing || !self.options.new_work_notify.is_empty() self.options.force_sealing || !self.options.new_work_notify.is_empty()
} }
@ -274,8 +270,7 @@ impl Miner {
Some(old_block) => { Some(old_block) => {
trace!(target: "miner", "Already have previous work; updating and returning"); trace!(target: "miner", "Already have previous work; updating and returning");
// add transactions to old_block // add transactions to old_block
let e = self.engine(); old_block.reopen(&*self.engine, chain.vm_factory())
old_block.reopen(e, chain.vm_factory())
} }
None => { None => {
// block not found - create it. // block not found - create it.
@ -338,13 +333,13 @@ impl Miner {
if !block.transactions().is_empty() { if !block.transactions().is_empty() {
trace!(target: "miner", "prepare_sealing: block has transaction - attempting internal seal."); trace!(target: "miner", "prepare_sealing: block has transaction - attempting internal seal.");
// block with transactions - see if we can seal immediately. // block with transactions - see if we can seal immediately.
let s = self.engine().generate_seal(block.block(), match self.accounts { let s = self.engine.generate_seal(block.block(), match self.accounts {
Some(ref x) => Some(&**x), Some(ref x) => Some(&**x),
None => None, None => None,
}); });
if let Some(seal) = s { if let Some(seal) = s {
trace!(target: "miner", "prepare_sealing: managed internal seal. importing..."); trace!(target: "miner", "prepare_sealing: managed internal seal. importing...");
if let Ok(sealed) = block.lock().try_seal(self.engine(), seal) { if let Ok(sealed) = block.lock().try_seal(&*self.engine, seal) {
if let Ok(_) = chain.import_block(sealed.rlp_bytes()) { if let Ok(_) = chain.import_block(sealed.rlp_bytes()) {
trace!(target: "miner", "prepare_sealing: sealed internally and imported. leaving."); trace!(target: "miner", "prepare_sealing: sealed internally and imported. leaving.");
} else { } else {
@ -497,7 +492,7 @@ impl MinerService for Miner {
state.add_balance(&sender, &(needed_balance - balance)); state.add_balance(&sender, &(needed_balance - balance));
} }
let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false }; let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false };
let mut ret = try!(Executive::new(&mut state, &env_info, self.engine(), chain.vm_factory()).transact(t, options)); let mut ret = try!(Executive::new(&mut state, &env_info, &*self.engine, chain.vm_factory()).transact(t, options));
// TODO gav move this into Executive. // TODO gav move this into Executive.
ret.state_diff = original_state.map(|original| state.diff_from(original)); ret.state_diff = original_state.map(|original| state.diff_from(original));
@ -795,7 +790,7 @@ impl MinerService for Miner {
fn submit_seal(&self, chain: &MiningBlockChainClient, pow_hash: H256, seal: Vec<Bytes>) -> Result<(), Error> { fn submit_seal(&self, chain: &MiningBlockChainClient, pow_hash: H256, seal: Vec<Bytes>) -> Result<(), Error> {
let result = if let Some(b) = self.sealing_work.lock().queue.get_used_if(if self.options.enable_resubmission { GetAction::Clone } else { GetAction::Take }, |b| &b.hash() == &pow_hash) { let result = if let Some(b) = self.sealing_work.lock().queue.get_used_if(if self.options.enable_resubmission { GetAction::Clone } else { GetAction::Take }, |b| &b.hash() == &pow_hash) {
b.lock().try_seal(self.engine(), seal).or_else(|_| { b.lock().try_seal(&*self.engine, seal).or_else(|_| {
warn!(target: "miner", "Mined solution rejected: Invalid."); warn!(target: "miner", "Mined solution rejected: Invalid.");
Err(Error::PowInvalid) Err(Error::PowInvalid)
}) })
@ -897,7 +892,7 @@ mod tests {
fn should_prepare_block_to_seal() { fn should_prepare_block_to_seal() {
// given // given
let client = TestBlockChainClient::default(); let client = TestBlockChainClient::default();
let miner = Miner::with_spec(Spec::new_test()); let miner = Miner::with_spec(&Spec::new_test());
// when // when
let sealing_work = miner.map_sealing_work(&client, |_| ()); let sealing_work = miner.map_sealing_work(&client, |_| ());
@ -908,7 +903,7 @@ mod tests {
fn should_still_work_after_a_couple_of_blocks() { fn should_still_work_after_a_couple_of_blocks() {
// given // given
let client = TestBlockChainClient::default(); let client = TestBlockChainClient::default();
let miner = Miner::with_spec(Spec::new_test()); let miner = Miner::with_spec(&Spec::new_test());
let res = miner.map_sealing_work(&client, |b| b.block().fields().header.hash()); let res = miner.map_sealing_work(&client, |b| b.block().fields().header.hash());
assert!(res.is_some()); assert!(res.is_some());
@ -940,7 +935,7 @@ mod tests {
enable_resubmission: true, enable_resubmission: true,
}, },
GasPricer::new_fixed(0u64.into()), GasPricer::new_fixed(0u64.into()),
Spec::new_test(), &Spec::new_test(),
None, // accounts provider None, // accounts provider
)).ok().expect("Miner was just created.") )).ok().expect("Miner was just created.")
} }

View File

@ -32,12 +32,12 @@
//! use ethcore::miner::{Miner, MinerService}; //! use ethcore::miner::{Miner, MinerService};
//! //!
//! fn main() { //! fn main() {
//! let miner: Miner = Miner::with_spec(ethereum::new_frontier()); //! let miner: Miner = Miner::with_spec(&ethereum::new_frontier());
//! // get status //! // get status
//! assert_eq!(miner.status().transactions_in_pending_queue, 0); //! assert_eq!(miner.status().transactions_in_pending_queue, 0);
//! //!
//! // Check block for sealing //! // Check block for sealing
//! //assert!(miner.sealing_block(client.deref()).lock().is_some()); //! //assert!(miner.sealing_block(&*client).lock().is_some());
//! } //! }
//! ``` //! ```

View File

@ -58,7 +58,7 @@ impl ClientService {
/// Start the service in a separate thread. /// Start the service in a separate thread.
pub fn start( pub fn start(
config: ClientConfig, config: ClientConfig,
spec: Spec, spec: &Spec,
db_path: &Path, db_path: &Path,
miner: Arc<Miner>, miner: Arc<Miner>,
) -> Result<ClientService, Error> ) -> Result<ClientService, Error>
@ -198,11 +198,12 @@ mod tests {
path.push("pruning"); path.push("pruning");
path.push("db"); path.push("db");
let spec = get_test_spec();
let service = ClientService::start( let service = ClientService::start(
ClientConfig::default(), ClientConfig::default(),
get_test_spec(), &spec,
&path, &path,
Arc::new(Miner::with_spec(get_test_spec())), Arc::new(Miner::with_spec(&spec)),
); );
assert!(service.is_ok()); assert!(service.is_ok());
} }

View File

@ -98,12 +98,12 @@ struct Restoration {
impl Restoration { impl Restoration {
// make a new restoration, building databases in the given path. // make a new restoration, building databases in the given path.
fn new(manifest: &ManifestData, pruning: Algorithm, path: &Path, spec: &Spec) -> Result<Self, Error> { fn new(manifest: &ManifestData, pruning: Algorithm, path: &Path, gb: &[u8]) -> Result<Self, Error> {
let cfg = DatabaseConfig::with_columns(::client::DB_NO_OF_COLUMNS); let cfg = DatabaseConfig::with_columns(::client::DB_NO_OF_COLUMNS);
let raw_db = Arc::new(try!(Database::open(&cfg, &*path.to_string_lossy()) let raw_db = Arc::new(try!(Database::open(&cfg, &*path.to_string_lossy())
.map_err(|s| UtilError::SimpleString(s)))); .map_err(|s| UtilError::SimpleString(s))));
let chain = BlockChain::new(Default::default(), &spec.genesis_block(), raw_db.clone()); let chain = BlockChain::new(Default::default(), gb, raw_db.clone());
let blocks = try!(BlockRebuilder::new(chain, manifest.block_number)); let blocks = try!(BlockRebuilder::new(chain, manifest.block_number));
Ok(Restoration { Ok(Restoration {
@ -173,14 +173,15 @@ pub struct Service {
pruning: Algorithm, pruning: Algorithm,
status: Mutex<RestorationStatus>, status: Mutex<RestorationStatus>,
reader: Option<LooseReader>, reader: Option<LooseReader>,
spec: Spec, engine: Arc<Engine>,
genesis_block: Bytes,
state_chunks: AtomicUsize, state_chunks: AtomicUsize,
block_chunks: AtomicUsize, block_chunks: AtomicUsize,
} }
impl Service { impl Service {
/// Create a new snapshot service. /// Create a new snapshot service.
pub fn new(spec: Spec, pruning: Algorithm, client_db: PathBuf, io_channel: Channel) -> Result<Self, Error> { pub fn new(spec: &Spec, pruning: Algorithm, client_db: PathBuf, io_channel: Channel) -> Result<Self, Error> {
let db_path = try!(client_db.parent().and_then(Path::parent) let db_path = try!(client_db.parent().and_then(Path::parent)
.ok_or_else(|| UtilError::SimpleString("Failed to find database root.".into()))).to_owned(); .ok_or_else(|| UtilError::SimpleString("Failed to find database root.".into()))).to_owned();
@ -199,7 +200,8 @@ impl Service {
pruning: pruning, pruning: pruning,
status: Mutex::new(RestorationStatus::Inactive), status: Mutex::new(RestorationStatus::Inactive),
reader: reader, reader: reader,
spec: spec, engine: spec.engine.clone(),
genesis_block: spec.genesis_block(),
state_chunks: AtomicUsize::new(0), state_chunks: AtomicUsize::new(0),
block_chunks: AtomicUsize::new(0), block_chunks: AtomicUsize::new(0),
}; };
@ -324,7 +326,7 @@ impl Service {
match is_state { match is_state {
true => rest.feed_state(hash, chunk), true => rest.feed_state(hash, chunk),
false => rest.feed_blocks(hash, chunk, &*self.spec.engine), false => rest.feed_blocks(hash, chunk, &*self.engine),
}.map(|_| rest.is_done()) }.map(|_| rest.is_done())
}; };
@ -411,7 +413,7 @@ impl SnapshotService for Service {
// make new restoration. // make new restoration.
let db_path = self.restoration_db(); let db_path = self.restoration_db();
*res = match Restoration::new(&manifest, self.pruning, &db_path, &self.spec) { *res = match Restoration::new(&manifest, self.pruning, &db_path, &self.genesis_block) {
Ok(b) => Some(b), Ok(b) => Some(b),
Err(e) => { Err(e) => {
warn!("encountered error {} while beginning snapshot restoration.", e); warn!("encountered error {} while beginning snapshot restoration.", e);

View File

@ -25,7 +25,8 @@ use miner::Miner;
#[test] #[test]
fn imports_from_empty() { fn imports_from_empty() {
let dir = RandomTempPath::new(); let dir = RandomTempPath::new();
let client = Client::new(ClientConfig::default(), &get_test_spec(), dir.as_path(), Arc::new(Miner::with_spec(get_test_spec())), IoChannel::disconnected()).unwrap(); let spec = get_test_spec();
let client = Client::new(ClientConfig::default(), &spec, dir.as_path(), Arc::new(Miner::with_spec(&spec)), IoChannel::disconnected()).unwrap();
client.import_verified_blocks(); client.import_verified_blocks();
client.flush_queue(); client.flush_queue();
} }
@ -43,7 +44,8 @@ fn returns_state_root_basic() {
#[test] #[test]
fn imports_good_block() { fn imports_good_block() {
let dir = RandomTempPath::new(); let dir = RandomTempPath::new();
let client = Client::new(ClientConfig::default(), &get_test_spec(), dir.as_path(), Arc::new(Miner::with_spec(get_test_spec())), IoChannel::disconnected()).unwrap(); let spec = get_test_spec();
let client = Client::new(ClientConfig::default(), &spec, dir.as_path(), Arc::new(Miner::with_spec(&spec)), IoChannel::disconnected()).unwrap();
let good_block = get_good_dummy_block(); let good_block = get_good_dummy_block();
if let Err(_) = client.import_block(good_block) { if let Err(_) = client.import_block(good_block) {
panic!("error importing block being good by definition"); panic!("error importing block being good by definition");
@ -58,7 +60,8 @@ fn imports_good_block() {
#[test] #[test]
fn query_none_block() { fn query_none_block() {
let dir = RandomTempPath::new(); let dir = RandomTempPath::new();
let client = Client::new(ClientConfig::default(), &get_test_spec(), dir.as_path(), Arc::new(Miner::with_spec(get_test_spec())), IoChannel::disconnected()).unwrap(); let spec = get_test_spec();
let client = Client::new(ClientConfig::default(), &spec, dir.as_path(), Arc::new(Miner::with_spec(&spec)), IoChannel::disconnected()).unwrap();
let non_existant = client.block_header(BlockID::Number(188)); let non_existant = client.block_header(BlockID::Number(188));
assert!(non_existant.is_none()); assert!(non_existant.is_none());

View File

@ -133,7 +133,7 @@ pub fn generate_dummy_client_with_spec_and_data<F>(get_test_spec: F, block_numbe
let dir = RandomTempPath::new(); let dir = RandomTempPath::new();
let test_spec = get_test_spec(); let test_spec = get_test_spec();
let client = Client::new(ClientConfig::default(), &get_test_spec(), dir.as_path(), Arc::new(Miner::with_spec(get_test_spec())), IoChannel::disconnected()).unwrap(); let client = Client::new(ClientConfig::default(), &test_spec, dir.as_path(), Arc::new(Miner::with_spec(&test_spec)), IoChannel::disconnected()).unwrap();
let test_engine = &test_spec.engine; let test_engine = &test_spec.engine;
let mut db_result = get_temp_journal_db(); let mut db_result = get_temp_journal_db();
@ -232,7 +232,8 @@ pub fn push_blocks_to_client(client: &Arc<Client>, timestamp_salt: u64, starting
pub fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> GuardedTempResult<Arc<Client>> { pub fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> GuardedTempResult<Arc<Client>> {
let dir = RandomTempPath::new(); let dir = RandomTempPath::new();
let client = Client::new(ClientConfig::default(), &get_test_spec(), dir.as_path(), Arc::new(Miner::with_spec(get_test_spec())), IoChannel::disconnected()).unwrap(); let test_spec = get_test_spec();
let client = Client::new(ClientConfig::default(), &test_spec, dir.as_path(), Arc::new(Miner::with_spec(&test_spec)), IoChannel::disconnected()).unwrap();
for block in &blocks { for block in &blocks {
if let Err(_) = client.import_block(block.clone()) { if let Err(_) = client.import_block(block.clone()) {
panic!("panic importing block which is well-formed"); panic!("panic importing block which is well-formed");

View File

@ -30,11 +30,12 @@ pub fn run_test_worker(scope: &crossbeam::Scope, stop: Arc<AtomicBool>, socket_p
let socket_path = socket_path.to_owned(); let socket_path = socket_path.to_owned();
scope.spawn(move || { scope.spawn(move || {
let temp = RandomTempPath::create_dir(); let temp = RandomTempPath::create_dir();
let spec = get_test_spec();
let client = Client::new( let client = Client::new(
ClientConfig::default(), ClientConfig::default(),
&get_test_spec(), &spec,
temp.as_path(), temp.as_path(),
Arc::new(Miner::with_spec(get_test_spec())), Arc::new(Miner::with_spec(&spec)),
IoChannel::disconnected()).unwrap(); IoChannel::disconnected()).unwrap();
let mut worker = nanoipc::Worker::new(&(client as Arc<BlockChainClient>)); let mut worker = nanoipc::Worker::new(&(client as Arc<BlockChainClient>));
worker.add_reqrep(&socket_path).unwrap(); worker.add_reqrep(&socket_path).unwrap();

View File

@ -136,9 +136,9 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
// build client // build client
let service = try!(ClientService::start( let service = try!(ClientService::start(
client_config, client_config,
spec, &spec,
Path::new(&client_path), Path::new(&client_path),
Arc::new(Miner::with_spec(try!(cmd.spec.spec()))), Arc::new(Miner::with_spec(&spec)),
).map_err(|e| format!("Client service error: {:?}", e))); ).map_err(|e| format!("Client service error: {:?}", e)));
panic_handler.forward_from(&service); panic_handler.forward_from(&service);
@ -246,9 +246,9 @@ fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
let service = try!(ClientService::start( let service = try!(ClientService::start(
client_config, client_config,
spec, &spec,
Path::new(&client_path), Path::new(&client_path),
Arc::new(Miner::with_spec(try!(cmd.spec.spec()))) Arc::new(Miner::with_spec(&spec)),
).map_err(|e| format!("Client service error: {:?}", e))); ).map_err(|e| format!("Client service error: {:?}", e)));
panic_handler.forward_from(&service); panic_handler.forward_from(&service);

View File

@ -139,7 +139,7 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> {
let account_provider = Arc::new(try!(prepare_account_provider(&cmd.dirs, cmd.acc_conf))); let account_provider = Arc::new(try!(prepare_account_provider(&cmd.dirs, cmd.acc_conf)));
// create miner // create miner
let miner = Miner::new(cmd.miner_options, cmd.gas_pricer.into(), spec, Some(account_provider.clone())); let miner = Miner::new(cmd.miner_options, cmd.gas_pricer.into(), &spec, Some(account_provider.clone()));
miner.set_author(cmd.miner_extras.author); miner.set_author(cmd.miner_extras.author);
miner.set_gas_floor_target(cmd.miner_extras.gas_floor_target); miner.set_gas_floor_target(cmd.miner_extras.gas_floor_target);
miner.set_gas_ceil_target(cmd.miner_extras.gas_ceil_target); miner.set_gas_ceil_target(cmd.miner_extras.gas_ceil_target);
@ -161,10 +161,6 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> {
fork_name.as_ref(), fork_name.as_ref(),
); );
// load spec
// TODO: make it clonable and load it only once!
let spec = try!(cmd.spec.spec());
// set up bootnodes // set up bootnodes
let mut net_conf = cmd.net_conf; let mut net_conf = cmd.net_conf;
if !cmd.custom_bootnodes { if !cmd.custom_bootnodes {
@ -174,7 +170,7 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> {
// create client service. // create client service.
let service = try!(ClientService::start( let service = try!(ClientService::start(
client_config, client_config,
spec, &spec,
Path::new(&client_path), Path::new(&client_path),
miner.clone(), miner.clone(),
).map_err(|e| format!("Client service error: {:?}", e))); ).map_err(|e| format!("Client service error: {:?}", e)));

View File

@ -89,9 +89,9 @@ impl SnapshotCommand {
let service = try!(ClientService::start( let service = try!(ClientService::start(
client_config, client_config,
spec, &spec,
Path::new(&client_path), Path::new(&client_path),
Arc::new(Miner::with_spec(try!(self.spec.spec()))) Arc::new(Miner::with_spec(&spec))
).map_err(|e| format!("Client service error: {:?}", e))); ).map_err(|e| format!("Client service error: {:?}", e)));
Ok((service, panic_handler)) Ok((service, panic_handler))

View File

@ -50,7 +50,7 @@ fn sync_provider() -> Arc<TestSyncProvider> {
})) }))
} }
fn miner_service(spec: Spec, accounts: Arc<AccountProvider>) -> Arc<Miner> { fn miner_service(spec: &Spec, accounts: Arc<AccountProvider>) -> Arc<Miner> {
Miner::new( Miner::new(
MinerOptions { MinerOptions {
new_work_notify: vec![], new_work_notify: vec![],
@ -65,8 +65,8 @@ fn miner_service(spec: Spec, accounts: Arc<AccountProvider>) -> Arc<Miner> {
enable_resubmission: true, enable_resubmission: true,
}, },
GasPricer::new_fixed(20_000_000_000u64.into()), GasPricer::new_fixed(20_000_000_000u64.into()),
spec, &spec,
Some(accounts) Some(accounts),
) )
} }
@ -89,7 +89,7 @@ struct EthTester {
impl EthTester { impl EthTester {
fn from_chain(chain: &BlockChain) -> Self { fn from_chain(chain: &BlockChain) -> Self {
let tester = Self::from_spec_provider(|| make_spec(chain)); let tester = Self::from_spec(make_spec(chain));
for b in &chain.blocks_rlp() { for b in &chain.blocks_rlp() {
if Block::is_good(&b) { if Block::is_good(&b) {
@ -105,13 +105,11 @@ impl EthTester {
tester tester
} }
fn from_spec_provider<F>(spec_provider: F) -> Self fn from_spec(spec: Spec) -> Self {
where F: Fn() -> Spec {
let dir = RandomTempPath::new(); let dir = RandomTempPath::new();
let account_provider = account_provider(); let account_provider = account_provider();
let miner_service = miner_service(spec_provider(), account_provider.clone()); let miner_service = miner_service(&spec, account_provider.clone());
let client = Client::new(ClientConfig::default(), &spec_provider(), dir.as_path(), miner_service.clone(), IoChannel::disconnected()).unwrap(); let client = Client::new(ClientConfig::default(), &spec, dir.as_path(), miner_service.clone(), IoChannel::disconnected()).unwrap();
let sync_provider = sync_provider(); let sync_provider = sync_provider();
let external_miner = Arc::new(ExternalMiner::default()); let external_miner = Arc::new(ExternalMiner::default());
@ -291,7 +289,7 @@ fn eth_transaction_count() {
use util::crypto::Secret; use util::crypto::Secret;
let secret = Secret::from_str("8a283037bb19c4fed7b1c569e40c7dcff366165eb869110a1b11532963eb9cb2").unwrap(); let secret = Secret::from_str("8a283037bb19c4fed7b1c569e40c7dcff366165eb869110a1b11532963eb9cb2").unwrap();
let tester = EthTester::from_spec_provider(|| Spec::load(TRANSACTION_COUNT_SPEC)); let tester = EthTester::from_spec(Spec::load(TRANSACTION_COUNT_SPEC));
let address = tester.accounts.insert_account(secret, "").unwrap(); let address = tester.accounts.insert_account(secret, "").unwrap();
tester.accounts.unlock_account_permanently(address, "".into()).unwrap(); tester.accounts.unlock_account_permanently(address, "".into()).unwrap();
@ -417,7 +415,7 @@ fn verify_transaction_counts(name: String, chain: BlockChain) {
#[test] #[test]
fn starting_nonce_test() { fn starting_nonce_test() {
let tester = EthTester::from_spec_provider(|| Spec::load(POSITIVE_NONCE_SPEC)); let tester = EthTester::from_spec(Spec::load(POSITIVE_NONCE_SPEC));
let address = ::util::hash::Address::from(10); let address = ::util::hash::Address::from(10);
let sample = tester.handler.handle_request(&(r#" let sample = tester.handler.handle_request(&(r#"

View File

@ -43,15 +43,16 @@
//! //!
//! fn main() { //! fn main() {
//! let dir = env::temp_dir(); //! let dir = env::temp_dir();
//! let spec = ethereum::new_frontier();
//! let miner = Miner::new( //! let miner = Miner::new(
//! Default::default(), //! Default::default(),
//! GasPricer::new_fixed(20_000_000_000u64.into()), //! GasPricer::new_fixed(20_000_000_000u64.into()),
//! ethereum::new_frontier(), //! &spec,
//! None //! None
//! ); //! );
//! let client = Client::new( //! let client = Client::new(
//! ClientConfig::default(), //! ClientConfig::default(),
//! &ethereum::new_frontier(), //! &spec,
//! &dir, //! &dir,
//! miner, //! miner,
//! IoChannel::disconnected() //! IoChannel::disconnected()