Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

New signer token RPC & Initial signer connection without token. #2096

Merged
merged 6 commits into from
Sep 21, 2016
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion devtools/src/http_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

use std::time::Duration;
use std::io::{Read, Write};
use std::str::{self, Lines};
use std::net::{TcpStream, SocketAddr};
Expand Down Expand Up @@ -43,10 +44,11 @@ pub fn read_block(lines: &mut Lines, all: bool) -> String {

pub fn request(address: &SocketAddr, request: &str) -> Response {
let mut req = TcpStream::connect(address).unwrap();
req.set_read_timeout(Some(Duration::from_secs(1))).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there an indication that this is in fact enough time for all requests to be handled? Spurious test failures caused by a too-short timeout would be annoying.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So there are no requests that are doing any heavy stuff, but of course there is no guarantee that all of them will be handled.
Unfortunatelly it's necessary for some other requests that are not closing the connection after replying with a handshake (i.e. websocket upgrade requests).

I didn't have any other idea how to handle those - read without timeout blocks idefinitely, setting non-blocking mode returns WouldBlock on every try, tbh I have no idea why I cannot just read a handshake and then close the connection (Same thing happens if http server is trying to keep the connection alive (i.e. Connection: close header is missing))

I'm open to any ideas.

req.write_all(request.as_bytes()).unwrap();

let mut response = String::new();
req.read_to_string(&mut response).unwrap();
let _ = req.read_to_string(&mut response);

let mut lines = response.lines();
let status = lines.next().unwrap().to_owned();
Expand Down
19 changes: 15 additions & 4 deletions devtools/src/random_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ use std::ops::{Deref, DerefMut};
use rand::random;

pub struct RandomTempPath {
path: PathBuf
path: PathBuf,
pub panic_on_drop_failure: bool,
}

pub fn random_filename() -> String {
Expand All @@ -39,7 +40,8 @@ impl RandomTempPath {
let mut dir = env::temp_dir();
dir.push(random_filename());
RandomTempPath {
path: dir.clone()
path: dir.clone(),
panic_on_drop_failure: true,
}
}

Expand All @@ -48,7 +50,8 @@ impl RandomTempPath {
dir.push(random_filename());
fs::create_dir_all(dir.as_path()).unwrap();
RandomTempPath {
path: dir.clone()
path: dir.clone(),
panic_on_drop_failure: true,
}
}

Expand All @@ -72,12 +75,20 @@ impl AsRef<Path> for RandomTempPath {
self.as_path()
}
}
impl Deref for RandomTempPath {
type Target = Path;
fn deref(&self) -> &Self::Target {
self.as_path()
}
}

impl Drop for RandomTempPath {
fn drop(&mut self) {
if let Err(_) = fs::remove_dir_all(&self) {
if let Err(e) = fs::remove_file(&self) {
panic!("Failed to remove temp directory. Here's what prevented this from happening: ({})", e);
if self.panic_on_drop_failure {
panic!("Failed to remove temp directory. Here's what prevented this from happening: ({})", e);
}
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions parity/rpc_apis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use ethcore::client::Client;
use ethcore::account_provider::AccountProvider;
use ethsync::{ManageNetwork, SyncProvider};
use ethcore_rpc::{Extendable, NetworkSettings};
pub use ethcore_rpc::ConfirmationsQueue;
pub use ethcore_rpc::SignerService;


#[derive(Debug, PartialEq, Clone, Eq, Hash)]
Expand Down Expand Up @@ -94,7 +94,7 @@ impl FromStr for ApiSet {

pub struct Dependencies {
pub signer_port: Option<u16>,
pub signer_queue: Arc<ConfirmationsQueue>,
pub signer_service: Arc<SignerService>,
pub client: Arc<Client>,
pub sync: Arc<SyncProvider>,
pub net: Arc<ManageNetwork>,
Expand Down Expand Up @@ -173,7 +173,7 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
server.add_delegate(filter_client.to_delegate());

if deps.signer_port.is_some() {
server.add_delegate(EthSigningQueueClient::new(&deps.signer_queue, &deps.client, &deps.miner, &deps.secret_store).to_delegate());
server.add_delegate(EthSigningQueueClient::new(&deps.signer_service, &deps.client, &deps.miner, &deps.secret_store).to_delegate());
} else {
server.add_delegate(EthSigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner).to_delegate());
}
Expand All @@ -182,11 +182,11 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner, deps.signer_port, deps.geth_compatibility).to_delegate());
},
Api::Signer => {
server.add_delegate(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_queue).to_delegate());
server.add_delegate(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_service).to_delegate());
},
Api::Ethcore => {
let queue = deps.signer_port.map(|_| deps.signer_queue.clone());
server.add_delegate(EthcoreClient::new(&deps.client, &deps.miner, &deps.sync, &deps.net_service, deps.logger.clone(), deps.settings.clone(), queue).to_delegate())
let signer = deps.signer_port.map(|_| deps.signer_service.clone());
server.add_delegate(EthcoreClient::new(&deps.client, &deps.miner, &deps.sync, &deps.net_service, deps.logger.clone(), deps.settings.clone(), signer).to_delegate())
},
Api::EthcoreSet => {
server.add_delegate(EthcoreSetClient::new(&deps.client, &deps.miner, &deps.net_service).to_delegate())
Expand Down
3 changes: 2 additions & 1 deletion parity/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,10 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> {
}

// set up dependencies for rpc servers
let signer_path = cmd.signer_conf.signer_path.clone();
let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies {
signer_port: cmd.signer_port,
signer_queue: Arc::new(rpc_apis::ConfirmationsQueue::default()),
signer_service: Arc::new(rpc_apis::SignerService::new(move || signer::new_token(signer_path.clone()))),
client: client.clone(),
sync: sync_provider.clone(),
net: manage_network.clone(),
Expand Down
2 changes: 1 addition & 1 deletion parity/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ fn do_start(conf: Configuration, deps: Dependencies) -> Result<SignerServer, Str

let start_result = {
let server = signer::ServerBuilder::new(
deps.apis.signer_queue.clone(),
deps.apis.signer_service.queue(),
codes_path(conf.signer_path),
);
if conf.skip_origin_validation {
Expand Down
2 changes: 1 addition & 1 deletion rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ use self::jsonrpc_core::{IoHandler, IoDelegate};

pub use jsonrpc_http_server::{ServerBuilder, Server, RpcServerError};
pub mod v1;
pub use v1::{SigningQueue, ConfirmationsQueue, NetworkSettings};
pub use v1::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings};

/// An object that can be extended with `IoDelegates`
pub trait Extendable {
Expand Down
7 changes: 7 additions & 0 deletions rpc/src/v1/helpers/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,13 @@ pub fn no_author() -> Error {
}
}

pub fn token(e: String) -> Error {
Error {
code: ErrorCode::ServerError(codes::UNKNOWN_ERROR),
message: "There was an error when saving your authorization tokens.".into(),
data: Some(Value::String(e)),
}
}

pub fn signer_disabled() -> Error {
Error {
Expand Down
2 changes: 2 additions & 0 deletions rpc/src/v1/helpers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ pub mod params;
mod poll_manager;
mod poll_filter;
mod requests;
mod signer;
mod signing_queue;
mod network_settings;

pub use self::poll_manager::PollManager;
pub use self::poll_filter::PollFilter;
pub use self::requests::{TransactionRequest, FilledTransactionRequest, ConfirmationRequest, ConfirmationPayload, CallRequest};
pub use self::signing_queue::{ConfirmationsQueue, ConfirmationPromise, ConfirmationResult, SigningQueue, QueueEvent};
pub use self::signer::SignerService;
pub use self::network_settings::NetworkSettings;
61 changes: 61 additions & 0 deletions rpc/src/v1/helpers/signer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// 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 <http://www.gnu.org/licenses/>.

use std::sync::Arc;
use std::ops::Deref;
use v1::helpers::signing_queue::{ConfirmationsQueue};

/// Manages communication with Signer crate
pub struct SignerService {
queue: Arc<ConfirmationsQueue>,
generate_new_token: Box<Fn() -> Result<String, String> + Send + Sync + 'static>,
}

impl SignerService {

/// Creates new Signer Service given function to generate new tokens.
pub fn new<F>(new_token: F) -> Self
where F: Fn() -> Result<String, String> + Send + Sync + 'static {
SignerService {
queue: Arc::new(ConfirmationsQueue::default()),
generate_new_token: Box::new(new_token),
}
}

/// Generates new token.
pub fn generate_token(&self) -> Result<String, String> {
(self.generate_new_token)()
}

/// Returns a reference to `ConfirmationsQueue`
pub fn queue(&self) -> Arc<ConfirmationsQueue> {
self.queue.clone()
}

#[cfg(test)]
/// Creates new Signer Service for tests.
pub fn new_test() -> Self {
SignerService::new(|| Ok("new_token".into()))
}
}

impl Deref for SignerService {
type Target = ConfirmationsQueue;
fn deref(&self) -> &Self::Target {
&self.queue
}
}

16 changes: 8 additions & 8 deletions rpc/src/v1/impls/eth_signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use ethcore::client::MiningBlockChainClient;
use util::{U256, Address, H256, Mutex};
use transient_hashmap::TransientHashMap;
use ethcore::account_provider::AccountProvider;
use v1::helpers::{errors, SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationsQueue, ConfirmationPayload, TransactionRequest as TRequest, FilledTransactionRequest as FilledRequest};
use v1::helpers::{errors, SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, TransactionRequest as TRequest, FilledTransactionRequest as FilledRequest, SignerService};
use v1::helpers::dispatch::{default_gas_price, sign_and_dispatch};
use v1::traits::EthSigning;
use v1::types::{TransactionRequest, H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, U256 as RpcU256};
Expand All @@ -43,7 +43,7 @@ fn fill_optional_fields<C, M>(request: TRequest, client: &C, miner: &M) -> Fille

/// Implementation of functions that require signing when no trusted signer is used.
pub struct EthSigningQueueClient<C, M> where C: MiningBlockChainClient, M: MinerService {
queue: Weak<ConfirmationsQueue>,
signer: Weak<SignerService>,
accounts: Weak<AccountProvider>,
client: Weak<C>,
miner: Weak<M>,
Expand All @@ -60,9 +60,9 @@ pub enum DispatchResult {

impl<C, M> EthSigningQueueClient<C, M> where C: MiningBlockChainClient, M: MinerService {
/// Creates a new signing queue client given shared signing queue.
pub fn new(queue: &Arc<ConfirmationsQueue>, client: &Arc<C>, miner: &Arc<M>, accounts: &Arc<AccountProvider>) -> Self {
pub fn new(signer: &Arc<SignerService>, client: &Arc<C>, miner: &Arc<M>, accounts: &Arc<AccountProvider>) -> Self {
EthSigningQueueClient {
queue: Arc::downgrade(queue),
signer: Arc::downgrade(signer),
accounts: Arc::downgrade(accounts),
client: Arc::downgrade(client),
miner: Arc::downgrade(miner),
Expand All @@ -86,8 +86,8 @@ impl<C, M> EthSigningQueueClient<C, M> where C: MiningBlockChainClient, M: Miner
return Ok(DispatchResult::Value(to_value(&accounts.sign(address, msg).ok().map_or_else(RpcH520::default, Into::into))))
}

let queue = take_weak!(self.queue);
queue.add_request(ConfirmationPayload::Sign(address, msg))
let signer = take_weak!(self.signer);
signer.add_request(ConfirmationPayload::Sign(address, msg))
.map(DispatchResult::Promise)
.map_err(|_| errors::request_rejected_limit())
})
Expand All @@ -105,9 +105,9 @@ impl<C, M> EthSigningQueueClient<C, M> where C: MiningBlockChainClient, M: Miner
return sign_and_dispatch(&*client, &*miner, request, &*accounts, sender).map(DispatchResult::Value);
}

let queue = take_weak!(self.queue);
let signer = take_weak!(self.signer);
let request = fill_optional_fields(request, &*client, &*miner);
queue.add_request(ConfirmationPayload::Transaction(request))
signer.add_request(ConfirmationPayload::Transaction(request))
.map(DispatchResult::Promise)
.map_err(|_| errors::request_rejected_limit())
})
Expand Down
12 changes: 6 additions & 6 deletions rpc/src/v1/impls/ethcore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use ethcore::client::{MiningBlockChainClient};
use jsonrpc_core::*;
use v1::traits::Ethcore;
use v1::types::{Bytes, U256, H160, Peers};
use v1::helpers::{errors, SigningQueue, ConfirmationsQueue, NetworkSettings};
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
use v1::helpers::params::expect_no_params;

/// Ethcore implementation.
Expand All @@ -45,7 +45,7 @@ pub struct EthcoreClient<C, M, S: ?Sized> where
net: Weak<ManageNetwork>,
logger: Arc<RotatingLogger>,
settings: Arc<NetworkSettings>,
confirmations_queue: Option<Arc<ConfirmationsQueue>>,
signer: Option<Arc<SignerService>>,
}

impl<C, M, S: ?Sized> EthcoreClient<C, M, S> where C: MiningBlockChainClient, M: MinerService, S: SyncProvider {
Expand All @@ -57,7 +57,7 @@ impl<C, M, S: ?Sized> EthcoreClient<C, M, S> where C: MiningBlockChainClient, M:
net: &Arc<ManageNetwork>,
logger: Arc<RotatingLogger>,
settings: Arc<NetworkSettings>,
queue: Option<Arc<ConfirmationsQueue>>
signer: Option<Arc<SignerService>>
) -> Self {
EthcoreClient {
client: Arc::downgrade(client),
Expand All @@ -66,7 +66,7 @@ impl<C, M, S: ?Sized> EthcoreClient<C, M, S> where C: MiningBlockChainClient, M:
net: Arc::downgrade(net),
logger: logger,
settings: settings,
confirmations_queue: queue,
signer: signer,
}
}

Expand Down Expand Up @@ -198,9 +198,9 @@ impl<C, M, S: ?Sized> Ethcore for EthcoreClient<C, M, S> where M: MinerService +
try!(self.active());
try!(expect_no_params(params));

match self.confirmations_queue {
match self.signer {
None => Err(errors::signer_disabled()),
Some(ref queue) => Ok(to_value(&queue.len())),
Some(ref signer) => Ok(to_value(&signer.len())),
}
}

Expand Down
Loading