Merge branch 'master' into cli-rpc
This commit is contained in:
@@ -14,23 +14,32 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::path::PathBuf;
|
||||
use ethcore::ethstore::{EthStore, SecretStore, import_accounts, read_geth_accounts};
|
||||
use ethcore::ethstore::dir::DiskDirectory;
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use helpers::{password_prompt, password_from_file};
|
||||
use params::SpecType;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum AccountCmd {
|
||||
New(NewAccount),
|
||||
List(String),
|
||||
List(ListAccounts),
|
||||
Import(ImportAccounts),
|
||||
ImportFromGeth(ImportFromGethAccounts)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ListAccounts {
|
||||
pub path: String,
|
||||
pub spec: SpecType,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct NewAccount {
|
||||
pub iterations: u32,
|
||||
pub path: String,
|
||||
pub spec: SpecType,
|
||||
pub password_file: Option<String>,
|
||||
}
|
||||
|
||||
@@ -38,6 +47,7 @@ pub struct NewAccount {
|
||||
pub struct ImportAccounts {
|
||||
pub from: Vec<String>,
|
||||
pub to: String,
|
||||
pub spec: SpecType,
|
||||
}
|
||||
|
||||
/// Parameters for geth accounts' import
|
||||
@@ -47,18 +57,22 @@ pub struct ImportFromGethAccounts {
|
||||
pub testnet: bool,
|
||||
/// directory to import accounts to
|
||||
pub to: String,
|
||||
pub spec: SpecType,
|
||||
}
|
||||
|
||||
pub fn execute(cmd: AccountCmd) -> Result<String, String> {
|
||||
match cmd {
|
||||
AccountCmd::New(new_cmd) => new(new_cmd),
|
||||
AccountCmd::List(path) => list(path),
|
||||
AccountCmd::List(list_cmd) => list(list_cmd),
|
||||
AccountCmd::Import(import_cmd) => import(import_cmd),
|
||||
AccountCmd::ImportFromGeth(import_geth_cmd) => import_geth(import_geth_cmd)
|
||||
}
|
||||
}
|
||||
|
||||
fn keys_dir(path: String) -> Result<DiskDirectory, String> {
|
||||
fn keys_dir(path: String, spec: SpecType) -> Result<DiskDirectory, String> {
|
||||
let spec = try!(spec.spec());
|
||||
let mut path = PathBuf::from(&path);
|
||||
path.push(spec.data_dir);
|
||||
DiskDirectory::create(path).map_err(|e| format!("Could not open keys directory: {}", e))
|
||||
}
|
||||
|
||||
@@ -75,15 +89,15 @@ fn new(n: NewAccount) -> Result<String, String> {
|
||||
None => try!(password_prompt()),
|
||||
};
|
||||
|
||||
let dir = Box::new(try!(keys_dir(n.path)));
|
||||
let dir = Box::new(try!(keys_dir(n.path, n.spec)));
|
||||
let secret_store = Box::new(try!(secret_store(dir, Some(n.iterations))));
|
||||
let acc_provider = AccountProvider::new(secret_store);
|
||||
let new_account = try!(acc_provider.new_account(&password).map_err(|e| format!("Could not create new account: {}", e)));
|
||||
Ok(format!("{:?}", new_account))
|
||||
}
|
||||
|
||||
fn list(path: String) -> Result<String, String> {
|
||||
let dir = Box::new(try!(keys_dir(path)));
|
||||
fn list(list_cmd: ListAccounts) -> Result<String, String> {
|
||||
let dir = Box::new(try!(keys_dir(list_cmd.path, list_cmd.spec)));
|
||||
let secret_store = Box::new(try!(secret_store(dir, None)));
|
||||
let acc_provider = AccountProvider::new(secret_store);
|
||||
let accounts = acc_provider.accounts();
|
||||
@@ -96,7 +110,7 @@ fn list(path: String) -> Result<String, String> {
|
||||
}
|
||||
|
||||
fn import(i: ImportAccounts) -> Result<String, String> {
|
||||
let to = try!(keys_dir(i.to));
|
||||
let to = try!(keys_dir(i.to, i.spec));
|
||||
let mut imported = 0;
|
||||
for path in &i.from {
|
||||
let from = DiskDirectory::at(path);
|
||||
@@ -109,7 +123,7 @@ fn import_geth(i: ImportFromGethAccounts) -> Result<String, String> {
|
||||
use std::io::ErrorKind;
|
||||
use ethcore::ethstore::Error;
|
||||
|
||||
let dir = Box::new(try!(keys_dir(i.to)));
|
||||
let dir = Box::new(try!(keys_dir(i.to, i.spec)));
|
||||
let secret_store = Box::new(try!(secret_store(dir, None)));
|
||||
let geth_accounts = read_geth_accounts(i.testnet);
|
||||
match secret_store.import_geth_accounts(geth_accounts, i.testnet) {
|
||||
|
||||
@@ -64,11 +64,19 @@ impl FromStr for DataFormat {
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum BlockchainCmd {
|
||||
Kill(KillBlockchain),
|
||||
Import(ImportBlockchain),
|
||||
Export(ExportBlockchain),
|
||||
ExportState(ExportState),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct KillBlockchain {
|
||||
pub spec: SpecType,
|
||||
pub dirs: Directories,
|
||||
pub pruning: Pruning,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ImportBlockchain {
|
||||
pub spec: SpecType,
|
||||
@@ -128,6 +136,7 @@ pub struct ExportState {
|
||||
|
||||
pub fn execute(cmd: BlockchainCmd) -> Result<String, String> {
|
||||
match cmd {
|
||||
BlockchainCmd::Kill(kill_cmd) => kill_db(kill_cmd),
|
||||
BlockchainCmd::Import(import_cmd) => execute_import(import_cmd),
|
||||
BlockchainCmd::Export(export_cmd) => execute_export(export_cmd),
|
||||
BlockchainCmd::ExportState(export_cmd) => execute_export_state(export_cmd),
|
||||
@@ -140,9 +149,6 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
||||
// Setup panic handler
|
||||
let panic_handler = PanicHandler::new_in_arc();
|
||||
|
||||
// create dirs used by parity
|
||||
try!(cmd.dirs.create_dirs(false, false));
|
||||
|
||||
// load spec file
|
||||
let spec = try!(cmd.spec.spec());
|
||||
|
||||
@@ -150,7 +156,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
||||
let genesis_hash = spec.genesis_header().hash();
|
||||
|
||||
// database paths
|
||||
let db_dirs = cmd.dirs.database(genesis_hash, spec.fork_name.clone());
|
||||
let db_dirs = cmd.dirs.database(genesis_hash, None, spec.data_dir.clone());
|
||||
|
||||
// user defaults path
|
||||
let user_defaults_path = db_dirs.user_defaults_path();
|
||||
@@ -174,7 +180,10 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
||||
let snapshot_path = db_dirs.snapshot_path();
|
||||
|
||||
// execute upgrades
|
||||
try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.fork_path().as_path())));
|
||||
try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.db_root_path().as_path())));
|
||||
|
||||
// create dirs used by parity
|
||||
try!(cmd.dirs.create_dirs(false, false));
|
||||
|
||||
// prepare client config
|
||||
let mut client_config = to_client_config(
|
||||
@@ -311,9 +320,6 @@ fn start_client(
|
||||
wal: bool,
|
||||
cache_config: CacheConfig) -> Result<ClientService, String> {
|
||||
|
||||
// create dirs used by parity
|
||||
try!(dirs.create_dirs(false, false));
|
||||
|
||||
// load spec file
|
||||
let spec = try!(spec.spec());
|
||||
|
||||
@@ -321,7 +327,7 @@ fn start_client(
|
||||
let genesis_hash = spec.genesis_header().hash();
|
||||
|
||||
// database paths
|
||||
let db_dirs = dirs.database(genesis_hash, spec.fork_name.clone());
|
||||
let db_dirs = dirs.database(genesis_hash, None, spec.data_dir.clone());
|
||||
|
||||
// user defaults path
|
||||
let user_defaults_path = db_dirs.user_defaults_path();
|
||||
@@ -345,7 +351,10 @@ fn start_client(
|
||||
let snapshot_path = db_dirs.snapshot_path();
|
||||
|
||||
// execute upgrades
|
||||
try!(execute_upgrades(&db_dirs, algorithm, compaction.compaction_profile(db_dirs.fork_path().as_path())));
|
||||
try!(execute_upgrades(&db_dirs, algorithm, compaction.compaction_profile(db_dirs.db_root_path().as_path())));
|
||||
|
||||
// create dirs used by parity
|
||||
try!(dirs.create_dirs(false, false));
|
||||
|
||||
// prepare client config
|
||||
let client_config = to_client_config(&cache_config, Mode::Active, tracing, fat_db, compaction, wal, VMType::default(), "".into(), algorithm, pruning_history, true);
|
||||
@@ -473,6 +482,18 @@ fn execute_export_state(cmd: ExportState) -> Result<String, String> {
|
||||
Ok("Export completed.".into())
|
||||
}
|
||||
|
||||
pub fn kill_db(cmd: KillBlockchain) -> Result<String, String> {
|
||||
let spec = try!(cmd.spec.spec());
|
||||
let genesis_hash = spec.genesis_header().hash();
|
||||
let db_dirs = cmd.dirs.database(genesis_hash, None, spec.data_dir);
|
||||
let user_defaults_path = db_dirs.user_defaults_path();
|
||||
let user_defaults = try!(UserDefaults::load(&user_defaults_path));
|
||||
let algorithm = cmd.pruning.to_algorithm(&user_defaults);
|
||||
let dir = db_dirs.db_path(algorithm);
|
||||
try!(fs::remove_dir_all(&dir).map_err(|e| format!("Error removing database: {:?}", e)));
|
||||
Ok("Database deleted.".to_owned())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::DataFormat;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#[macro_use]
|
||||
mod usage;
|
||||
use dir::default_data_path;
|
||||
|
||||
usage! {
|
||||
{
|
||||
@@ -38,6 +39,8 @@ usage! {
|
||||
cmd_ui: bool,
|
||||
cmd_tools: bool,
|
||||
cmd_hash: bool,
|
||||
cmd_kill: bool,
|
||||
cmd_db: bool,
|
||||
|
||||
// Arguments
|
||||
arg_pid_file: String,
|
||||
@@ -83,8 +86,8 @@ usage! {
|
||||
flag_mode_timeout: u64 = 300u64, or |c: &Config| otry!(c.parity).mode_timeout.clone(),
|
||||
flag_mode_alarm: u64 = 3600u64, or |c: &Config| otry!(c.parity).mode_alarm.clone(),
|
||||
flag_chain: String = "homestead", or |c: &Config| otry!(c.parity).chain.clone(),
|
||||
flag_db_path: String = "$HOME/.parity", or |c: &Config| otry!(c.parity).db_path.clone(),
|
||||
flag_keys_path: String = "$HOME/.parity/keys", or |c: &Config| otry!(c.parity).keys_path.clone(),
|
||||
flag_db_path: String = default_data_path(), or |c: &Config| otry!(c.parity).db_path.clone(),
|
||||
flag_keys_path: String = "$DATA/keys", or |c: &Config| otry!(c.parity).keys_path.clone(),
|
||||
flag_identity: String = "", or |c: &Config| otry!(c.parity).identity.clone(),
|
||||
|
||||
// -- Account Options
|
||||
@@ -103,7 +106,7 @@ usage! {
|
||||
or |c: &Config| otry!(c.ui).port.clone(),
|
||||
flag_ui_interface: String = "local",
|
||||
or |c: &Config| otry!(c.ui).interface.clone(),
|
||||
flag_ui_path: String = "$HOME/.parity/signer",
|
||||
flag_ui_path: String = "$DATA/signer",
|
||||
or |c: &Config| otry!(c.ui).path.clone(),
|
||||
// NOTE [todr] For security reasons don't put this to config files
|
||||
flag_ui_no_validation: bool = false, or |_| None,
|
||||
@@ -159,7 +162,7 @@ usage! {
|
||||
// IPC
|
||||
flag_no_ipc: bool = false,
|
||||
or |c: &Config| otry!(c.ipc).disable.clone(),
|
||||
flag_ipc_path: String = "$HOME/.parity/jsonrpc.ipc",
|
||||
flag_ipc_path: String = "$DATA/jsonrpc.ipc",
|
||||
or |c: &Config| otry!(c.ipc).path.clone(),
|
||||
flag_ipc_apis: String = "web3,eth,net,parity,parity_accounts,traces,rpc",
|
||||
or |c: &Config| otry!(c.ipc).apis.clone().map(|vec| vec.join(",")),
|
||||
@@ -173,7 +176,7 @@ usage! {
|
||||
or |c: &Config| otry!(c.dapps).interface.clone(),
|
||||
flag_dapps_hosts: String = "none",
|
||||
or |c: &Config| otry!(c.dapps).hosts.clone().map(|vec| vec.join(",")),
|
||||
flag_dapps_path: String = "$HOME/.parity/dapps",
|
||||
flag_dapps_path: String = "$DATA/dapps",
|
||||
or |c: &Config| otry!(c.dapps).path.clone(),
|
||||
flag_dapps_user: Option<String> = None,
|
||||
or |c: &Config| otry!(c.dapps).user.clone().map(Some),
|
||||
@@ -274,7 +277,7 @@ usage! {
|
||||
or |c: &Config| otry!(c.vm).jit.clone(),
|
||||
|
||||
// -- Miscellaneous Options
|
||||
flag_config: String = "$HOME/.parity/config.toml", or |_| None,
|
||||
flag_config: String = "$DATA/config.toml", or |_| None,
|
||||
flag_logging: Option<String> = None,
|
||||
or |c: &Config| otry!(c.misc).logging.clone().map(Some),
|
||||
flag_log_file: Option<String> = None,
|
||||
@@ -517,6 +520,8 @@ mod tests {
|
||||
cmd_ui: false,
|
||||
cmd_tools: false,
|
||||
cmd_hash: false,
|
||||
cmd_db: false,
|
||||
cmd_kill: false,
|
||||
|
||||
// Arguments
|
||||
arg_pid_file: "".into(),
|
||||
@@ -671,7 +676,7 @@ mod tests {
|
||||
|
||||
// -- Miscellaneous Options
|
||||
flag_version: false,
|
||||
flag_config: "$HOME/.parity/config.toml".into(),
|
||||
flag_config: "$DATA/config.toml".into(),
|
||||
flag_logging: Some("own_tx=trace".into()),
|
||||
flag_log_file: Some("/var/log/parity.log".into()),
|
||||
flag_no_color: false,
|
||||
|
||||
@@ -145,7 +145,7 @@ macro_rules! usage {
|
||||
}
|
||||
|
||||
let config_file = raw_args.flag_config.clone().unwrap_or_else(|| raw_args.clone().into_args(Config::default()).flag_config);
|
||||
let config_file = replace_home(&config_file);
|
||||
let config_file = replace_home("", &config_file);
|
||||
let config = match (fs::File::open(&config_file), raw_args.flag_config.is_some()) {
|
||||
// Load config file
|
||||
(Ok(mut file), _) => {
|
||||
|
||||
@@ -18,6 +18,7 @@ Usage:
|
||||
parity snapshot <file> [options]
|
||||
parity restore [ <file> ] [options]
|
||||
parity tools hash <file>
|
||||
parity db kill [options]
|
||||
|
||||
Operating Options:
|
||||
--mode MODE Set the operating mode. MODE can be one of:
|
||||
@@ -285,10 +286,8 @@ Import/Export Options:
|
||||
(default: {flag_format:?} = Import: auto, Export: binary)
|
||||
--no-seal-check Skip block seal check. (default: {flag_no_seal_check})
|
||||
--at BLOCK Export state at the given block, which may be an
|
||||
index, hash, or 'latest'. Note that taking snapshots at
|
||||
non-recent blocks will only work with --pruning archive
|
||||
(default: {flag_at})
|
||||
--no-storage Don't export account storge. (default: {flag_no_storage})
|
||||
index, hash, or 'latest'. (default: {flag_at})
|
||||
--no-storage Don't export account storage. (default: {flag_no_storage})
|
||||
--no-code Don't export account code. (default: {flag_no_code})
|
||||
--min-balance WEI Don't export accounts with balance less than specified.
|
||||
(default: {flag_min_balance:?})
|
||||
|
||||
@@ -38,9 +38,9 @@ use dir::Directories;
|
||||
use dapps::Configuration as DappsConfiguration;
|
||||
use signer::{Configuration as SignerConfiguration};
|
||||
use run::RunCmd;
|
||||
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, ExportState, DataFormat};
|
||||
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, KillBlockchain, ExportState, DataFormat};
|
||||
use presale::ImportWallet;
|
||||
use account::{AccountCmd, NewAccount, ImportAccounts, ImportFromGethAccounts};
|
||||
use account::{AccountCmd, NewAccount, ListAccounts, ImportAccounts, ImportFromGethAccounts};
|
||||
use snapshot::{self, SnapshotCommand};
|
||||
|
||||
const AUTHCODE_FILENAME: &'static str = "authcodes";
|
||||
@@ -152,20 +152,32 @@ impl Configuration {
|
||||
}
|
||||
} else if self.args.cmd_tools && self.args.cmd_hash {
|
||||
Cmd::Hash(self.args.arg_file)
|
||||
} else if self.args.cmd_db && self.args.cmd_kill {
|
||||
Cmd::Blockchain(BlockchainCmd::Kill(KillBlockchain {
|
||||
spec: spec,
|
||||
dirs: dirs,
|
||||
pruning: pruning,
|
||||
}))
|
||||
} else if self.args.cmd_account {
|
||||
let account_cmd = if self.args.cmd_new {
|
||||
let new_acc = NewAccount {
|
||||
iterations: self.args.flag_keys_iterations,
|
||||
path: dirs.keys,
|
||||
spec: spec,
|
||||
password_file: self.args.flag_password.first().cloned(),
|
||||
};
|
||||
AccountCmd::New(new_acc)
|
||||
} else if self.args.cmd_list {
|
||||
AccountCmd::List(dirs.keys)
|
||||
let list_acc = ListAccounts {
|
||||
path: dirs.keys,
|
||||
spec: spec,
|
||||
};
|
||||
AccountCmd::List(list_acc)
|
||||
} else if self.args.cmd_import {
|
||||
let import_acc = ImportAccounts {
|
||||
from: self.args.arg_path.clone(),
|
||||
to: dirs.keys,
|
||||
spec: spec,
|
||||
};
|
||||
AccountCmd::Import(import_acc)
|
||||
} else {
|
||||
@@ -175,6 +187,7 @@ impl Configuration {
|
||||
} else if self.args.flag_import_geth_keys {
|
||||
let account_cmd = AccountCmd::ImportFromGeth(
|
||||
ImportFromGethAccounts {
|
||||
spec: spec,
|
||||
to: dirs.keys,
|
||||
testnet: self.args.flag_testnet
|
||||
}
|
||||
@@ -184,6 +197,7 @@ impl Configuration {
|
||||
let presale_cmd = ImportWallet {
|
||||
iterations: self.args.flag_keys_iterations,
|
||||
path: dirs.keys,
|
||||
spec: spec,
|
||||
wallet_path: self.args.arg_path.first().unwrap().clone(),
|
||||
password_file: self.args.flag_password.first().cloned(),
|
||||
};
|
||||
@@ -575,7 +589,7 @@ impl Configuration {
|
||||
ret.snapshot_peers = self.snapshot_peers();
|
||||
ret.allow_ips = try!(self.allow_ips());
|
||||
ret.max_pending_peers = self.max_pending_peers();
|
||||
let mut net_path = PathBuf::from(self.directories().db);
|
||||
let mut net_path = PathBuf::from(self.directories().data);
|
||||
net_path.push("network");
|
||||
ret.config_path = Some(net_path.to_str().unwrap().to_owned());
|
||||
ret.reserved_nodes = try!(self.init_reserved_nodes());
|
||||
@@ -669,18 +683,11 @@ impl Configuration {
|
||||
fn directories(&self) -> Directories {
|
||||
use util::path;
|
||||
|
||||
let db_path = replace_home(self.args.flag_datadir.as_ref().unwrap_or(&self.args.flag_db_path));
|
||||
let data_path = replace_home("", self.args.flag_datadir.as_ref().unwrap_or(&self.args.flag_db_path));
|
||||
|
||||
let keys_path = replace_home(
|
||||
if self.args.flag_testnet {
|
||||
"$HOME/.parity/testnet_keys"
|
||||
} else {
|
||||
&self.args.flag_keys_path
|
||||
}
|
||||
);
|
||||
|
||||
let dapps_path = replace_home(&self.args.flag_dapps_path);
|
||||
let ui_path = replace_home(&self.args.flag_ui_path);
|
||||
let keys_path = replace_home(&data_path, &self.args.flag_keys_path);
|
||||
let dapps_path = replace_home(&data_path, &self.args.flag_dapps_path);
|
||||
let ui_path = replace_home(&data_path, &self.args.flag_ui_path);
|
||||
|
||||
if self.args.flag_geth && !cfg!(windows) {
|
||||
let geth_root = if self.args.flag_testnet { path::ethereum::test() } else { path::ethereum::default() };
|
||||
@@ -689,7 +696,7 @@ impl Configuration {
|
||||
}
|
||||
|
||||
if cfg!(feature = "ipc") && !cfg!(feature = "windows") {
|
||||
let mut path_buf = PathBuf::from(db_path.clone());
|
||||
let mut path_buf = PathBuf::from(data_path.clone());
|
||||
path_buf.push("ipc");
|
||||
let ipc_path = path_buf.to_str().unwrap();
|
||||
::std::fs::create_dir_all(ipc_path).unwrap_or_else(
|
||||
@@ -699,7 +706,7 @@ impl Configuration {
|
||||
|
||||
Directories {
|
||||
keys: keys_path,
|
||||
db: db_path,
|
||||
data: data_path,
|
||||
dapps: dapps_path,
|
||||
signer: ui_path,
|
||||
}
|
||||
@@ -709,7 +716,7 @@ impl Configuration {
|
||||
if self.args.flag_geth {
|
||||
geth_ipc_path(self.args.flag_testnet)
|
||||
} else {
|
||||
parity_ipc_path(&self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone()))
|
||||
parity_ipc_path(&self.directories().data, &self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -777,12 +784,14 @@ mod tests {
|
||||
use ethcore_rpc::NetworkSettings;
|
||||
use ethcore::client::{VMType, BlockId};
|
||||
use ethcore::miner::{MinerOptions, PrioritizationStrategy};
|
||||
use helpers::{replace_home, default_network_config};
|
||||
use helpers::{default_network_config};
|
||||
use run::RunCmd;
|
||||
use dir::Directories;
|
||||
use signer::{Configuration as SignerConfiguration};
|
||||
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, DataFormat, ExportState};
|
||||
use presale::ImportWallet;
|
||||
use account::{AccountCmd, NewAccount, ImportAccounts};
|
||||
use params::SpecType;
|
||||
use account::{AccountCmd, NewAccount, ImportAccounts, ListAccounts};
|
||||
use devtools::{RandomTempPath};
|
||||
use std::io::Write;
|
||||
use std::fs::{File, create_dir};
|
||||
@@ -809,8 +818,9 @@ mod tests {
|
||||
let conf = parse(&args);
|
||||
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account(AccountCmd::New(NewAccount {
|
||||
iterations: 10240,
|
||||
path: replace_home("$HOME/.parity/keys"),
|
||||
path: Directories::default().keys,
|
||||
password_file: None,
|
||||
spec: SpecType::default(),
|
||||
})));
|
||||
}
|
||||
|
||||
@@ -819,7 +829,10 @@ mod tests {
|
||||
let args = vec!["parity", "account", "list"];
|
||||
let conf = parse(&args);
|
||||
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account(
|
||||
AccountCmd::List(replace_home("$HOME/.parity/keys")),
|
||||
AccountCmd::List(ListAccounts {
|
||||
path: Directories::default().keys,
|
||||
spec: SpecType::default(),
|
||||
})
|
||||
));
|
||||
}
|
||||
|
||||
@@ -829,7 +842,8 @@ mod tests {
|
||||
let conf = parse(&args);
|
||||
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account(AccountCmd::Import(ImportAccounts {
|
||||
from: vec!["my_dir".into(), "another_dir".into()],
|
||||
to: replace_home("$HOME/.parity/keys"),
|
||||
to: Directories::default().keys,
|
||||
spec: SpecType::default(),
|
||||
})));
|
||||
}
|
||||
|
||||
@@ -839,9 +853,10 @@ mod tests {
|
||||
let conf = parse(&args);
|
||||
assert_eq!(conf.into_command().unwrap().cmd, Cmd::ImportPresaleWallet(ImportWallet {
|
||||
iterations: 10240,
|
||||
path: replace_home("$HOME/.parity/keys"),
|
||||
path: Directories::default().keys,
|
||||
wallet_path: "my_wallet.json".into(),
|
||||
password_file: Some("pwd".into()),
|
||||
spec: SpecType::default(),
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -940,7 +955,7 @@ mod tests {
|
||||
fn test_command_signer_new_token() {
|
||||
let args = vec!["parity", "signer", "new-token"];
|
||||
let conf = parse(&args);
|
||||
let expected = replace_home("$HOME/.parity/signer");
|
||||
let expected = Directories::default().signer;
|
||||
assert_eq!(conf.into_command().unwrap().cmd, Cmd::SignerToken(SignerConfiguration {
|
||||
enabled: true,
|
||||
signer_path: expected,
|
||||
|
||||
@@ -20,6 +20,7 @@ use rpc_apis;
|
||||
use ethcore::client::Client;
|
||||
use ethsync::SyncProvider;
|
||||
use helpers::replace_home;
|
||||
use dir::default_data_path;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Configuration {
|
||||
@@ -34,6 +35,7 @@ pub struct Configuration {
|
||||
|
||||
impl Default for Configuration {
|
||||
fn default() -> Self {
|
||||
let data_dir = default_data_path();
|
||||
Configuration {
|
||||
enabled: true,
|
||||
interface: "127.0.0.1".into(),
|
||||
@@ -41,7 +43,7 @@ impl Default for Configuration {
|
||||
hosts: Some(Vec::new()),
|
||||
user: None,
|
||||
pass: None,
|
||||
dapps_path: replace_home("$HOME/.parity/dapps"),
|
||||
dapps_path: replace_home(&data_dir, "$DATA/dapps"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
118
parity/dir.rs
118
parity/dir.rs
@@ -19,6 +19,7 @@ use std::path::{PathBuf, Path};
|
||||
use util::{H64, H256};
|
||||
use util::journaldb::Algorithm;
|
||||
use helpers::replace_home;
|
||||
use app_dirs::{AppInfo, get_app_root, AppDataType};
|
||||
|
||||
// this const is irrelevent cause we do have migrations now,
|
||||
// but we still use it for backwards compatibility
|
||||
@@ -26,7 +27,7 @@ const LEGACY_CLIENT_DB_VER_STR: &'static str = "5.3";
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Directories {
|
||||
pub db: String,
|
||||
pub data: String,
|
||||
pub keys: String,
|
||||
pub signer: String,
|
||||
pub dapps: String,
|
||||
@@ -34,18 +35,19 @@ pub struct Directories {
|
||||
|
||||
impl Default for Directories {
|
||||
fn default() -> Self {
|
||||
let data_dir = default_data_path();
|
||||
Directories {
|
||||
db: replace_home("$HOME/.parity"),
|
||||
keys: replace_home("$HOME/.parity/keys"),
|
||||
signer: replace_home("$HOME/.parity/signer"),
|
||||
dapps: replace_home("$HOME/.parity/dapps"),
|
||||
data: replace_home(&data_dir, "$DATA"),
|
||||
keys: replace_home(&data_dir, "$DATA/keys"),
|
||||
signer: replace_home(&data_dir, "$DATA/signer"),
|
||||
dapps: replace_home(&data_dir, "$DATA/dapps"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Directories {
|
||||
pub fn create_dirs(&self, dapps_enabled: bool, signer_enabled: bool) -> Result<(), String> {
|
||||
try!(fs::create_dir_all(&self.db).map_err(|e| e.to_string()));
|
||||
try!(fs::create_dir_all(&self.data).map_err(|e| e.to_string()));
|
||||
try!(fs::create_dir_all(&self.keys).map_err(|e| e.to_string()));
|
||||
if signer_enabled {
|
||||
try!(fs::create_dir_all(&self.signer).map_err(|e| e.to_string()));
|
||||
@@ -57,20 +59,38 @@ impl Directories {
|
||||
}
|
||||
|
||||
/// Database paths.
|
||||
pub fn database(&self, genesis_hash: H256, fork_name: Option<String>) -> DatabaseDirectories {
|
||||
pub fn database(&self, genesis_hash: H256, fork_name: Option<String>, spec_name: String) -> DatabaseDirectories {
|
||||
DatabaseDirectories {
|
||||
path: self.db.clone(),
|
||||
path: self.data.clone(),
|
||||
genesis_hash: genesis_hash,
|
||||
fork_name: fork_name,
|
||||
spec_name: spec_name,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the ipc sockets path
|
||||
pub fn ipc_path(&self) -> PathBuf {
|
||||
let mut dir = Path::new(&self.db).to_path_buf();
|
||||
let mut dir = Path::new(&self.data).to_path_buf();
|
||||
dir.push("ipc");
|
||||
dir
|
||||
}
|
||||
|
||||
// TODO: remove in 1.7
|
||||
pub fn legacy_keys_path(&self, testnet: bool) -> PathBuf {
|
||||
let mut dir = Path::new(&self.data).to_path_buf();
|
||||
if testnet {
|
||||
dir.push("testnet_keys");
|
||||
} else {
|
||||
dir.push("keys");
|
||||
}
|
||||
dir
|
||||
}
|
||||
|
||||
pub fn keys_path(&self, spec_name: &str) -> PathBuf {
|
||||
let mut dir = PathBuf::from(&self.keys);
|
||||
dir.push(spec_name);
|
||||
dir
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@@ -78,52 +98,103 @@ pub struct DatabaseDirectories {
|
||||
pub path: String,
|
||||
pub genesis_hash: H256,
|
||||
pub fork_name: Option<String>,
|
||||
pub spec_name: String,
|
||||
}
|
||||
|
||||
impl DatabaseDirectories {
|
||||
/// Base DB directory for the given fork.
|
||||
pub fn fork_path(&self) -> PathBuf {
|
||||
// TODO: remove in 1.7
|
||||
pub fn legacy_fork_path(&self) -> PathBuf {
|
||||
let mut dir = Path::new(&self.path).to_path_buf();
|
||||
dir.push(format!("{:?}{}", H64::from(self.genesis_hash), self.fork_name.as_ref().map(|f| format!("-{}", f)).unwrap_or_default()));
|
||||
dir
|
||||
}
|
||||
|
||||
/// Get the root path for database
|
||||
pub fn version_path(&self, pruning: Algorithm) -> PathBuf {
|
||||
let mut dir = self.fork_path();
|
||||
dir.push(format!("v{}-sec-{}", LEGACY_CLIENT_DB_VER_STR, pruning.as_internal_name_str()));
|
||||
pub fn spec_root_path(&self) -> PathBuf {
|
||||
let mut dir = Path::new(&self.path).to_path_buf();
|
||||
dir.push("chains");
|
||||
dir.push(&self.spec_name);
|
||||
dir
|
||||
}
|
||||
|
||||
/// Get the path for the databases given the genesis_hash and information on the databases.
|
||||
pub fn client_path(&self, pruning: Algorithm) -> PathBuf {
|
||||
let mut dir = self.version_path(pruning);
|
||||
let mut dir = self.db_root_path();
|
||||
dir.push(pruning.as_internal_name_str());
|
||||
dir.push("db");
|
||||
dir
|
||||
}
|
||||
|
||||
pub fn db_root_path(&self) -> PathBuf {
|
||||
let mut dir = self.spec_root_path();
|
||||
dir.push("db");
|
||||
dir.push(H64::from(self.genesis_hash).hex());
|
||||
dir
|
||||
}
|
||||
|
||||
pub fn db_path(&self, pruning: Algorithm) -> PathBuf {
|
||||
let mut dir = self.db_root_path();
|
||||
dir.push(pruning.as_internal_name_str());
|
||||
dir
|
||||
}
|
||||
|
||||
/// Get the root path for database
|
||||
// TODO: remove in 1.7
|
||||
pub fn legacy_version_path(&self, pruning: Algorithm) -> PathBuf {
|
||||
let mut dir = self.legacy_fork_path();
|
||||
dir.push(format!("v{}-sec-{}", LEGACY_CLIENT_DB_VER_STR, pruning.as_internal_name_str()));
|
||||
dir
|
||||
}
|
||||
|
||||
/// Get user defaults path
|
||||
// TODO: remove in 1.7
|
||||
pub fn legacy_user_defaults_path(&self) -> PathBuf {
|
||||
let mut dir = self.legacy_fork_path();
|
||||
dir.push("user_defaults");
|
||||
dir
|
||||
}
|
||||
|
||||
/// Get user defaults path
|
||||
// TODO: remove in 1.7
|
||||
pub fn legacy_snapshot_path(&self) -> PathBuf {
|
||||
let mut dir = self.legacy_fork_path();
|
||||
dir.push("snapshot");
|
||||
dir
|
||||
}
|
||||
|
||||
/// Get user defaults path
|
||||
// TODO: remove in 1.7
|
||||
pub fn legacy_network_path(&self) -> PathBuf {
|
||||
let mut dir = self.legacy_fork_path();
|
||||
dir.push("network");
|
||||
dir
|
||||
}
|
||||
|
||||
pub fn user_defaults_path(&self) -> PathBuf {
|
||||
let mut dir = self.fork_path();
|
||||
let mut dir = self.spec_root_path();
|
||||
dir.push("user_defaults");
|
||||
dir
|
||||
}
|
||||
|
||||
/// Get the path for the snapshot directory given the genesis hash and fork name.
|
||||
pub fn snapshot_path(&self) -> PathBuf {
|
||||
let mut dir = self.fork_path();
|
||||
let mut dir = self.db_root_path();
|
||||
dir.push("snapshot");
|
||||
dir
|
||||
}
|
||||
|
||||
/// Get the path for the network directory.
|
||||
pub fn network_path(&self) -> PathBuf {
|
||||
let mut dir = self.fork_path();
|
||||
let mut dir = self.spec_root_path();
|
||||
dir.push("network");
|
||||
dir
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default_data_path() -> String {
|
||||
let app_info = AppInfo { name: "parity", author: "parity" };
|
||||
get_app_root(AppDataType::UserData, &app_info).map(|p| p.to_string_lossy().into_owned()).unwrap_or_else(|_| "$HOME/.parity".to_owned())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Directories;
|
||||
@@ -131,11 +202,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_default_directories() {
|
||||
let data_dir = super::default_data_path();
|
||||
let expected = Directories {
|
||||
db: replace_home("$HOME/.parity"),
|
||||
keys: replace_home("$HOME/.parity/keys"),
|
||||
signer: replace_home("$HOME/.parity/signer"),
|
||||
dapps: replace_home("$HOME/.parity/dapps"),
|
||||
data: replace_home(&data_dir, "$DATA"),
|
||||
keys: replace_home(&data_dir, "$DATA/keys"),
|
||||
signer: replace_home(&data_dir, "$DATA/signer"),
|
||||
dapps: replace_home(&data_dir, "$DATA/dapps"),
|
||||
};
|
||||
assert_eq!(expected, Directories::default());
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ use ethcore::client::{Mode, BlockId, VMType, DatabaseCompactionProfile, ClientCo
|
||||
use ethcore::miner::{PendingSet, GasLimit, PrioritizationStrategy};
|
||||
use cache::CacheConfig;
|
||||
use dir::DatabaseDirectories;
|
||||
use upgrade::upgrade;
|
||||
use upgrade::{upgrade, upgrade_data_paths};
|
||||
use migration::migrate;
|
||||
use ethsync::is_valid_node_url;
|
||||
|
||||
@@ -132,9 +132,10 @@ pub fn to_price(s: &str) -> Result<f32, String> {
|
||||
}
|
||||
|
||||
/// Replaces `$HOME` str with home directory path.
|
||||
pub fn replace_home(arg: &str) -> String {
|
||||
pub fn replace_home(base: &str, arg: &str) -> String {
|
||||
// the $HOME directory on mac os should be `~/Library` or `~/Library/Application Support`
|
||||
let r = arg.replace("$HOME", env::home_dir().unwrap().to_str().unwrap());
|
||||
let r = r.replace("$DATA", base );
|
||||
r.replace("/", &::std::path::MAIN_SEPARATOR.to_string() )
|
||||
}
|
||||
|
||||
@@ -159,13 +160,13 @@ pub fn geth_ipc_path(testnet: bool) -> String {
|
||||
}
|
||||
|
||||
/// Formats and returns parity ipc path.
|
||||
pub fn parity_ipc_path(s: &str) -> String {
|
||||
pub fn parity_ipc_path(base: &str, s: &str) -> String {
|
||||
// Windows path should not be hardcoded here.
|
||||
if cfg!(windows) {
|
||||
return r"\\.\pipe\parity.jsonrpc".to_owned();
|
||||
}
|
||||
|
||||
replace_home(s)
|
||||
replace_home(base, s)
|
||||
}
|
||||
|
||||
/// Validates and formats bootnodes option.
|
||||
@@ -187,7 +188,7 @@ pub fn to_bootnodes(bootnodes: &Option<String>) -> Result<Vec<String>, String> {
|
||||
pub fn default_network_config() -> ::ethsync::NetworkConfiguration {
|
||||
use ethsync::{NetworkConfiguration, AllowIP};
|
||||
NetworkConfiguration {
|
||||
config_path: Some(replace_home("$HOME/.parity/network")),
|
||||
config_path: Some(replace_home(&::dir::default_data_path(), "$DATA/network")),
|
||||
net_config_path: None,
|
||||
listen_address: Some("0.0.0.0:30303".into()),
|
||||
public_address: None,
|
||||
@@ -261,6 +262,8 @@ pub fn execute_upgrades(
|
||||
compaction_profile: CompactionProfile
|
||||
) -> Result<(), String> {
|
||||
|
||||
upgrade_data_paths(dirs, pruning);
|
||||
|
||||
match upgrade(Some(&dirs.path)) {
|
||||
Ok(upgrades_applied) if upgrades_applied > 0 => {
|
||||
debug!("Executed {} upgrade scripts - ok", upgrades_applied);
|
||||
@@ -271,7 +274,7 @@ pub fn execute_upgrades(
|
||||
_ => {},
|
||||
}
|
||||
|
||||
let client_path = dirs.version_path(pruning);
|
||||
let client_path = dirs.db_path(pruning);
|
||||
migrate(&client_path, pruning, compaction_profile).map_err(|e| format!("{}", e))
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
|
||||
use std::time::{Instant, Duration};
|
||||
use isatty::{stdout_isatty};
|
||||
use ethsync::{SyncProvider, ManageNetwork};
|
||||
use util::{Uint, RwLock, Mutex, H256, Colour};
|
||||
use util::{Uint, RwLock, Mutex, H256, Colour, Bytes};
|
||||
use ethcore::client::*;
|
||||
use ethcore::views::BlockView;
|
||||
use ethcore::snapshot::service::Service as SnapshotService;
|
||||
@@ -176,14 +176,13 @@ impl Informant {
|
||||
}
|
||||
|
||||
impl ChainNotify for Informant {
|
||||
fn new_blocks(&self, imported: Vec<H256>, _invalid: Vec<H256>, _enacted: Vec<H256>, _retracted: Vec<H256>, _sealed: Vec<H256>, duration: u64) {
|
||||
fn new_blocks(&self, imported: Vec<H256>, _invalid: Vec<H256>, _enacted: Vec<H256>, _retracted: Vec<H256>, _sealed: Vec<H256>, _proposed: Vec<Bytes>, duration: u64) {
|
||||
let mut last_import = self.last_import.lock();
|
||||
let sync_state = self.sync.as_ref().map(|s| s.status().state);
|
||||
let importing = is_major_importing(sync_state, self.client.queue_info());
|
||||
|
||||
let ripe = Instant::now() > *last_import + Duration::from_secs(1) && !importing;
|
||||
let txs_imported = imported.iter()
|
||||
.take(imported.len() - if ripe {1} else {0})
|
||||
.take(imported.len().saturating_sub(if ripe { 1 } else { 0 }))
|
||||
.filter_map(|h| self.client.block(BlockId::Hash(*h)))
|
||||
.map(|b| BlockView::new(&b).transactions_count())
|
||||
.sum();
|
||||
|
||||
@@ -54,6 +54,7 @@ extern crate ansi_term;
|
||||
extern crate regex;
|
||||
extern crate isatty;
|
||||
extern crate toml;
|
||||
extern crate app_dirs;
|
||||
|
||||
#[macro_use]
|
||||
extern crate ethcore_util as util;
|
||||
|
||||
@@ -76,6 +76,14 @@ impl SpecType {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn legacy_fork_name(&self) -> Option<String> {
|
||||
match *self {
|
||||
SpecType::Classic => Some("classic".to_owned()),
|
||||
SpecType::Expanse => Some("expanse".to_owned()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
||||
@@ -18,11 +18,13 @@ use ethcore::ethstore::{PresaleWallet, EthStore};
|
||||
use ethcore::ethstore::dir::DiskDirectory;
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use helpers::{password_prompt, password_from_file};
|
||||
use params::SpecType;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ImportWallet {
|
||||
pub iterations: u32,
|
||||
pub path: String,
|
||||
pub spec: SpecType,
|
||||
pub wallet_path: String,
|
||||
pub password_file: Option<String>,
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ use ethcore_rpc::{RpcServerError, RpcServer as Server, IpcServerError};
|
||||
use rpc_apis;
|
||||
use rpc_apis::ApiSet;
|
||||
use helpers::parity_ipc_path;
|
||||
use dir::default_data_path;
|
||||
|
||||
pub use ethcore_rpc::{IpcServer, Server as HttpServer};
|
||||
|
||||
@@ -58,9 +59,10 @@ pub struct IpcConfiguration {
|
||||
|
||||
impl Default for IpcConfiguration {
|
||||
fn default() -> Self {
|
||||
let data_dir = default_data_path();
|
||||
IpcConfiguration {
|
||||
enabled: true,
|
||||
socket_addr: parity_ipc_path("$HOME/.parity/jsonrpc.ipc"),
|
||||
socket_addr: parity_ipc_path(&data_dir, "$DATA/jsonrpc.ipc"),
|
||||
apis: ApiSet::IpcContext,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ use params::{
|
||||
tracing_switch_to_bool, fatdb_switch_to_bool, mode_switch_to_bool
|
||||
};
|
||||
use helpers::{to_client_config, execute_upgrades, passwords_from_files};
|
||||
use upgrade::upgrade_key_location;
|
||||
use dir::Directories;
|
||||
use cache::CacheConfig;
|
||||
use user_defaults::UserDefaults;
|
||||
@@ -129,9 +130,6 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
||||
// increase max number of open files
|
||||
raise_fd_limit();
|
||||
|
||||
// create dirs used by parity
|
||||
try!(cmd.dirs.create_dirs(cmd.dapps_conf.enabled, cmd.signer_conf.enabled));
|
||||
|
||||
// load spec
|
||||
let spec = try!(cmd.spec.spec());
|
||||
|
||||
@@ -139,7 +137,7 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
||||
let genesis_hash = spec.genesis_header().hash();
|
||||
|
||||
// database paths
|
||||
let db_dirs = cmd.dirs.database(genesis_hash, spec.fork_name.clone());
|
||||
let db_dirs = cmd.dirs.database(genesis_hash, cmd.spec.legacy_fork_name(), spec.data_dir.clone());
|
||||
|
||||
// user defaults path
|
||||
let user_defaults_path = db_dirs.user_defaults_path();
|
||||
@@ -166,7 +164,10 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
||||
let snapshot_path = db_dirs.snapshot_path();
|
||||
|
||||
// execute upgrades
|
||||
try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.fork_path().as_path())));
|
||||
try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.db_root_path().as_path())));
|
||||
|
||||
// create dirs used by parity
|
||||
try!(cmd.dirs.create_dirs(cmd.dapps_conf.enabled, cmd.signer_conf.enabled));
|
||||
|
||||
// run in daemon mode
|
||||
if let Some(pid_file) = cmd.daemon {
|
||||
@@ -175,7 +176,7 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
||||
|
||||
// display info about used pruning algorithm
|
||||
info!("Starting {}", Colour::White.bold().paint(version()));
|
||||
info!("State DB configuation: {}{}{}",
|
||||
info!("State DB configuration: {}{}{}",
|
||||
Colour::White.bold().paint(algorithm.as_str()),
|
||||
match fat_db {
|
||||
true => Colour::White.bold().paint(" +Fat").to_string(),
|
||||
@@ -217,7 +218,7 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
||||
let passwords = try!(passwords_from_files(&cmd.acc_conf.password_files));
|
||||
|
||||
// prepare account provider
|
||||
let account_provider = Arc::new(try!(prepare_account_provider(&cmd.dirs, cmd.acc_conf, &passwords)));
|
||||
let account_provider = Arc::new(try!(prepare_account_provider(&cmd.dirs, &spec.data_dir, cmd.acc_conf, &passwords)));
|
||||
|
||||
// let the Engine access the accounts
|
||||
spec.engine.register_account_provider(account_provider.clone());
|
||||
@@ -449,11 +450,13 @@ fn daemonize(_pid_file: String) -> Result<(), String> {
|
||||
Err("daemon is no supported on windows".into())
|
||||
}
|
||||
|
||||
fn prepare_account_provider(dirs: &Directories, cfg: AccountsConfig, passwords: &[String]) -> Result<AccountProvider, String> {
|
||||
fn prepare_account_provider(dirs: &Directories, data_dir: &str, cfg: AccountsConfig, passwords: &[String]) -> Result<AccountProvider, String> {
|
||||
use ethcore::ethstore::EthStore;
|
||||
use ethcore::ethstore::dir::DiskDirectory;
|
||||
|
||||
let dir = Box::new(try!(DiskDirectory::create(dirs.keys.clone()).map_err(|e| format!("Could not open keys directory: {}", e))));
|
||||
let path = dirs.keys_path(data_dir);
|
||||
upgrade_key_location(&dirs.legacy_keys_path(cfg.testnet), &path);
|
||||
let dir = Box::new(try!(DiskDirectory::create(&path).map_err(|e| format!("Could not open keys directory: {}", e))));
|
||||
let account_service = AccountProvider::new(Box::new(
|
||||
try!(EthStore::open_with_iterations(dir, cfg.iterations).map_err(|e| format!("Could not open keys directory: {}", e)))
|
||||
));
|
||||
|
||||
@@ -23,6 +23,7 @@ use util::path::restrict_permissions_owner;
|
||||
use rpc_apis;
|
||||
use ethcore_signer as signer;
|
||||
use helpers::replace_home;
|
||||
use dir::default_data_path;
|
||||
pub use ethcore_signer::Server as SignerServer;
|
||||
|
||||
const CODES_FILENAME: &'static str = "authcodes";
|
||||
@@ -38,11 +39,12 @@ pub struct Configuration {
|
||||
|
||||
impl Default for Configuration {
|
||||
fn default() -> Self {
|
||||
let data_dir = default_data_path();
|
||||
Configuration {
|
||||
enabled: true,
|
||||
port: 8180,
|
||||
interface: "127.0.0.1".into(),
|
||||
signer_path: replace_home("$HOME/.parity/signer"),
|
||||
signer_path: replace_home(&data_dir, "$DATA/signer"),
|
||||
skip_origin_validation: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ impl SnapshotCommand {
|
||||
let genesis_hash = spec.genesis_header().hash();
|
||||
|
||||
// database paths
|
||||
let db_dirs = self.dirs.database(genesis_hash, spec.fork_name.clone());
|
||||
let db_dirs = self.dirs.database(genesis_hash, None, spec.data_dir.clone());
|
||||
|
||||
// user defaults path
|
||||
let user_defaults_path = db_dirs.user_defaults_path();
|
||||
@@ -167,7 +167,7 @@ impl SnapshotCommand {
|
||||
let snapshot_path = db_dirs.snapshot_path();
|
||||
|
||||
// execute upgrades
|
||||
try!(execute_upgrades(&db_dirs, algorithm, self.compaction.compaction_profile(db_dirs.fork_path().as_path())));
|
||||
try!(execute_upgrades(&db_dirs, algorithm, self.compaction.compaction_profile(db_dirs.db_root_path().as_path())));
|
||||
|
||||
// prepare client config
|
||||
let client_config = to_client_config(&self.cache_config, Mode::Active, tracing, fat_db, self.compaction, self.wal, VMType::default(), "".into(), algorithm, self.pruning_history, true);
|
||||
|
||||
@@ -18,10 +18,14 @@
|
||||
|
||||
use semver::Version;
|
||||
use std::collections::*;
|
||||
use std::fs::{File, create_dir_all};
|
||||
use std::fs::{self, File, create_dir_all};
|
||||
use std::env;
|
||||
use std::io;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::path::{PathBuf, Path};
|
||||
use dir::{DatabaseDirectories, default_data_path};
|
||||
use helpers::replace_home;
|
||||
use util::journaldb::Algorithm;
|
||||
|
||||
#[cfg_attr(feature="dev", allow(enum_variant_names))]
|
||||
#[derive(Debug)]
|
||||
@@ -126,3 +130,84 @@ pub fn upgrade(db_path: Option<&str>) -> Result<usize, Error> {
|
||||
upgrade_from_version(ver)
|
||||
})
|
||||
}
|
||||
|
||||
fn file_exists(path: &Path) -> bool {
|
||||
match fs::metadata(&path) {
|
||||
Err(ref e) if e.kind() == io::ErrorKind::NotFound => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn upgrade_key_location(from: &PathBuf, to: &PathBuf) {
|
||||
let mut parent = to.clone();
|
||||
parent.pop();
|
||||
match fs::create_dir_all(&parent).and_then(|()| fs::read_dir(from)) {
|
||||
Ok(entries) => {
|
||||
let files: Vec<_> = entries.filter_map(|f| f.ok().and_then(|f| if f.file_type().ok().map_or(false, |f| f.is_file()) { f.file_name().to_str().map(|s| s.to_owned()) } else { None })).collect();
|
||||
let mut num: usize = 0;
|
||||
for name in files {
|
||||
let mut from = from.clone();
|
||||
from.push(&name);
|
||||
let mut to = to.clone();
|
||||
to.push(&name);
|
||||
if !file_exists(&to) {
|
||||
if let Err(e) = fs::rename(&from, &to) {
|
||||
debug!("Error upgrading key {:?}: {:?}", from, e);
|
||||
} else {
|
||||
num += 1;
|
||||
}
|
||||
} else {
|
||||
debug!("Skipped upgrading key {:?}", from);
|
||||
}
|
||||
}
|
||||
if num > 0 {
|
||||
info!("Moved {} keys from {} to {}", num, from.to_string_lossy(), to.to_string_lossy());
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
warn!("Error moving keys from {:?} to {:?}: {:?}", from, to, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn upgrade_dir_location(source: &PathBuf, dest: &PathBuf) {
|
||||
if file_exists(&source) {
|
||||
if !file_exists(&dest) {
|
||||
let mut parent = dest.clone();
|
||||
parent.pop();
|
||||
if let Err(e) = fs::create_dir_all(&parent).and_then(|()| fs::rename(&source, &dest)) {
|
||||
debug!("Skipped path {:?} -> {:?} :{:?}", source, dest, e);
|
||||
} else {
|
||||
info!("Moved {} to {}", source.to_string_lossy(), dest.to_string_lossy());
|
||||
}
|
||||
} else {
|
||||
debug!("Skipped upgrading directory {:?}, Destination already exists at {:?}", source, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn upgrade_user_defaults(dirs: &DatabaseDirectories) {
|
||||
let source = dirs.legacy_user_defaults_path();
|
||||
let dest = dirs.user_defaults_path();
|
||||
if file_exists(&source) {
|
||||
if !file_exists(&dest) {
|
||||
if let Err(e) = fs::rename(&source, &dest) {
|
||||
debug!("Skipped upgrading user defaults {:?}:{:?}", dest, e);
|
||||
}
|
||||
} else {
|
||||
debug!("Skipped upgrading user defaults {:?}, File exists at {:?}", source, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn upgrade_data_paths(dirs: &DatabaseDirectories, pruning: Algorithm) {
|
||||
let legacy_root_path = replace_home("", "$HOME/.parity");
|
||||
let default_path = default_data_path();
|
||||
if legacy_root_path != dirs.path && dirs.path == default_path {
|
||||
upgrade_dir_location(&PathBuf::from(legacy_root_path), &PathBuf::from(&dirs.path));
|
||||
}
|
||||
upgrade_dir_location(&dirs.legacy_version_path(pruning), &dirs.db_path(pruning));
|
||||
upgrade_dir_location(&dirs.legacy_snapshot_path(), &dirs.snapshot_path());
|
||||
upgrade_dir_location(&dirs.legacy_network_path(), &dirs.network_path());
|
||||
upgrade_user_defaults(&dirs);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user