2016-02-05 13:40:41 +01:00
// 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/>.
2016-01-27 17:08:59 +01:00
//! Eth rpc implementation.
2016-03-26 18:51:27 +01:00
extern crate ethash ;
2016-03-14 14:18:29 +01:00
use std ::sync ::{ Arc , Weak , Mutex } ;
2016-03-08 16:23:32 +01:00
use std ::ops ::Deref ;
2016-03-10 17:32:17 +01:00
use ethsync ::{ SyncProvider , SyncState } ;
2016-05-31 21:31:42 +02:00
use ethcore ::miner ::{ MinerService , ExternalMinerService } ;
2016-01-26 19:24:33 +01:00
use jsonrpc_core ::* ;
2016-02-29 22:21:15 +01:00
use util ::numbers ::* ;
2016-01-27 12:31:54 +01:00
use util ::sha3 ::* ;
2016-05-19 00:41:41 +02:00
use util ::rlp ::{ encode , decode , UntrustedRlp , View } ;
2016-05-29 15:46:57 +02:00
use util ::keys ::store ::AccountProvider ;
2016-05-31 21:31:42 +02:00
use ethcore ::client ::{ MiningBlockChainClient , BlockID , TransactionID , UncleID } ;
2016-03-14 14:18:29 +01:00
use ethcore ::block ::IsBlock ;
2016-01-27 12:31:54 +01:00
use ethcore ::views ::* ;
2016-02-29 19:30:13 +01:00
use ethcore ::ethereum ::Ethash ;
2016-03-22 17:17:50 +01:00
use ethcore ::transaction ::{ Transaction as EthTransaction , SignedTransaction , Action } ;
2016-05-24 21:56:32 +02:00
use ethcore ::log_entry ::LogEntry ;
use ethcore ::filter ::Filter as EthcoreFilter ;
2016-03-26 18:51:27 +01:00
use self ::ethash ::SeedHashCompute ;
2016-06-01 19:37:34 +02:00
use v1 ::traits ::Eth ;
use v1 ::types ::{ Block , BlockTransactions , BlockNumber , Bytes , SyncStatus , SyncInfo , Transaction , CallRequest , OptionalValue , Index , Filter , Log , Receipt } ;
2016-06-15 18:32:21 +02:00
use v1 ::impls ::{ dispatch_transaction , error_codes } ;
2016-03-26 12:35:15 +01:00
use serde ;
2016-01-21 01:19:29 +01:00
2016-01-27 17:08:59 +01:00
/// Eth rpc implementation.
2016-05-22 12:42:22 +02:00
pub struct EthClient < C , S , A , M , EM > where
2016-05-31 21:31:42 +02:00
C : MiningBlockChainClient ,
2016-05-22 12:42:22 +02:00
S : SyncProvider ,
A : AccountProvider ,
M : MinerService ,
EM : ExternalMinerService {
2016-05-23 11:30:11 +02:00
2016-03-09 17:31:43 +01:00
client : Weak < C > ,
sync : Weak < S > ,
2016-03-10 17:18:01 +01:00
accounts : Weak < A > ,
2016-03-10 16:18:33 +01:00
miner : Weak < M > ,
2016-04-21 17:32:53 +02:00
external_miner : Arc < EM > ,
2016-03-26 18:51:27 +01:00
seed_compute : Mutex < SeedHashCompute > ,
2016-06-19 14:51:51 +02:00
allow_pending_receipt_query : bool ,
2016-01-21 01:19:29 +01:00
}
2016-05-22 12:42:22 +02:00
impl < C , S , A , M , EM > EthClient < C , S , A , M , EM > where
2016-05-31 21:31:42 +02:00
C : MiningBlockChainClient ,
2016-05-22 12:42:22 +02:00
S : SyncProvider ,
A : AccountProvider ,
M : MinerService ,
EM : ExternalMinerService {
2016-03-14 14:18:29 +01:00
2016-04-21 17:32:53 +02:00
/// Creates new EthClient.
2016-06-19 14:51:51 +02:00
pub fn new ( client : & Arc < C > , sync : & Arc < S > , accounts : & Arc < A > , miner : & Arc < M > , em : & Arc < EM > , allow_pending_receipt_query : bool )
2016-03-14 14:18:29 +01:00
-> EthClient < C , S , A , M , EM > {
2016-01-21 01:19:29 +01:00
EthClient {
2016-02-29 11:58:33 +01:00
client : Arc ::downgrade ( client ) ,
2016-03-01 01:52:22 +01:00
sync : Arc ::downgrade ( sync ) ,
2016-03-08 15:46:44 +01:00
miner : Arc ::downgrade ( miner ) ,
2016-03-10 17:18:01 +01:00
accounts : Arc ::downgrade ( accounts ) ,
2016-04-21 17:32:53 +02:00
external_miner : em . clone ( ) ,
2016-03-26 18:51:27 +01:00
seed_compute : Mutex ::new ( SeedHashCompute ::new ( ) ) ,
2016-06-19 14:51:51 +02:00
allow_pending_receipt_query : allow_pending_receipt_query ,
2016-01-21 01:19:29 +01:00
}
}
2016-02-10 22:54:12 +01:00
2016-05-19 11:00:32 +02:00
fn block ( & self , id : BlockID , include_txs : bool ) -> Result < Value , Error > {
2016-02-29 11:58:33 +01:00
let client = take_weak! ( self . client ) ;
match ( client . block ( id . clone ( ) ) , client . block_total_difficulty ( id ) ) {
2016-02-10 22:54:12 +01:00
( Some ( bytes ) , Some ( total_difficulty ) ) = > {
let block_view = BlockView ::new ( & bytes ) ;
let view = block_view . header_view ( ) ;
let block = Block {
hash : OptionalValue ::Value ( view . sha3 ( ) ) ,
parent_hash : view . parent_hash ( ) ,
uncles_hash : view . uncles_hash ( ) ,
author : view . author ( ) ,
miner : view . author ( ) ,
state_root : view . state_root ( ) ,
transactions_root : view . transactions_root ( ) ,
receipts_root : view . receipts_root ( ) ,
number : OptionalValue ::Value ( U256 ::from ( view . number ( ) ) ) ,
gas_used : view . gas_used ( ) ,
gas_limit : view . gas_limit ( ) ,
logs_bloom : view . log_bloom ( ) ,
timestamp : U256 ::from ( view . timestamp ( ) ) ,
difficulty : view . difficulty ( ) ,
total_difficulty : total_difficulty ,
2016-05-19 00:41:41 +02:00
seal_fields : view . seal ( ) . into_iter ( ) . map ( | f | decode ( & f ) ) . map ( Bytes ::new ) . collect ( ) ,
2016-03-19 12:23:48 +01:00
uncles : block_view . uncle_hashes ( ) ,
2016-02-10 22:54:12 +01:00
transactions : {
if include_txs {
BlockTransactions ::Full ( block_view . localized_transactions ( ) . into_iter ( ) . map ( From ::from ) . collect ( ) )
} else {
BlockTransactions ::Hashes ( block_view . transaction_hashes ( ) )
}
} ,
2016-03-19 11:44:36 +01:00
extra_data : Bytes ::new ( view . extra_data ( ) )
2016-02-10 22:54:12 +01:00
} ;
to_value ( & block )
} ,
_ = > Ok ( Value ::Null )
}
}
2016-02-29 11:58:33 +01:00
2016-05-19 11:00:32 +02:00
fn transaction ( & self , id : TransactionID ) -> Result < Value , Error > {
2016-02-29 11:58:33 +01:00
match take_weak! ( self . client ) . transaction ( id ) {
2016-02-10 22:54:12 +01:00
Some ( t ) = > to_value ( & Transaction ::from ( t ) ) ,
None = > Ok ( Value ::Null )
}
}
2016-03-14 17:01:10 +01:00
2016-05-19 11:00:32 +02:00
fn uncle ( & self , id : UncleID ) -> Result < Value , Error > {
2016-03-22 16:07:42 +01:00
let client = take_weak! ( self . client ) ;
2016-05-19 11:00:32 +02:00
match client . uncle ( id ) . and_then ( | u | client . block_total_difficulty ( BlockID ::Hash ( u . parent_hash ( ) . clone ( ) ) ) . map ( | diff | ( diff , u ) ) ) {
2016-05-16 12:46:09 +02:00
Some ( ( parent_difficulty , uncle ) ) = > {
2016-03-22 16:07:42 +01:00
let block = Block {
hash : OptionalValue ::Value ( uncle . hash ( ) ) ,
parent_hash : uncle . parent_hash ,
uncles_hash : uncle . uncles_hash ,
author : uncle . author ,
miner : uncle . author ,
state_root : uncle . state_root ,
transactions_root : uncle . transactions_root ,
number : OptionalValue ::Value ( U256 ::from ( uncle . number ) ) ,
gas_used : uncle . gas_used ,
gas_limit : uncle . gas_limit ,
logs_bloom : uncle . log_bloom ,
timestamp : U256 ::from ( uncle . timestamp ) ,
2016-05-16 13:33:29 +02:00
difficulty : uncle . difficulty ,
total_difficulty : uncle . difficulty + parent_difficulty ,
2016-03-22 16:07:42 +01:00
receipts_root : uncle . receipts_root ,
extra_data : Bytes ::new ( uncle . extra_data ) ,
2016-05-19 00:41:41 +02:00
seal_fields : uncle . seal . into_iter ( ) . map ( | f | decode ( & f ) ) . map ( Bytes ::new ) . collect ( ) ,
2016-03-22 16:07:42 +01:00
uncles : vec ! [ ] ,
transactions : BlockTransactions ::Hashes ( vec! [ ] ) ,
} ;
to_value ( & block )
} ,
None = > Ok ( Value ::Null )
}
2016-03-14 17:01:10 +01:00
}
2016-03-22 17:17:50 +01:00
2016-06-16 12:44:08 +02:00
fn default_gas_price ( & self ) -> Result < U256 , Error > {
let miner = take_weak! ( self . miner ) ;
Ok ( take_weak! ( self . client )
. gas_price_statistics ( 100 , 8 )
. map ( | x | x [ 4 ] )
. unwrap_or_else ( | _ | miner . sensible_gas_price ( ) )
)
}
2016-03-28 18:53:33 +02:00
fn sign_call ( & self , request : CallRequest ) -> Result < SignedTransaction , Error > {
let client = take_weak! ( self . client ) ;
2016-03-26 13:30:02 +01:00
let from = request . from . unwrap_or ( Address ::zero ( ) ) ;
2016-03-28 18:53:33 +02:00
Ok ( EthTransaction {
2016-05-26 22:17:55 +02:00
nonce : request . nonce . unwrap_or_else ( | | client . latest_nonce ( & from ) ) ,
2016-03-26 13:30:02 +01:00
action : request . to . map_or ( Action ::Create , Action ::Call ) ,
2016-04-14 21:01:12 +02:00
gas : request . gas . unwrap_or ( U256 ::from ( 50_000_000 ) ) ,
2016-06-16 12:44:08 +02:00
gas_price : request . gas_price . unwrap_or_else ( | | self . default_gas_price ( ) . expect ( " call only fails if client or miner are unavailable; client and miner are both available to be here; qed " ) ) ,
2016-03-26 13:30:02 +01:00
value : request . value . unwrap_or_else ( U256 ::zero ) ,
data : request . data . map_or_else ( Vec ::new , | d | d . to_vec ( ) )
2016-03-28 18:53:33 +02:00
} . fake_sign ( from ) )
2016-03-22 17:17:50 +01:00
}
2016-01-21 01:19:29 +01:00
}
2016-03-22 17:17:50 +01:00
2016-06-01 19:37:34 +02:00
pub fn pending_logs < M > ( miner : & M , filter : & EthcoreFilter ) -> Vec < Log > where M : MinerService {
let receipts = miner . pending_receipts ( ) ;
let pending_logs = receipts . into_iter ( )
. flat_map ( | ( hash , r ) | r . logs . into_iter ( ) . map ( | l | ( hash . clone ( ) , l ) ) . collect ::< Vec < ( H256 , LogEntry ) > > ( ) )
. collect ::< Vec < ( H256 , LogEntry ) > > ( ) ;
let result = pending_logs . into_iter ( )
. filter ( | pair | filter . matches ( & pair . 1 ) )
. map ( | pair | {
let mut log = Log ::from ( pair . 1 ) ;
log . transaction_hash = Some ( pair . 0 ) ;
log
} )
. collect ( ) ;
result
}
2016-03-24 15:13:43 +01:00
const MAX_QUEUE_SIZE_TO_MINE_ON : usize = 4 ; // because uncles go back 6.
2016-03-22 17:17:50 +01:00
2016-03-26 12:35:15 +01:00
fn params_len ( params : & Params ) -> usize {
match params {
& Params ::Array ( ref vec ) = > vec . len ( ) ,
_ = > 0 ,
2016-03-14 17:01:10 +01:00
}
2016-01-21 01:19:29 +01:00
}
2016-04-28 21:47:44 +02:00
fn from_params_default_second < F > ( params : Params ) -> Result < ( F , BlockNumber , ) , Error > where F : serde ::de ::Deserialize {
2016-03-26 12:35:15 +01:00
match params_len ( & params ) {
2016-04-28 21:47:44 +02:00
1 = > from_params ::< ( F , ) > ( params ) . map ( | ( f , ) | ( f , BlockNumber ::Latest ) ) ,
_ = > from_params ::< ( F , BlockNumber ) > ( params ) ,
2016-03-26 12:35:15 +01:00
}
}
2016-04-28 21:47:44 +02:00
fn from_params_default_third < F1 , F2 > ( params : Params ) -> Result < ( F1 , F2 , BlockNumber , ) , Error > where F1 : serde ::de ::Deserialize , F2 : serde ::de ::Deserialize {
2016-03-26 12:35:15 +01:00
match params_len ( & params ) {
2016-04-28 21:47:44 +02:00
2 = > from_params ::< ( F1 , F2 , ) > ( params ) . map ( | ( f1 , f2 ) | ( f1 , f2 , BlockNumber ::Latest ) ) ,
_ = > from_params ::< ( F1 , F2 , BlockNumber ) > ( params )
2016-03-26 12:35:15 +01:00
}
}
2016-03-24 15:13:43 +01:00
2016-05-25 17:35:15 +02:00
fn make_unsupported_err ( ) -> Error {
Error {
2016-06-15 18:32:21 +02:00
code : ErrorCode ::ServerError ( error_codes ::UNSUPPORTED_REQUEST_CODE ) ,
2016-05-27 16:25:06 +02:00
message : " Unsupported request. " . into ( ) ,
data : None
2016-05-25 17:35:15 +02:00
}
}
2016-06-14 15:17:17 +02:00
fn no_work_err ( ) -> Error {
Error {
2016-06-15 18:32:21 +02:00
code : ErrorCode ::ServerError ( error_codes ::NO_WORK_CODE ) ,
2016-06-15 01:12:46 +02:00
message : " Still syncing. " . into ( ) ,
2016-06-14 15:17:17 +02:00
data : None
}
}
2016-05-22 12:42:22 +02:00
impl < C , S , A , M , EM > Eth for EthClient < C , S , A , M , EM > where
2016-05-31 21:31:42 +02:00
C : MiningBlockChainClient + 'static ,
2016-05-22 12:42:22 +02:00
S : SyncProvider + 'static ,
A : AccountProvider + 'static ,
M : MinerService + 'static ,
EM : ExternalMinerService + 'static {
2016-03-11 14:26:23 +01:00
2016-01-21 01:19:29 +01:00
fn protocol_version ( & self , params : Params ) -> Result < Value , Error > {
match params {
2016-03-13 12:09:30 +01:00
Params ::None = > Ok ( Value ::String ( format! ( " {} " , take_weak! ( self . sync ) . status ( ) . protocol_version ) . to_owned ( ) ) ) ,
2016-01-21 01:19:29 +01:00
_ = > Err ( Error ::invalid_params ( ) )
}
}
2016-02-05 13:21:34 +01:00
fn syncing ( & self , params : Params ) -> Result < Value , Error > {
match params {
2016-02-10 16:28:59 +01:00
Params ::None = > {
2016-02-29 11:58:33 +01:00
let status = take_weak! ( self . sync ) . status ( ) ;
2016-02-10 16:28:59 +01:00
let res = match status . state {
2016-05-16 14:41:41 +02:00
SyncState ::Idle = > SyncStatus ::None ,
2016-05-22 11:47:17 +02:00
SyncState ::Waiting | SyncState ::Blocks | SyncState ::NewBlocks | SyncState ::ChainHead = > {
2016-05-31 10:31:36 +02:00
let current_block = U256 ::from ( take_weak! ( self . client ) . chain_info ( ) . best_block_number ) ;
2016-05-22 11:47:17 +02:00
let info = SyncInfo {
starting_block : U256 ::from ( status . start_block_number ) ,
2016-05-31 10:31:36 +02:00
current_block : current_block ,
2016-05-22 11:47:17 +02:00
highest_block : U256 ::from ( status . highest_block_number . unwrap_or ( status . start_block_number ) )
} ;
2016-05-31 10:31:36 +02:00
match info . highest_block > info . current_block + U256 ::from ( 6 ) {
2016-05-22 11:47:17 +02:00
true = > SyncStatus ::Info ( info ) ,
false = > SyncStatus ::None ,
}
}
2016-02-10 16:28:59 +01:00
} ;
to_value ( & res )
}
2016-02-05 13:21:34 +01:00
_ = > Err ( Error ::invalid_params ( ) )
}
}
2016-01-21 01:19:29 +01:00
fn author ( & self , params : Params ) -> Result < Value , Error > {
match params {
2016-03-22 19:12:17 +01:00
Params ::None = > to_value ( & take_weak! ( self . miner ) . author ( ) ) ,
_ = > Err ( Error ::invalid_params ( ) ) ,
2016-01-21 01:19:29 +01:00
}
}
2016-02-05 13:21:34 +01:00
fn is_mining ( & self , params : Params ) -> Result < Value , Error > {
2016-01-21 11:25:39 +01:00
match params {
2016-03-14 14:18:29 +01:00
Params ::None = > to_value ( & self . external_miner . is_mining ( ) ) ,
2016-01-21 11:25:39 +01:00
_ = > Err ( Error ::invalid_params ( ) )
}
}
2016-02-05 13:21:34 +01:00
fn hashrate ( & self , params : Params ) -> Result < Value , Error > {
2016-01-21 01:19:29 +01:00
match params {
2016-03-14 14:18:29 +01:00
Params ::None = > to_value ( & self . external_miner . hashrate ( ) ) ,
2016-01-21 01:19:29 +01:00
_ = > Err ( Error ::invalid_params ( ) )
}
}
2016-02-05 13:21:34 +01:00
fn gas_price ( & self , params : Params ) -> Result < Value , Error > {
2016-01-21 01:19:29 +01:00
match params {
2016-06-16 12:44:08 +02:00
Params ::None = > to_value ( & try ! ( self . default_gas_price ( ) ) ) ,
2016-01-21 01:19:29 +01:00
_ = > Err ( Error ::invalid_params ( ) )
}
}
2016-01-21 11:25:39 +01:00
2016-03-12 19:21:08 +01:00
fn accounts ( & self , _ : Params ) -> Result < Value , Error > {
let store = take_weak! ( self . accounts ) ;
match store . accounts ( ) {
Ok ( account_list ) = > to_value ( & account_list ) ,
Err ( _ ) = > Err ( Error ::internal_error ( ) )
}
}
2016-02-05 13:21:34 +01:00
fn block_number ( & self , params : Params ) -> Result < Value , Error > {
2016-01-21 11:25:39 +01:00
match params {
2016-02-29 11:58:33 +01:00
Params ::None = > to_value ( & U256 ::from ( take_weak! ( self . client ) . chain_info ( ) . best_block_number ) ) ,
2016-01-21 11:25:39 +01:00
_ = > Err ( Error ::invalid_params ( ) )
}
}
2016-01-26 00:42:07 +01:00
2016-03-12 19:51:24 +01:00
fn balance ( & self , params : Params ) -> Result < Value , Error > {
2016-04-28 21:47:44 +02:00
from_params_default_second ( params )
. and_then ( | ( address , block_number , ) | match block_number {
BlockNumber ::Pending = > to_value ( & take_weak! ( self . miner ) . balance ( take_weak! ( self . client ) . deref ( ) , & address ) ) ,
2016-05-26 11:46:45 +02:00
id = > to_value ( & try ! ( take_weak! ( self . client ) . balance ( & address , id . into ( ) ) . ok_or_else ( make_unsupported_err ) ) ) ,
2016-04-28 21:47:44 +02:00
} )
2016-03-12 19:51:24 +01:00
}
2016-03-13 12:09:30 +01:00
fn storage_at ( & self , params : Params ) -> Result < Value , Error > {
2016-04-28 21:47:44 +02:00
from_params_default_third ::< Address , U256 > ( params )
. and_then ( | ( address , position , block_number , ) | match block_number {
2016-05-25 17:54:20 +02:00
BlockNumber ::Pending = > to_value ( & U256 ::from ( take_weak! ( self . miner ) . storage_at ( & * take_weak! ( self . client ) , & address , & H256 ::from ( position ) ) ) ) ,
2016-05-26 11:46:45 +02:00
id = > match take_weak! ( self . client ) . storage_at ( & address , & H256 ::from ( position ) , id . into ( ) ) {
2016-05-27 16:25:06 +02:00
Some ( s ) = > to_value ( & U256 ::from ( s ) ) ,
None = > Err ( make_unsupported_err ( ) ) , // None is only returned on unsupported requests.
2016-05-26 11:46:45 +02:00
}
2016-04-28 21:47:44 +02:00
} )
2016-03-13 12:09:30 +01:00
}
2016-03-13 14:37:33 +01:00
fn transaction_count ( & self , params : Params ) -> Result < Value , Error > {
2016-04-28 21:47:44 +02:00
from_params_default_second ( params )
. and_then ( | ( address , block_number , ) | match block_number {
BlockNumber ::Pending = > to_value ( & take_weak! ( self . miner ) . nonce ( take_weak! ( self . client ) . deref ( ) , & address ) ) ,
2016-05-26 12:57:15 +02:00
id = > to_value ( & take_weak! ( self . client ) . nonce ( & address , id . into ( ) ) ) ,
2016-04-28 21:47:44 +02:00
} )
2016-03-13 14:37:33 +01:00
}
2016-02-25 16:58:18 +01:00
fn block_transaction_count_by_hash ( & self , params : Params ) -> Result < Value , Error > {
2016-02-10 10:12:56 +01:00
from_params ::< ( H256 , ) > ( params )
2016-03-13 14:37:33 +01:00
. and_then ( | ( hash , ) | // match
2016-05-19 11:00:32 +02:00
take_weak! ( self . client ) . block ( BlockID ::Hash ( hash ) )
2016-03-19 12:23:48 +01:00
. map_or ( Ok ( Value ::Null ) , | bytes | to_value ( & U256 ::from ( BlockView ::new ( & bytes ) . transactions_count ( ) ) ) ) )
2016-02-05 13:21:34 +01:00
}
2016-02-25 16:58:18 +01:00
fn block_transaction_count_by_number ( & self , params : Params ) -> Result < Value , Error > {
from_params ::< ( BlockNumber , ) > ( params )
. and_then ( | ( block_number , ) | match block_number {
2016-03-17 13:18:26 +01:00
BlockNumber ::Pending = > to_value (
2016-03-17 11:19:12 +01:00
& U256 ::from ( take_weak! ( self . miner ) . status ( ) . transactions_in_pending_block )
) ,
2016-03-19 12:23:48 +01:00
_ = > take_weak! ( self . client ) . block ( block_number . into ( ) )
. map_or ( Ok ( Value ::Null ) , | bytes | to_value ( & U256 ::from ( BlockView ::new ( & bytes ) . transactions_count ( ) ) ) )
2016-02-25 16:58:18 +01:00
} )
}
2016-03-13 14:37:33 +01:00
fn block_uncles_count_by_hash ( & self , params : Params ) -> Result < Value , Error > {
2016-02-10 10:12:56 +01:00
from_params ::< ( H256 , ) > ( params )
2016-03-13 14:37:33 +01:00
. and_then ( | ( hash , ) |
2016-05-19 11:00:32 +02:00
take_weak! ( self . client ) . block ( BlockID ::Hash ( hash ) )
2016-03-19 12:23:48 +01:00
. map_or ( Ok ( Value ::Null ) , | bytes | to_value ( & U256 ::from ( BlockView ::new ( & bytes ) . uncles_count ( ) ) ) ) )
2016-03-13 14:37:33 +01:00
}
fn block_uncles_count_by_number ( & self , params : Params ) -> Result < Value , Error > {
from_params ::< ( BlockNumber , ) > ( params )
. and_then ( | ( block_number , ) | match block_number {
BlockNumber ::Pending = > to_value ( & U256 ::from ( 0 ) ) ,
2016-03-19 12:23:48 +01:00
_ = > take_weak! ( self . client ) . block ( block_number . into ( ) )
. map_or ( Ok ( Value ::Null ) , | bytes | to_value ( & U256 ::from ( BlockView ::new ( & bytes ) . uncles_count ( ) ) ) )
2016-02-10 10:12:56 +01:00
} )
2016-01-26 00:42:07 +01:00
}
2016-01-26 11:37:24 +01:00
2016-02-08 10:58:08 +01:00
fn code_at ( & self , params : Params ) -> Result < Value , Error > {
2016-04-28 21:47:44 +02:00
from_params_default_second ( params )
. and_then ( | ( address , block_number , ) | match block_number {
BlockNumber ::Pending = > to_value ( & take_weak! ( self . miner ) . code ( take_weak! ( self . client ) . deref ( ) , & address ) . map_or_else ( Bytes ::default , Bytes ::new ) ) ,
BlockNumber ::Latest = > to_value ( & take_weak! ( self . client ) . code ( & address ) . map_or_else ( Bytes ::default , Bytes ::new ) ) ,
_ = > Err ( Error ::invalid_params ( ) ) ,
} )
2016-02-08 10:58:08 +01:00
}
2016-02-10 22:54:12 +01:00
fn block_by_hash ( & self , params : Params ) -> Result < Value , Error > {
2016-02-10 10:12:56 +01:00
from_params ::< ( H256 , bool ) > ( params )
2016-05-19 11:00:32 +02:00
. and_then ( | ( hash , include_txs ) | self . block ( BlockID ::Hash ( hash ) , include_txs ) )
2016-02-10 22:54:12 +01:00
}
fn block_by_number ( & self , params : Params ) -> Result < Value , Error > {
from_params ::< ( BlockNumber , bool ) > ( params )
. and_then ( | ( number , include_txs ) | self . block ( number . into ( ) , include_txs ) )
2016-01-26 11:37:24 +01:00
}
2016-02-09 13:17:44 +01:00
2016-02-10 10:12:56 +01:00
fn transaction_by_hash ( & self , params : Params ) -> Result < Value , Error > {
from_params ::< ( H256 , ) > ( params )
2016-03-27 15:12:21 +02:00
. and_then ( | ( hash , ) | {
let miner = take_weak! ( self . miner ) ;
match miner . transaction ( & hash ) {
Some ( pending_tx ) = > to_value ( & Transaction ::from ( pending_tx ) ) ,
2016-05-19 11:00:32 +02:00
None = > self . transaction ( TransactionID ::Hash ( hash ) )
2016-03-27 15:12:21 +02:00
}
} )
2016-02-10 11:28:40 +01:00
}
fn transaction_by_block_hash_and_index ( & self , params : Params ) -> Result < Value , Error > {
from_params ::< ( H256 , Index ) > ( params )
2016-05-19 11:00:32 +02:00
. and_then ( | ( hash , index ) | self . transaction ( TransactionID ::Location ( BlockID ::Hash ( hash ) , index . value ( ) ) ) )
2016-02-10 11:28:40 +01:00
}
2016-02-10 22:36:59 +01:00
fn transaction_by_block_number_and_index ( & self , params : Params ) -> Result < Value , Error > {
from_params ::< ( BlockNumber , Index ) > ( params )
2016-05-19 11:00:32 +02:00
. and_then ( | ( number , index ) | self . transaction ( TransactionID ::Location ( number . into ( ) , index . value ( ) ) ) )
2016-02-09 13:17:44 +01:00
}
2016-02-15 13:18:26 +01:00
2016-03-20 17:29:39 +01:00
fn transaction_receipt ( & self , params : Params ) -> Result < Value , Error > {
2016-03-20 18:44:57 +01:00
from_params ::< ( H256 , ) > ( params )
. and_then ( | ( hash , ) | {
2016-06-18 12:09:29 +02:00
let miner = take_weak! ( self . miner ) ;
match miner . pending_receipts ( ) . get ( & hash ) {
2016-06-19 14:51:51 +02:00
Some ( receipt ) if self . allow_pending_receipt_query = > to_value ( & Receipt ::from ( receipt . clone ( ) ) ) ,
_ = > {
2016-06-18 12:09:29 +02:00
let client = take_weak! ( self . client ) ;
let receipt = client . transaction_receipt ( TransactionID ::Hash ( hash ) ) ;
to_value ( & receipt . map ( Receipt ::from ) )
}
}
2016-03-20 18:44:57 +01:00
} )
2016-03-20 17:29:39 +01:00
}
2016-03-14 17:01:10 +01:00
fn uncle_by_block_hash_and_index ( & self , params : Params ) -> Result < Value , Error > {
from_params ::< ( H256 , Index ) > ( params )
2016-05-19 11:00:32 +02:00
. and_then ( | ( hash , index ) | self . uncle ( UncleID ( BlockID ::Hash ( hash ) , index . value ( ) ) ) )
2016-03-14 17:01:10 +01:00
}
fn uncle_by_block_number_and_index ( & self , params : Params ) -> Result < Value , Error > {
from_params ::< ( BlockNumber , Index ) > ( params )
2016-05-19 11:00:32 +02:00
. and_then ( | ( number , index ) | self . uncle ( UncleID ( number . into ( ) , index . value ( ) ) ) )
2016-03-14 17:01:10 +01:00
}
2016-03-13 15:02:46 +01:00
fn compilers ( & self , params : Params ) -> Result < Value , Error > {
match params {
Params ::None = > to_value ( & vec! [ ] as & Vec < String > ) ,
_ = > Err ( Error ::invalid_params ( ) )
}
}
2016-02-15 13:18:26 +01:00
fn logs ( & self , params : Params ) -> Result < Value , Error > {
from_params ::< ( Filter , ) > ( params )
. and_then ( | ( filter , ) | {
2016-05-24 21:56:32 +02:00
let include_pending = filter . to_block = = Some ( BlockNumber ::Pending ) ;
let filter : EthcoreFilter = filter . into ( ) ;
let mut logs = take_weak! ( self . client ) . logs ( filter . clone ( ) )
2016-02-15 13:39:58 +01:00
. into_iter ( )
2016-02-17 14:13:51 +01:00
. map ( From ::from )
. collect ::< Vec < Log > > ( ) ;
2016-05-24 21:56:32 +02:00
if include_pending {
let pending = pending_logs ( take_weak! ( self . miner ) . deref ( ) , & filter ) ;
logs . extend ( pending ) ;
}
2016-02-17 14:13:51 +01:00
to_value ( & logs )
2016-02-15 13:18:26 +01:00
} )
}
2016-02-29 19:30:13 +01:00
fn work ( & self , params : Params ) -> Result < Value , Error > {
match params {
Params ::None = > {
2016-03-15 23:58:46 +01:00
let client = take_weak! ( self . client ) ;
2016-03-22 13:05:18 +01:00
// check if we're still syncing and return empty strings in that case
2016-03-15 17:13:44 +01:00
{
2016-03-24 17:07:54 +01:00
//TODO: check if initial sync is complete here
2016-03-24 17:00:32 +01:00
//let sync = take_weak!(self.sync);
2016-03-24 15:29:54 +01:00
if /* sync.status().state != SyncState::Idle || */ client . queue_info ( ) . total_queue_size ( ) > MAX_QUEUE_SIZE_TO_MINE_ON {
2016-03-24 14:51:51 +01:00
trace! ( target : " miner " , " Syncing. Cannot give any work. " ) ;
2016-06-14 15:17:17 +02:00
return Err ( no_work_err ( ) ) ;
2016-03-15 17:13:44 +01:00
}
}
2016-03-08 15:46:44 +01:00
let miner = take_weak! ( self . miner ) ;
2016-03-24 23:03:22 +01:00
miner . map_sealing_work ( client . deref ( ) , | b | {
let pow_hash = b . hash ( ) ;
let target = Ethash ::difficulty_to_boundary ( b . block ( ) . header ( ) . difficulty ( ) ) ;
2016-03-28 11:23:22 +02:00
let seed_hash = & self . seed_compute . lock ( ) . unwrap ( ) . get_seedhash ( b . block ( ) . header ( ) . number ( ) ) ;
to_value ( & ( pow_hash , H256 ::from_slice ( & seed_hash [ .. ] ) , target ) )
2016-03-24 23:03:22 +01:00
} ) . unwrap_or ( Err ( Error ::internal_error ( ) ) ) // no work found.
2016-02-29 19:30:13 +01:00
} ,
_ = > Err ( Error ::invalid_params ( ) )
}
}
2016-03-01 00:02:48 +01:00
fn submit_work ( & self , params : Params ) -> Result < Value , Error > {
from_params ::< ( H64 , H256 , H256 ) > ( params ) . and_then ( | ( nonce , pow_hash , mix_hash ) | {
2016-04-10 23:01:41 +02:00
trace! ( target : " miner " , " submit_work: Decoded: nonce={}, pow_hash={}, mix_hash={} " , nonce , pow_hash , mix_hash ) ;
2016-03-08 15:46:44 +01:00
let miner = take_weak! ( self . miner ) ;
2016-03-08 16:23:32 +01:00
let client = take_weak! ( self . client ) ;
2016-03-01 00:02:48 +01:00
let seal = vec! [ encode ( & mix_hash ) . to_vec ( ) , encode ( & nonce ) . to_vec ( ) ] ;
2016-03-08 16:23:32 +01:00
let r = miner . submit_seal ( client . deref ( ) , pow_hash , seal ) ;
2016-03-01 16:58:14 +01:00
to_value ( & r . is_ok ( ) )
2016-03-01 00:02:48 +01:00
} )
}
2016-02-29 19:30:13 +01:00
2016-03-01 01:15:00 +01:00
fn submit_hashrate ( & self , params : Params ) -> Result < Value , Error > {
2016-03-14 14:18:29 +01:00
from_params ::< ( U256 , H256 ) > ( params ) . and_then ( | ( rate , id ) | {
self . external_miner . submit_hashrate ( rate , id ) ;
2016-03-01 01:15:00 +01:00
to_value ( & true )
} )
}
2016-03-04 18:10:07 +01:00
2016-03-21 12:00:30 +01:00
fn send_raw_transaction ( & self , params : Params ) -> Result < Value , Error > {
from_params ::< ( Bytes , ) > ( params )
. and_then ( | ( raw_transaction , ) | {
2016-03-28 18:11:00 +02:00
let raw_transaction = raw_transaction . to_vec ( ) ;
match UntrustedRlp ::new ( & raw_transaction ) . as_val ( ) {
2016-06-15 09:01:57 +02:00
Ok ( signed_transaction ) = > dispatch_transaction ( & * take_weak! ( self . client ) , & * take_weak! ( self . miner ) , signed_transaction ) ,
2016-03-28 18:11:00 +02:00
Err ( _ ) = > to_value ( & H256 ::zero ( ) ) ,
2016-03-19 21:37:11 +01:00
}
2016-03-21 12:00:30 +01:00
} )
2016-03-19 21:37:11 +01:00
}
2016-03-20 10:29:21 +01:00
2016-03-19 21:37:11 +01:00
fn call ( & self , params : Params ) -> Result < Value , Error > {
2016-04-14 21:01:12 +02:00
trace! ( target : " jsonrpc " , " call: {:?} " , params ) ;
2016-04-28 21:47:44 +02:00
from_params_default_second ( params )
. and_then ( | ( request , block_number , ) | {
let signed = try ! ( self . sign_call ( request ) ) ;
let r = match block_number {
2016-05-31 21:03:44 +02:00
BlockNumber ::Pending = > take_weak! ( self . miner ) . call ( take_weak! ( self . client ) . deref ( ) , & signed , Default ::default ( ) ) ,
BlockNumber ::Latest = > take_weak! ( self . client ) . call ( & signed , Default ::default ( ) ) ,
2016-04-28 21:47:44 +02:00
_ = > panic! ( " {:?} " , block_number ) ,
} ;
to_value ( & r . map ( | e | Bytes ( e . output ) ) . unwrap_or ( Bytes ::new ( vec! [ ] ) ) )
} )
2016-03-19 21:37:11 +01:00
}
2016-03-20 10:29:21 +01:00
fn estimate_gas ( & self , params : Params ) -> Result < Value , Error > {
2016-04-28 21:47:44 +02:00
from_params_default_second ( params )
. and_then ( | ( request , block_number , ) | {
let signed = try ! ( self . sign_call ( request ) ) ;
let r = match block_number {
2016-05-31 21:03:44 +02:00
BlockNumber ::Pending = > take_weak! ( self . miner ) . call ( take_weak! ( self . client ) . deref ( ) , & signed , Default ::default ( ) ) ,
BlockNumber ::Latest = > take_weak! ( self . client ) . call ( & signed , Default ::default ( ) ) ,
2016-04-28 21:47:44 +02:00
_ = > return Err ( Error ::invalid_params ( ) ) ,
} ;
to_value ( & r . map ( | res | res . gas_used + res . refunded ) . unwrap_or ( From ::from ( 0 ) ) )
} )
2016-03-20 10:29:21 +01:00
}
2016-05-28 15:25:37 +02:00
2016-05-29 15:46:57 +02:00
fn compile_lll ( & self , _ : Params ) -> Result < Value , Error > {
2016-05-28 15:25:37 +02:00
rpc_unimplemented! ( )
}
2016-05-29 15:46:57 +02:00
fn compile_serpent ( & self , _ : Params ) -> Result < Value , Error > {
2016-05-28 15:25:37 +02:00
rpc_unimplemented! ( )
}
2016-05-29 15:46:57 +02:00
fn compile_solidity ( & self , _ : Params ) -> Result < Value , Error > {
2016-05-28 15:25:37 +02:00
rpc_unimplemented! ( )
}
2016-01-21 11:25:39 +01:00
}