980418898a
* Fix slow balances (#6471)
* Update token updates
* Update token info fetching
* Update logger
* Minor fixes to updates and notifications for balances
* Use Pubsub
* Fix timeout.
* Use pubsub for status.
* Fix signer subscription.
* Process tokens in chunks.
* Fix tokens loaded by chunks
* Linting
* Dispatch tokens asap
* Fix chunks processing.
* Better filter options
* Parallel log fetching.
* Fix signer polling.
* Fix initial block query.
* Token balances updates : the right(er) way
* Better tokens info fetching
* Fixes in token data fetching
* Only fetch what's needed (tokens)
* Fix linting issues
* Revert "Transaction permissioning (#6441)"
This reverts commit eed0e8b03a
.
* Revert "Revert "Transaction permissioning (#6441)""
This reverts commit 8f96415e58dde652e5828706eb2639d43416f448.
* Update wasm-tests.
* Fixing balances fetching
* Fix requests tracking in UI
* Fix request watching
* Update the Logger
* PR Grumbles Fixes
* PR Grumbles fixes
* Linting...
* eth_call returns output of contract creations (#6420)
* eth_call returns output of contract creations
* Fix parameters order.
* Save outputs for light client as well.
* Don't accept transactions above block gas limit.
* Expose health status over RPC (#6274)
* Node-health to a separate crate.
* Initialize node_health outside of dapps.
* Expose health over RPC.
* Bring back 412 and fix JS.
* Add health to workspace and tests.
* Fix compilation without default features.
* Fix borked merge.
* Revert to generics to avoid virtual calls.
* Fix node-health tests.
* Add missing trailing comma.
* Fixing/removing failing JS tests.
* do not activate genesis epoch in immediate transition validator contract (#6349)
* Fix memory tracing.
* Add test to cover that.
* ensure balances of constructor accounts are kept
* test balance of spec-constructed account is kept
284 lines
6.9 KiB
Rust
284 lines
6.9 KiB
Rust
// Copyright 2015-2017 Parity Technologies (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 <http://www.gnu.org/licenses/>.
|
|
|
|
//! Ethcore Webapplications for Parity
|
|
#![warn(missing_docs)]
|
|
#![cfg_attr(feature="nightly", feature(plugin))]
|
|
#![cfg_attr(feature="nightly", plugin(clippy))]
|
|
|
|
extern crate base32;
|
|
extern crate futures;
|
|
extern crate linked_hash_map;
|
|
extern crate mime_guess;
|
|
extern crate rand;
|
|
extern crate rustc_hex;
|
|
extern crate serde;
|
|
extern crate serde_json;
|
|
extern crate time;
|
|
extern crate unicase;
|
|
extern crate url as url_lib;
|
|
extern crate zip;
|
|
|
|
extern crate jsonrpc_core;
|
|
extern crate jsonrpc_http_server;
|
|
|
|
extern crate ethcore_util as util;
|
|
extern crate fetch;
|
|
extern crate node_health;
|
|
extern crate parity_dapps_glue as parity_dapps;
|
|
extern crate parity_hash_fetch as hash_fetch;
|
|
extern crate parity_reactor;
|
|
extern crate parity_ui;
|
|
|
|
#[macro_use]
|
|
extern crate log;
|
|
#[macro_use]
|
|
extern crate mime;
|
|
#[macro_use]
|
|
extern crate serde_derive;
|
|
|
|
#[cfg(test)]
|
|
extern crate ethcore_devtools as devtools;
|
|
#[cfg(test)]
|
|
extern crate env_logger;
|
|
|
|
mod endpoint;
|
|
mod apps;
|
|
mod page;
|
|
mod router;
|
|
mod handlers;
|
|
mod api;
|
|
mod proxypac;
|
|
mod url;
|
|
mod web;
|
|
#[cfg(test)]
|
|
mod tests;
|
|
|
|
use std::path::PathBuf;
|
|
use std::sync::Arc;
|
|
use std::collections::HashMap;
|
|
|
|
use jsonrpc_http_server::{self as http, hyper, Origin};
|
|
|
|
use fetch::Fetch;
|
|
use node_health::NodeHealth;
|
|
use parity_reactor::Remote;
|
|
|
|
pub use hash_fetch::urlhint::ContractClient;
|
|
pub use node_health::SyncStatus;
|
|
|
|
|
|
/// Validates Web Proxy tokens
|
|
pub trait WebProxyTokens: Send + Sync {
|
|
/// Should return a domain allowed to be accessed by this token or `None` if the token is not valid
|
|
fn domain(&self, token: &str) -> Option<Origin>;
|
|
}
|
|
|
|
impl<F> WebProxyTokens for F where F: Fn(String) -> Option<Origin> + Send + Sync {
|
|
fn domain(&self, token: &str) -> Option<Origin> { self(token.to_owned()) }
|
|
}
|
|
|
|
/// Current supported endpoints.
|
|
pub struct Endpoints {
|
|
endpoints: endpoint::Endpoints,
|
|
}
|
|
|
|
impl Endpoints {
|
|
/// Returns a current list of app endpoints.
|
|
pub fn list(&self) -> Vec<apps::App> {
|
|
self.endpoints.iter().filter_map(|(ref k, ref e)| {
|
|
e.info().map(|ref info| apps::App::from_info(k, info))
|
|
}).collect()
|
|
}
|
|
}
|
|
|
|
/// Dapps server as `jsonrpc-http-server` request middleware.
|
|
pub struct Middleware {
|
|
router: router::Router,
|
|
endpoints: endpoint::Endpoints,
|
|
}
|
|
|
|
impl Middleware {
|
|
/// Get local endpoints handle.
|
|
pub fn endpoints(&self) -> Endpoints {
|
|
Endpoints {
|
|
endpoints: self.endpoints.clone(),
|
|
}
|
|
}
|
|
|
|
/// Creates new middleware for UI server.
|
|
pub fn ui<F: Fetch>(
|
|
health: NodeHealth,
|
|
remote: Remote,
|
|
dapps_domain: &str,
|
|
registrar: Arc<ContractClient>,
|
|
sync_status: Arc<SyncStatus>,
|
|
fetch: F,
|
|
) -> Self {
|
|
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(
|
|
hash_fetch::urlhint::URLHintContract::new(registrar),
|
|
sync_status.clone(),
|
|
remote.clone(),
|
|
fetch.clone(),
|
|
).embeddable_on(None).allow_dapps(false));
|
|
let special = {
|
|
let mut special = special_endpoints(
|
|
health,
|
|
content_fetcher.clone(),
|
|
remote.clone(),
|
|
);
|
|
special.insert(router::SpecialEndpoint::Home, Some(apps::ui()));
|
|
special
|
|
};
|
|
let router = router::Router::new(
|
|
content_fetcher,
|
|
None,
|
|
special,
|
|
None,
|
|
dapps_domain.to_owned(),
|
|
);
|
|
|
|
Middleware {
|
|
router: router,
|
|
endpoints: Default::default(),
|
|
}
|
|
}
|
|
|
|
/// Creates new Dapps server middleware.
|
|
pub fn dapps<F: Fetch>(
|
|
health: NodeHealth,
|
|
remote: Remote,
|
|
ui_address: Option<(String, u16)>,
|
|
extra_embed_on: Vec<(String, u16)>,
|
|
extra_script_src: Vec<(String, u16)>,
|
|
dapps_path: PathBuf,
|
|
extra_dapps: Vec<PathBuf>,
|
|
dapps_domain: &str,
|
|
registrar: Arc<ContractClient>,
|
|
sync_status: Arc<SyncStatus>,
|
|
web_proxy_tokens: Arc<WebProxyTokens>,
|
|
fetch: F,
|
|
) -> Self {
|
|
let embeddable = as_embeddable(ui_address, extra_embed_on, extra_script_src, dapps_domain);
|
|
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(
|
|
hash_fetch::urlhint::URLHintContract::new(registrar),
|
|
sync_status.clone(),
|
|
remote.clone(),
|
|
fetch.clone(),
|
|
).embeddable_on(embeddable.clone()).allow_dapps(true));
|
|
let endpoints = apps::all_endpoints(
|
|
dapps_path,
|
|
extra_dapps,
|
|
dapps_domain,
|
|
embeddable.clone(),
|
|
web_proxy_tokens,
|
|
remote.clone(),
|
|
fetch.clone(),
|
|
);
|
|
|
|
let special = {
|
|
let mut special = special_endpoints(
|
|
health,
|
|
content_fetcher.clone(),
|
|
remote.clone(),
|
|
);
|
|
special.insert(
|
|
router::SpecialEndpoint::Home,
|
|
Some(apps::ui_redirection(embeddable.clone())),
|
|
);
|
|
special
|
|
};
|
|
|
|
let router = router::Router::new(
|
|
content_fetcher,
|
|
Some(endpoints.clone()),
|
|
special,
|
|
embeddable,
|
|
dapps_domain.to_owned(),
|
|
);
|
|
|
|
Middleware {
|
|
router: router,
|
|
endpoints: endpoints,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl http::RequestMiddleware for Middleware {
|
|
fn on_request(&self, req: &hyper::server::Request<hyper::net::HttpStream>, control: &hyper::Control) -> http::RequestMiddlewareAction {
|
|
self.router.on_request(req, control)
|
|
}
|
|
}
|
|
|
|
fn special_endpoints(
|
|
health: NodeHealth,
|
|
content_fetcher: Arc<apps::fetcher::Fetcher>,
|
|
remote: Remote,
|
|
) -> HashMap<router::SpecialEndpoint, Option<Box<endpoint::Endpoint>>> {
|
|
let mut special = HashMap::new();
|
|
special.insert(router::SpecialEndpoint::Rpc, None);
|
|
special.insert(router::SpecialEndpoint::Utils, Some(apps::utils()));
|
|
special.insert(router::SpecialEndpoint::Api, Some(api::RestApi::new(
|
|
content_fetcher,
|
|
health,
|
|
remote,
|
|
)));
|
|
special
|
|
}
|
|
|
|
fn address(host: &str, port: u16) -> String {
|
|
format!("{}:{}", host, port)
|
|
}
|
|
|
|
fn as_embeddable(
|
|
ui_address: Option<(String, u16)>,
|
|
extra_embed_on: Vec<(String, u16)>,
|
|
extra_script_src: Vec<(String, u16)>,
|
|
dapps_domain: &str,
|
|
) -> Option<ParentFrameSettings> {
|
|
ui_address.map(|(host, port)| ParentFrameSettings {
|
|
host,
|
|
port,
|
|
extra_embed_on,
|
|
extra_script_src,
|
|
dapps_domain: dapps_domain.to_owned(),
|
|
})
|
|
}
|
|
|
|
/// Random filename
|
|
fn random_filename() -> String {
|
|
use ::rand::Rng;
|
|
let mut rng = ::rand::OsRng::new().unwrap();
|
|
rng.gen_ascii_chars().take(12).collect()
|
|
}
|
|
|
|
type Embeddable = Option<ParentFrameSettings>;
|
|
|
|
/// Parent frame host and port allowed to embed the content.
|
|
#[derive(Debug, Clone)]
|
|
pub struct ParentFrameSettings {
|
|
/// Hostname
|
|
pub host: String,
|
|
/// Port
|
|
pub port: u16,
|
|
/// Additional URLs the dapps can be embedded on.
|
|
pub extra_embed_on: Vec<(String, u16)>,
|
|
/// Additional URLs the dapp scripts can be loaded from.
|
|
pub extra_script_src: Vec<(String, u16)>,
|
|
/// Dapps Domain (web3.site)
|
|
pub dapps_domain: String,
|
|
}
|