From 6d5ba59515ac23cad62861b66b02ec96c1c6e0a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sat, 28 May 2016 17:07:40 +0200 Subject: [PATCH] Stubs for Personal Signer methods --- parity/main.rs | 5 +- parity/rpc_apis.rs | 11 ++- rpc/src/lib.rs | 1 + rpc/src/v1/helpers/mod.rs | 2 + .../src/v1/helpers}/signing_queue.rs | 35 ++++++---- rpc/src/v1/impls/eth_signing.rs | 28 ++++++++ rpc/src/v1/impls/mod.rs | 4 +- rpc/src/v1/impls/personal.rs | 2 +- rpc/src/v1/impls/personal_signer.rs | 69 +++++++++++++++++++ rpc/src/v1/mod.rs | 1 + rpc/src/v1/tests/mocked/eth_signing.rs | 17 +++++ rpc/src/v1/tests/mocked/personal_signer.rs | 17 +++++ rpc/src/v1/traits/mod.rs | 2 +- rpc/src/v1/traits/personal.rs | 23 +++++++ rpc/src/v1/types/transaction_request.rs | 2 +- signer/src/lib.rs | 2 - 16 files changed, 198 insertions(+), 23 deletions(-) rename {signer/src => rpc/src/v1/helpers}/signing_queue.rs (58%) create mode 100644 rpc/src/v1/impls/personal_signer.rs create mode 100644 rpc/src/v1/tests/mocked/eth_signing.rs create mode 100644 rpc/src/v1/tests/mocked/personal_signer.rs diff --git a/parity/main.rs b/parity/main.rs index 874bb35b5..5c8cc60e0 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -79,6 +79,7 @@ use std::fs::File; use std::str::{FromStr, from_utf8}; use std::thread::sleep; use std::time::Duration; +use std::collections::HashSet; use rustc_serialize::hex::FromHex; use ctrlc::CtrlC; use util::{H256, ToPretty, NetworkConfiguration, PayloadInfo, Bytes}; @@ -199,6 +200,8 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) let sync = EthSync::register(service.network(), sync_config, client.clone(), miner.clone()); let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies { + signer_enabled: conf.args.flag_signer, + signer_queue: Arc::new(Mutex::new(HashSet::new())), client: client.clone(), sync: sync.clone(), secret_store: account_service.clone(), @@ -239,7 +242,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) // Set up a signer let signer_server = signer::start(signer::Configuration { - enabled: conf.args.flag_signer, + enabled: deps_for_rpc_apis.signer_enabled, port: conf.args.flag_signer_port, }, signer::Dependencies { panic_handler: panic_handler.clone(), diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index 1f1994d9e..7d6e55fee 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -26,7 +26,7 @@ use util::RotatingLogger; use util::keys::store::AccountService; use util::network_settings::NetworkSettings; -use ethcore_rpc::Extendable; +use ethcore_rpc::{SigningQueue, Extendable}; pub enum Api { Web3, @@ -61,6 +61,8 @@ impl FromStr for Api { } pub struct Dependencies { + pub signer_enabled: bool, + pub signer_queue: Arc, pub client: Arc, pub sync: Arc, pub secret_store: Arc, @@ -115,7 +117,12 @@ pub fn setup_rpc(server: T, deps: Arc, apis: Option Api::Eth => { server.add_delegate(EthClient::new(&deps.client, &deps.sync, &deps.secret_store, &deps.miner, &deps.external_miner).to_delegate()); server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate()); - server.add_delegate(EthSigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner).to_delegate()); + + if deps.signer_enabled { + server.add_delegate(EthSigningQueueClient::new(&deps.signer_queue).to_delegate()); + } else { + server.add_delegate(EthSigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner).to_delegate()); + } }, Api::Personal => { server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner).to_delegate()) diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index a82c70af0..80ecf8b71 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -39,6 +39,7 @@ use self::jsonrpc_core::{IoHandler, IoDelegate}; pub use jsonrpc_http_server::{Server, RpcServerError}; pub mod v1; +pub use v1::SigningQueue; /// An object that can be extended with `IoDelegates` pub trait Extendable { diff --git a/rpc/src/v1/helpers/mod.rs b/rpc/src/v1/helpers/mod.rs index b1a5c05ba..8e5a5564d 100644 --- a/rpc/src/v1/helpers/mod.rs +++ b/rpc/src/v1/helpers/mod.rs @@ -16,6 +16,8 @@ mod poll_manager; mod poll_filter; +mod signing_queue; pub use self::poll_manager::PollManager; pub use self::poll_filter::PollFilter; +pub use self::signing_queue::SigningQueue; diff --git a/signer/src/signing_queue.rs b/rpc/src/v1/helpers/signing_queue.rs similarity index 58% rename from signer/src/signing_queue.rs rename to rpc/src/v1/helpers/signing_queue.rs index 611d467c2..b6ab6126f 100644 --- a/signer/src/signing_queue.rs +++ b/rpc/src/v1/helpers/signing_queue.rs @@ -14,44 +14,51 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +use std::sync::Mutex; use std::collections::HashSet; -use rpc::v1::types::TransactionRequest; +use v1::types::TransactionRequest; -pub trait SigningQueue { - fn add_request(&mut self, transaction: TransactionRequest); +/// A queue of transactions awaiting to be confirmed and signed. +pub trait SigningQueue: Send + Sync { + /// Add new request to the queue. + fn add_request(&self, transaction: TransactionRequest); - fn remove_request(&mut self, id: TransactionRequest); + /// Remove request from the queue. + fn remove_request(&self, id: TransactionRequest); - fn requests(&self) -> &HashSet; + /// Return copy of all the requests in the queue. + fn requests(&self) -> HashSet; } -impl SigningQueue for HashSet { - fn add_request(&mut self, transaction: TransactionRequest) { - self.insert(transaction); +impl SigningQueue for Mutex> { + fn add_request(&self, transaction: TransactionRequest) { + self.lock().unwrap().insert(transaction); } - fn remove_request(&mut self, id: TransactionRequest) { - self.remove(&id); + fn remove_request(&self, id: TransactionRequest) { + self.lock().unwrap().remove(&id); } - fn requests(&self) -> &HashSet { - self + fn requests(&self) -> HashSet { + let queue = self.lock().unwrap(); + queue.clone() } } #[cfg(test)] mod test { + use std::sync::Mutex; use std::collections::HashSet; use util::hash::Address; use util::numbers::U256; - use rpc::v1::types::TransactionRequest; + use v1::types::TransactionRequest; use super::*; #[test] fn should_work_for_hashset() { // given - let mut queue = HashSet::new(); + let mut queue = Mutex::new(HashSet::new()); let request = TransactionRequest { from: Address::from(1), diff --git a/rpc/src/v1/impls/eth_signing.rs b/rpc/src/v1/impls/eth_signing.rs index 9c193e1d2..2a4c845b8 100644 --- a/rpc/src/v1/impls/eth_signing.rs +++ b/rpc/src/v1/impls/eth_signing.rs @@ -22,10 +22,38 @@ use ethminer::MinerService; use ethcore::client::BlockChainClient; use util::numbers::*; use util::keys::store::AccountProvider; +use v1::helpers::SigningQueue; use v1::traits::EthSigning; use v1::types::TransactionRequest; use v1::impls::sign_and_dispatch; + +/// Implementation of functions that require signing when no trusted signer is used. +pub struct EthSigningQueueClient { + queue: Weak, +} + +impl EthSigningQueueClient { + /// Creates a new signing queue client given shared signing queue. + pub fn new(queue: &Arc) -> Self { + EthSigningQueueClient { + queue: Arc::downgrade(queue), + } + } +} + +impl EthSigning for EthSigningQueueClient { + fn send_transaction(&self, params: Params) -> Result { + from_params::<(TransactionRequest, )>(params) + .and_then(|(request, )| { + let queue = take_weak!(self.queue); + queue.add_request(request); + // TODO [ToDr] Block and wait for confirmation? + to_value(&H256::zero()) + }) + } +} + /// Implementation of functions that require signing when no trusted signer is used. pub struct EthSigningUnsafeClient where C: BlockChainClient, diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index d3b7944f7..d3a9b70a2 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -31,6 +31,7 @@ mod eth_filter; mod eth_signing; mod net; mod personal; +mod personal_signer; mod ethcore; mod traces; mod rpc; @@ -38,9 +39,10 @@ mod rpc; pub use self::web3::Web3Client; pub use self::eth::EthClient; pub use self::eth_filter::EthFilterClient; -pub use self::eth_signing::EthSigningUnsafeClient; +pub use self::eth_signing::{EthSigningUnsafeClient, EthSigningQueueClient}; pub use self::net::NetClient; pub use self::personal::PersonalClient; +pub use self::personal_signer::SignerClient; pub use self::ethcore::EthcoreClient; pub use self::traces::TracesClient; pub use self::rpc::RpcClient; diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index 19e902996..30d541772 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -20,7 +20,7 @@ use jsonrpc_core::*; use v1::traits::Personal; use v1::types::TransactionRequest; use v1::impls::sign_and_dispatch; -use util::keys::store::*; +use util::keys::store::AccountProvider; use util::numbers::*; use ethcore::client::BlockChainClient; use ethminer::MinerService; diff --git a/rpc/src/v1/impls/personal_signer.rs b/rpc/src/v1/impls/personal_signer.rs new file mode 100644 index 000000000..bfb3c9eb5 --- /dev/null +++ b/rpc/src/v1/impls/personal_signer.rs @@ -0,0 +1,69 @@ +// 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 . + +//! Transactions Confirmations (personal) rpc implementation + +use std::sync::{Arc, Weak}; +use jsonrpc_core::*; +use v1::traits::SignerPersonal; +use v1::types::TransactionRequest; +use v1::impls::sign_and_dispatch; +use v1::helpers::SigningQueue; +use util::keys::store::AccountProvider; +use util::numbers::*; +use ethcore::client::BlockChainClient; +use ethminer::MinerService; + +/// Transactions confirmation (personal) rpc implementation. +pub struct SignerClient + where A: AccountProvider, C: BlockChainClient, M: MinerService { + queue: Weak, + accounts: Weak, + client: Weak, + miner: Weak, +} + +impl SignerClient + where A: AccountProvider, C: BlockChainClient, M: MinerService { + + /// Create new instance of signer client. + pub fn new(store: &Arc, client: &Arc, miner: &Arc, queue: &Arc) -> Self { + SignerClient { + queue: Arc::downgrade(queue), + accounts: Arc::downgrade(store), + client: Arc::downgrade(client), + miner: Arc::downgrade(miner), + } + } +} + +impl SignerPersonal for SignerClient + where A: AccountProvider, C: BlockChainClient, M: MinerService { + + fn transactions_to_confirm(&self, params: Params) -> Result { + let queue = take_weak!(self.queue); + to_value(&queue.requests()) + } + + fn confirm_transaction(&self, params: Params) -> Result { + Err(Error::internal_error()) + } + + fn reject_transaction(&self, params: Params) -> Result { + Err(Error::internal_error()) + } +} + diff --git a/rpc/src/v1/mod.rs b/rpc/src/v1/mod.rs index 49f9e3a38..308e921d2 100644 --- a/rpc/src/v1/mod.rs +++ b/rpc/src/v1/mod.rs @@ -27,3 +27,4 @@ pub mod types; pub use self::traits::{Web3, Eth, EthFilter, EthSigning, Personal, Net, Ethcore, Traces, Rpc}; pub use self::impls::*; +pub use self::helpers::SigningQueue; diff --git a/rpc/src/v1/tests/mocked/eth_signing.rs b/rpc/src/v1/tests/mocked/eth_signing.rs new file mode 100644 index 000000000..05ceaf3d3 --- /dev/null +++ b/rpc/src/v1/tests/mocked/eth_signing.rs @@ -0,0 +1,17 @@ +// 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 . + + diff --git a/rpc/src/v1/tests/mocked/personal_signer.rs b/rpc/src/v1/tests/mocked/personal_signer.rs new file mode 100644 index 000000000..05ceaf3d3 --- /dev/null +++ b/rpc/src/v1/tests/mocked/personal_signer.rs @@ -0,0 +1,17 @@ +// 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 . + + diff --git a/rpc/src/v1/traits/mod.rs b/rpc/src/v1/traits/mod.rs index e5d5f3324..2355d6137 100644 --- a/rpc/src/v1/traits/mod.rs +++ b/rpc/src/v1/traits/mod.rs @@ -31,7 +31,7 @@ pub mod rpc; pub use self::web3::Web3; pub use self::eth::{Eth, EthFilter, EthSigning}; pub use self::net::Net; -pub use self::personal::Personal; +pub use self::personal::{Personal, SignerPersonal}; pub use self::ethcore::Ethcore; pub use self::traces::Traces; pub use self::rpc::Rpc; diff --git a/rpc/src/v1/traits/personal.rs b/rpc/src/v1/traits/personal.rs index 0619d7ada..d8eb7ee75 100644 --- a/rpc/src/v1/traits/personal.rs +++ b/rpc/src/v1/traits/personal.rs @@ -43,3 +43,26 @@ pub trait Personal: Sized + Send + Sync + 'static { delegate } } + +/// Personal extension for transactions confirmations rpc interface. +pub trait SignerPersonal: Sized + Send + Sync + 'static { + + /// Returns a list of transactions to confirm. + fn transactions_to_confirm(&self, _: Params) -> Result; + + /// Confirm and send a specific transaction. + fn confirm_transaction(&self, _: Params) -> Result; + + /// Reject the transaction request. + fn reject_transaction(&self, _: Params) -> Result; + + /// Should be used to convert object to io delegate. + fn to_delegate(self) -> IoDelegate { + let mut delegate = IoDelegate::new(Arc::new(self)); + delegate.add_method("personal_transactionsToConfirm", SignerPersonal::transactions_to_confirm); + delegate.add_method("personal_confirmTransaction", SignerPersonal::confirm_transaction); + delegate.add_method("personal_rejectTransaction", SignerPersonal::reject_transaction); + delegate + } +} + diff --git a/rpc/src/v1/types/transaction_request.rs b/rpc/src/v1/types/transaction_request.rs index 1b51e6b12..276f14f07 100644 --- a/rpc/src/v1/types/transaction_request.rs +++ b/rpc/src/v1/types/transaction_request.rs @@ -21,7 +21,7 @@ use util::numbers::U256; use v1::types::bytes::Bytes; /// Transaction request coming from RPC -#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize)] +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Serialize, Deserialize)] pub struct TransactionRequest { /// Sender pub from: Address, diff --git a/signer/src/lib.rs b/signer/src/lib.rs index a39fe68f0..60f7e9aba 100644 --- a/signer/src/lib.rs +++ b/signer/src/lib.rs @@ -53,9 +53,7 @@ extern crate ethcore_rpc as rpc; extern crate jsonrpc_core; extern crate ws; -mod signing_queue; mod ws_server; - pub use ws_server::*; #[cfg(test)]