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

* Allowing signer to use initial token

* Generating new tokens via RPC

* Fixing RPC tests

* Fixing signer doctest

* whitespace

[ci:skip]

* whitespace

[ci:skip]
This commit is contained in:
Tomasz Drwięga
2016-09-21 12:44:49 +02:00
committed by Gav Wood
parent 93f82a1164
commit b7e2afd5c0
21 changed files with 377 additions and 94 deletions

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -21,6 +21,7 @@ pub mod params;
mod poll_manager;
mod poll_filter;
mod requests;
mod signer;
mod signing_queue;
mod network_settings;
@@ -28,4 +29,5 @@ 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;

View File

@@ -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
}
}

View File

@@ -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};
@@ -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>,
@@ -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),
@@ -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())
})
@@ -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())
})

View File

@@ -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.
@@ -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 {
@@ -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),
@@ -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,
}
}
@@ -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())),
}
}

View File

@@ -23,13 +23,13 @@ use ethcore::client::MiningBlockChainClient;
use ethcore::miner::MinerService;
use v1::traits::PersonalSigner;
use v1::types::{TransactionModification, ConfirmationRequest, U256};
use v1::helpers::{errors, SigningQueue, ConfirmationsQueue, ConfirmationPayload};
use v1::helpers::{errors, SignerService, SigningQueue, ConfirmationPayload};
use v1::helpers::params::expect_no_params;
use v1::helpers::dispatch::{unlock_sign_and_dispatch, signature_with_password};
/// Transactions confirmation (personal) rpc implementation.
pub struct SignerClient<C, M> where C: MiningBlockChainClient, M: MinerService {
queue: Weak<ConfirmationsQueue>,
signer: Weak<SignerService>,
accounts: Weak<AccountProvider>,
client: Weak<C>,
miner: Weak<M>,
@@ -38,9 +38,14 @@ pub struct SignerClient<C, M> where C: MiningBlockChainClient, M: MinerService {
impl<C: 'static, M: 'static> SignerClient<C, M> where C: MiningBlockChainClient, M: MinerService {
/// Create new instance of signer client.
pub fn new(store: &Arc<AccountProvider>, client: &Arc<C>, miner: &Arc<M>, queue: &Arc<ConfirmationsQueue>) -> Self {
pub fn new(
store: &Arc<AccountProvider>,
client: &Arc<C>,
miner: &Arc<M>,
signer: &Arc<SignerService>,
) -> Self {
SignerClient {
queue: Arc::downgrade(queue),
signer: Arc::downgrade(signer),
accounts: Arc::downgrade(store),
client: Arc::downgrade(client),
miner: Arc::downgrade(miner),
@@ -59,8 +64,8 @@ impl<C: 'static, M: 'static> PersonalSigner for SignerClient<C, M> where C: Mini
fn requests_to_confirm(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
try!(expect_no_params(params));
let queue = take_weak!(self.queue);
Ok(to_value(&queue.requests().into_iter().map(From::from).collect::<Vec<ConfirmationRequest>>()))
let signer = take_weak!(self.signer);
Ok(to_value(&signer.requests().into_iter().map(From::from).collect::<Vec<ConfirmationRequest>>()))
}
fn confirm_request(&self, params: Params) -> Result<Value, Error> {
@@ -71,11 +76,11 @@ impl<C: 'static, M: 'static> PersonalSigner for SignerClient<C, M> where C: Mini
|(id, modification, pass)| {
let id = id.into();
let accounts = take_weak!(self.accounts);
let queue = take_weak!(self.queue);
let signer = take_weak!(self.signer);
let client = take_weak!(self.client);
let miner = take_weak!(self.miner);
queue.peek(&id).map(|confirmation| {
signer.peek(&id).map(|confirmation| {
let result = match confirmation.payload {
ConfirmationPayload::Transaction(mut request) => {
// apply modification
@@ -90,7 +95,7 @@ impl<C: 'static, M: 'static> PersonalSigner for SignerClient<C, M> where C: Mini
}
};
if let Ok(ref response) = result {
queue.request_confirmed(id, Ok(response.clone()));
signer.request_confirmed(id, Ok(response.clone()));
}
result
}).unwrap_or_else(|| Err(errors::invalid_params("Unknown RequestID", id)))
@@ -102,11 +107,20 @@ impl<C: 'static, M: 'static> PersonalSigner for SignerClient<C, M> where C: Mini
try!(self.active());
from_params::<(U256, )>(params).and_then(
|(id, )| {
let queue = take_weak!(self.queue);
let res = queue.request_rejected(id.into());
let signer = take_weak!(self.signer);
let res = signer.request_rejected(id.into());
Ok(to_value(&res.is_some()))
}
)
}
fn generate_token(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
try!(expect_no_params(params));
let signer = take_weak!(self.signer);
signer.generate_token()
.map(|token| to_value(&token))
.map_err(|e| errors::token(e))
}
}

View File

@@ -28,4 +28,4 @@ pub mod types;
pub use self::traits::{Web3, Eth, EthFilter, EthSigning, Personal, PersonalSigner, Net, Ethcore, EthcoreSet, Traces, Rpc};
pub use self::impls::*;
pub use self::helpers::{SigningQueue, ConfirmationsQueue, NetworkSettings};
pub use self::helpers::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings};

View File

@@ -19,7 +19,7 @@ use std::sync::Arc;
use jsonrpc_core::{IoHandler, to_value};
use v1::impls::EthSigningQueueClient;
use v1::traits::EthSigning;
use v1::helpers::{ConfirmationsQueue, SigningQueue};
use v1::helpers::{SignerService, SigningQueue};
use v1::types::{H256 as RpcH256, H520 as RpcH520};
use v1::tests::helpers::TestMinerService;
use util::{Address, FixedHash, Uint, U256, H256, H520};
@@ -28,7 +28,7 @@ use ethcore::client::TestBlockChainClient;
use ethcore::transaction::{Transaction, Action};
struct EthSigningTester {
pub queue: Arc<ConfirmationsQueue>,
pub signer: Arc<SignerService>,
pub client: Arc<TestBlockChainClient>,
pub miner: Arc<TestMinerService>,
pub accounts: Arc<AccountProvider>,
@@ -37,15 +37,15 @@ struct EthSigningTester {
impl Default for EthSigningTester {
fn default() -> Self {
let queue = Arc::new(ConfirmationsQueue::default());
let signer = Arc::new(SignerService::new_test());
let client = Arc::new(TestBlockChainClient::default());
let miner = Arc::new(TestMinerService::default());
let accounts = Arc::new(AccountProvider::transient_provider());
let io = IoHandler::new();
io.add_delegate(EthSigningQueueClient::new(&queue, &client, &miner, &accounts).to_delegate());
io.add_delegate(EthSigningQueueClient::new(&signer, &client, &miner, &accounts).to_delegate());
EthSigningTester {
queue: queue,
signer: signer,
client: client,
miner: miner,
accounts: accounts,
@@ -63,7 +63,7 @@ fn should_add_sign_to_queue() {
// given
let tester = eth_signing();
let address = Address::random();
assert_eq!(tester.queue.requests().len(), 0);
assert_eq!(tester.signer.requests().len(), 0);
// when
let request = r#"{
@@ -79,9 +79,9 @@ fn should_add_sign_to_queue() {
// then
let async_result = tester.io.handle_request(&request).unwrap();
assert_eq!(tester.queue.requests().len(), 1);
assert_eq!(tester.signer.requests().len(), 1);
// respond
tester.queue.request_confirmed(U256::from(1), Ok(to_value(&RpcH520::from(H520::default()))));
tester.signer.request_confirmed(U256::from(1), Ok(to_value(&RpcH520::from(H520::default()))));
assert!(async_result.on_result(move |res| {
assert_eq!(res, response.to_owned());
}));
@@ -92,7 +92,7 @@ fn should_post_sign_to_queue() {
// given
let tester = eth_signing();
let address = Address::random();
assert_eq!(tester.queue.requests().len(), 0);
assert_eq!(tester.signer.requests().len(), 0);
// when
let request = r#"{
@@ -108,7 +108,7 @@ fn should_post_sign_to_queue() {
// then
assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned()));
assert_eq!(tester.queue.requests().len(), 1);
assert_eq!(tester.signer.requests().len(), 1);
}
#[test]
@@ -155,7 +155,7 @@ fn should_check_status_of_request_when_its_resolved() {
"id": 1
}"#;
tester.io.handle_request_sync(&request).expect("Sent");
tester.queue.request_confirmed(U256::from(1), Ok(to_value(&"Hello World!")));
tester.signer.request_confirmed(U256::from(1), Ok(to_value(&"Hello World!")));
// when
let request = r#"{
@@ -192,7 +192,7 @@ fn should_sign_if_account_is_unlocked() {
}"#;
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{}", signature).as_ref() + r#"","id":1}"#;
assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned()));
assert_eq!(tester.queue.requests().len(), 0);
assert_eq!(tester.signer.requests().len(), 0);
}
#[test]
@@ -200,7 +200,7 @@ fn should_add_transaction_to_queue() {
// given
let tester = eth_signing();
let address = Address::random();
assert_eq!(tester.queue.requests().len(), 0);
assert_eq!(tester.signer.requests().len(), 0);
// when
let request = r#"{
@@ -219,9 +219,9 @@ fn should_add_transaction_to_queue() {
// then
let async_result = tester.io.handle_request(&request).unwrap();
assert_eq!(tester.queue.requests().len(), 1);
assert_eq!(tester.signer.requests().len(), 1);
// respond
tester.queue.request_confirmed(U256::from(1), Ok(to_value(&RpcH256::from(H256::default()))));
tester.signer.request_confirmed(U256::from(1), Ok(to_value(&RpcH256::from(H256::default()))));
assert!(async_result.on_result(move |res| {
assert_eq!(res, response.to_owned());
}));

View File

@@ -22,7 +22,7 @@ use ethcore::client::{TestBlockChainClient};
use jsonrpc_core::IoHandler;
use v1::{Ethcore, EthcoreClient};
use v1::helpers::{ConfirmationsQueue, NetworkSettings};
use v1::helpers::{SignerService, NetworkSettings};
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService};
use super::manage_network::TestManageNetwork;
@@ -262,8 +262,8 @@ fn rpc_ethcore_unsigned_transactions_count() {
let sync = sync_provider();
let net = network_service();
let io = IoHandler::new();
let queue = Arc::new(ConfirmationsQueue::default());
let ethcore = EthcoreClient::new(&client, &miner, &sync, &net, logger(), settings(), Some(queue)).to_delegate();
let signer = Arc::new(SignerService::new_test());
let ethcore = EthcoreClient::new(&client, &miner, &sync, &net, logger(), settings(), Some(signer)).to_delegate();
io.add_delegate(ethcore);
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_unsignedTransactionsCount", "params":[], "id": 1}"#;

View File

@@ -23,10 +23,10 @@ use ethcore::client::TestBlockChainClient;
use ethcore::transaction::{Transaction, Action};
use v1::{SignerClient, PersonalSigner};
use v1::tests::helpers::TestMinerService;
use v1::helpers::{SigningQueue, ConfirmationsQueue, FilledTransactionRequest, ConfirmationPayload};
use v1::helpers::{SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload};
struct PersonalSignerTester {
queue: Arc<ConfirmationsQueue>,
signer: Arc<SignerService>,
accounts: Arc<AccountProvider>,
io: IoHandler,
miner: Arc<TestMinerService>,
@@ -49,16 +49,16 @@ fn miner_service() -> Arc<TestMinerService> {
}
fn signer_tester() -> PersonalSignerTester {
let queue = Arc::new(ConfirmationsQueue::default());
let signer = Arc::new(SignerService::new_test());
let accounts = accounts_provider();
let client = blockchain_client();
let miner = miner_service();
let io = IoHandler::new();
io.add_delegate(SignerClient::new(&accounts, &client, &miner, &queue).to_delegate());
io.add_delegate(SignerClient::new(&accounts, &client, &miner, &signer).to_delegate());
PersonalSignerTester {
queue: queue,
signer: signer,
accounts: accounts,
io: io,
miner: miner,
@@ -71,7 +71,7 @@ fn signer_tester() -> PersonalSignerTester {
fn should_return_list_of_items_to_confirm() {
// given
let tester = signer_tester();
tester.queue.add_request(ConfirmationPayload::Transaction(FilledTransactionRequest {
tester.signer.add_request(ConfirmationPayload::Transaction(FilledTransactionRequest {
from: Address::from(1),
to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
gas_price: U256::from(10_000),
@@ -80,7 +80,7 @@ fn should_return_list_of_items_to_confirm() {
data: vec![],
nonce: None,
})).unwrap();
tester.queue.add_request(ConfirmationPayload::Sign(1.into(), 5.into())).unwrap();
tester.signer.add_request(ConfirmationPayload::Sign(1.into(), 5.into())).unwrap();
// when
let request = r#"{"jsonrpc":"2.0","method":"personal_requestsToConfirm","params":[],"id":1}"#;
@@ -100,7 +100,7 @@ fn should_return_list_of_items_to_confirm() {
fn should_reject_transaction_from_queue_without_dispatching() {
// given
let tester = signer_tester();
tester.queue.add_request(ConfirmationPayload::Transaction(FilledTransactionRequest {
tester.signer.add_request(ConfirmationPayload::Transaction(FilledTransactionRequest {
from: Address::from(1),
to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
gas_price: U256::from(10_000),
@@ -109,7 +109,7 @@ fn should_reject_transaction_from_queue_without_dispatching() {
data: vec![],
nonce: None,
})).unwrap();
assert_eq!(tester.queue.requests().len(), 1);
assert_eq!(tester.signer.requests().len(), 1);
// when
let request = r#"{"jsonrpc":"2.0","method":"personal_rejectRequest","params":["0x1"],"id":1}"#;
@@ -117,7 +117,7 @@ fn should_reject_transaction_from_queue_without_dispatching() {
// then
assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned()));
assert_eq!(tester.queue.requests().len(), 0);
assert_eq!(tester.signer.requests().len(), 0);
assert_eq!(tester.miner.imported_transactions.lock().len(), 0);
}
@@ -125,7 +125,7 @@ fn should_reject_transaction_from_queue_without_dispatching() {
fn should_not_remove_transaction_if_password_is_invalid() {
// given
let tester = signer_tester();
tester.queue.add_request(ConfirmationPayload::Transaction(FilledTransactionRequest {
tester.signer.add_request(ConfirmationPayload::Transaction(FilledTransactionRequest {
from: Address::from(1),
to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
gas_price: U256::from(10_000),
@@ -134,7 +134,7 @@ fn should_not_remove_transaction_if_password_is_invalid() {
data: vec![],
nonce: None,
})).unwrap();
assert_eq!(tester.queue.requests().len(), 1);
assert_eq!(tester.signer.requests().len(), 1);
// when
let request = r#"{"jsonrpc":"2.0","method":"personal_confirmRequest","params":["0x1",{},"xxx"],"id":1}"#;
@@ -142,15 +142,15 @@ fn should_not_remove_transaction_if_password_is_invalid() {
// then
assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned()));
assert_eq!(tester.queue.requests().len(), 1);
assert_eq!(tester.signer.requests().len(), 1);
}
#[test]
fn should_not_remove_sign_if_password_is_invalid() {
// given
let tester = signer_tester();
tester.queue.add_request(ConfirmationPayload::Sign(0.into(), 5.into())).unwrap();
assert_eq!(tester.queue.requests().len(), 1);
tester.signer.add_request(ConfirmationPayload::Sign(0.into(), 5.into())).unwrap();
assert_eq!(tester.signer.requests().len(), 1);
// when
let request = r#"{"jsonrpc":"2.0","method":"personal_confirmRequest","params":["0x1",{},"xxx"],"id":1}"#;
@@ -158,7 +158,7 @@ fn should_not_remove_sign_if_password_is_invalid() {
// then
assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned()));
assert_eq!(tester.queue.requests().len(), 1);
assert_eq!(tester.signer.requests().len(), 1);
}
#[test]
@@ -167,7 +167,7 @@ fn should_confirm_transaction_and_dispatch() {
let tester = signer_tester();
let address = tester.accounts.new_account("test").unwrap();
let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap();
tester.queue.add_request(ConfirmationPayload::Transaction(FilledTransactionRequest {
tester.signer.add_request(ConfirmationPayload::Transaction(FilledTransactionRequest {
from: address,
to: Some(recipient),
gas_price: U256::from(10_000),
@@ -189,7 +189,7 @@ fn should_confirm_transaction_and_dispatch() {
let signature = tester.accounts.sign(address, t.hash()).unwrap();
let t = t.with_signature(signature);
assert_eq!(tester.queue.requests().len(), 1);
assert_eq!(tester.signer.requests().len(), 1);
// when
let request = r#"{
@@ -202,7 +202,24 @@ fn should_confirm_transaction_and_dispatch() {
// then
assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned()));
assert_eq!(tester.queue.requests().len(), 0);
assert_eq!(tester.signer.requests().len(), 0);
assert_eq!(tester.miner.imported_transactions.lock().len(), 1);
}
#[test]
fn should_generate_new_token() {
// given
let tester = signer_tester();
// when
let request = r#"{
"jsonrpc":"2.0",
"method":"personal_generateAuthorizationToken",
"params":[],
"id":1
}"#;
let response = r#"{"jsonrpc":"2.0","result":"new_token","id":1}"#;
// then
assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned()));
}

View File

@@ -92,12 +92,16 @@ pub trait PersonalSigner: Sized + Send + Sync + 'static {
/// Reject the confirmation request.
fn reject_request(&self, _: Params) -> Result<Value, Error>;
/// Generates new authorization token.
fn generate_token(&self, _: Params) -> Result<Value, Error>;
/// Should be used to convert object to io delegate.
fn to_delegate(self) -> IoDelegate<Self> {
let mut delegate = IoDelegate::new(Arc::new(self));
delegate.add_method("personal_requestsToConfirm", PersonalSigner::requests_to_confirm);
delegate.add_method("personal_confirmRequest", PersonalSigner::confirm_request);
delegate.add_method("personal_rejectRequest", PersonalSigner::reject_request);
delegate.add_method("personal_generateAuthorizationToken", PersonalSigner::generate_token);
delegate
}
}