// Copyright 2015-2019 Parity Technologies (UK) Ltd. // This file is part of Parity Ethereum. // Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . //! Unsafe Signing RPC implementation. use std::sync::Arc; use ethcore::account_provider::AccountProvider; use jsonrpc_core::{BoxFuture, Result}; use jsonrpc_core::futures::{future, Future}; use v1::helpers::{errors, DefaultAccount}; use v1::helpers::dispatch::{self, Dispatcher}; use v1::metadata::Metadata; use v1::traits::{EthSigning, ParitySigning}; use v1::types::{ U256 as RpcU256, H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, Bytes as RpcBytes, Either as RpcEither, RichRawTransaction as RpcRichRawTransaction, TransactionRequest as RpcTransactionRequest, ConfirmationPayload as RpcConfirmationPayload, ConfirmationResponse as RpcConfirmationResponse, }; /// Implementation of functions that require signing when no trusted signer is used. pub struct SigningUnsafeClient { accounts: Arc, dispatcher: D, } impl SigningUnsafeClient { /// Creates new SigningUnsafeClient. pub fn new(accounts: &Arc, dispatcher: D) -> Self { SigningUnsafeClient { accounts: accounts.clone(), dispatcher: dispatcher, } } fn handle(&self, payload: RpcConfirmationPayload, account: DefaultAccount) -> BoxFuture { let accounts = self.accounts.clone(); let default = match account { DefaultAccount::Provided(acc) => acc, }; let dis = self.dispatcher.clone(); Box::new(dispatch::from_rpc(payload, default, &dis) .and_then(move |payload| { dispatch::execute(dis, accounts, payload, dispatch::SignWith::Nothing) }) .map(|v| v.into_value())) } } impl EthSigning for SigningUnsafeClient { type Metadata = Metadata; fn sign(&self, _: Metadata, address: RpcH160, data: RpcBytes) -> BoxFuture { Box::new(self.handle(RpcConfirmationPayload::EthSignMessage((address.clone(), data).into()), address.into()) .then(|res| match res { Ok(RpcConfirmationResponse::Signature(signature)) => Ok(signature), Err(e) => Err(e), e => Err(errors::internal("Unexpected result", e)), })) } fn send_transaction(&self, _meta: Metadata, request: RpcTransactionRequest) -> BoxFuture { Box::new(self.handle(RpcConfirmationPayload::SendTransaction(request), DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default())) .then(|res| match res { Ok(RpcConfirmationResponse::SendTransaction(hash)) => Ok(hash), Err(e) => Err(e), e => Err(errors::internal("Unexpected result", e)), })) } fn sign_transaction(&self, _meta: Metadata, request: RpcTransactionRequest) -> BoxFuture { Box::new(self.handle(RpcConfirmationPayload::SignTransaction(request), DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default())) .then(|res| match res { Ok(RpcConfirmationResponse::SignTransaction(tx)) => Ok(tx), Err(e) => Err(e), e => Err(errors::internal("Unexpected result", e)), })) } } impl ParitySigning for SigningUnsafeClient { type Metadata = Metadata; fn compose_transaction(&self, _meta: Metadata, transaction: RpcTransactionRequest) -> BoxFuture { let accounts = self.accounts.clone(); let default_account = accounts.default_account().ok().unwrap_or_default(); Box::new(self.dispatcher.fill_optional_fields(transaction.into(), default_account, true).map(Into::into)) } fn decrypt_message(&self, _: Metadata, address: RpcH160, data: RpcBytes) -> BoxFuture { Box::new(self.handle(RpcConfirmationPayload::Decrypt((address.clone(), data).into()), address.into()) .then(|res| match res { Ok(RpcConfirmationResponse::Decrypt(data)) => Ok(data), Err(e) => Err(e), e => Err(errors::internal("Unexpected result", e)), })) } fn post_sign(&self, _: Metadata, _: RpcH160, _: RpcBytes) -> BoxFuture> { // We don't support this in non-signer mode. Box::new(future::err(errors::signer_disabled())) } fn post_transaction(&self, _: Metadata, _: RpcTransactionRequest) -> BoxFuture> { // We don't support this in non-signer mode. Box::new(future::err(errors::signer_disabled())) } fn check_request(&self, _: RpcU256) -> Result> { // We don't support this in non-signer mode. Err(errors::signer_disabled()) } }