// 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::PersonalSigner; use v1::types::TransactionModification; use v1::impls::unlock_sign_and_dispatch; use v1::helpers::{SigningQueue, ConfirmationsQueue}; use ethcore::account_provider::AccountProvider; use util::numbers::*; use ethcore::client::MiningBlockChainClient; use ethcore::miner::MinerService; /// Transactions confirmation (personal) rpc implementation. pub struct SignerClient where C: MiningBlockChainClient, M: MinerService { queue: Weak, accounts: Weak, client: Weak, miner: Weak, } impl SignerClient where C: MiningBlockChainClient, 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), } } fn active(&self) -> Result<(), Error> { // TODO: only call every 30s at most. take_weak!(self.client).keep_alive(); Ok(()) } } impl PersonalSigner for SignerClient where C: MiningBlockChainClient, M: MinerService { fn transactions_to_confirm(&self, _params: Params) -> Result { try!(self.active()); let queue = take_weak!(self.queue); to_value(&queue.requests()) } fn confirm_transaction(&self, params: Params) -> Result { try!(self.active()); from_params::<(U256, TransactionModification, String)>(params).and_then( |(id, modification, pass)| { let accounts = take_weak!(self.accounts); let queue = take_weak!(self.queue); let client = take_weak!(self.client); let miner = take_weak!(self.miner); queue.peek(&id).and_then(|confirmation| { let mut request = confirmation.transaction; // apply modification if let Some(gas_price) = modification.gas_price { request.gas_price = Some(gas_price); } let sender = request.from; match unlock_sign_and_dispatch(&*client, &*miner, request, &*accounts, sender, pass) { Ok(hash) => { queue.request_confirmed(id, Ok(hash.clone())); Some(to_value(&hash)) }, _ => None } }) .unwrap_or_else(|| { to_value(&false) }) } ) } fn reject_transaction(&self, params: Params) -> Result { try!(self.active()); from_params::<(U256, )>(params).and_then( |(id, )| { let queue = take_weak!(self.queue); let res = queue.request_rejected(id); to_value(&res.is_some()) } ) } }