Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Stronghold #691

Merged
merged 14 commits into from
Mar 9, 2022
1 change: 1 addition & 0 deletions identity-account/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ identity-iota = { version = "=0.5.0-dev.4", path = "../identity-iota", default-f
itoa = { version = "0.4" }
log = { version = "0.4", default-features = false }
once_cell = { version = "1.7", default-features = false, features = ["std"] }
parking_lot = { version = "0.12" }
paste = { version = "1.0" }
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] }
slog = { version = "2.7" }
Expand Down
19 changes: 2 additions & 17 deletions identity-account/src/storage/stronghold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,7 @@ impl Storage for Stronghold {

match data {
None => return Ok(None),
Some(data) => {
if data.is_empty() {
return Ok(None);
}
Ok(Some(ChainState::from_json_slice(&data)?))
}
Some(data) => Ok(Some(ChainState::from_json_slice(&data)?)),
}
}

Expand All @@ -194,14 +189,7 @@ impl Storage for Stronghold {

match data {
None => return Ok(None),
Some(data) => {
// No state data found
if data.is_empty() {
return Ok(None);
}
// Deserialize and return
Ok(Some(IdentityState::from_json_slice(&data)?))
}
Some(data) => Ok(Some(IdentityState::from_json_slice(&data)?)),
}
}

Expand Down Expand Up @@ -231,9 +219,6 @@ impl Storage for Stronghold {
match bytes {
None => return Ok(None),
Some(bytes) => {
if bytes.is_empty() {
return Ok(None);
}
let le_bytes: [u8; 4] = <[u8; 4]>::try_from(bytes.as_ref()).map_err(|_| {
io::Error::new(
io::ErrorKind::InvalidData,
Expand Down
53 changes: 22 additions & 31 deletions identity-account/src/stronghold/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ use once_cell::sync::Lazy;
use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;
// use std::sync::Mutex;
use parking_lot::Mutex;
use parking_lot::MutexGuard;
// use std::sync::MutexGuard;
abdulmth marked this conversation as resolved.
Show resolved Hide resolved
use std::thread;
use std::time::Duration;
use std::time::Instant;
Expand All @@ -38,7 +40,7 @@ pub struct Context {

async fn clear_expired_passwords() -> Result<()> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also return an IotaStrongholdResult.

let this: &'static Context = Context::get().await?;
let interval: Duration = *this.runtime.password_clear()?;
let interval: Duration = *this.runtime.password_clear();

tokio::time::sleep(interval).await;

Expand All @@ -48,7 +50,7 @@ async fn clear_expired_passwords() -> Result<()> {

let cleared: Vec<PathBuf> = this
.runtime
.password_store()?
.password_store()
.drain_filter(|_, (_, instant)| instant.elapsed() > interval)
.map(|(path, _)| path)
.collect();
Expand Down Expand Up @@ -373,22 +375,22 @@ impl Runtime {
where
T: FnMut(&Path, &SnapshotStatus) + Send + 'static,
{
self.event_listeners()?.push(Listener(Box::new(listener)));
self.event_listeners().push(Listener(Box::new(listener)));

Ok(())
}

fn emit(&self, path: &Path, status: SnapshotStatus) -> IotaStrongholdResult<()> {
for listener in self.event_listeners()?.iter_mut() {
for listener in self.event_listeners().iter_mut() {
(listener.0)(path, &status);
}

Ok(())
}

fn snapshot_status(&self, path: &Path) -> IotaStrongholdResult<SnapshotStatus> {
if let Some(elapsed) = self.password_elapsed(path)? {
let interval: Duration = *self.password_clear()?;
if let Some(elapsed) = self.password_elapsed(path) {
let interval: Duration = *self.password_clear();
let locked: bool = interval.as_millis() > 0 && elapsed >= interval;

if locked {
Expand All @@ -405,28 +407,26 @@ impl Runtime {

fn password(&self, path: &Path) -> IotaStrongholdResult<Password> {
self
.password_store()?
.password_store()
.get(path)
.map(|(password, _)| *password)
.ok_or(StrongholdError::StrongholdPasswordNotSet)
}

fn password_elapsed(&self, path: &Path) -> IotaStrongholdResult<Option<Duration>> {
self
.password_store()
.map(|store| store.get(path).map(|(_, interval)| interval.elapsed()))
fn password_elapsed(&self, path: &Path) -> Option<Duration> {
self.password_store().get(path).map(|(_, interval)| interval.elapsed())
}

fn set_password(&self, path: &Path, password: Password) -> IotaStrongholdResult<()> {
self
.password_store()?
.password_store()
.insert(path.to_path_buf(), (password, Instant::now()));

Ok(())
}

fn set_password_access(&self, path: &Path) -> IotaStrongholdResult<()> {
if let Some((_, ref mut time)) = self.password_store()?.get_mut(path) {
if let Some((_, ref mut time)) = self.password_store().get_mut(path) {
*time = Instant::now();
} else {
return Err(StrongholdError::StrongholdPasswordNotSet);
Expand All @@ -436,29 +436,20 @@ impl Runtime {
}

fn set_password_clear(&self, interval: Duration) -> IotaStrongholdResult<()> {
*self.password_clear()? = interval;
*self.password_clear() = interval;

Ok(())
}

fn event_listeners(&self) -> IotaStrongholdResult<MutexGuard<'_, Vec<Listener>>> {
self
.event_listeners
.lock()
.map_err(|_| StrongholdError::StrongholdMutexPoisoned("listeners"))
fn event_listeners(&self) -> MutexGuard<'_, Vec<Listener>> {
self.event_listeners.lock()
}

fn password_store(&self) -> IotaStrongholdResult<MutexGuard<'_, PasswordMap>> {
self
.password_store
.lock()
.map_err(|_| StrongholdError::StrongholdMutexPoisoned("passwords"))
fn password_store(&self) -> MutexGuard<'_, PasswordMap> {
self.password_store.lock()
}

fn password_clear(&self) -> IotaStrongholdResult<MutexGuard<'_, Duration>> {
self
.password_clear
.lock()
.map_err(|_| StrongholdError::StrongholdMutexPoisoned("passwords"))
fn password_clear(&self) -> MutexGuard<'_, Duration> {
self.password_clear.lock()
}
}
5 changes: 1 addition & 4 deletions identity-account/src/stronghold/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use iota_stronghold::procedures::ProcedureError;

pub type IotaStrongholdResult<T> = Result<T, StrongholdError>;

/// Caused by errors from the [`iota_stronghold`] crate.
#[derive(Debug, thiserror::Error, strum::IntoStaticStr)]
pub enum StrongholdError {
/// Caused by errors from the [iota_stronghold] crate.
#[error(transparent)]
StrongholdActorError(#[from] iota_stronghold::ActorError),
#[error(transparent)]
Expand All @@ -27,9 +27,6 @@ pub enum StrongholdError {
/// Caused by attempting to access a Stronghold snapshot without a password.
#[error("Stronghold snapshot password not found")]
StrongholdPasswordNotSet,
/// Caused by an internal panic in the Stronghold runtime.
#[error("Stronghold mutex poisoned: {0}")]
StrongholdMutexPoisoned(&'static str),
/// Caused by errors from an invalid Stronghold procedure.
#[error("Stronghold error: {0}")]
StrongholdResult(String),
Expand Down
16 changes: 2 additions & 14 deletions identity-account/src/stronghold/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ use std::time::Duration;

use crate::stronghold::error::IotaStrongholdResult;
use crate::stronghold::Context;
use crate::stronghold::StrongholdError;

const STRONG_404: &str = "Unable to read from store";

#[derive(Debug)]
pub struct Store<'snapshot> {
Expand Down Expand Up @@ -51,17 +48,8 @@ impl Store<'_> {

/// Gets a record.
pub async fn get(&self, location: Location) -> IotaStrongholdResult<Option<Vec<u8>>> {
match self.get_strict(location.vault_path().to_vec()).await {
Ok(data) => Ok(data),
Err(StrongholdError::StrongholdResult(message)) if message == STRONG_404 => Ok(Some(Vec::new())),
Err(error) => Err(error),
}
}

/// Gets a record.
pub async fn get_strict(&self, location: Vec<u8>) -> IotaStrongholdResult<Option<Vec<u8>>> {
let scope: _ = Context::scope(self.path, &self.name, &self.flags).await?;
Ok(scope.read_from_store(location).await?)
Ok(scope.read_from_store(location.vault_path().to_vec()).await?)
}

/// Adds a record.
Expand All @@ -70,7 +58,7 @@ impl Store<'_> {
T: Into<Vec<u8>>,
{
let location = location.vault_path().to_vec();
let _a = Context::scope(self.path, &self.name, &self.flags)
Context::scope(self.path, &self.name, &self.flags)
.await?
.write_to_store(location, payload.into(), ttl)
.await?;
Expand Down