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

Add Persistent KeyStore #604

Merged
merged 11 commits into from
Aug 11, 2020
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions forest/src/daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use message_pool::{MessagePool, MpoolRpcProvider};
use rpc::{start_rpc, RpcState};
use std::sync::Arc;
use utils::write_to_file;
use wallet::MemKeyStore;
use wallet::PersistantKeyStore;

/// Starts daemon process
pub(super) async fn start(config: Config) {
Expand All @@ -41,7 +41,7 @@ pub(super) async fn start(config: Config) {
let mut db = RocksDb::new(config.data_dir + "/db");
db.open().unwrap();
let db = Arc::new(db);
let keystore = Arc::new(RwLock::new(MemKeyStore::new()));
let keystore = Arc::new(RwLock::new(PersistantKeyStore::new()));
let mut chain_store = ChainStore::new(Arc::clone(&db));

// Read Genesis file
Expand Down
1 change: 1 addition & 0 deletions key_management/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ rand = "0.7.3"
encoding = { package = "forest_encoding", path = "../encoding", version = "0.1" }
serde = { version = "1.0", features = ["derive"] }
base64 = { version = "0.12.1", optional = true }
serde_json = "1.0.57"

[features]
json = ["base64", "crypto/json"]
65 changes: 65 additions & 0 deletions key_management/src/keystore.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
// Copyright 2020 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

extern crate serde_json;

use super::errors::Error;
use crypto::SignatureType;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs::File;
use std::fs::OpenOptions;
use std::io::BufReader;

const KEYSTORE_LOCATION: &str = "keystore.json";
flodesi marked this conversation as resolved.
Show resolved Hide resolved

/// KeyInfo struct, this contains the type of key (stored as a string) and the private key.
/// note how the private key is stored as a byte vector
Expand Down Expand Up @@ -131,3 +138,61 @@ impl KeyStore for MemKeyStore {
self.key_info.remove(&key)
}
}

/// KeyStore that persists data in KEYSTORE_LOCATION
#[derive(Default, Clone, PartialEq, Debug, Eq)]
pub struct PersistentKeyStore {
pub key_info: HashMap<String, KeyInfo>,
}

impl PersistentKeyStore {
pub fn new() -> Self {
let file_op = File::open(KEYSTORE_LOCATION);
match file_op {
Ok(file) => {
let reader = BufReader::new(file);
let data: HashMap<String, KeyInfo> = serde_json::from_reader(reader).unwrap();
Self { key_info: data }
}
Err(_) => Self {
flodesi marked this conversation as resolved.
Show resolved Hide resolved
key_info: HashMap::new(),
},
}
}
}

impl KeyStore for PersistentKeyStore {
fn list(&self) -> Vec<String> {
self.key_info.iter().map(|(key, _)| key.clone()).collect()
}

fn get(&self, k: &str) -> Result<KeyInfo, Error> {
self.key_info.get(k).cloned().ok_or(Error::KeyInfo)
}

fn put(&mut self, key: String, key_info: KeyInfo) -> Result<(), Error> {
if self.key_info.contains_key(&key) {
return Err(Error::KeyExists);
}
self.key_info.insert(key, key_info);
let file = OpenOptions::new()
.write(true)
.create(true)
.open(KEYSTORE_LOCATION)
.map_err(|err| Error::Other(err.to_string()))?;
serde_json::to_writer(&file, &self.key_info)
.map_err(|err| Error::Other(err.to_string()))?;
Ok(())
}

fn remove(&mut self, key: String) -> Option<KeyInfo> {
flodesi marked this conversation as resolved.
Show resolved Hide resolved
let key_out = self.key_info.remove(&key);
let file = OpenOptions::new()
.write(true)
.create(true)
.open(KEYSTORE_LOCATION)
.ok()?;
serde_json::to_writer(file, &self.key_info).ok()?;
key_out
}
}