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:
parent
abb1da5f4b
commit
8dff4012a6
@ -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 || {};
|
||||
|
@ -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]) => {
|
||||
|
@ -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]) => {
|
||||
|
@ -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) => {
|
||||
|
@ -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]) => {
|
||||
|
@ -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 || {};
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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>>()))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
194
rpc/src/v1/impls/personal_accounts.rs
Normal file
194
rpc/src/v1/impls/personal_accounts.rs
Normal 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>>()))
|
||||
}
|
||||
}
|
@ -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};
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user