Ethstore optimizations (#6827) (#6844) (#7347)

This commit is contained in:
Tomasz Drwięga 2017-12-27 23:36:01 +01:00 committed by Afri Schoedon
parent 9075ff883f
commit cfa197061e
5 changed files with 54 additions and 23 deletions

View File

@ -268,7 +268,7 @@ impl AccountProvider {
/// Checks whether an account with a given address is present. /// Checks whether an account with a given address is present.
pub fn has_account(&self, address: Address) -> Result<bool, Error> { 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. /// Returns addresses of all accounts.

View File

@ -627,10 +627,6 @@ impl Miner {
condition: Option<TransactionCondition>, condition: Option<TransactionCondition>,
transaction_queue: &mut BanningTransactionQueue, transaction_queue: &mut BanningTransactionQueue,
) -> Vec<Result<TransactionImportResult, Error>> { ) -> 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 best_block_header = client.best_block_header().decode();
let insertion_time = client.chain_info().best_block_number; let insertion_time = client.chain_info().best_block_number;
@ -649,8 +645,8 @@ impl Miner {
Err(e) Err(e)
}, },
Ok(transaction) => { Ok(transaction) => {
let origin = accounts.as_ref().and_then(|accounts| { let origin = self.accounts.as_ref().and_then(|accounts| {
match accounts.contains(&transaction.sender()) { match accounts.has_account(transaction.sender()).unwrap_or(false) {
true => Some(TransactionOrigin::Local), true => Some(TransactionOrigin::Local),
false => None, false => None,
} }

View File

@ -122,6 +122,13 @@ impl<T> DiskDirectory<T> where T: KeyFileManager {
Ok(hasher.finish()) 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 /// all accounts found in keys directory
fn files_content(&self) -> Result<HashMap<PathBuf, SafeAccount>, Error> { fn files_content(&self) -> Result<HashMap<PathBuf, SafeAccount>, Error> {
// it's not done using one iterator cause // 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> { 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::mem;
use std::path::PathBuf; use std::path::PathBuf;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use std::time::{Instant, Duration};
use crypto::KEY_ITERATIONS; use crypto::KEY_ITERATIONS;
use random::Random; use random::Random;
@ -28,6 +29,8 @@ use presale::PresaleWallet;
use json::{self, Uuid, OpaqueKeyFile}; use json::{self, Uuid, OpaqueKeyFile};
use {import, Error, SimpleSecretStore, SecretStore, SecretVaultRef, StoreAccountRef, Derivation, OpaqueSecret}; use {import, Error, SimpleSecretStore, SecretStore, SecretVaultRef, StoreAccountRef, Derivation, OpaqueSecret};
const REFRESH_TIME_SEC: u64 = 5;
/// Accounts store. /// Accounts store.
pub struct EthStore { pub struct EthStore {
store: EthMultiStore, store: EthMultiStore,
@ -241,7 +244,12 @@ pub struct EthMultiStore {
// order lock: cache, then vaults // order lock: cache, then vaults
cache: RwLock<BTreeMap<StoreAccountRef, Vec<SafeAccount>>>, cache: RwLock<BTreeMap<StoreAccountRef, Vec<SafeAccount>>>,
vaults: Mutex<HashMap<String, Box<VaultKeyDirectory>>>, 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 { impl EthMultiStore {
@ -257,20 +265,27 @@ impl EthMultiStore {
vaults: Mutex::new(HashMap::new()), vaults: Mutex::new(HashMap::new()),
iterations: iterations, iterations: iterations,
cache: Default::default(), cache: Default::default(),
dir_hash: Default::default(), timestamp: Mutex::new(Timestamp {
dir_hash: None,
last_checked: Instant::now(),
}),
}; };
store.reload_accounts()?; store.reload_accounts()?;
Ok(store) Ok(store)
} }
fn reload_if_changed(&self) -> Result<(), Error> { fn reload_if_changed(&self) -> Result<(), Error> {
let mut last_dir_hash = self.dir_hash.lock(); let mut last_timestamp = self.timestamp.lock();
let dir_hash = Some(self.dir.unique_repr()?); let now = Instant::now();
if *last_dir_hash == dir_hash { if (now - last_timestamp.last_checked) > Duration::from_secs(REFRESH_TIME_SEC) {
return Ok(()) 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(()) Ok(())
} }
@ -451,11 +466,11 @@ impl SimpleSecretStore for EthMultiStore {
} }
fn account_ref(&self, address: &Address) -> Result<StoreAccountRef, Error> { fn account_ref(&self, address: &Address) -> Result<StoreAccountRef, Error> {
use std::collections::Bound;
self.reload_if_changed()?; self.reload_if_changed()?;
self.cache.read().keys() let cache = self.cache.read();
.find(|r| &r.address == address) let mut r = cache.range((Bound::Included(*address), Bound::Included(*address)));
.cloned() r.next().ok_or(Error::InvalidAccount).map(|(k, _)| k.clone())
.ok_or(Error::InvalidAccount)
} }
fn accounts(&self) -> Result<Vec<StoreAccountRef>, Error> { fn accounts(&self) -> Result<Vec<StoreAccountRef>, Error> {

View File

@ -16,6 +16,7 @@
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::path::PathBuf; use std::path::PathBuf;
use std::cmp::Ordering;
use ethkey::{Address, Message, Signature, Secret, Public}; use ethkey::{Address, Message, Signature, Secret, Public};
use Error; use Error;
use json::{Uuid, OpaqueKeyFile}; use json::{Uuid, OpaqueKeyFile};
@ -32,12 +33,24 @@ pub enum SecretVaultRef {
} }
/// Stored account reference /// Stored account reference
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, PartialEq, Eq, Ord)]
pub struct StoreAccountRef { pub struct StoreAccountRef {
/// Vault reference
pub vault: SecretVaultRef,
/// Account address /// Account address
pub address: 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 /// Simple Secret Store API