diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 2225cbc61..bfa1b75ec 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -197,7 +197,7 @@ impl EthClient where let client = take_weak!(self.client); let miner = take_weak!(self.miner); - miner.import_own_transaction(client.deref(), signed_transaction, |a: &Address| { + miner.import_own_transaction(&*client, signed_transaction, |a: &Address| { AccountDetails { nonce: client.latest_nonce(&a), balance: client.latest_balance(&a), @@ -550,17 +550,6 @@ impl Eth for EthClient where }) } - fn sign_and_send_transaction(&self, params: Params) -> Result { - from_params::<(TransactionRequest, String)>(params) - .and_then(|(request, password)| { - let accounts = take_weak!(self.accounts); - match accounts.locked_account_secret(&request.from, &password) { - Ok(secret) => self.sign_and_dispatch(request, secret), - Err(_) => to_value(&H256::zero()), - } - }) - } - fn send_raw_transaction(&self, params: Params) -> Result { from_params::<(Bytes, )>(params) .and_then(|(raw_transaction, )| { diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index 9fec1af6b..4f2bae3a3 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -18,24 +18,82 @@ use std::sync::{Arc, Weak}; use jsonrpc_core::*; use v1::traits::Personal; +use v1::types::TransactionRequest; +use util::bytes::ToPretty; use util::keys::store::*; -use util::Address; +use util::numbers::*; +use util::rlp::encode; +use ethcore::client::BlockChainClient; +use ethcore::transaction::{Action, SignedTransaction, Transaction as EthTransaction}; +use ethminer::{AccountDetails, MinerService}; /// Account management (personal) rpc implementation. -pub struct PersonalClient where A: AccountProvider { +pub struct PersonalClient + where A: AccountProvider, C: BlockChainClient, M: MinerService { accounts: Weak, + client: Weak, + miner: Weak, } -impl PersonalClient where A: AccountProvider { +impl PersonalClient + where A: AccountProvider, C: BlockChainClient, M: MinerService { /// Creates new PersonalClient - pub fn new(store: &Arc) -> Self { + pub fn new(store: &Arc, client: &Arc, miner: &Arc) -> Self { PersonalClient { accounts: Arc::downgrade(store), + client: Arc::downgrade(client), + miner: Arc::downgrade(miner), } } + + fn dispatch_transaction(&self, signed_transaction: SignedTransaction) -> Result { + let hash = signed_transaction.hash(); + + let import = { + let client = take_weak!(self.client); + let miner = take_weak!(self.miner); + + miner.import_own_transaction(&*client, signed_transaction, |a: &Address| { + AccountDetails { + nonce: client.nonce(&a), + balance: client.balance(&a), + } + }) + }; + + match import { + Ok(_) => to_value(&hash), + Err(e) => { + warn!("Error sending transaction: {:?}", e); + to_value(&H256::zero()) + } + } + } + + fn sign_and_dispatch(&self, request: TransactionRequest, secret: H256) -> Result { + let signed_transaction = { + let client = take_weak!(self.client); + let miner = take_weak!(self.miner); + EthTransaction { + nonce: request.nonce + .or_else(|| miner + .last_nonce(&request.from) + .map(|nonce| nonce + U256::one())) + .unwrap_or_else(|| client.nonce(&request.from)), + action: request.to.map_or(Action::Create, Action::Call), + gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()), + gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()), + value: request.value.unwrap_or_else(U256::zero), + data: request.data.map_or_else(Vec::new, |b| b.to_vec()), + }.sign(&secret) + }; + trace!(target: "miner", "send_transaction: dispatching tx: {}", encode(&signed_transaction).to_vec().pretty()); + self.dispatch_transaction(signed_transaction) + } } -impl Personal for PersonalClient where A: AccountProvider + 'static { +impl Personal for PersonalClient + where A: AccountProvider, C: BlockChainClient, M: MinerService { fn accounts(&self, _: Params) -> Result { let store = take_weak!(self.accounts); match store.accounts() { @@ -66,4 +124,15 @@ impl Personal for PersonalClient where A: AccountProvider + 'static { } }) } + + fn sign_and_send_transaction(&self, params: Params) -> Result { + from_params::<(TransactionRequest, String)>(params) + .and_then(|(request, password)| { + let accounts = take_weak!(self.accounts); + match accounts.locked_account_secret(&request.from, &password) { + Ok(secret) => self.sign_and_dispatch(request, secret), + Err(_) => to_value(&H256::zero()), + } + }) + } } diff --git a/rpc/src/v1/types/bytes.rs b/rpc/src/v1/types/bytes.rs index 4febacec9..0dc2d3b31 100644 --- a/rpc/src/v1/types/bytes.rs +++ b/rpc/src/v1/types/bytes.rs @@ -28,7 +28,7 @@ impl Bytes { pub fn new(bytes: Vec) -> Bytes { Bytes(bytes) } - pub fn to_vec(self) -> Vec { let Bytes(x) = self; x } + pub fn to_vec(self) -> Vec { self.0 } } impl Serialize for Bytes {