diff --git a/Cargo.lock b/Cargo.lock index b0c9e5eb3..932b077fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -356,10 +356,15 @@ dependencies = [ "jsonrpc-core 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-idmanager 0.1.3 (git+https://github.com/ethcore/parity-idmanager-rs.git)", - "parity-status 0.4.1 (git+https://github.com/ethcore/parity-status.git)", - "parity-wallet 0.3.0 (git+https://github.com/ethcore/parity-wallet.git)", - "parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)", + "parity-idmanager 0.2.2 (git+https://github.com/ethcore/parity-idmanager-rs.git)", + "parity-status 0.4.3 (git+https://github.com/ethcore/parity-status.git)", + "parity-wallet 0.4.0 (git+https://github.com/ethcore/parity-wallet.git)", + "parity-webapp 0.2.0 (git+https://github.com/ethcore/parity-webapp.git)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -831,32 +836,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "parity-idmanager" -version = "0.1.3" -source = "git+https://github.com/ethcore/parity-idmanager-rs.git#efb69592b87854f41d8882de75982c8f1e748666" +version = "0.2.2" +source = "git+https://github.com/ethcore/parity-idmanager-rs.git#e93ef48a78722561d52ab88c3dfcc5c1465558ac" dependencies = [ - "parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)", + "parity-webapp 0.2.0 (git+https://github.com/ethcore/parity-webapp.git)", ] [[package]] name = "parity-status" -version = "0.4.1" -source = "git+https://github.com/ethcore/parity-status.git#f121ebd1f49986545d9fc262ba210cdf07039e6d" +version = "0.4.3" +source = "git+https://github.com/ethcore/parity-status.git#1d383d74010f6ebcd712b60b8fc5ff547b44f4e5" dependencies = [ - "parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)", + "parity-webapp 0.2.0 (git+https://github.com/ethcore/parity-webapp.git)", ] [[package]] name = "parity-wallet" -version = "0.3.0" -source = "git+https://github.com/ethcore/parity-wallet.git#664fd2b85dd94ca184868bd3965e14a4ba68c03f" +version = "0.4.0" +source = "git+https://github.com/ethcore/parity-wallet.git#5391a89dc5dbf162d1beeba555f03c24bfd619bd" dependencies = [ - "parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)", + "parity-webapp 0.2.0 (git+https://github.com/ethcore/parity-webapp.git)", ] [[package]] name = "parity-webapp" -version = "0.1.0" -source = "git+https://github.com/ethcore/parity-webapp.git#0bf133f193863ba0e88b0b824a5c330037cce3f1" +version = "0.2.0" +source = "git+https://github.com/ethcore/parity-webapp.git#f31681af69631bcadfbef89a7e60dcc49552f7c6" [[package]] name = "primal" diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 1ceffbb6a..dae7f4139 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -436,10 +436,6 @@ impl BlockChainClient for Client where V: Verifier { block.try_seal(self.engine.deref().deref(), seal) } - fn engine(&self) -> &Engine { - self.engine.deref().deref() - } - fn vm_factory(&self) -> &EvmFactory { &self.vm_factory } diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 0acfa1bbe..6fb4f5389 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -35,17 +35,15 @@ use std::collections::HashSet; use util::bytes::Bytes; use util::hash::{Address, H256, H2048}; use util::numbers::U256; -use util::keys::store::AccountProvider; use blockchain::TreeRoute; use block_queue::BlockQueueInfo; -use block::{ExecutedBlock, ClosedBlock, LockedBlock, SealedBlock}; +use block::{ClosedBlock, LockedBlock, SealedBlock}; use header::{BlockNumber, Header}; use transaction::{LocalizedTransaction, SignedTransaction}; use log_entry::LocalizedLogEntry; use filter::Filter; use error::{ImportResult, ExecutionError}; use receipt::LocalizedReceipt; -use engine::{Engine}; use trace::LocalizedTrace; use evm::Factory as EvmFactory; @@ -137,12 +135,6 @@ pub trait BlockChainClient : Sync + Send { /// Makes a non-persistent transaction call. fn call(&self, t: &SignedTransaction) -> Result; - /// Attempt to seal the block internally. See `Engine`. - fn generate_seal(&self, block: &ExecutedBlock, accounts: Option<&AccountProvider>) -> Option> { self.engine().generate_seal(block, accounts) } - - /// Executes a function providing it with a reference to an engine. - fn engine(&self) -> &Engine; - /// Returns EvmFactory. fn vm_factory(&self) -> &EvmFactory; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 80bb1d63d..279d4c0bc 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -33,7 +33,6 @@ use block_queue::BlockQueueInfo; use block::{SealedBlock, ClosedBlock, LockedBlock}; use executive::Executed; use error::{ExecutionError}; -use engine::Engine; use trace::LocalizedTrace; /// Test client. @@ -431,10 +430,6 @@ impl BlockChainClient for TestBlockChainClient { } } - fn engine(&self) -> &Engine { - unimplemented!(); - } - fn vm_factory(&self) -> &EvmFactory { unimplemented!(); } diff --git a/ethcore/src/engine.rs b/ethcore/src/engine.rs index d0c72f26c..ed482db89 100644 --- a/ethcore/src/engine.rs +++ b/ethcore/src/engine.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +//! Consensus engine specification + use common::*; use util::keys::store::AccountProvider; use block::ExecutedBlock; diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index f443647bd..c5fae168e 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -107,6 +107,7 @@ pub mod trace; pub mod spec; pub mod views; pub mod pod_state; +pub mod engine; mod db; mod common; @@ -116,7 +117,6 @@ mod env_info; mod pod_account; mod account_diff; mod state_diff; -mod engine; mod state; mod account; mod account_db; diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 35056bc03..e989fce90 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -25,6 +25,8 @@ use ethcore::block::{ClosedBlock, IsBlock}; use ethcore::error::*; use ethcore::client::{Executive, Executed, EnvInfo, TransactOptions}; use ethcore::transaction::SignedTransaction; +use ethcore::spec::Spec; +use ethcore::engine::Engine; use super::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; /// Keeps track of transactions using priority queue and holds currently mined block. @@ -39,6 +41,7 @@ pub struct Miner { gas_floor_target: RwLock, author: RwLock
, extra_data: RwLock, + spec: Spec, accounts: RwLock>>, // TODO: this is horrible since AccountService already contains a single RwLock field. refactor. } @@ -55,13 +58,14 @@ impl Default for Miner { author: RwLock::new(Address::default()), extra_data: RwLock::new(Vec::new()), accounts: RwLock::new(None), + spec: Spec::new_test(), } } } impl Miner { /// Creates new instance of miner - pub fn new(force_sealing: bool) -> Arc { + pub fn new(force_sealing: bool, spec: Spec) -> Arc { Arc::new(Miner { transaction_queue: Mutex::new(TransactionQueue::new()), force_sealing: force_sealing, @@ -72,11 +76,12 @@ impl Miner { author: RwLock::new(Address::default()), extra_data: RwLock::new(Vec::new()), accounts: RwLock::new(None), + spec: spec, }) } /// Creates new instance of miner - pub fn with_accounts(force_sealing: bool, accounts: Arc) -> Arc { + pub fn with_accounts(force_sealing: bool, spec: Spec, accounts: Arc) -> Arc { Arc::new(Miner { transaction_queue: Mutex::new(TransactionQueue::new()), force_sealing: force_sealing, @@ -87,9 +92,14 @@ impl Miner { author: RwLock::new(Address::default()), extra_data: RwLock::new(Vec::new()), accounts: RwLock::new(Some(accounts)), + spec: spec, }) } + fn engine(&self) -> &Engine { + self.spec.engine.deref() + } + /// Prepares new block for sealing including top transactions from queue. #[cfg_attr(feature="dev", allow(match_same_arms))] fn prepare_sealing(&self, chain: &BlockChainClient) { @@ -111,7 +121,7 @@ impl Miner { Some(old_block) => { trace!(target: "miner", "Already have previous work; updating and returning"); // add transactions to old_block - let e = chain.engine(); + let e = self.engine(); let mut invalid_transactions = HashSet::new(); let mut block = old_block.reopen(e, chain.vm_factory()); let block_number = block.block().fields().header.number(); @@ -166,7 +176,7 @@ impl Miner { trace!(target: "miner", "prepare_sealing: block has transaction - attempting internal seal."); // block with transactions - see if we can seal immediately. let a = self.accounts.read().unwrap(); - let s = chain.generate_seal(block.block(), match *a.deref() { + let s = self.engine().generate_seal(block.block(), match *a.deref() { Some(ref x) => Some(x.deref() as &AccountProvider), None => None, }); @@ -267,7 +277,8 @@ impl MinerService for Miner { state.sub_balance(&sender, &balance); state.add_balance(&sender, &U256::max_value()); let options = TransactOptions { tracing: false, check_nonce: false }; - Executive::new(&mut state, &env_info, chain.engine(), chain.vm_factory()).transact(t, options) + + Executive::new(&mut state, &env_info, self.engine(), chain.vm_factory()).transact(t, options) }, None => { chain.call(t) diff --git a/parity/main.rs b/parity/main.rs index 862e3d336..a2750dff4 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -145,7 +145,7 @@ fn execute_client(conf: Configuration) { let client = service.client(); // Miner - let miner = Miner::with_accounts(conf.args.flag_force_sealing, account_service.clone()); + let miner = Miner::with_accounts(conf.args.flag_force_sealing, conf.spec(), account_service.clone()); miner.set_author(conf.author()); miner.set_gas_floor_target(conf.gas_floor_target()); miner.set_extra_data(conf.extra_data()); diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 6e900e97e..dbbcc4708 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -45,7 +45,7 @@ //! let mut service = NetworkService::start(NetworkConfiguration::new()).unwrap(); //! let dir = env::temp_dir(); //! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(), &dir, service.io().channel()).unwrap(); -//! let miner = Miner::new(false); +//! let miner = Miner::new(false, ethereum::new_frontier()); //! EthSync::register(&mut service, SyncConfig::default(), client, miner); //! } //! ``` diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 41eadf716..461553924 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -16,6 +16,7 @@ use util::*; use ethcore::client::{TestBlockChainClient, BlockChainClient}; +use ethcore::spec::Spec; use io::SyncIo; use chain::ChainSync; use ethminer::Miner; @@ -93,7 +94,7 @@ impl TestNet { for _ in 0..n { net.peers.push(TestPeer { chain: TestBlockChainClient::new(), - sync: ChainSync::new(SyncConfig::default(), Miner::new(false)), + sync: ChainSync::new(SyncConfig::default(), Miner::new(false, Spec::new_test())), queue: VecDeque::new(), }); } diff --git a/webapp/Cargo.toml b/webapp/Cargo.toml index fe6fb9bf6..8f9353386 100644 --- a/webapp/Cargo.toml +++ b/webapp/Cargo.toml @@ -4,6 +4,7 @@ name = "ethcore-webapp" version = "1.2.0" license = "GPL-3.0" authors = ["Ethcore . + +#[cfg(not(feature = "serde_macros"))] +mod inner { + extern crate syntex; + extern crate serde_codegen; + + use std::env; + use std::path::Path; + + pub fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + + let src = Path::new("./src/api/mod.rs.in"); + let dst = Path::new(&out_dir).join("mod.rs"); + + let mut registry = syntex::Registry::new(); + + serde_codegen::register(&mut registry); + registry.expand("", &src, &dst).unwrap(); + } +} + +#[cfg(feature = "serde_macros")] +mod inner { + pub fn main() {} +} + +fn main() { + inner::main(); +} diff --git a/webapp/src/api.rs b/webapp/src/api/api.rs similarity index 59% rename from webapp/src/api.rs rename to webapp/src/api/api.rs index 75cdb4c58..fdfef1394 100644 --- a/webapp/src/api.rs +++ b/webapp/src/api/api.rs @@ -14,15 +14,26 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! Simple REST API - use std::sync::Arc; -use endpoint::{Endpoint, Endpoints, ContentHandler, Handler, EndpointPath}; +use endpoint::{Endpoint, Endpoints, Handler, EndpointPath}; + +use api::response::as_json; pub struct RestApi { endpoints: Arc, } +#[derive(Debug, PartialEq, Serialize)] +struct App { + pub id: String, + pub name: String, + pub description: String, + pub version: String, + pub author: String, + #[serde(rename="iconUrl")] + pub icon_url: String, +} + impl RestApi { pub fn new(endpoints: Arc) -> Box { Box::new(RestApi { @@ -30,20 +41,23 @@ impl RestApi { }) } - fn list_pages(&self) -> String { - let mut s = "[".to_owned(); - for name in self.endpoints.keys() { - s.push_str(&format!("\"{}\",", name)); - } - s.push_str("\"rpc\""); - s.push_str("]"); - s + fn list_apps(&self) -> Vec { + self.endpoints.iter().filter_map(|(ref k, ref e)| { + e.info().map(|ref info| App { + id: k.to_owned().clone(), + name: info.name.clone(), + description: info.description.clone(), + version: info.version.clone(), + author: info.author.clone(), + icon_url: info.icon_url.clone(), + }) + }).collect() } } impl Endpoint for RestApi { fn to_handler(&self, _path: EndpointPath) -> Box { - Box::new(ContentHandler::new(self.list_pages(), "application/json".to_owned())) + as_json(&self.list_apps()) } } diff --git a/webapp/src/api/mod.rs b/webapp/src/api/mod.rs new file mode 100644 index 000000000..088d7f6b2 --- /dev/null +++ b/webapp/src/api/mod.rs @@ -0,0 +1,28 @@ +// 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 . + +//! REST API + +#![warn(missing_docs)] +#![cfg_attr(feature="nightly", feature(custom_derive, custom_attribute, plugin))] +#![cfg_attr(feature="nightly", plugin(serde_macros, clippy))] + +#[cfg(feature = "serde_macros")] +include!("mod.rs.in"); + +#[cfg(not(feature = "serde_macros"))] +include!(concat!(env!("OUT_DIR"), "/mod.rs")); + diff --git a/webapp/src/api/mod.rs.in b/webapp/src/api/mod.rs.in new file mode 100644 index 000000000..0eff6b397 --- /dev/null +++ b/webapp/src/api/mod.rs.in @@ -0,0 +1,20 @@ +// 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 . + +mod api; +mod response; + +pub use self::api::RestApi; diff --git a/webapp/src/api/response.rs b/webapp/src/api/response.rs new file mode 100644 index 000000000..345b8a6ee --- /dev/null +++ b/webapp/src/api/response.rs @@ -0,0 +1,23 @@ +// 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 . + +use serde::Serialize; +use serde_json; +use endpoint::{ContentHandler, Handler}; + +pub fn as_json(val: &T) -> Box { + Box::new(ContentHandler::new(serde_json::to_string(val).unwrap(), "application/json".to_owned())) +} diff --git a/webapp/src/apps.rs b/webapp/src/apps.rs index 1c9b7e5a8..410a5bc2c 100644 --- a/webapp/src/apps.rs +++ b/webapp/src/apps.rs @@ -30,7 +30,7 @@ pub const API_PATH : &'static str = "api"; pub const UTILS_PATH : &'static str = "parity-utils"; pub fn main_page() -> &'static str { - "/status/" + "/home/" } pub fn utils() -> Box { @@ -43,6 +43,7 @@ pub fn all_endpoints() -> Endpoints { insert::(&mut pages, "status"); insert::(&mut pages, "parity"); + insert::(&mut pages, "home"); wallet_page(&mut pages); pages diff --git a/webapp/src/endpoint.rs b/webapp/src/endpoint.rs index d367734c4..ebb665b9d 100644 --- a/webapp/src/endpoint.rs +++ b/webapp/src/endpoint.rs @@ -30,7 +30,18 @@ pub struct EndpointPath { pub port: u16, } +#[derive(Debug, PartialEq)] +pub struct EndpointInfo { + pub name: String, + pub description: String, + pub version: String, + pub author: String, + pub icon_url: String, +} + pub trait Endpoint : Send + Sync { + fn info(&self) -> Option { None } + fn to_handler(&self, path: EndpointPath) -> Box>; } diff --git a/webapp/src/lib.rs b/webapp/src/lib.rs index 819e9d362..4cf8f0764 100644 --- a/webapp/src/lib.rs +++ b/webapp/src/lib.rs @@ -47,6 +47,8 @@ extern crate log; extern crate url; extern crate hyper; +extern crate serde; +extern crate serde_json; extern crate jsonrpc_core; extern crate jsonrpc_http_server; extern crate parity_webapp; diff --git a/webapp/src/page/mod.rs b/webapp/src/page/mod.rs index 1d987c393..c4e39161c 100644 --- a/webapp/src/page/mod.rs +++ b/webapp/src/page/mod.rs @@ -22,8 +22,8 @@ use hyper::header; use hyper::status::StatusCode; use hyper::net::HttpStream; use hyper::{Decoder, Encoder, Next}; -use endpoint::{Endpoint, EndpointPath}; -use parity_webapp::WebApp; +use endpoint::{Endpoint, EndpointInfo, EndpointPath}; +use parity_webapp::{WebApp, Info}; pub struct PageEndpoint { /// Content of the files @@ -39,6 +39,7 @@ impl PageEndpoint { prefix: None, } } + pub fn with_prefix(app: T, prefix: String) -> Self { PageEndpoint { app: Arc::new(app), @@ -48,6 +49,11 @@ impl PageEndpoint { } impl Endpoint for PageEndpoint { + + fn info(&self) -> Option { + Some(EndpointInfo::from(self.app.info())) + } + fn to_handler(&self, path: EndpointPath) -> Box> { Box::new(PageHandler { app: self.app.clone(), @@ -59,6 +65,18 @@ impl Endpoint for PageEndpoint { } } +impl From for EndpointInfo { + fn from(info: Info) -> Self { + EndpointInfo { + name: info.name, + description: info.description, + author: info.author, + icon_url: info.icon_url, + version: info.version, + } + } +} + struct PageHandler { app: Arc, prefix: Option,