Merge remote-tracking branch 'origin/master' into fixing_warnings

This commit is contained in:
Gav Wood 2016-03-14 01:00:12 +01:00
commit e792998d0a
3 changed files with 72 additions and 6 deletions

View File

@ -83,7 +83,7 @@ Protocol Options:
--testnet Equivalent to --chain testnet (geth-compatible). --testnet Equivalent to --chain testnet (geth-compatible).
--networkid INDEX Override the network identifier from the chain we are on. --networkid INDEX Override the network identifier from the chain we are on.
--pruning METHOD Configure pruning of the state/storage trie. METHOD may be one of: archive, --pruning METHOD Configure pruning of the state/storage trie. METHOD may be one of: archive,
basic (experimental), light (experimental), fast (experimental) [default: archive]. basic (experimental), fast (experimental) [default: archive].
-d --datadir PATH Specify the database & configuration directory path [default: $HOME/.parity] -d --datadir PATH Specify the database & configuration directory path [default: $HOME/.parity]
--db-path PATH Specify the database & configuration directory path [default: $HOME/.parity] --db-path PATH Specify the database & configuration directory path [default: $HOME/.parity]
--keys-path PATH Specify the path for JSON key files to be found [default: $HOME/.web3/keys] --keys-path PATH Specify the path for JSON key files to be found [default: $HOME/.web3/keys]
@ -523,6 +523,7 @@ impl Configuration {
client: service.client(), client: service.client(),
info: Default::default(), info: Default::default(),
sync: sync.clone(), sync: sync.clone(),
accounts: account_service.clone(),
}); });
service.io().register_handler(io_handler).expect("Error registering IO handler"); service.io().register_handler(io_handler).expect("Error registering IO handler");
@ -618,20 +619,28 @@ impl Informant {
const INFO_TIMER: TimerToken = 0; const INFO_TIMER: TimerToken = 0;
const ACCOUNT_TICK_TIMER: TimerToken = 10;
const ACCOUNT_TICK_MS: u64 = 60000;
struct ClientIoHandler { struct ClientIoHandler {
client: Arc<Client>, client: Arc<Client>,
sync: Arc<EthSync>, sync: Arc<EthSync>,
accounts: Arc<AccountService>,
info: Informant, info: Informant,
} }
impl IoHandler<NetSyncMessage> for ClientIoHandler { impl IoHandler<NetSyncMessage> for ClientIoHandler {
fn initialize(&self, io: &IoContext<NetSyncMessage>) { fn initialize(&self, io: &IoContext<NetSyncMessage>) {
io.register_timer(INFO_TIMER, 5000).expect("Error registering timer"); io.register_timer(INFO_TIMER, 5000).expect("Error registering timer");
io.register_timer(ACCOUNT_TICK_TIMER, ACCOUNT_TICK_MS).expect("Error registering account timer");
} }
fn timeout(&self, _io: &IoContext<NetSyncMessage>, timer: TimerToken) { fn timeout(&self, _io: &IoContext<NetSyncMessage>, timer: TimerToken) {
if INFO_TIMER == timer { match timer {
self.info.tick(&self.client, &self.sync); INFO_TIMER => { self.info.tick(&self.client, &self.sync); }
ACCOUNT_TICK_TIMER => { self.accounts.tick(); },
_ => {}
} }
} }
} }

View File

@ -542,6 +542,8 @@ impl KeyDirectory {
if removes.is_empty() { return; } if removes.is_empty() { return; }
let mut cache = self.cache.write().unwrap(); let mut cache = self.cache.write().unwrap();
for key in removes { cache.remove(&key); } for key in removes { cache.remove(&key); }
cache.shrink_to_fit();
} }
/// Reports how many keys are currently cached. /// Reports how many keys are currently cached.

View File

@ -135,7 +135,21 @@ impl AccountService {
secret_store: secret_store secret_store: secret_store
} }
} }
#[cfg(test)]
fn new_test(temp: &::devtools::RandomTempPath) -> Self {
let secret_store = RwLock::new(SecretStore::new_test(temp));
AccountService {
secret_store: secret_store
} }
}
/// Ticks the account service
pub fn tick(&self) {
self.secret_store.write().unwrap().collect_garbage();
}
}
impl Default for SecretStore { impl Default for SecretStore {
fn default() -> Self { fn default() -> Self {
@ -256,6 +270,20 @@ impl SecretStore {
let unlock = try!(read_lock.get(account).ok_or(SigningError::AccountNotUnlocked)); let unlock = try!(read_lock.get(account).ok_or(SigningError::AccountNotUnlocked));
Ok(unlock.secret as crypto::Secret) Ok(unlock.secret as crypto::Secret)
} }
/// Makes account unlocks expire and removes unused key files from memory
pub fn collect_garbage(&mut self) {
let mut garbage_lock = self.unlocks.write().unwrap();
self.directory.collect_garbage();
let utc = UTC::now();
let expired_addresses = garbage_lock.iter()
.filter(|&(_, unlock)| unlock.expires < utc)
.map(|(address, _)| address.clone()).collect::<Vec<Address>>();
for expired in expired_addresses { garbage_lock.remove(&expired); }
garbage_lock.shrink_to_fit();
}
} }
fn derive_key_iterations(password: &str, salt: &H256, c: u32) -> (Bytes, Bytes) { fn derive_key_iterations(password: &str, salt: &H256, c: u32) -> (Bytes, Bytes) {
@ -362,13 +390,11 @@ impl EncryptedHashMap<H128> for SecretStore {
} }
#[cfg(test)] #[cfg(all(test, feature="heavy-tests"))]
#[cfg(feature="heavy-tests")]
mod vector_tests { mod vector_tests {
use super::{derive_mac,derive_key_iterations}; use super::{derive_mac,derive_key_iterations};
use common::*; use common::*;
#[test] #[test]
fn mac_vector() { fn mac_vector() {
let password = "testpassword"; let password = "testpassword";
@ -395,6 +421,7 @@ mod tests {
use devtools::*; use devtools::*;
use common::*; use common::*;
use crypto::KeyPair; use crypto::KeyPair;
use chrono::*;
#[test] #[test]
fn can_insert() { fn can_insert() {
@ -581,4 +608,32 @@ mod tests {
let kp = KeyPair::from_secret(secret).unwrap(); let kp = KeyPair::from_secret(secret).unwrap();
assert_eq!(Address::from(kp.public().sha3()), addr); assert_eq!(Address::from(kp.public().sha3()), addr);
} }
#[test]
fn can_create_service() {
let temp = RandomTempPath::create_dir();
let svc = AccountService::new_test(&temp);
assert!(svc.accounts().unwrap().is_empty());
}
#[test]
fn accounts_expire() {
use std::collections::hash_map::*;
let temp = RandomTempPath::create_dir();
let svc = AccountService::new_test(&temp);
let address = svc.new_account("pass").unwrap();
svc.unlock_account(&address, "pass").unwrap();
assert!(svc.account_secret(&address).is_ok());
{
let ss_rw = svc.secret_store.write().unwrap();
let mut ua_rw = ss_rw.unlocks.write().unwrap();
let entry = ua_rw.entry(address);
if let Entry::Occupied(mut occupied) = entry { occupied.get_mut().expires = UTC::now() - Duration::minutes(1); }
}
svc.tick();
assert!(svc.account_secret(&address).is_err());
}
} }