Merge branch 'lightrpc' into light-txq
This commit is contained in:
@@ -24,6 +24,7 @@ use futures::{future, Future, BoxFuture};
|
||||
use light::client::LightChainClient;
|
||||
use light::on_demand::{request, OnDemand};
|
||||
use light::TransactionQueue as LightTransactionQueue;
|
||||
use rlp::{self, Stream};
|
||||
use util::{Address, H520, H256, U256, Uint, Bytes, RwLock};
|
||||
use util::sha3::Hashable;
|
||||
|
||||
@@ -118,7 +119,7 @@ impl<C: MiningBlockChainClient, M: MinerService> Dispatcher for FullDispatcher<C
|
||||
let (client, miner) = (take_weakf!(self.client), take_weakf!(self.miner));
|
||||
let network_id = client.signing_network_id();
|
||||
let address = filled.from;
|
||||
future::ok({
|
||||
future::done({
|
||||
let t = Transaction {
|
||||
nonce: filled.nonce
|
||||
.or_else(|| miner
|
||||
@@ -133,13 +134,16 @@ impl<C: MiningBlockChainClient, M: MinerService> Dispatcher for FullDispatcher<C
|
||||
data: filled.data,
|
||||
};
|
||||
|
||||
let hash = t.hash(network_id);
|
||||
let signature = try_bf!(signature(&accounts, address, hash, password));
|
||||
|
||||
signature.map(|sig| {
|
||||
SignedTransaction::new(t.with_signature(sig, network_id))
|
||||
.expect("Transaction was signed by AccountsProvider; it never produces invalid signatures; qed")
|
||||
})
|
||||
if accounts.is_hardware_address(address) {
|
||||
hardware_signature(&*accounts, address, t, network_id).map(WithToken::No)
|
||||
} else {
|
||||
let hash = t.hash(network_id);
|
||||
let signature = try_bf!(signature(&*accounts, address, hash, password));
|
||||
Ok(signature.map(|sig| {
|
||||
SignedTransaction::new(t.with_signature(sig, network_id))
|
||||
.expect("Transaction was signed by AccountsProvider; it never produces invalid signatures; qed")
|
||||
}))
|
||||
}
|
||||
}).boxed()
|
||||
}
|
||||
|
||||
@@ -219,8 +223,13 @@ impl Dispatcher for LightDispatcher {
|
||||
value: filled.value,
|
||||
data: filled.data,
|
||||
};
|
||||
|
||||
if accounts.is_hardware_address(address) {
|
||||
return hardware_signature(&*accounts, address, t, network_id).map(WithToken::No)
|
||||
}
|
||||
|
||||
let hash = t.hash(network_id);
|
||||
let signature = signature(&accounts, address, hash, password)?;
|
||||
let signature = signature(&*accounts, address, hash, password)?;
|
||||
|
||||
Ok(signature.map(|sig| {
|
||||
SignedTransaction::new(t.with_signature(sig, network_id))
|
||||
@@ -411,6 +420,27 @@ fn signature(accounts: &AccountProvider, address: Address, hash: H256, password:
|
||||
})
|
||||
}
|
||||
|
||||
// obtain a hardware signature from the given account.
|
||||
fn hardware_signature(accounts: &AccountProvider, address: Address, t: Transaction, network_id: Option<u64>)
|
||||
-> Result<SignedTransaction, Error>
|
||||
{
|
||||
debug_assert!(accounts.is_hardware_address(address));
|
||||
|
||||
let mut stream = rlp::RlpStream::new();
|
||||
t.rlp_append_unsigned_transaction(&mut stream, network_id);
|
||||
let signature = accounts.sign_with_hardware(address, &stream.as_raw())
|
||||
.map_err(|e| {
|
||||
debug!(target: "miner", "Error signing transaction with hardware wallet: {}", e);
|
||||
errors::account("Error signing transaction with hardware wallet", e)
|
||||
})?;
|
||||
|
||||
SignedTransaction::new(t.with_signature(signature, network_id))
|
||||
.map_err(|e| {
|
||||
debug!(target: "miner", "Hardware wallet has produced invalid signature: {}", e);
|
||||
errors::account("Invalid signature generated", e)
|
||||
})
|
||||
}
|
||||
|
||||
fn decrypt(accounts: &AccountProvider, address: Address, msg: Bytes, password: SignWith) -> Result<WithToken<Bytes>, Error> {
|
||||
match password.clone() {
|
||||
SignWith::Nothing => accounts.decrypt(address, None, &DEFAULT_MAC, &msg).map(WithToken::No),
|
||||
@@ -422,7 +452,7 @@ fn decrypt(accounts: &AccountProvider, address: Address, msg: Bytes, password: S
|
||||
})
|
||||
}
|
||||
|
||||
/// Extract default gas price from a client and miner.
|
||||
/// Extract the default gas price from a client and miner.
|
||||
pub fn default_gas_price<C, M>(client: &C, miner: &M) -> U256
|
||||
where C: MiningBlockChainClient, M: MinerService
|
||||
{
|
||||
|
||||
@@ -45,6 +45,7 @@ use v1::types::{
|
||||
TransactionStats, LocalTransactionStatus,
|
||||
BlockNumber, ConsensusCapability, VersionInfo,
|
||||
OperationsInfo, DappId, ChainStatus,
|
||||
AccountInfo, HwAccountInfo
|
||||
};
|
||||
|
||||
/// Parity implementation.
|
||||
@@ -111,7 +112,7 @@ impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where
|
||||
{
|
||||
type Metadata = Metadata;
|
||||
|
||||
fn accounts_info(&self, dapp: Trailing<DappId>) -> Result<BTreeMap<String, BTreeMap<String, String>>, Error> {
|
||||
fn accounts_info(&self, dapp: Trailing<DappId>) -> Result<BTreeMap<H160, AccountInfo>, Error> {
|
||||
let dapp = dapp.0;
|
||||
|
||||
let store = take_weak!(self.accounts);
|
||||
@@ -128,12 +129,17 @@ impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where
|
||||
.into_iter()
|
||||
.chain(other.into_iter())
|
||||
.filter(|&(ref a, _)| dapp_accounts.contains(a))
|
||||
.map(|(a, v)| {
|
||||
let m = map![
|
||||
"name".to_owned() => v.name
|
||||
];
|
||||
(format!("0x{}", a.hex()), m)
|
||||
})
|
||||
.map(|(a, v)| (H160::from(a), AccountInfo { name: v.name }))
|
||||
.collect()
|
||||
)
|
||||
}
|
||||
|
||||
fn hardware_accounts_info(&self) -> Result<BTreeMap<H160, HwAccountInfo>, Error> {
|
||||
let store = take_weak!(self.accounts);
|
||||
let info = store.hardware_accounts_info().map_err(|e| errors::account("Could not fetch account info.", e))?;
|
||||
Ok(info
|
||||
.into_iter()
|
||||
.map(|(a, v)| (H160::from(a), HwAccountInfo { name: v.name, manufacturer: v.meta }))
|
||||
.collect()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::account_provider::{AccountProvider, AccountProviderSettings};
|
||||
use ethstore::EthStore;
|
||||
use ethstore::dir::RootDiskDirectory;
|
||||
use devtools::RandomTempPath;
|
||||
@@ -36,7 +36,7 @@ fn accounts_provider() -> Arc<AccountProvider> {
|
||||
fn accounts_provider_with_vaults_support(temp_path: &str) -> Arc<AccountProvider> {
|
||||
let root_keys_dir = RootDiskDirectory::create(temp_path).unwrap();
|
||||
let secret_store = EthStore::open(Box::new(root_keys_dir)).unwrap();
|
||||
Arc::new(AccountProvider::new(Box::new(secret_store)))
|
||||
Arc::new(AccountProvider::new(Box::new(secret_store), AccountProviderSettings::default()))
|
||||
}
|
||||
|
||||
fn setup_with_accounts_provider(accounts_provider: Arc<AccountProvider>) -> ParityAccountsTester {
|
||||
@@ -314,6 +314,14 @@ fn rpc_parity_vault_adds_vault_field_to_acount_meta() {
|
||||
let response = format!(r#"{{"jsonrpc":"2.0","result":{{"0x{}":{{"meta":"{{\"vault\":\"vault1\"}}","name":"","uuid":"{}"}}}},"id":1}}"#, address1.hex(), uuid1);
|
||||
|
||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
||||
|
||||
// and then
|
||||
assert!(tester.accounts.change_vault(address1, "").is_ok());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_allAccountsInfo", "params":[], "id": 1}"#;
|
||||
let response = format!(r#"{{"jsonrpc":"2.0","result":{{"0x{}":{{"meta":"{{}}","name":"","uuid":"{}"}}}},"id":1}}"#, address1.hex(), uuid1);
|
||||
|
||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -358,6 +366,14 @@ fn rpc_parity_get_set_vault_meta() {
|
||||
let tester = setup_with_vaults_support(temp_path.as_str());
|
||||
|
||||
assert!(tester.accounts.create_vault("vault1", "password1").is_ok());
|
||||
|
||||
// when no meta set
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_getVaultMeta", "params":["vault1"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":"{}","id":1}"#;
|
||||
|
||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
||||
|
||||
// when meta set
|
||||
assert!(tester.accounts.set_vault_meta("vault1", "vault1_meta").is_ok());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_getVaultMeta", "params":["vault1"], "id": 1}"#;
|
||||
@@ -365,11 +381,13 @@ fn rpc_parity_get_set_vault_meta() {
|
||||
|
||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
||||
|
||||
// change meta
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setVaultMeta", "params":["vault1", "updated_vault1_meta"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
|
||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
||||
|
||||
// query changed meta
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_getVaultMeta", "params":["vault1"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":"updated_vault1_meta","id":1}"#;
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ use v1::types::{
|
||||
TransactionStats, LocalTransactionStatus,
|
||||
BlockNumber, ConsensusCapability, VersionInfo,
|
||||
OperationsInfo, DappId, ChainStatus,
|
||||
AccountInfo, HwAccountInfo,
|
||||
};
|
||||
|
||||
build_rpc_trait! {
|
||||
@@ -37,7 +38,11 @@ build_rpc_trait! {
|
||||
|
||||
/// Returns accounts information.
|
||||
#[rpc(name = "parity_accountsInfo")]
|
||||
fn accounts_info(&self, Trailing<DappId>) -> Result<BTreeMap<String, BTreeMap<String, String>>, Error>;
|
||||
fn accounts_info(&self, Trailing<DappId>) -> Result<BTreeMap<H160, AccountInfo>, Error>;
|
||||
|
||||
/// Returns hardware accounts information.
|
||||
#[rpc(name = "parity_hardwareAccountsInfo")]
|
||||
fn hardware_accounts_info(&self) -> Result<BTreeMap<H160, HwAccountInfo>, Error>;
|
||||
|
||||
/// Returns default account for dapp.
|
||||
#[rpc(meta, name = "parity_defaultAccount")]
|
||||
|
||||
31
rpc/src/v1/types/account_info.rs
Normal file
31
rpc/src/v1/types/account_info.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2015-2017 Parity Technologies (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 information.
|
||||
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
|
||||
pub struct AccountInfo {
|
||||
/// Account name
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// Hardware wallet information.
|
||||
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
|
||||
pub struct HwAccountInfo {
|
||||
/// Device name.
|
||||
pub name: String,
|
||||
/// Device manufacturer.
|
||||
pub manufacturer: String,
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
mod account_info;
|
||||
mod bytes;
|
||||
mod block;
|
||||
mod block_number;
|
||||
@@ -65,3 +66,4 @@ pub use self::uint::{U128, U256};
|
||||
pub use self::work::Work;
|
||||
pub use self::histogram::Histogram;
|
||||
pub use self::consensus_status::*;
|
||||
pub use self::account_info::{AccountInfo, HwAccountInfo};
|
||||
|
||||
Reference in New Issue
Block a user