[light/jsonrpc] Provide the actual account for eth_coinbase RPC and unify error handeling for light and full client (#9383)

* Provide the actual `account` for eth_coinbase

The previous implementation always provided the `zero address` on
`eth_coinbase` RPC. Now, instead the actual address is returned on
success or an error when no account(s) is found!

* full client `eth_coinbase` return err

In the full-client return an error when no account is found instead of
returning the `zero address`

* Remove needless blocks on single import

* Remove needless `static` lifetime on const

* Fix `rpc_eth_author` test
This commit is contained in:
Niklas Adolfsson 2018-09-05 19:21:08 +02:00 committed by cheme
parent ab9843cb00
commit dca88ff85c
3 changed files with 22 additions and 12 deletions

View File

@ -33,7 +33,7 @@ use ethcore::log_entry::LogEntry;
use ethcore::miner::{self, MinerService}; use ethcore::miner::{self, MinerService};
use ethcore::snapshot::SnapshotService; use ethcore::snapshot::SnapshotService;
use ethcore::encoded; use ethcore::encoded;
use sync::{SyncProvider}; use sync::SyncProvider;
use miner::external::ExternalMinerService; use miner::external::ExternalMinerService;
use transaction::{SignedTransaction, LocalizedTransaction}; use transaction::{SignedTransaction, LocalizedTransaction};
@ -52,7 +52,7 @@ use v1::types::{
}; };
use v1::metadata::Metadata; use v1::metadata::Metadata;
const EXTRA_INFO_PROOF: &'static str = "Object exists in blockchain (fetched earlier), extra_info is always available if object exists; qed"; const EXTRA_INFO_PROOF: &str = "Object exists in blockchain (fetched earlier), extra_info is always available if object exists; qed";
/// Eth RPC options /// Eth RPC options
pub struct EthClientOptions { pub struct EthClientOptions {
@ -500,12 +500,16 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
} }
fn author(&self) -> Result<RpcH160> { fn author(&self) -> Result<RpcH160> {
let mut miner = self.miner.authoring_params().author; let miner = self.miner.authoring_params().author;
if miner == 0.into() { if miner == 0.into() {
miner = self.accounts.accounts().ok().and_then(|a| a.get(0).cloned()).unwrap_or_default(); self.accounts.accounts()
.ok()
.and_then(|a| a.first().cloned())
.map(From::from)
.ok_or_else(|| errors::account("No accounts were found", ""))
} else {
Ok(RpcH160::from(miner))
} }
Ok(RpcH160::from(miner))
} }
fn is_mining(&self) -> Result<bool> { fn is_mining(&self) -> Result<bool> {

View File

@ -252,7 +252,11 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
} }
fn author(&self) -> Result<RpcH160> { fn author(&self) -> Result<RpcH160> {
Ok(Default::default()) self.accounts.accounts()
.ok()
.and_then(|a| a.first().cloned())
.map(From::from)
.ok_or_else(|| errors::account("No accounts were found", ""))
} }
fn is_mining(&self) -> Result<bool> { fn is_mining(&self) -> Result<bool> {

View File

@ -359,25 +359,27 @@ fn rpc_eth_author() {
let make_res = |addr| r#"{"jsonrpc":"2.0","result":""#.to_owned() + &format!("0x{:x}", addr) + r#"","id":1}"#; let make_res = |addr| r#"{"jsonrpc":"2.0","result":""#.to_owned() + &format!("0x{:x}", addr) + r#"","id":1}"#;
let tester = EthTester::default(); let tester = EthTester::default();
let req = r#"{ let request = r#"{
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "eth_coinbase", "method": "eth_coinbase",
"params": [], "params": [],
"id": 1 "id": 1
}"#; }"#;
// No accounts - returns zero let response = r#"{"jsonrpc":"2.0","error":{"code":-32023,"message":"No accounts were found","data":"\"\""},"id":1}"#;
assert_eq!(tester.io.handle_request_sync(req), Some(make_res(Address::zero())));
// No accounts - returns an error indicating that no accounts were found
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_string()));
// Account set - return first account // Account set - return first account
let addr = tester.accounts_provider.new_account(&"123".into()).unwrap(); let addr = tester.accounts_provider.new_account(&"123".into()).unwrap();
assert_eq!(tester.io.handle_request_sync(req), Some(make_res(addr))); assert_eq!(tester.io.handle_request_sync(request), Some(make_res(addr)));
for i in 0..20 { for i in 0..20 {
let addr = tester.accounts_provider.new_account(&format!("{}", i).into()).unwrap(); let addr = tester.accounts_provider.new_account(&format!("{}", i).into()).unwrap();
tester.miner.set_author(addr.clone(), None).unwrap(); tester.miner.set_author(addr.clone(), None).unwrap();
assert_eq!(tester.io.handle_request_sync(req), Some(make_res(addr))); assert_eq!(tester.io.handle_request_sync(request), Some(make_res(addr)));
} }
} }