Ethstore optimizations (#6827) (#6844)

This commit is contained in:
Arkadiy Paronyan 2017-10-20 20:22:01 +02:00 committed by GitHub
parent 8f0eb3e192
commit d470773fec
5 changed files with 54 additions and 23 deletions

View File

@ -269,7 +269,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.

View File

@ -647,10 +647,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;
@ -669,8 +665,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,
}

View File

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

View File

@ -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;
@ -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,
@ -245,7 +248,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 {
@ -261,20 +269,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(())
}
@ -455,11 +470,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> {

View File

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