Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Refactor to get rid off as much annotations asap
Browse files Browse the repository at this point in the history
* Might consume slight more memory than pure conditional compilation
flags
  • Loading branch information
niklasad1 committed Jun 1, 2018
1 parent 3343388 commit b55b04d
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 109 deletions.
73 changes: 22 additions & 51 deletions ethcore/src/account_provider/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

mod stores;

#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
mod no_hw;

use ethstore::{
SimpleSecretStore, SecretStore, Error as SSError, EthStore, EthMultiStore,
random_string, SecretVaultRef, StoreAccountRef, OpaqueSecret,
Expand All @@ -26,46 +29,31 @@ use ethjson::misc::AccountMeta;
use ethstore::accounts_dir::MemoryDirectory;
use ethstore::ethkey::{Address, Message, Public, Secret, Random, Generator};
use parking_lot::RwLock;
use self::hw::*;
use self::stores::{AddressBook, DappsSettingsStore, NewDappsPolicy};
use std::collections::{HashMap, HashSet};
use std::fmt;
use std::time::{Instant, Duration};

pub use ethstore::ethkey::Signature;
pub use ethstore::{Derivation, IndexDerivation, KeyFile};
pub use super::transaction::{Action, Transaction};

#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
mod hw {
pub use hardware_wallet::{Error as HardwareError, HardwareWalletManager, KeyPath, TransactionInfo};
pub use ::transaction::{Action, Transaction};
}

#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))]
mod hw {
use super::fmt;

#[derive(Debug)]
/// `ErrorType` for devices with no `hardware wallet`
pub enum HardwareError {
NoWallet,
}
/// `HardwareWalletManager` for devices with no `hardware wallet`
pub struct HardwareWalletManager;

impl fmt::Display for HardwareError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "")
}
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
mod hw {
pub use account_provider::no_hw::{HardwareError, HardwareWalletManager};
}

/// Type of unlock.
#[derive(Clone, PartialEq)]
enum Unlock {
/// If account is unlocked temporarily, it should be locked after first usage.
OneTime,
/// Account unlocked permantently can always sign message.
/// Account unlocked permanently can always sign message.
/// Use with caution.
Perm,
/// Account unlocked with a timeout
Expand All @@ -87,7 +75,7 @@ pub enum SignError {
/// Account does not exist.
NotFound,
/// Low-level hardware device error.
Hardware(HardwareError),
Hardware(hw::HardwareError),
/// Low-level error from store
SStore(SSError),
}
Expand All @@ -103,8 +91,8 @@ impl fmt::Display for SignError {
}
}

impl From<HardwareError> for SignError {
fn from(e: HardwareError) -> Self {
impl From<hw::HardwareError> for SignError {
fn from(e: hw::HardwareError) -> Self {
SignError::Hardware(e)
}
}
Expand Down Expand Up @@ -154,7 +142,7 @@ pub struct AccountProvider {
/// Accounts unlocked with rolling tokens
transient_sstore: EthMultiStore,
/// Accounts in hardware wallets.
hardware_store: Option<HardwareWalletManager>,
hardware_store: Option<hw::HardwareWalletManager>,
/// When unlocking account permanently we additionally keep a raw secret in memory
/// to increase the performance of transaction signing.
unlock_keep_secret: bool,
Expand Down Expand Up @@ -190,12 +178,12 @@ impl AccountProvider {
pub fn new(sstore: Box<SecretStore>, settings: AccountProviderSettings) -> Self {
let mut hardware_store = None;

#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
{
if settings.enable_hardware_wallets {
match HardwareWalletManager::new() {
match hw::HardwareWalletManager::new() {
Ok(manager) => {
manager.set_key_path(if settings.hardware_wallet_classic_key { KeyPath::EthereumClassic } else { KeyPath::Ethereum });
manager.set_key_path(if settings.hardware_wallet_classic_key { hw::KeyPath::EthereumClassic } else { hw::KeyPath::Ethereum });
hardware_store = Some(manager)
},
Err(e) => debug!("Error initializing hardware wallets: {}", e),
Expand Down Expand Up @@ -316,14 +304,12 @@ impl AccountProvider {
}

/// Returns addresses of hardware accounts.
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
pub fn hardware_accounts(&self) -> Result<Vec<Address>, Error> {
let accounts = self.hardware_store.as_ref().map_or_else(|| Vec::new(), |h| h.list_wallets());
Ok(accounts.into_iter().map(|a| a.address).collect())
}

/// Get a list of paths to locked hardware wallets
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
pub fn locked_hardware_accounts(&self) -> Result<Vec<String>, SignError> {
match self.hardware_store.as_ref().map(|h| h.list_locked_wallets()) {
None => Err(SignError::NotFound),
Expand All @@ -333,7 +319,6 @@ impl AccountProvider {
}

/// Provide a pin to a locked hardware wallet on USB path to unlock it
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
pub fn hardware_pin_matrix_ack(&self, path: &str, pin: &str) -> Result<bool, SignError> {
match self.hardware_store.as_ref().map(|h| h.pin_matrix_ack(path, pin)) {
None => Err(SignError::NotFound),
Expand Down Expand Up @@ -526,7 +511,7 @@ impl AccountProvider {
self.address_book.write().set_meta(account, meta)
}

/// Removes and address from the addressbook
/// Removes and address from the address book
pub fn remove_address(&self, addr: Address) {
self.address_book.write().remove(addr)
}
Expand All @@ -542,7 +527,6 @@ impl AccountProvider {
}

/// Returns each hardware account along with name and meta.
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
pub fn hardware_accounts_info(&self) -> Result<HashMap<Address, AccountMeta>, Error> {
let r = self.hardware_accounts()?
.into_iter()
Expand All @@ -552,13 +536,11 @@ impl AccountProvider {
}

/// Returns each hardware account along with name and meta.
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
pub fn is_hardware_address(&self, address: &Address) -> bool {
self.hardware_store.as_ref().and_then(|s| s.wallet_info(address)).is_some()
}

/// Returns each account along with name and meta.
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
pub fn account_meta(&self, address: Address) -> Result<AccountMeta, Error> {
if let Some(info) = self.hardware_store.as_ref().and_then(|s| s.wallet_info(&address)) {
Ok(AccountMeta {
Expand All @@ -576,17 +558,6 @@ impl AccountProvider {
}
}

/// Returns each account along with name and meta without a hardware-wallet
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))]
pub fn account_meta(&self, address: Address) -> Result<AccountMeta, Error> {
let account = self.sstore.account_ref(&address)?;
Ok(AccountMeta {
name: self.sstore.name(&account)?,
meta: self.sstore.meta(&account)?,
uuid: self.sstore.uuid(&account).ok().map(Into::into), // allowed to not have a Uuid
})
}

/// Returns account public key.
pub fn account_public(&self, address: Address, password: &str) -> Result<Public, Error> {
self.sstore.public(&self.sstore.account_ref(&address)?, password)
Expand Down Expand Up @@ -630,7 +601,7 @@ impl AccountProvider {
fn unlock_account(&self, address: Address, password: String, unlock: Unlock) -> Result<(), Error> {
let account = self.sstore.account_ref(&address)?;

// check if account is already unlocked pernamently, if it is, do nothing
// check if account is already unlocked permanently, if it is, do nothing
let mut unlocked = self.unlocked.write();
if let Some(data) = unlocked.get(&account) {
if let Unlock::Perm = data.unlock {
Expand Down Expand Up @@ -855,9 +826,9 @@ impl AccountProvider {
}

/// Sign transaction with hardware wallet.
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
pub fn sign_with_hardware(&self, address: Address, transaction: &Transaction, chain_id: Option<u64>, rlp_encoded_transaction: &[u8]) -> Result<Signature, SignError> {
let t_info = TransactionInfo {
let t_info = hw::TransactionInfo {
nonce: transaction.nonce,
gas_price: transaction.gas_price,
gas_limit: transaction.gas,
Expand All @@ -870,7 +841,7 @@ impl AccountProvider {
chain_id: chain_id,
};
match self.hardware_store.as_ref().map(|s| s.sign_transaction(&address, &t_info, rlp_encoded_transaction)) {
None | Some(Err(HardwareError::KeyNotFound)) => Err(SignError::NotFound),
None | Some(Err(hw::HardwareError::KeyNotFound)) => Err(SignError::NotFound),
Some(Err(e)) => Err(From::from(e)),
Some(Ok(s)) => Ok(s),
}
Expand Down
42 changes: 42 additions & 0 deletions ethcore/src/account_provider/no_hw.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//! Dummy module for platforms that does not provide support for hardware wallets (libusb)

use super::{fmt, Address};

pub struct WalletInfo {
pub address: Address,
pub name: String,
pub manufacturer: String,
}

#[derive(Debug)]
/// `ErrorType` for devices with no `hardware wallet`
pub enum HardwareError {
NoWallet,
}

/// `HardwareWalletManager` for devices with no `hardware wallet`
pub struct HardwareWalletManager;

impl HardwareWalletManager {
pub fn wallet_info(&self, _: &Address) -> Option<WalletInfo> {
None
}

pub fn list_wallets(&self) -> Vec<WalletInfo> {
Vec::with_capacity(0)
}

pub fn list_locked_wallets(&self) -> Result<Vec<String>, HardwareError> {
Err(HardwareError::NoWallet)
}

pub fn pin_matrix_ack(&self, _: &str, _: &str) -> Result<bool, HardwareError> {
Err(HardwareError::NoWallet)
}
}

impl fmt::Display for HardwareError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "")
}
}
3 changes: 1 addition & 2 deletions ethcore/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ extern crate ethereum_types;
extern crate ethjson;
extern crate ethkey;


extern crate hashdb;
extern crate itertools;
extern crate lru_cache;
Expand Down Expand Up @@ -109,7 +108,7 @@ extern crate wasm;
extern crate memory_cache;
extern crate journaldb;

#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
extern crate hardware_wallet;

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ extern crate rlp;
extern crate stats;
extern crate keccak_hash as hash;

#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
extern crate hardware_wallet;

extern crate patricia_trie as trie;
Expand Down
20 changes: 7 additions & 13 deletions rpc/src/v1/helpers/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ use v1::types::{
DecryptRequest as RpcDecryptRequest,
};

#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
use rlp;

pub use self::nonce::Reservations;
Expand Down Expand Up @@ -433,7 +433,7 @@ fn sign_transaction(
data: filled.data,
};

#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
{
if accounts.is_hardware_address(&filled.from) {
return hardware_signature(accounts, filled.from, t, chain_id).map(WithToken::No)
Expand Down Expand Up @@ -678,11 +678,8 @@ pub fn execute<D: Dispatcher + 'static>(
))
},
ConfirmationPayload::EthSignMessage(address, data) => {
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
{
if accounts.is_hardware_address(&address) {
return Box::new(future::err(errors::unsupported("Signing via hardware wallets is not supported.", None)));
}
if accounts.is_hardware_address(&address) {
return Box::new(future::err(errors::unsupported("Signing via hardware wallets is not supported.", None)));
}

let hash = eth_data_hash(data);
Expand All @@ -695,11 +692,8 @@ pub fn execute<D: Dispatcher + 'static>(
Box::new(future::done(res))
},
ConfirmationPayload::Decrypt(address, data) => {
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
{
if accounts.is_hardware_address(&address) {
return Box::new(future::err(errors::unsupported("Decrypting via hardware wallets is not supported.", None)));
}
if accounts.is_hardware_address(&address) {
return Box::new(future::err(errors::unsupported("Decrypting via hardware wallets is not supported.", None)));
}
let res = decrypt(&accounts, address, data, pass)
.map(|result| result
Expand All @@ -723,7 +717,7 @@ fn signature(accounts: &AccountProvider, address: Address, hash: H256, password:
}

// obtain a hardware signature from the given account.
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
fn hardware_signature(accounts: &AccountProvider, address: Address, t: Transaction, chain_id: Option<u64>)
-> Result<SignedTransaction>
{
Expand Down
17 changes: 0 additions & 17 deletions rpc/src/v1/impls/light/parity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,6 @@ use v1::types::{
};
use Host;

#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))]
use jsonrpc_core::Error;

/// Parity implementation for light client.
pub struct ParityClient {
client: Arc<LightChainClient>,
Expand Down Expand Up @@ -133,7 +130,6 @@ impl Parity for ParityClient {
)
}

#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
fn hardware_accounts_info(&self) -> Result<BTreeMap<H160, HwAccountInfo>> {
let store = &self.accounts;
let info = store.hardware_accounts_info().map_err(|e| errors::account("Could not fetch account info.", e))?;
Expand All @@ -144,24 +140,11 @@ impl Parity for ParityClient {
)
}

#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))]
// `unimplemented`, workaround to get it to compile because the trait requires this method
fn hardware_accounts_info(&self) -> Result<BTreeMap<H160, HwAccountInfo>> {
Err(Error::parse_error())
}

#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
fn locked_hardware_accounts_info(&self) -> Result<Vec<String>> {
let store = &self.accounts;
Ok(store.locked_hardware_accounts().map_err(|e| errors::account("Error communicating with hardware wallet.", e))?)
}

#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))]
// `unimplemented`, workaround to get it to compile because the trait requires this method
fn locked_hardware_accounts_info(&self) -> Result<Vec<String>> {
Err(Error::parse_error())
}

fn default_account(&self, meta: Self::Metadata) -> Result<H160> {
let dapp_id = meta.dapp_id();
Ok(self.accounts
Expand Down
Loading

0 comments on commit b55b04d

Please sign in to comment.