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

Commit

Permalink
Ethstore optimizations (#6827) (#6844)
Browse files Browse the repository at this point in the history
  • Loading branch information
arkpar authored and tomusdrw committed Dec 20, 2017
1 parent 3931713 commit f53ee5f
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 23 deletions.
2 changes: 1 addition & 1 deletion ethcore/src/account_provider/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ impl AccountProvider {

/// Checks whether an account with a given address is present.
pub fn has_account(&self, address: Address) -> Result<bool, Error> {
Ok(self.accounts()?.iter().any(|&a| a == address))
Ok(self.sstore.account_ref(&address).is_ok() && !self.blacklisted_accounts.contains(&address))
}

/// Returns addresses of all accounts.
Expand Down
8 changes: 2 additions & 6 deletions ethcore/src/miner/miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,10 +627,6 @@ impl Miner {
condition: Option<TransactionCondition>,
transaction_queue: &mut BanningTransactionQueue,
) -> Vec<Result<TransactionImportResult, Error>> {
let accounts = self.accounts.as_ref()
.and_then(|provider| provider.accounts().ok())
.map(|accounts| accounts.into_iter().collect::<HashSet<_>>());

let best_block_header = client.best_block_header().decode();
let insertion_time = client.chain_info().best_block_number;

Expand All @@ -649,8 +645,8 @@ impl Miner {
Err(e)
},
Ok(transaction) => {
let origin = accounts.as_ref().and_then(|accounts| {
match accounts.contains(&transaction.sender()) {
let origin = self.accounts.as_ref().and_then(|accounts| {
match accounts.has_account(transaction.sender()).unwrap_or(false) {
true => Some(TransactionOrigin::Local),
false => None,
}
Expand Down
9 changes: 8 additions & 1 deletion ethstore/src/dir/disk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,13 @@ impl<T> DiskDirectory<T> where T: KeyFileManager {
Ok(hasher.finish())
}

fn last_modification_date(&self) -> Result<u64, Error> {
use std::time::{Duration, UNIX_EPOCH};
let duration = fs::metadata(&self.path)?.modified()?.duration_since(UNIX_EPOCH).unwrap_or(Duration::default());
let timestamp = duration.as_secs() ^ (duration.subsec_nanos() as u64);
Ok(timestamp)
}

/// all accounts found in keys directory
fn files_content(&self) -> Result<HashMap<PathBuf, SafeAccount>, Error> {
// it's not done using one iterator cause
Expand Down Expand Up @@ -226,7 +233,7 @@ impl<T> KeyDirectory for DiskDirectory<T> where T: KeyFileManager {
}

fn unique_repr(&self) -> Result<u64, Error> {
self.files_hash()
self.last_modification_date()
}
}

Expand Down
39 changes: 27 additions & 12 deletions ethstore/src/ethstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use std::collections::{BTreeMap, HashMap};
use std::mem;
use std::path::PathBuf;
use parking_lot::{Mutex, RwLock};
use std::time::{Instant, Duration};

use crypto::KEY_ITERATIONS;
use random::Random;
Expand All @@ -28,6 +29,8 @@ use presale::PresaleWallet;
use json::{self, Uuid, OpaqueKeyFile};
use {import, Error, SimpleSecretStore, SecretStore, SecretVaultRef, StoreAccountRef, Derivation, OpaqueSecret};

const REFRESH_TIME_SEC: u64 = 5;

/// Accounts store.
pub struct EthStore {
store: EthMultiStore,
Expand Down Expand Up @@ -241,7 +244,12 @@ pub struct EthMultiStore {
// order lock: cache, then vaults
cache: RwLock<BTreeMap<StoreAccountRef, Vec<SafeAccount>>>,
vaults: Mutex<HashMap<String, Box<VaultKeyDirectory>>>,
dir_hash: Mutex<Option<u64>>,
timestamp: Mutex<Timestamp>,
}

struct Timestamp {
dir_hash: Option<u64>,
last_checked: Instant,
}

impl EthMultiStore {
Expand All @@ -257,20 +265,27 @@ impl EthMultiStore {
vaults: Mutex::new(HashMap::new()),
iterations: iterations,
cache: Default::default(),
dir_hash: Default::default(),
timestamp: Mutex::new(Timestamp {
dir_hash: None,
last_checked: Instant::now(),
}),
};
store.reload_accounts()?;
Ok(store)
}

fn reload_if_changed(&self) -> Result<(), Error> {
let mut last_dir_hash = self.dir_hash.lock();
let dir_hash = Some(self.dir.unique_repr()?);
if *last_dir_hash == dir_hash {
return Ok(())
let mut last_timestamp = self.timestamp.lock();
let now = Instant::now();
if (now - last_timestamp.last_checked) > Duration::from_secs(REFRESH_TIME_SEC) {
let dir_hash = Some(self.dir.unique_repr()?);
last_timestamp.last_checked = now;
if last_timestamp.dir_hash == dir_hash {
return Ok(())
}
self.reload_accounts()?;
last_timestamp.dir_hash = dir_hash;
}
self.reload_accounts()?;
*last_dir_hash = dir_hash;
Ok(())
}

Expand Down Expand Up @@ -451,11 +466,11 @@ impl SimpleSecretStore for EthMultiStore {
}

fn account_ref(&self, address: &Address) -> Result<StoreAccountRef, Error> {
use std::collections::Bound;
self.reload_if_changed()?;
self.cache.read().keys()
.find(|r| &r.address == address)
.cloned()
.ok_or(Error::InvalidAccount)
let cache = self.cache.read();
let mut r = cache.range((Bound::Included(*address), Bound::Included(*address)));
r.next().ok_or(Error::InvalidAccount).map(|(k, _)| k.clone())
}

fn accounts(&self) -> Result<Vec<StoreAccountRef>, Error> {
Expand Down
19 changes: 16 additions & 3 deletions ethstore/src/secret_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

use std::hash::{Hash, Hasher};
use std::path::PathBuf;
use std::cmp::Ordering;
use ethkey::{Address, Message, Signature, Secret, Public};
use Error;
use json::{Uuid, OpaqueKeyFile};
Expand All @@ -32,12 +33,24 @@ pub enum SecretVaultRef {
}

/// Stored account reference
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Clone, PartialEq, Eq, Ord)]
pub struct StoreAccountRef {
/// Vault reference
pub vault: SecretVaultRef,
/// Account address
pub address: Address,
/// Vault reference
pub vault: SecretVaultRef,
}

impl PartialOrd for StoreAccountRef {
fn partial_cmp(&self, other: &StoreAccountRef) -> Option<Ordering> {
Some(self.address.cmp(&other.address).then_with(|| self.vault.cmp(&other.vault)))
}
}

impl ::std::borrow::Borrow<Address> for StoreAccountRef {
fn borrow(&self) -> &Address {
&self.address
}
}

/// Simple Secret Store API
Expand Down

0 comments on commit f53ee5f

Please sign in to comment.