Merge branch 'lightrpc' into light-txq

This commit is contained in:
Robert Habermeier
2017-02-10 14:31:17 +01:00
91 changed files with 2095 additions and 640 deletions

View File

@@ -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
{

View File

@@ -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()
)
}

View File

@@ -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}"#;

View File

@@ -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")]

View 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,
}

View File

@@ -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};