Personal split (#2879)

* Split personal namespace into Safe and Unsafe part

* Re-add api.personal.accountsInfo() calls to dapps

* Removing listGethAccounts from safe personal
This commit is contained in:
Jaco Greeff 2016-10-27 19:26:34 +02:00 committed by Gav Wood
parent abb1da5f4b
commit 8dff4012a6
17 changed files with 276 additions and 199 deletions

View File

@ -16,7 +16,7 @@
import React, { Component, PropTypes } from 'react';
// import { api } from '../parity';
import { api } from '../parity';
import { attachInstances } from '../services';
import Header from './Header';
@ -83,7 +83,7 @@ export default class Application extends Component {
Promise
.all([
attachInstances(),
null // api.personal.accountsInfo()
api.personal.accountsInfo()
])
.then(([{ managerInstance, registryInstance, tokenregInstance }, accountsInfo]) => {
accountsInfo = accountsInfo || {};

View File

@ -206,7 +206,7 @@ export default class Application extends Component {
.all([
registry.getAddress.call({}, [api.util.sha3('gavcoin'), 'A']),
api.eth.accounts(),
null // api.personal.accountsInfo()
api.personal.accountsInfo()
]);
})
.then(([address, addresses, infos]) => {

View File

@ -29,7 +29,7 @@ export function attachInterface () {
.all([
registry.getAddress.call({}, [api.util.sha3('githubhint'), 'A']),
api.eth.accounts(),
null // api.personal.accountsInfo()
api.personal.accountsInfo()
]);
})
.then(([address, addresses, accountsInfo]) => {

View File

@ -22,12 +22,16 @@ export const fetch = () => (dispatch) => {
return Promise
.all([
api.eth.accounts(),
null // api.personal.accountsInfo()
api.personal.accountsInfo()
])
.then(([ accounts, data ]) => {
const addresses = accounts.map((address) => {
return { address, isAccount: true };
});
data = data || {};
const addresses = Object.keys(data)
.filter((address) => data[address] && !data[address].meta.deleted)
.map((address) => ({
...data[address], address,
isAccount: accounts.includes(address)
}));
dispatch(set(addresses));
})
.catch((error) => {

View File

@ -50,7 +50,7 @@ export function attachInterface (callback) {
.all([
registry.getAddress.call({}, [api.util.sha3('signaturereg'), 'A']),
api.eth.accounts(),
null // api.personal.accountsInfo()
api.personal.accountsInfo()
]);
})
.then(([address, addresses, accountsInfo]) => {

View File

@ -38,7 +38,7 @@ export const loadAccounts = () => (dispatch) => {
Promise
.all([
api.eth.accounts(),
null // api.personal.accountsInfo()
api.personal.accountsInfo()
])
.then(([ accounts, accountsInfo ]) => {
accountsInfo = accountsInfo || {};

View File

@ -41,13 +41,13 @@ disable = false
port = 8545
interface = "local"
cors = "null"
apis = ["web3", "eth", "net", "ethcore", "traces", "rpc"]
apis = ["web3", "eth", "net", "ethcore", "traces", "rpc", "personal_safe"]
hosts = ["none"]
[ipc]
disable = false
path = "$HOME/.parity/jsonrpc.ipc"
apis = ["web3", "eth", "net", "ethcore", "traces", "rpc"]
apis = ["web3", "eth", "net", "ethcore", "traces", "rpc", "personal_safe"]
[dapps]
disable = false

View File

@ -145,7 +145,7 @@ usage! {
or |c: &Config| otry!(c.rpc).interface.clone(),
flag_jsonrpc_cors: Option<String> = None,
or |c: &Config| otry!(c.rpc).cors.clone().map(Some),
flag_jsonrpc_apis: String = "web3,eth,net,ethcore,traces,rpc",
flag_jsonrpc_apis: String = "web3,eth,net,ethcore,traces,rpc,personal_safe",
or |c: &Config| otry!(c.rpc).apis.clone().map(|vec| vec.join(",")),
flag_jsonrpc_hosts: String = "none",
or |c: &Config| otry!(c.rpc).hosts.clone().map(|vec| vec.join(",")),
@ -155,7 +155,7 @@ usage! {
or |c: &Config| otry!(c.ipc).disable.clone(),
flag_ipc_path: String = "$HOME/.parity/jsonrpc.ipc",
or |c: &Config| otry!(c.ipc).path.clone(),
flag_ipc_apis: String = "web3,eth,net,ethcore,traces,rpc",
flag_ipc_apis: String = "web3,eth,net,ethcore,traces,rpc,personal_safe",
or |c: &Config| otry!(c.ipc).apis.clone().map(|vec| vec.join(",")),
// DAPPS
@ -534,13 +534,13 @@ mod tests {
flag_jsonrpc_port: 8545u16,
flag_jsonrpc_interface: "local".into(),
flag_jsonrpc_cors: Some("null".into()),
flag_jsonrpc_apis: "web3,eth,net,ethcore,traces,rpc".into(),
flag_jsonrpc_apis: "web3,eth,net,ethcore,traces,rpc,personal_safe".into(),
flag_jsonrpc_hosts: "none".into(),
// IPC
flag_no_ipc: false,
flag_ipc_path: "$HOME/.parity/jsonrpc.ipc".into(),
flag_ipc_apis: "web3,eth,net,ethcore,traces,rpc".into(),
flag_ipc_apis: "web3,eth,net,ethcore,traces,rpc,personal_safe".into(),
// DAPPS
flag_no_dapps: false,

View File

@ -107,7 +107,7 @@ API and Console Options:
--jsonrpc-apis APIS Specify the APIs available through the JSONRPC
interface. APIS is a comma-delimited list of API
name. Possible name are web3, eth, net, personal,
ethcore, ethcore_set, traces, rpc.
ethcore, ethcore_set, traces, rpc, personal_safe.
(default: {flag_jsonrpc_apis}).
--jsonrpc-hosts HOSTS List of allowed Host header values. This option will
validate the Host header sent by the browser, it

View File

@ -33,7 +33,8 @@ pub enum Api {
Web3,
Net,
Eth,
Personal,
PersonalSafe,
PersonalAccounts,
Signer,
Ethcore,
EthcoreSet,
@ -51,7 +52,8 @@ impl FromStr for Api {
"web3" => Ok(Web3),
"net" => Ok(Net),
"eth" => Ok(Eth),
"personal" => Ok(Personal),
"personal" => Ok(PersonalAccounts),
"personal_safe" => Ok(PersonalSafe),
"signer" => Ok(Signer),
"ethcore" => Ok(Ethcore),
"ethcore_set" => Ok(EthcoreSet),
@ -114,7 +116,8 @@ fn to_modules(apis: &[Api]) -> BTreeMap<String, String> {
Api::Web3 => ("web3", "1.0"),
Api::Net => ("net", "1.0"),
Api::Eth => ("eth", "1.0"),
Api::Personal => ("personal", "1.0"),
Api::PersonalSafe => ("personal_safe", "1.0"),
Api::PersonalAccounts => ("personal", "1.0"),
Api::Signer => ("signer", "1.0"),
Api::Ethcore => ("ethcore", "1.0"),
Api::EthcoreSet => ("ethcore_set", "1.0"),
@ -131,11 +134,11 @@ impl ApiSet {
match *self {
ApiSet::List(ref apis) => apis.clone(),
ApiSet::UnsafeContext => {
vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc]
vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc, Api::PersonalSafe]
.into_iter().collect()
},
ApiSet::SafeContext => {
vec![Api::Web3, Api::Net, Api::Eth, Api::Personal, Api::Signer, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc]
vec![Api::Web3, Api::Net, Api::Eth, Api::PersonalAccounts, Api::PersonalSafe, Api::Signer, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc]
.into_iter().collect()
},
}
@ -178,8 +181,11 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
server.add_delegate(EthSigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner).to_delegate());
}
},
Api::Personal => {
server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner, deps.geth_compatibility).to_delegate());
Api::PersonalAccounts => {
server.add_delegate(PersonalAccountsClient::new(&deps.secret_store, &deps.client, &deps.miner, deps.geth_compatibility).to_delegate());
},
Api::PersonalSafe => {
server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client).to_delegate());
},
Api::Signer => {
server.add_delegate(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_service).to_delegate());
@ -224,7 +230,8 @@ mod test {
assert_eq!(Api::Web3, "web3".parse().unwrap());
assert_eq!(Api::Net, "net".parse().unwrap());
assert_eq!(Api::Eth, "eth".parse().unwrap());
assert_eq!(Api::Personal, "personal".parse().unwrap());
assert_eq!(Api::PersonalAccounts, "personal".parse().unwrap());
assert_eq!(Api::PersonalSafe, "personal_safe".parse().unwrap());
assert_eq!(Api::Signer, "signer".parse().unwrap());
assert_eq!(Api::Ethcore, "ethcore".parse().unwrap());
assert_eq!(Api::EthcoreSet, "ethcore_set".parse().unwrap());
@ -245,14 +252,14 @@ mod test {
#[test]
fn test_api_set_unsafe_context() {
let expected = vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc]
let expected = vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc, Api::PersonalSafe]
.into_iter().collect();
assert_eq!(ApiSet::UnsafeContext.list_apis(), expected);
}
#[test]
fn test_api_set_safe_context() {
let expected = vec![Api::Web3, Api::Net, Api::Eth, Api::Personal, Api::Signer, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc]
let expected = vec![Api::Web3, Api::Net, Api::Eth, Api::PersonalAccounts, Api::PersonalSafe, Api::Signer, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc]
.into_iter().collect();
assert_eq!(ApiSet::SafeContext.list_apis(), expected);
}

View File

@ -32,6 +32,7 @@ mod ethcore;
mod ethcore_set;
mod net;
mod personal;
mod personal_accounts;
mod personal_signer;
mod rpc;
mod traces;
@ -43,6 +44,7 @@ pub use self::eth_filter::EthFilterClient;
pub use self::eth_signing::{EthSigningUnsafeClient, EthSigningQueueClient};
pub use self::net::NetClient;
pub use self::personal::PersonalClient;
pub use self::personal_accounts::PersonalAccountsClient;
pub use self::personal_signer::SignerClient;
pub use self::ethcore::EthcoreClient;
pub use self::ethcore_set::EthcoreSetClient;

View File

@ -17,34 +17,26 @@
//! Account management (personal) rpc implementation
use std::sync::{Arc, Weak};
use std::collections::{BTreeMap};
use util::{Address};
use jsonrpc_core::*;
use ethkey::{Brain, Generator};
use v1::traits::Personal;
use v1::types::{H160 as RpcH160, TransactionRequest};
use v1::types::{H160 as RpcH160};
use v1::helpers::errors;
use v1::helpers::params::expect_no_params;
use v1::helpers::dispatch::sign_and_dispatch;
use ethcore::account_provider::AccountProvider;
use ethcore::client::MiningBlockChainClient;
use ethcore::miner::MinerService;
/// Account management (personal) rpc implementation.
pub struct PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService {
pub struct PersonalClient<C> where C: MiningBlockChainClient {
accounts: Weak<AccountProvider>,
client: Weak<C>,
miner: Weak<M>,
allow_perm_unlock: bool,
}
impl<C, M> PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService {
impl<C> PersonalClient<C> where C: MiningBlockChainClient {
/// Creates new PersonalClient
pub fn new(store: &Arc<AccountProvider>, client: &Arc<C>, miner: &Arc<M>, allow_perm_unlock: bool) -> Self {
pub fn new(store: &Arc<AccountProvider>, client: &Arc<C>) -> Self {
PersonalClient {
accounts: Arc::downgrade(store),
client: Arc::downgrade(client),
miner: Arc::downgrade(miner),
allow_perm_unlock: allow_perm_unlock,
}
}
@ -55,7 +47,7 @@ impl<C, M> PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService
}
}
impl<C: 'static, M: 'static> Personal for PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService {
impl<C: 'static> Personal for PersonalClient<C> where C: MiningBlockChainClient {
fn accounts(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
@ -66,125 +58,6 @@ impl<C: 'static, M: 'static> Personal for PersonalClient<C, M> where C: MiningBl
Ok(to_value(&accounts.into_iter().map(Into::into).collect::<Vec<RpcH160>>()))
}
fn new_account(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
from_params::<(String, )>(params).and_then(
|(pass, )| {
let store = take_weak!(self.accounts);
match store.new_account(&pass) {
Ok(address) => Ok(to_value(&RpcH160::from(address))),
Err(e) => Err(errors::account("Could not create account.", e)),
}
}
)
}
fn new_account_from_phrase(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
from_params::<(String, String, )>(params).and_then(
|(phrase, pass, )| {
let store = take_weak!(self.accounts);
match store.insert_account(*Brain::new(phrase).generate().unwrap().secret(), &pass) {
Ok(address) => Ok(to_value(&RpcH160::from(address))),
Err(e) => Err(errors::account("Could not create account.", e)),
}
}
)
}
fn new_account_from_wallet(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
from_params::<(String, String, )>(params).and_then(
|(json, pass, )| {
let store = take_weak!(self.accounts);
match store.import_presale(json.as_bytes(), &pass).or_else(|_| store.import_wallet(json.as_bytes(), &pass)) {
Ok(address) => Ok(to_value(&RpcH160::from(address))),
Err(e) => Err(errors::account("Could not create account.", e)),
}
}
)
}
fn unlock_account(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
from_params::<(RpcH160, String, Option<u64>)>(params).and_then(
|(account, account_pass, duration)| {
let account: Address = account.into();
let store = take_weak!(self.accounts);
let r = match (self.allow_perm_unlock, duration) {
(false, _) => store.unlock_account_temporarily(account, account_pass),
(true, Some(0)) => store.unlock_account_permanently(account, account_pass),
(true, Some(d)) => store.unlock_account_timed(account, account_pass, d as u32 * 1000),
(true, None) => store.unlock_account_timed(account, account_pass, 300_000),
};
match r {
Ok(_) => Ok(Value::Bool(true)),
Err(_) => Ok(Value::Bool(false)),
}
}
)
}
fn test_password(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
from_params::<(RpcH160, String)>(params).and_then(
|(account, password)| {
let account: Address = account.into();
take_weak!(self.accounts)
.test_password(&account, password)
.map(|b| Value::Bool(b))
.map_err(|e| errors::account("Could not fetch account info.", e))
}
)
}
fn change_password(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
from_params::<(RpcH160, String, String)>(params).and_then(
|(account, password, new_password)| {
let account: Address = account.into();
take_weak!(self.accounts)
.change_password(&account, password, new_password)
.map(|_| Value::Null)
.map_err(|e| errors::account("Could not fetch account info.", e))
}
)
}
fn sign_and_send_transaction(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
from_params::<(TransactionRequest, String)>(params)
.and_then(|(request, password)| {
sign_and_dispatch(
&*take_weak!(self.client),
&*take_weak!(self.miner),
&*take_weak!(self.accounts),
request.into(),
Some(password)
)
})
}
fn set_account_name(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
let store = take_weak!(self.accounts);
from_params::<(RpcH160, String)>(params).and_then(|(addr, name)| {
let addr: Address = addr.into();
store.set_account_name(addr.clone(), name.clone()).or_else(|_| store.set_address_name(addr, name)).expect("set_address_name always returns Ok; qed");
Ok(Value::Null)
})
}
fn set_account_meta(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
let store = take_weak!(self.accounts);
from_params::<(RpcH160, String)>(params).and_then(|(addr, meta)| {
let addr: Address = addr.into();
store.set_account_meta(addr.clone(), meta.clone()).or_else(|_| store.set_address_meta(addr, meta)).expect("set_address_meta always returns Ok; qed");
Ok(Value::Null)
})
}
fn accounts_info(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
try!(expect_no_params(params));
@ -204,21 +77,4 @@ impl<C: 'static, M: 'static> Personal for PersonalClient<C, M> where C: MiningBl
(format!("0x{}", a.hex()), Value::Object(m))
}).collect::<BTreeMap<_, _>>()))
}
fn geth_accounts(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
try!(expect_no_params(params));
let store = take_weak!(self.accounts);
Ok(to_value(&store.list_geth_accounts(false).into_iter().map(Into::into).collect::<Vec<RpcH160>>()))
}
fn import_geth_accounts(&self, params: Params) -> Result<Value, Error> {
from_params::<(Vec<RpcH160>,)>(params).and_then(|(addresses,)| {
let store = take_weak!(self.accounts);
Ok(to_value(&try!(store
.import_geth_accounts(addresses.into_iter().map(Into::into).collect(), false)
.map_err(|e| errors::account("Couldn't import Geth accounts", e))
).into_iter().map(Into::into).collect::<Vec<RpcH160>>()))
})
}
}

View File

@ -0,0 +1,194 @@
// 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/>.
//! Account management (personal) rpc implementation
use std::sync::{Arc, Weak};
use util::{Address};
use jsonrpc_core::*;
use ethkey::{Brain, Generator};
use v1::traits::PersonalAccounts;
use v1::types::{H160 as RpcH160, TransactionRequest};
use v1::helpers::errors;
use v1::helpers::params::expect_no_params;
use v1::helpers::dispatch::sign_and_dispatch;
use ethcore::account_provider::AccountProvider;
use ethcore::client::MiningBlockChainClient;
use ethcore::miner::MinerService;
/// Account management (personal) rpc implementation.
pub struct PersonalAccountsClient<C, M> where C: MiningBlockChainClient, M: MinerService {
accounts: Weak<AccountProvider>,
client: Weak<C>,
miner: Weak<M>,
allow_perm_unlock: bool,
}
impl<C, M> PersonalAccountsClient<C, M> where C: MiningBlockChainClient, M: MinerService {
/// Creates new PersonalClient
pub fn new(store: &Arc<AccountProvider>, client: &Arc<C>, miner: &Arc<M>, allow_perm_unlock: bool) -> Self {
PersonalAccountsClient {
accounts: Arc::downgrade(store),
client: Arc::downgrade(client),
miner: Arc::downgrade(miner),
allow_perm_unlock: allow_perm_unlock,
}
}
fn active(&self) -> Result<(), Error> {
// TODO: only call every 30s at most.
take_weak!(self.client).keep_alive();
Ok(())
}
}
impl<C: 'static, M: 'static> PersonalAccounts for PersonalAccountsClient<C, M> where C: MiningBlockChainClient, M: MinerService {
fn new_account(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
from_params::<(String, )>(params).and_then(
|(pass, )| {
let store = take_weak!(self.accounts);
match store.new_account(&pass) {
Ok(address) => Ok(to_value(&RpcH160::from(address))),
Err(e) => Err(errors::account("Could not create account.", e)),
}
}
)
}
fn new_account_from_phrase(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
from_params::<(String, String, )>(params).and_then(
|(phrase, pass, )| {
let store = take_weak!(self.accounts);
match store.insert_account(*Brain::new(phrase).generate().unwrap().secret(), &pass) {
Ok(address) => Ok(to_value(&RpcH160::from(address))),
Err(e) => Err(errors::account("Could not create account.", e)),
}
}
)
}
fn new_account_from_wallet(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
from_params::<(String, String, )>(params).and_then(
|(json, pass, )| {
let store = take_weak!(self.accounts);
match store.import_presale(json.as_bytes(), &pass).or_else(|_| store.import_wallet(json.as_bytes(), &pass)) {
Ok(address) => Ok(to_value(&RpcH160::from(address))),
Err(e) => Err(errors::account("Could not create account.", e)),
}
}
)
}
fn unlock_account(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
from_params::<(RpcH160, String, Option<u64>)>(params).and_then(
|(account, account_pass, duration)| {
let account: Address = account.into();
let store = take_weak!(self.accounts);
let r = match (self.allow_perm_unlock, duration) {
(false, _) => store.unlock_account_temporarily(account, account_pass),
(true, Some(0)) => store.unlock_account_permanently(account, account_pass),
(true, Some(d)) => store.unlock_account_timed(account, account_pass, d as u32 * 1000),
(true, None) => store.unlock_account_timed(account, account_pass, 300_000),
};
match r {
Ok(_) => Ok(Value::Bool(true)),
Err(_) => Ok(Value::Bool(false)),
}
}
)
}
fn test_password(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
from_params::<(RpcH160, String)>(params).and_then(
|(account, password)| {
let account: Address = account.into();
take_weak!(self.accounts)
.test_password(&account, password)
.map(|b| Value::Bool(b))
.map_err(|e| errors::account("Could not fetch account info.", e))
}
)
}
fn change_password(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
from_params::<(RpcH160, String, String)>(params).and_then(
|(account, password, new_password)| {
let account: Address = account.into();
take_weak!(self.accounts)
.change_password(&account, password, new_password)
.map(|_| Value::Null)
.map_err(|e| errors::account("Could not fetch account info.", e))
}
)
}
fn sign_and_send_transaction(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
from_params::<(TransactionRequest, String)>(params)
.and_then(|(request, password)| {
sign_and_dispatch(
&*take_weak!(self.client),
&*take_weak!(self.miner),
&*take_weak!(self.accounts),
request.into(),
Some(password)
)
})
}
fn set_account_name(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
let store = take_weak!(self.accounts);
from_params::<(RpcH160, String)>(params).and_then(|(addr, name)| {
let addr: Address = addr.into();
store.set_account_name(addr.clone(), name.clone()).or_else(|_| store.set_address_name(addr, name)).expect("set_address_name always returns Ok; qed");
Ok(Value::Null)
})
}
fn set_account_meta(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
let store = take_weak!(self.accounts);
from_params::<(RpcH160, String)>(params).and_then(|(addr, meta)| {
let addr: Address = addr.into();
store.set_account_meta(addr.clone(), meta.clone()).or_else(|_| store.set_address_meta(addr, meta)).expect("set_address_meta always returns Ok; qed");
Ok(Value::Null)
})
}
fn import_geth_accounts(&self, params: Params) -> Result<Value, Error> {
from_params::<(Vec<RpcH160>,)>(params).and_then(|(addresses,)| {
let store = take_weak!(self.accounts);
Ok(to_value(&try!(store
.import_geth_accounts(addresses.into_iter().map(Into::into).collect(), false)
.map_err(|e| errors::account("Couldn't import Geth accounts", e))
).into_iter().map(Into::into).collect::<Vec<RpcH160>>()))
})
}
fn geth_accounts(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
try!(expect_no_params(params));
let store = take_weak!(self.accounts);
Ok(to_value(&store.list_geth_accounts(false).into_iter().map(Into::into).collect::<Vec<RpcH160>>()))
}
}

View File

@ -26,6 +26,6 @@ pub mod traits;
pub mod tests;
pub mod types;
pub use self::traits::{Web3, Eth, EthFilter, EthSigning, Personal, PersonalSigner, Net, Ethcore, EthcoreSet, Traces, Rpc};
pub use self::traits::{Web3, Eth, EthFilter, EthSigning, Personal, PersonalAccounts, PersonalSigner, Net, Ethcore, EthcoreSet, Traces, Rpc};
pub use self::impls::*;
pub use self::helpers::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings, block_import};

View File

@ -19,7 +19,7 @@ use std::str::FromStr;
use jsonrpc_core::IoHandler;
use util::{U256, Uint, Address};
use ethcore::account_provider::AccountProvider;
use v1::{PersonalClient, Personal};
use v1::{PersonalClient, PersonalAccountsClient, PersonalAccounts, Personal};
use v1::tests::helpers::TestMinerService;
use ethcore::client::TestBlockChainClient;
use ethcore::transaction::{Action, Transaction};
@ -50,10 +50,12 @@ fn setup() -> PersonalTester {
let accounts = accounts_provider();
let client = blockchain_client();
let miner = miner_service();
let personal = PersonalClient::new(&accounts, &client, &miner, false);
let personal = PersonalClient::new(&accounts, &client);
let personal_accounts = PersonalAccountsClient::new(&accounts, &client, &miner, false);
let io = IoHandler::new();
io.add_delegate(personal.to_delegate());
io.add_delegate(personal_accounts.to_delegate());
let tester = PersonalTester {
accounts: accounts,

View File

@ -30,7 +30,7 @@ pub use self::web3::Web3;
pub use self::eth::{Eth, EthFilter};
pub use self::eth_signing::EthSigning;
pub use self::net::Net;
pub use self::personal::{Personal, PersonalSigner};
pub use self::personal::{Personal, PersonalAccounts, PersonalSigner};
pub use self::ethcore::Ethcore;
pub use self::ethcore_set::EthcoreSet;
pub use self::traces::Traces;

View File

@ -18,12 +18,28 @@
use std::sync::Arc;
use jsonrpc_core::*;
/// Personal rpc interface.
/// Personal rpc interface. Safe (read-only) functions.
pub trait Personal: Sized + Send + Sync + 'static {
/// Lists all stored accounts
fn accounts(&self, _: Params) -> Result<Value, Error>;
/// Returns accounts information.
fn accounts_info(&self, _: Params) -> Result<Value, Error>;
/// Should be used to convert object to io delegate.
fn to_delegate(self) -> IoDelegate<Self> {
let mut delegate = IoDelegate::new(Arc::new(self));
delegate.add_method("personal_listAccounts", Personal::accounts);
delegate.add_method("personal_accountsInfo", Personal::accounts_info);
delegate
}
}
/// Personal rpc methods altering stored accounts or their settings.
pub trait PersonalAccounts: Sized + Send + Sync + 'static {
/// Creates new account (it becomes new current unlocked account)
/// Param is the password for the account.
fn new_account(&self, _: Params) -> Result<Value, Error>;
@ -56,31 +72,26 @@ pub trait Personal: Sized + Send + Sync + 'static {
/// Set an account's metadata string.
fn set_account_meta(&self, _: Params) -> Result<Value, Error>;
/// Returns accounts information.
fn accounts_info(&self, _: Params) -> Result<Value, Error>;
/// Imports a number of Geth accounts, with the list provided as the argument.
fn import_geth_accounts(&self, _: Params) -> Result<Value, Error>;
/// Returns the accounts available for importing from Geth.
fn geth_accounts(&self, _: Params) -> Result<Value, Error>;
/// Imports a number of Geth accounts, with the list provided as the argument.
fn import_geth_accounts(&self, _: Params) -> Result<Value, Error>;
/// Should be used to convert object to io delegate.
fn to_delegate(self) -> IoDelegate<Self> {
let mut delegate = IoDelegate::new(Arc::new(self));
delegate.add_method("personal_listAccounts", Personal::accounts);
delegate.add_method("personal_newAccount", Personal::new_account);
delegate.add_method("personal_newAccountFromPhrase", Personal::new_account_from_phrase);
delegate.add_method("personal_newAccountFromWallet", Personal::new_account_from_wallet);
delegate.add_method("personal_unlockAccount", Personal::unlock_account);
delegate.add_method("personal_testPassword", Personal::test_password);
delegate.add_method("personal_changePassword", Personal::change_password);
delegate.add_method("personal_signAndSendTransaction", Personal::sign_and_send_transaction);
delegate.add_method("personal_setAccountName", Personal::set_account_name);
delegate.add_method("personal_setAccountMeta", Personal::set_account_meta);
delegate.add_method("personal_accountsInfo", Personal::accounts_info);
delegate.add_method("personal_listGethAccounts", Personal::geth_accounts);
delegate.add_method("personal_importGethAccounts", Personal::import_geth_accounts);
delegate.add_method("personal_newAccount", PersonalAccounts::new_account);
delegate.add_method("personal_newAccountFromPhrase", PersonalAccounts::new_account_from_phrase);
delegate.add_method("personal_newAccountFromWallet", PersonalAccounts::new_account_from_wallet);
delegate.add_method("personal_unlockAccount", PersonalAccounts::unlock_account);
delegate.add_method("personal_testPassword", PersonalAccounts::test_password);
delegate.add_method("personal_changePassword", PersonalAccounts::change_password);
delegate.add_method("personal_signAndSendTransaction", PersonalAccounts::sign_and_send_transaction);
delegate.add_method("personal_setAccountName", PersonalAccounts::set_account_name);
delegate.add_method("personal_setAccountMeta", PersonalAccounts::set_account_meta);
delegate.add_method("personal_importGethAccounts", PersonalAccounts::import_geth_accounts);
delegate.add_method("personal_listGethAccounts", PersonalAccounts::geth_accounts);
delegate
}
@ -108,6 +119,7 @@ pub trait PersonalSigner: Sized + Send + Sync + 'static {
delegate.add_method("personal_confirmRequest", PersonalSigner::confirm_request);
delegate.add_method("personal_rejectRequest", PersonalSigner::reject_request);
delegate.add_method("personal_generateAuthorizationToken", PersonalSigner::generate_token);
delegate
}
}