1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.

// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity Ethereum.  If not, see <http://www.gnu.org/licenses/>.

//! Accounts Directory

use crate::{Error, SafeAccount};
use cfxkey::Password;
use std::path::PathBuf;

mod disk;
mod memory;
mod vault;

/// `VaultKeyDirectory::set_key` error
#[derive(Debug)]
pub enum SetKeyError {
    /// Error is fatal and directory is probably in inconsistent state
    Fatal(Error),
    /// Error is non fatal, directory is reverted to pre-operation state
    NonFatalOld(Error),
    /// Error is non fatal, directory is consistent with new key
    NonFatalNew(Error),
}

/// Vault key
#[derive(Clone, PartialEq, Eq)]
pub struct VaultKey {
    /// Vault password
    pub password: Password,
    /// Number of iterations to produce a derived key from password
    pub iterations: u32,
}

/// Keys directory
pub trait KeyDirectory: Send + Sync {
    /// Read keys from directory
    fn load(&self) -> Result<Vec<SafeAccount>, Error>;
    /// Insert new key to directory
    fn insert(&self, account: SafeAccount) -> Result<SafeAccount, Error>;
    /// Update key in the directory
    fn update(&self, account: SafeAccount) -> Result<SafeAccount, Error>;
    /// Remove key from directory
    fn remove(&self, account: &SafeAccount) -> Result<(), Error>;
    /// Get directory filesystem path, if available
    fn path(&self) -> Option<&PathBuf> { None }
    /// Return vault provider, if available
    fn as_vault_provider(&self) -> Option<&dyn VaultKeyDirectoryProvider> {
        None
    }
    /// Unique representation of directory account collection
    fn unique_repr(&self) -> Result<u64, Error>;
}

/// Vaults provider
pub trait VaultKeyDirectoryProvider {
    /// Create new vault with given key
    fn create(
        &self, name: &str, key: VaultKey,
    ) -> Result<Box<dyn VaultKeyDirectory>, Error>;
    /// Open existing vault with given key
    fn open(
        &self, name: &str, key: VaultKey,
    ) -> Result<Box<dyn VaultKeyDirectory>, Error>;
    /// List all vaults
    fn list_vaults(&self) -> Result<Vec<String>, Error>;
    /// Get vault meta
    fn vault_meta(&self, name: &str) -> Result<String, Error>;
}

/// Vault directory
pub trait VaultKeyDirectory: KeyDirectory {
    /// Cast to `KeyDirectory`
    fn as_key_directory(&self) -> &dyn KeyDirectory;
    /// Vault name
    fn name(&self) -> &str;
    /// Get vault key
    fn key(&self) -> VaultKey;
    /// Set new key for vault
    fn set_key(&self, key: VaultKey) -> Result<(), SetKeyError>;
    /// Get vault meta
    fn meta(&self) -> String;
    /// Set vault meta
    fn set_meta(&self, meta: &str) -> Result<(), Error>;
}

pub use self::{
    disk::{DiskKeyFileManager, KeyFileManager, RootDiskDirectory},
    memory::MemoryDirectory,
    vault::VaultDiskDirectory,
};

impl VaultKey {
    /// Create new vault key
    pub fn new(password: &Password, iterations: u32) -> Self {
        VaultKey {
            password: password.clone(),
            iterations,
        }
    }
}