2017-01-25 18:51:41 +01:00
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
2016-04-21 13:57:27 +02:00
// 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 <http://www.gnu.org/licenses/>.
2017-01-06 16:05:58 +01:00
use std ::path ::PathBuf ;
2016-04-21 13:57:27 +02:00
use std ::sync ::Arc ;
2017-01-30 10:46:50 +01:00
use dir ::default_data_path ;
2016-08-23 19:28:21 +02:00
use ethcore ::client ::Client ;
2017-02-04 22:18:19 +01:00
use ethcore_rpc ::informant ::RpcStats ;
2016-09-01 11:16:19 +02:00
use ethsync ::SyncProvider ;
2017-01-30 10:46:50 +01:00
use hash_fetch ::fetch ::Client as FetchClient ;
2016-07-25 16:09:47 +02:00
use helpers ::replace_home ;
2017-01-30 10:46:50 +01:00
use rpc_apis ::{ self , SignerService } ;
2017-03-22 07:02:14 +01:00
use parity_reactor ;
2016-04-21 13:57:27 +02:00
2016-07-25 16:09:47 +02:00
#[ derive(Debug, PartialEq, Clone) ]
2016-04-21 13:57:27 +02:00
pub struct Configuration {
pub enabled : bool ,
pub interface : String ,
pub port : u16 ,
2016-08-25 08:57:13 +02:00
pub hosts : Option < Vec < String > > ,
2017-03-07 17:33:28 +01:00
pub cors : Option < Vec < String > > ,
2016-04-21 13:57:27 +02:00
pub user : Option < String > ,
pub pass : Option < String > ,
2017-01-06 16:05:58 +01:00
pub dapps_path : PathBuf ,
pub extra_dapps : Vec < PathBuf > ,
2017-01-30 10:46:50 +01:00
pub all_apis : bool ,
2016-04-21 13:57:27 +02:00
}
2016-07-25 16:09:47 +02:00
impl Default for Configuration {
fn default ( ) -> Self {
2016-12-13 23:38:29 +01:00
let data_dir = default_data_path ( ) ;
2016-07-25 16:09:47 +02:00
Configuration {
enabled : true ,
interface : " 127.0.0.1 " . into ( ) ,
port : 8080 ,
2016-08-25 08:57:13 +02:00
hosts : Some ( Vec ::new ( ) ) ,
2017-03-07 17:33:28 +01:00
cors : None ,
2016-07-25 16:09:47 +02:00
user : None ,
pass : None ,
2017-01-06 16:05:58 +01:00
dapps_path : replace_home ( & data_dir , " $BASE/dapps " ) . into ( ) ,
extra_dapps : vec ! [ ] ,
2017-01-30 10:46:50 +01:00
all_apis : false ,
2016-07-25 16:09:47 +02:00
}
}
}
2016-04-21 13:57:27 +02:00
pub struct Dependencies {
2016-06-01 19:37:34 +02:00
pub apis : Arc < rpc_apis ::Dependencies > ,
2016-08-23 19:28:21 +02:00
pub client : Arc < Client > ,
2016-09-01 11:16:19 +02:00
pub sync : Arc < SyncProvider > ,
2017-03-22 07:02:14 +01:00
pub remote : parity_reactor ::TokioRemote ,
2016-12-22 18:26:39 +01:00
pub fetch : FetchClient ,
2016-12-27 11:15:02 +01:00
pub signer : Arc < SignerService > ,
2017-02-04 22:18:19 +01:00
pub stats : Arc < RpcStats > ,
2016-04-21 13:57:27 +02:00
}
2016-07-25 16:09:47 +02:00
pub fn new ( configuration : Configuration , deps : Dependencies ) -> Result < Option < WebappServer > , String > {
2016-04-21 13:57:27 +02:00
if ! configuration . enabled {
2016-07-25 16:09:47 +02:00
return Ok ( None ) ;
2016-04-21 13:57:27 +02:00
}
2016-06-24 12:10:36 +02:00
let url = format! ( " {} : {} " , configuration . interface , configuration . port ) ;
2016-12-27 12:53:56 +01:00
let addr = url . parse ( ) . map_err ( | _ | format! ( " Invalid Webapps listen host/port given: {} " , url ) ) ? ;
2016-04-21 13:57:27 +02:00
let auth = configuration . user . as_ref ( ) . map ( | username | {
let password = configuration . pass . as_ref ( ) . map_or_else ( | | {
use rpassword ::read_password ;
println! ( " Type password for WebApps server (user: {} ): " , username ) ;
let pass = read_password ( ) . unwrap ( ) ;
println! ( " OK, got it. Starting server... " ) ;
pass
} , | pass | pass . to_owned ( ) ) ;
( username . to_owned ( ) , password )
} ) ;
2017-01-06 16:05:58 +01:00
Ok ( Some ( setup_dapps_server (
deps ,
configuration . dapps_path ,
configuration . extra_dapps ,
& addr ,
configuration . hosts ,
2017-03-07 17:33:28 +01:00
configuration . cors ,
2017-01-30 10:46:50 +01:00
auth ,
configuration . all_apis ,
2017-01-06 16:05:58 +01:00
) ? ) )
2016-04-21 13:57:27 +02:00
}
2016-08-23 19:28:21 +02:00
pub use self ::server ::WebappServer ;
pub use self ::server ::setup_dapps_server ;
2016-05-26 18:21:15 +02:00
#[ cfg(not(feature = " dapps " )) ]
2016-08-23 19:28:21 +02:00
mod server {
use super ::Dependencies ;
use std ::net ::SocketAddr ;
2017-01-09 11:16:05 +01:00
use std ::path ::PathBuf ;
2016-08-23 19:28:21 +02:00
pub struct WebappServer ;
pub fn setup_dapps_server (
_deps : Dependencies ,
2017-01-06 16:05:58 +01:00
_dapps_path : PathBuf ,
_extra_dapps : Vec < PathBuf > ,
2016-08-23 19:28:21 +02:00
_url : & SocketAddr ,
2016-08-25 08:57:13 +02:00
_allowed_hosts : Option < Vec < String > > ,
2017-03-07 17:33:28 +01:00
_cors : Option < Vec < String > > ,
2016-08-23 19:28:21 +02:00
_auth : Option < ( String , String ) > ,
2017-01-30 10:46:50 +01:00
_all_apis : bool ,
2016-08-23 19:28:21 +02:00
) -> Result < WebappServer , String > {
Err ( " Your Parity version has been compiled without WebApps support. " . into ( ) )
}
2016-04-21 13:57:27 +02:00
}
2016-05-26 18:21:15 +02:00
#[ cfg(feature = " dapps " ) ]
2016-08-23 19:28:21 +02:00
mod server {
use super ::Dependencies ;
2017-01-06 16:05:58 +01:00
use std ::path ::PathBuf ;
2016-08-23 19:28:21 +02:00
use std ::sync ::Arc ;
use std ::net ::SocketAddr ;
2016-10-25 15:55:53 +02:00
use std ::io ;
2016-08-23 19:28:21 +02:00
use util ::{ Bytes , Address , U256 } ;
2017-01-30 10:46:50 +01:00
use ansi_term ::Colour ;
2016-08-23 19:28:21 +02:00
use ethcore ::transaction ::{ Transaction , Action } ;
2016-12-09 23:01:43 +01:00
use ethcore ::client ::{ Client , BlockChainClient , BlockId } ;
2017-03-22 07:02:14 +01:00
use ethcore_dapps ::{ AccessControlAllowOrigin , Host } ;
2016-10-20 23:36:18 +02:00
use ethcore_rpc ::is_major_importing ;
2016-11-20 22:40:23 +01:00
use hash_fetch ::urlhint ::ContractClient ;
2017-01-11 20:02:27 +01:00
use parity_reactor ;
2017-01-30 10:46:50 +01:00
use rpc_apis ;
2016-08-23 19:28:21 +02:00
pub use ethcore_dapps ::Server as WebappServer ;
pub fn setup_dapps_server (
deps : Dependencies ,
2017-01-06 16:05:58 +01:00
dapps_path : PathBuf ,
extra_dapps : Vec < PathBuf > ,
2016-08-23 19:28:21 +02:00
url : & SocketAddr ,
2016-08-25 08:57:13 +02:00
allowed_hosts : Option < Vec < String > > ,
2017-03-07 17:33:28 +01:00
cors : Option < Vec < String > > ,
2016-10-19 11:02:21 +02:00
auth : Option < ( String , String ) > ,
2017-01-30 10:46:50 +01:00
all_apis : bool ,
2016-08-23 19:28:21 +02:00
) -> Result < WebappServer , String > {
use ethcore_dapps as dapps ;
2016-12-27 16:38:55 +01:00
let server = dapps ::ServerBuilder ::new (
2017-01-06 16:05:58 +01:00
& dapps_path ,
2016-12-22 18:26:39 +01:00
Arc ::new ( Registrar { client : deps . client . clone ( ) } ) ,
2017-01-11 20:02:27 +01:00
parity_reactor ::Remote ::new ( deps . remote . clone ( ) ) ,
2016-09-01 11:16:19 +02:00
) ;
2017-03-22 07:02:14 +01:00
let allowed_hosts : Option < Vec < _ > > = allowed_hosts . map ( | hosts | hosts . into_iter ( ) . map ( Host ::from ) . collect ( ) ) ;
let cors : Option < Vec < _ > > = cors . map ( | cors | cors . into_iter ( ) . map ( AccessControlAllowOrigin ::from ) . collect ( ) ) ;
2017-01-11 20:02:27 +01:00
2016-09-01 11:16:19 +02:00
let sync = deps . sync . clone ( ) ;
2016-10-20 23:36:18 +02:00
let client = deps . client . clone ( ) ;
2016-12-27 11:15:02 +01:00
let signer = deps . signer . clone ( ) ;
2016-12-27 16:38:55 +01:00
let server = server
. fetch ( deps . fetch . clone ( ) )
. sync_status ( Arc ::new ( move | | is_major_importing ( Some ( sync . status ( ) . state ) , client . queue_info ( ) ) ) )
. web_proxy_tokens ( Arc ::new ( move | token | signer . is_valid_web_proxy_access_token ( & token ) ) )
2017-01-06 16:05:58 +01:00
. extra_dapps ( & extra_dapps )
2017-01-11 20:02:27 +01:00
. signer_address ( deps . signer . address ( ) )
2017-03-22 07:02:14 +01:00
. allowed_hosts ( allowed_hosts . into ( ) )
. extra_cors_headers ( cors . into ( ) ) ;
2016-10-19 11:02:21 +02:00
2017-01-30 10:46:50 +01:00
let api_set = if all_apis {
warn! ( " {} " , Colour ::Red . bold ( ) . paint ( " *** INSECURE *** Running Dapps with all APIs exposed. " ) ) ;
info! ( " If you do not intend this, exit now. " ) ;
rpc_apis ::ApiSet ::SafeContext
} else {
rpc_apis ::ApiSet ::UnsafeContext
} ;
2017-02-04 22:18:19 +01:00
let apis = rpc_apis ::setup_rpc ( deps . stats , deps . apis . clone ( ) , api_set ) ;
2016-08-23 19:28:21 +02:00
let start_result = match auth {
None = > {
2017-03-22 07:02:14 +01:00
server . start_unsecured_http ( url , apis , deps . remote )
2016-08-23 19:28:21 +02:00
} ,
Some ( ( username , password ) ) = > {
2017-03-22 07:02:14 +01:00
server . start_basic_auth_http ( url , & username , & password , apis , deps . remote )
2016-08-23 19:28:21 +02:00
} ,
} ;
match start_result {
2016-10-25 15:55:53 +02:00
Err ( dapps ::ServerError ::IoError ( err ) ) = > match err . kind ( ) {
io ::ErrorKind ::AddrInUse = > Err ( format! ( " WebApps address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --dapps-port and --dapps-interface options. " , url ) ) ,
_ = > Err ( format! ( " WebApps io error: {} " , err ) ) ,
} ,
2016-08-23 19:28:21 +02:00
Err ( e ) = > Err ( format! ( " WebApps error: {:?} " , e ) ) ,
2017-03-22 07:02:14 +01:00
Ok ( server ) = > Ok ( server ) ,
2016-08-23 19:28:21 +02:00
}
2016-04-21 13:57:27 +02:00
}
2016-08-23 19:28:21 +02:00
struct Registrar {
client : Arc < Client > ,
}
impl ContractClient for Registrar {
fn registrar ( & self ) -> Result < Address , String > {
self . client . additional_params ( ) . get ( " registrar " )
. ok_or_else ( | | " Registrar not defined. " . into ( ) )
. and_then ( | registrar | {
registrar . parse ( ) . map_err ( | e | format! ( " Invalid registrar address: {:?} " , e ) )
} )
}
fn call ( & self , address : Address , data : Bytes ) -> Result < Bytes , String > {
let from = Address ::default ( ) ;
let transaction = Transaction {
nonce : self . client . latest_nonce ( & from ) ,
action : Action ::Call ( address ) ,
gas : U256 ::from ( 50_000_000 ) ,
gas_price : U256 ::default ( ) ,
value : U256 ::default ( ) ,
data : data ,
} . fake_sign ( from ) ;
2016-12-09 23:01:43 +01:00
self . client . call ( & transaction , BlockId ::Latest , Default ::default ( ) )
2016-08-23 19:28:21 +02:00
. map_err ( | e | format! ( " {:?} " , e ) )
. map ( | executed | {
executed . output
} )
}
}
}