for PresaleWallet {
+ fn from(wallet: json::PresaleWallet) -> Self {
+ let mut iv = [0u8; 16];
+ iv.copy_from_slice(&wallet.encseed[..16]);
+
+ let mut ciphertext = [0u8; 80];
+ ciphertext.copy_from_slice(&wallet.encseed[16..]);
+
+ PresaleWallet {
+ iv: iv,
+ ciphertext: ciphertext,
+ address: Address::from(wallet.address),
+ }
+ }
+}
+
+impl PresaleWallet {
+ pub fn open(path: P) -> Result where P: AsRef {
+ let file = try!(fs::File::open(path));
+ let presale = json::PresaleWallet::load(file).unwrap();
+ Ok(PresaleWallet::from(presale))
+ }
+
+ pub fn decrypt(&self, password: &str) -> Result {
+ let mut h_mac = Hmac::new(Sha256::new(), password.as_bytes());
+ let mut derived_key = vec![0u8; 16];
+ pbkdf2(&mut h_mac, password.as_bytes(), 2000, &mut derived_key);
+
+ let mut key = [0u8; 64];
+ try!(crypto::aes::decrypt_cbc(&derived_key, &self.iv, &self.ciphertext, &mut key).map_err(|_| Error::InvalidPassword));
+
+ let secret = Secret::from(key.keccak256());
+ if let Ok(kp) = KeyPair::from_secret(secret) {
+ if kp.address() == self.address {
+ return Ok(kp)
+ }
+ }
+
+ Err(Error::InvalidPassword)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::PresaleWallet;
+ use json;
+
+ #[test]
+ fn test() {
+ let json = r#"
+ {
+ "encseed": "137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066",
+ "ethaddr": "ede84640d1a1d3e06902048e67aa7db8d52c2ce1",
+ "email": "123@gmail.com",
+ "btcaddr": "1JvqEc6WLhg6GnyrLBe2ztPAU28KRfuseH"
+ } "#;
+
+ let wallet = json::PresaleWallet::load(json.as_bytes()).unwrap();
+ let wallet = PresaleWallet::from(wallet);
+ assert!(wallet.decrypt("123").is_ok());
+ assert!(wallet.decrypt("124").is_err());
+ }
+}
diff --git a/ethstore/src/random.rs b/ethstore/src/random.rs
index 2693d4fcf..e0a7f52c7 100644
--- a/ethstore/src/random.rs
+++ b/ethstore/src/random.rs
@@ -1,3 +1,19 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity 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 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. If not, see .
+
use rand::{Rng, OsRng};
pub trait Random {
diff --git a/ethstore/src/secret_store.rs b/ethstore/src/secret_store.rs
index 620b8d9b9..5dab50ba7 100644
--- a/ethstore/src/secret_store.rs
+++ b/ethstore/src/secret_store.rs
@@ -1,3 +1,19 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity 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 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. If not, see .
+
use ethkey::{Address, Message, Signature, Secret};
use Error;
diff --git a/ethstore/tests/api.rs b/ethstore/tests/api.rs
index a29b143db..3b6a9f784 100644
--- a/ethstore/tests/api.rs
+++ b/ethstore/tests/api.rs
@@ -1,10 +1,28 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity 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 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. If not, see .
+
extern crate rand;
extern crate ethstore;
mod util;
+use std::str::FromStr;
use ethstore::{SecretStore, EthStore};
-use ethstore::ethkey::{Random, Generator, Secret};
+use ethstore::ethkey::{Random, Generator, Secret, Address};
+use ethstore::dir::DiskDirectory;
use util::TransientDir;
#[test]
@@ -70,3 +88,40 @@ fn secret_store_remove_account() {
assert_eq!(store.accounts().len(), 0);
assert!(store.remove_account(&accounts[0], "").is_err());
}
+
+fn test_path() -> &'static str {
+ match ::std::fs::metadata("ethstore") {
+ Ok(_) => "ethstore/tests/res/geth_keystore",
+ Err(_) => "tests/res/geth_keystore",
+ }
+}
+
+fn pat_path() -> &'static str {
+ match ::std::fs::metadata("ethstore") {
+ Ok(_) => "ethstore/tests/res/pat",
+ Err(_) => "tests/res/pat",
+ }
+}
+
+#[test]
+fn secret_store_laod_geth_files() {
+ let dir = DiskDirectory::at(test_path());
+ let store = EthStore::open(Box::new(dir)).unwrap();
+ assert_eq!(store.accounts(), vec![
+ Address::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap(),
+ Address::from_str("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf").unwrap(),
+ Address::from_str("63121b431a52f8043c16fcf0d1df9cb7b5f66649").unwrap(),
+ ]);
+}
+
+#[test]
+fn secret_store_load_pat_files() {
+ let dir = DiskDirectory::at(pat_path());
+ let store = EthStore::open(Box::new(dir)).unwrap();
+ assert_eq!(store.accounts(), vec![
+ Address::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap(),
+ Address::from_str("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf").unwrap(),
+ ]);
+}
+
+
diff --git a/ethstore/tests/cli.rs b/ethstore/tests/cli.rs
index e69de29bb..d4ebdc448 100644
--- a/ethstore/tests/cli.rs
+++ b/ethstore/tests/cli.rs
@@ -0,0 +1,16 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity 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 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. If not, see .
+
diff --git a/util/res/geth_keystore/UTC--2016-02-17T09-20-45.721400158Z--3f49624084b67849c7b4e805c5988c21a430f9d9 b/ethstore/tests/res/geth_keystore/UTC--2016-02-17T09-20-45.721400158Z--3f49624084b67849c7b4e805c5988c21a430f9d9
similarity index 100%
rename from util/res/geth_keystore/UTC--2016-02-17T09-20-45.721400158Z--3f49624084b67849c7b4e805c5988c21a430f9d9
rename to ethstore/tests/res/geth_keystore/UTC--2016-02-17T09-20-45.721400158Z--3f49624084b67849c7b4e805c5988c21a430f9d9
diff --git a/util/res/geth_keystore/UTC--2016-02-20T09-33-03.984382741Z--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf b/ethstore/tests/res/geth_keystore/UTC--2016-02-20T09-33-03.984382741Z--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf
similarity index 100%
rename from util/res/geth_keystore/UTC--2016-02-20T09-33-03.984382741Z--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf
rename to ethstore/tests/res/geth_keystore/UTC--2016-02-20T09-33-03.984382741Z--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf
diff --git a/util/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649 b/ethstore/tests/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649
similarity index 91%
rename from util/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649
rename to ethstore/tests/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649
index 08272d43b..a3253e29a 100644
--- a/util/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649
+++ b/ethstore/tests/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649
@@ -1 +1 @@
-{"address":"63121b431a52f8043c16fcf0d1df9cb7b5f66649","crypto":{"cipher":"aes-128-ctr","ciphertext":"1dd21926c644b9983916d646f3a4f2c7f9362f7e1c9fb1abcb42494dae06fa01","cipherparams":{"iv":"c52c6ee66d89a7aa8c6839f4b6ed29c8"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"96f17c17bbf48db2dc4da00b3e7decce8e21f44a5d7963dadeeff70e1d38ad75"},"mac":"f279f3444585c2817701225e2196c1176386ad549ebaec2bcc4f94f309727fe6"},"id":"15e49cd2-51fb-4316-ba46-c3cf8db4ae44","version":3}
\ No newline at end of file
+{"address":"63121b431a52f8043c16fcf0d1df9cb7b5f66649","crypto":{"cipher":"aes-128-ctr","ciphertext":"1dd21926c644b9983916d646f3a4f2c7f9362f7e1c9fb1abcb42494dae06fa01","cipherparams":{"iv":"c52c6ee66d89a7aa8c6839f4b6ed29c8"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"96f17c17bbf48db2dc4da00b3e7decce8e21f44a5d7963dadeeff70e1d38ad75"},"mac":"f279f3444585c2817701225e2196c1176386ad549ebaec2bcc4f94f309727fe6"},"id":"15e49cd2-51fb-4316-ba46-c3cf8db4ae44","version":3}
diff --git a/util/res/pat/p1.json b/ethstore/tests/res/pat/p1.json
similarity index 100%
rename from util/res/pat/p1.json
rename to ethstore/tests/res/pat/p1.json
diff --git a/util/res/pat/p2.json b/ethstore/tests/res/pat/p2.json
similarity index 100%
rename from util/res/pat/p2.json
rename to ethstore/tests/res/pat/p2.json
diff --git a/ethstore/tests/util/mod.rs b/ethstore/tests/util/mod.rs
index 03bdb8af1..73c47ee61 100644
--- a/ethstore/tests/util/mod.rs
+++ b/ethstore/tests/util/mod.rs
@@ -1,3 +1,19 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity 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 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. If not, see .
+
mod transient_dir;
pub use self::transient_dir::TransientDir;
diff --git a/ethstore/tests/util/transient_dir.rs b/ethstore/tests/util/transient_dir.rs
index b29a5d775..f4998e124 100644
--- a/ethstore/tests/util/transient_dir.rs
+++ b/ethstore/tests/util/transient_dir.rs
@@ -1,3 +1,19 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity 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 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. If not, see .
+
use std::path::PathBuf;
use std::{env, fs};
use rand::{Rng, OsRng};
diff --git a/hook.sh b/hook.sh
index adb763f9d..9ce825f80 100755
--- a/hook.sh
+++ b/hook.sh
@@ -7,6 +7,6 @@ echo "set -e" >> $FILE
echo "cargo build --features dev" >> $FILE
# Build tests
echo "cargo test --no-run --features dev \\" >> $FILE
-echo " -p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethcore-dapps -p ethcore-signer" >> $FILE
+echo " -p ethkey -p ethstore -p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethcore-dapps -p ethcore-signer" >> $FILE
echo "" >> $FILE
chmod +x $FILE
diff --git a/json/Cargo.toml b/json/Cargo.toml
index a2a560c43..e93f493e1 100644
--- a/json/Cargo.toml
+++ b/json/Cargo.toml
@@ -10,7 +10,7 @@ rustc-serialize = "0.3"
serde = "0.7.0"
serde_json = "0.7.0"
serde_macros = { version = "0.7.0", optional = true }
-clippy = { version = "0.0.76", optional = true}
+clippy = { version = "0.0.77", optional = true}
[build-dependencies]
serde_codegen = { version = "0.7.0", optional = true }
diff --git a/json/src/spec/engine.rs b/json/src/spec/engine.rs
index e877e37a8..9659d8af7 100644
--- a/json/src/spec/engine.rs
+++ b/json/src/spec/engine.rs
@@ -53,7 +53,8 @@ mod tests {
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
- "frontierCompatibilityModeLimit" : "0x"
+ "frontierCompatibilityModeLimit" : "0x",
+ "daoRescueSoftFork": true
}
}
}"#;
diff --git a/json/src/spec/ethash.rs b/json/src/spec/ethash.rs
index 254ffff9b..5cb7475f2 100644
--- a/json/src/spec/ethash.rs
+++ b/json/src/spec/ethash.rs
@@ -42,6 +42,9 @@ pub struct EthashParams {
/// Homestead transition block number.
#[serde(rename="frontierCompatibilityModeLimit")]
pub frontier_compatibility_mode_limit: Uint,
+ /// DAO rescue soft-fork?
+ #[serde(rename="daoRescueSoftFork")]
+ pub dao_rescue_soft_fork: bool,
}
/// Ethash engine deserialization.
@@ -65,8 +68,9 @@ mod tests {
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
- "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
- "frontierCompatibilityModeLimit" : "0x42"
+ "registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
+ "frontierCompatibilityModeLimit": "0x42",
+ "daoRescueSoftFork": true
}
}"#;
diff --git a/json/src/spec/spec.rs b/json/src/spec/spec.rs
index fbb206c40..08724ca56 100644
--- a/json/src/spec/spec.rs
+++ b/json/src/spec/spec.rs
@@ -63,7 +63,8 @@ mod tests {
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
- "frontierCompatibilityModeLimit" : "0x"
+ "frontierCompatibilityModeLimit" : "0x",
+ "daoRescueSoftFork": false
}
}
},
diff --git a/parity/cli.rs b/parity/cli.rs
index 38af6af4c..cc68a8d4d 100644
--- a/parity/cli.rs
+++ b/parity/cli.rs
@@ -25,6 +25,7 @@ Usage:
parity daemon [options]
parity account (new | list ) [options]
parity account import ... [options]
+ parity wallet import --password FILE [options]
parity import [ ] [options]
parity export [ ] [options]
parity signer new-token [options]
@@ -42,6 +43,14 @@ Protocol Options:
[default: $HOME/.parity/keys].
--identity NAME Specify your node's name.
+DAO-Rescue Soft-fork Options:
+ --help-rescue-dao Does nothing - on by default.
+ --dont-help-rescue-dao Votes against the DAO-rescue soft-fork, but supports
+ it if it is triggered anyway.
+ Equivalent to --gas-floor-target=3141592.
+ --dogmatic Ignores all DAO-rescue soft-fork behaviour. Even if
+ it means losing mining rewards.
+
Account Options:
--unlock ACCOUNTS Unlock ACCOUNTS for the duration of the execution.
ACCOUNTS is a comma-delimited list of addresses.
@@ -67,9 +76,13 @@ Networking Options:
--no-discovery Disable new peer discovery.
--node-key KEY Specify node secret key, either as 64-character hex
string or input to SHA3 operation.
+ --reserved-peers FILE Provide a file containing enodes, one per line.
+ These nodes will always have a reserved slot on top
+ of the normal maximum peers.
+ --reserved-only Connect only to reserved nodes.
API and Console Options:
- --jsonrpc-off Disable the JSON-RPC API server.
+ --no-jsonrpc Disable the JSON-RPC API server.
--jsonrpc-port PORT Specify the port portion of the JSONRPC API server
[default: 8545].
--jsonrpc-interface IP Specify the hostname portion of the JSONRPC API
@@ -82,13 +95,13 @@ API and Console Options:
ethcore, ethcore_set, traces.
[default: web3,eth,net,ethcore,personal,traces].
- --ipc-off Disable JSON-RPC over IPC service.
+ --no-ipc Disable JSON-RPC over IPC service.
--ipc-path PATH Specify custom path for JSON-RPC over IPC service
[default: $HOME/.parity/jsonrpc.ipc].
--ipc-apis APIS Specify custom API set available via JSON-RPC over
- IPC [default: web3,eth,net,ethcore,personal,traces].
+ IPC [default: web3,eth,net,ethcore,personal,traces,rpc].
- --dapps-off Disable the Dapps server (e.g. status page).
+ --no-dapps Disable the Dapps server (e.g. status page).
--dapps-port PORT Specify the port portion of the Dapps server
[default: 8080].
--dapps-interface IP Specify the hostname portion of the Dapps
@@ -109,6 +122,8 @@ API and Console Options:
[default: 8180].
--signer-path PATH Specify directory where Signer UIs tokens should
be stored. [default: $HOME/.parity/signer]
+ --no-token By default a new system UI security token will be
+ output on start up. This will prevent it.
Sealing/Mining Options:
--force-sealing Force the node to author new blocks as if it were
@@ -145,7 +160,7 @@ Footprint Options:
light - early merges with partial tracking. Fast,
light, and experimental!
auto - use the method most recently synced or
- default to archive if none synced [default: auto].
+ default to fast if none synced [default: auto].
--cache-pref-size BYTES Specify the prefered size of the blockchain cache in
bytes [default: 16384].
--cache-max-size BYTES Specify the maximum size of the blockchain cache in
@@ -155,6 +170,7 @@ Footprint Options:
--cache MEGABYTES Set total amount of discretionary memory to use for
the entire system, overrides other cache and queue
options.
+ --db-cache-size MB Database cache size.
Import/Export Options:
--from BLOCK Export from block BLOCK, which may be an index or
@@ -181,13 +197,16 @@ Legacy Options:
--nodekey KEY Equivalent to --node-key KEY.
--nodiscover Equivalent to --no-discovery.
-j --jsonrpc Does nothing; JSON-RPC is on by default now.
+ --jsonrpc-off Equivalent to --no-jsonrpc.
-w --webapp Does nothing; dapps server is on by default now.
+ --dapps-off Equivalent to --no-dapps.
--rpc Does nothing; JSON-RPC is on by default now.
--rpcaddr IP Equivalent to --jsonrpc-interface IP.
--rpcport PORT Equivalent to --jsonrpc-port PORT.
--rpcapi APIS Equivalent to --jsonrpc-apis APIS.
--rpccorsdomain URL Equivalent to --jsonrpc-cors URL.
- --ipcdisable Equivalent to --ipc-off.
+ --ipcdisable Equivalent to --no-ipc.
+ --ipc-off Equivalent to --no-ipc.
--ipcapi APIS Equivalent to --ipc-apis APIS.
--ipcpath PATH Equivalent to --ipc-path PATH.
--gasprice WEI Minimum amount of Wei per GAS to be paid for a
@@ -208,6 +227,7 @@ Miscellaneous Options:
pub struct Args {
pub cmd_daemon: bool,
pub cmd_account: bool,
+ pub cmd_wallet: bool,
pub cmd_new: bool,
pub cmd_list: bool,
pub cmd_export: bool,
@@ -221,6 +241,8 @@ pub struct Args {
pub flag_chain: String,
pub flag_db_path: String,
pub flag_identity: String,
+ pub flag_dont_help_rescue_dao: bool,
+ pub flag_dogmatic: bool,
pub flag_unlock: Option,
pub flag_password: Vec,
pub flag_cache: Option,
@@ -236,18 +258,20 @@ pub struct Args {
pub flag_no_discovery: bool,
pub flag_nat: String,
pub flag_node_key: Option,
+ pub flag_reserved_peers: Option,
+ pub flag_reserved_only: bool,
pub flag_cache_pref_size: usize,
pub flag_cache_max_size: usize,
pub flag_queue_max_size: usize,
- pub flag_jsonrpc_off: bool,
+ pub flag_no_jsonrpc: bool,
pub flag_jsonrpc_interface: String,
pub flag_jsonrpc_port: u16,
pub flag_jsonrpc_cors: Option,
pub flag_jsonrpc_apis: String,
- pub flag_ipc_off: bool,
+ pub flag_no_ipc: bool,
pub flag_ipc_path: String,
pub flag_ipc_apis: String,
- pub flag_dapps_off: bool,
+ pub flag_no_dapps: bool,
pub flag_dapps_port: u16,
pub flag_dapps_interface: String,
pub flag_dapps_user: Option,
@@ -256,6 +280,7 @@ pub struct Args {
pub flag_signer: bool,
pub flag_signer_port: u16,
pub flag_signer_path: String,
+ pub flag_no_token: bool,
pub flag_force_sealing: bool,
pub flag_author: String,
pub flag_usd_per_tx: String,
@@ -290,8 +315,12 @@ pub struct Args {
pub flag_testnet: bool,
pub flag_networkid: Option,
pub flag_ipcdisable: bool,
+ pub flag_ipc_off: bool,
+ pub flag_jsonrpc_off: bool,
+ pub flag_dapps_off: bool,
pub flag_ipcpath: Option,
pub flag_ipcapi: Option,
+ pub flag_db_cache_size: Option,
}
pub fn print_version() {
diff --git a/parity/configuration.rs b/parity/configuration.rs
index 7c42f06e1..4560324d3 100644
--- a/parity/configuration.rs
+++ b/parity/configuration.rs
@@ -75,12 +75,18 @@ impl Configuration {
}
pub fn gas_floor_target(&self) -> U256 {
- let d = &self.args.flag_gas_floor_target;
- U256::from_dec_str(d).unwrap_or_else(|_| {
- die!("{}: Invalid target gas floor given. Must be a decimal unsigned 256-bit number.", d)
- })
+ if self.args.flag_dont_help_rescue_dao || self.args.flag_dogmatic {
+ 4_700_000.into()
+ } else {
+ let d = &self.args.flag_gas_floor_target;
+ U256::from_dec_str(d).unwrap_or_else(|_| {
+ die!("{}: Invalid target gas floor given. Must be a decimal unsigned 256-bit number.", d)
+ })
+ }
}
+
+
pub fn gas_price(&self) -> U256 {
match self.args.flag_gasprice.as_ref() {
Some(d) => {
@@ -115,16 +121,20 @@ impl Configuration {
}
pub fn extra_data(&self) -> Bytes {
- match self.args.flag_extradata.as_ref().or(self.args.flag_extra_data.as_ref()) {
- Some(ref x) if x.len() <= 32 => x.as_bytes().to_owned(),
- None => version_data(),
- Some(ref x) => { die!("{}: Extra data must be at most 32 characters.", x); }
+ if !self.args.flag_dont_help_rescue_dao {
+ (b"rescuedao"[..]).to_owned()
+ } else {
+ match self.args.flag_extradata.as_ref().or(self.args.flag_extra_data.as_ref()) {
+ Some(ref x) if x.len() <= 32 => x.as_bytes().to_owned(),
+ None => version_data(),
+ Some(ref x) => { die!("{}: Extra data must be at most 32 characters.", x); }
+ }
}
}
pub fn spec(&self) -> Spec {
match self.chain().as_str() {
- "frontier" | "homestead" | "mainnet" => ethereum::new_frontier(),
+ "frontier" | "homestead" | "mainnet" => ethereum::new_frontier(!self.args.flag_dogmatic),
"morden" | "testnet" => ethereum::new_morden(),
"olympic" => ethereum::new_olympic(),
f => Spec::load(contents(f).unwrap_or_else(|_| {
@@ -153,6 +163,25 @@ impl Configuration {
}
}
+ pub fn init_reserved_nodes(&self) -> Vec {
+ use std::fs::File;
+
+ if let Some(ref path) = self.args.flag_reserved_peers {
+ let mut buffer = String::new();
+ let mut node_file = File::open(path).unwrap_or_else(|e| {
+ die!("Error opening reserved nodes file: {}", e);
+ });
+ node_file.read_to_string(&mut buffer).expect("Error reading reserved node file");
+ buffer.lines().map(|s| {
+ Self::normalize_enode(s).unwrap_or_else(|| {
+ die!("{}: Invalid node address format given for a reserved node.", s);
+ })
+ }).collect()
+ } else {
+ Vec::new()
+ }
+ }
+
pub fn net_addresses(&self) -> (Option, Option) {
let port = self.net_port();
let listen_address = Some(SocketAddr::new(IpAddr::from_str("0.0.0.0").unwrap(), port));
@@ -179,6 +208,11 @@ impl Configuration {
let mut net_path = PathBuf::from(&self.path());
net_path.push("network");
ret.config_path = Some(net_path.to_str().unwrap().to_owned());
+ ret.reserved_nodes = self.init_reserved_nodes();
+
+ if self.args.flag_reserved_only {
+ ret.non_reserved_mode = ::util::network::NonReservedPeerMode::Deny;
+ }
ret
}
@@ -187,7 +221,7 @@ impl Configuration {
let mut latest_era = None;
let jdb_types = [journaldb::Algorithm::Archive, journaldb::Algorithm::EarlyMerge, journaldb::Algorithm::OverlayRecent, journaldb::Algorithm::RefCounted];
for i in jdb_types.into_iter() {
- let db = journaldb::new(&append_path(&get_db_path(Path::new(&self.path()), *i, spec.genesis_header().hash()), "state"), *i);
+ let db = journaldb::new(&append_path(&get_db_path(Path::new(&self.path()), *i, spec.genesis_header().hash()), "state"), *i, None);
trace!(target: "parity", "Looking for best DB: {} at {:?}", i, db.latest_era());
match (latest_era, db.latest_era()) {
(Some(best), Some(this)) if best >= this => {}
@@ -214,6 +248,8 @@ impl Configuration {
client_config.blockchain.max_cache_size = self.args.flag_cache_max_size;
}
}
+ // forced blockchain (blocks + extras) db cache size if provided
+ client_config.blockchain.db_cache_size = self.args.flag_db_cache_size.and_then(|cs| Some(cs / 2));
client_config.tracing.enabled = match self.args.flag_tracing.as_str() {
"auto" => Switch::Auto,
@@ -221,16 +257,21 @@ impl Configuration {
"off" => Switch::Off,
_ => { die!("Invalid tracing method given!") }
};
+ // forced trace db cache size if provided
+ client_config.tracing.db_cache_size = self.args.flag_db_cache_size.and_then(|cs| Some(cs / 4));
client_config.pruning = match self.args.flag_pruning.as_str() {
"archive" => journaldb::Algorithm::Archive,
"light" => journaldb::Algorithm::EarlyMerge,
"fast" => journaldb::Algorithm::OverlayRecent,
"basic" => journaldb::Algorithm::RefCounted,
- "auto" => self.find_best_db(spec).unwrap_or(journaldb::Algorithm::Archive),
+ "auto" => self.find_best_db(spec).unwrap_or(journaldb::Algorithm::OverlayRecent),
_ => { die!("Invalid pruning method given."); }
};
+ // forced state db cache size if provided
+ client_config.db_cache_size = self.args.flag_db_cache_size.and_then(|cs| Some(cs / 4));
+
if self.args.flag_jitvm {
client_config.vm_type = VMType::jit().unwrap_or_else(|| die!("Parity built without jit vm."))
}
@@ -263,16 +304,16 @@ impl Configuration {
}).collect::>();
if !self.args.flag_no_import_keys {
- let dir_type = match self.args.flag_testnet {
- true => DirectoryType::Testnet,
- false => DirectoryType::Main,
+ let dir_type = if self.args.flag_testnet {
+ DirectoryType::Testnet
+ } else {
+ DirectoryType::Main
};
let from = GethDirectory::open(dir_type);
let to = DiskDirectory::create(self.keys_path()).unwrap();
- if let Err(e) = import_accounts(&from, &to) {
- warn!("Could not import accounts {}", e);
- }
+ // ignore error, cause geth may not exist
+ let _ = import_accounts(&from, &to);
}
let dir = Box::new(DiskDirectory::create(self.keys_path()).unwrap());
@@ -318,7 +359,7 @@ impl Configuration {
pub fn ipc_settings(&self) -> IpcConfiguration {
IpcConfiguration {
- enabled: !(self.args.flag_ipcdisable || self.args.flag_ipc_off),
+ enabled: !(self.args.flag_ipcdisable || self.args.flag_ipc_off || self.args.flag_no_ipc),
socket_addr: self.ipc_path(),
apis: self.args.flag_ipcapi.clone().unwrap_or(self.args.flag_ipc_apis.clone()),
}
@@ -331,7 +372,7 @@ impl Configuration {
chain: self.chain(),
max_peers: self.max_peers(),
network_port: self.net_port(),
- rpc_enabled: !self.args.flag_jsonrpc_off,
+ rpc_enabled: !self.args.flag_jsonrpc_off && !self.args.flag_no_jsonrpc,
rpc_interface: self.args.flag_rpcaddr.clone().unwrap_or(self.args.flag_jsonrpc_interface.clone()),
rpc_port: self.args.flag_rpcport.unwrap_or(self.args.flag_jsonrpc_port),
}
@@ -391,10 +432,10 @@ impl Configuration {
}
pub fn signer_port(&self) -> Option {
- if self.args.flag_signer {
- Some(self.args.flag_signer_port)
- } else {
+ if !self.args.flag_signer {
None
+ } else {
+ Some(self.args.flag_signer_port)
}
}
}
diff --git a/parity/io_handler.rs b/parity/io_handler.rs
index ee6d6130f..3f0c04fbd 100644
--- a/parity/io_handler.rs
+++ b/parity/io_handler.rs
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
-use std::sync::Arc;
+use std::sync::{Arc, Weak};
use ethcore::client::Client;
use ethcore::service::{NetSyncMessage, SyncMessage};
use ethsync::EthSync;
@@ -30,7 +30,7 @@ pub struct ClientIoHandler {
pub sync: Arc,
pub accounts: Arc,
pub info: Informant,
- pub network: Arc>,
+ pub network: Weak>,
}
impl IoHandler for ClientIoHandler {
@@ -39,9 +39,8 @@ impl IoHandler for ClientIoHandler {
}
fn timeout(&self, _io: &IoContext, timer: TimerToken) {
- match timer {
- INFO_TIMER => { self.info.tick(&self.client, Some(&self.sync)); }
- _ => {}
+ if let INFO_TIMER = timer {
+ self.info.tick(&self.client, Some(&self.sync));
}
}
@@ -49,12 +48,16 @@ impl IoHandler for ClientIoHandler {
match *message {
NetworkIoMessage::User(SyncMessage::StartNetwork) => {
info!("Starting network");
- self.network.start().unwrap_or_else(|e| warn!("Error starting network: {:?}", e));
- EthSync::register(&*self.network, self.sync.clone()).unwrap_or_else(|e| warn!("Error registering eth protocol handler: {}", e));
+ if let Some(network) = self.network.upgrade() {
+ network.start().unwrap_or_else(|e| warn!("Error starting network: {:?}", e));
+ EthSync::register(&*network, self.sync.clone()).unwrap_or_else(|e| warn!("Error registering eth protocol handler: {}", e));
+ }
},
NetworkIoMessage::User(SyncMessage::StopNetwork) => {
info!("Stopping network");
- self.network.stop().unwrap_or_else(|e| warn!("Error stopping network: {:?}", e));
+ if let Some(network) = self.network.upgrade() {
+ network.stop().unwrap_or_else(|e| warn!("Error stopping network: {:?}", e));
+ }
},
_ => {/* Ignore other messages */},
}
diff --git a/parity/main.rs b/parity/main.rs
index e0465c1c6..81d829d24 100644
--- a/parity/main.rs
+++ b/parity/main.rs
@@ -129,6 +129,11 @@ fn execute(conf: Configuration) {
return;
}
+ if conf.args.cmd_wallet {
+ execute_wallet_cli(conf);
+ return;
+ }
+
if conf.args.cmd_export {
execute_export(conf);
return;
@@ -186,6 +191,19 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
let net_settings = conf.net_settings(&spec);
let sync_config = conf.sync_config(&spec);
+ // Create and display a new token for UIs.
+ if conf.args.flag_signer && !conf.args.flag_no_token {
+ new_token(conf.directories().signer).unwrap_or_else(|e| {
+ die!("Error generating token: {:?}", e)
+ });
+ }
+
+ // Display warning about using unlock with signer
+ if conf.args.flag_signer && conf.args.flag_unlock.is_some() {
+ warn!("Using Trusted Signer and --unlock is not recommended!");
+ warn!("NOTE that Signer will not ask you to confirm transactions from unlocked account.");
+ }
+
// Secret Store
let account_service = Arc::new(conf.account_service());
@@ -223,6 +241,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
logger: logger.clone(),
settings: network_settings.clone(),
allow_pending_receipt_query: !conf.args.flag_geth,
+ net_service: service.network(),
});
let dependencies = rpc::Dependencies {
@@ -245,7 +264,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
if conf.args.flag_webapp { println!("WARNING: Flag -w/--webapp is deprecated. Dapps server is now on by default. Ignoring."); }
let dapps_server = dapps::new(dapps::Configuration {
- enabled: !conf.args.flag_dapps_off,
+ enabled: !conf.args.flag_dapps_off && !conf.args.flag_no_dapps,
interface: conf.args.flag_dapps_interface.clone(),
port: conf.args.flag_dapps_port,
user: conf.args.flag_dapps_user.clone(),
@@ -272,7 +291,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
info: Informant::new(conf.have_color()),
sync: sync.clone(),
accounts: account_service.clone(),
- network: service.network(),
+ network: Arc::downgrade(&service.network()),
});
service.register_io_handler(io_handler).expect("Error registering IO handler");
@@ -308,10 +327,11 @@ fn execute_export(conf: Configuration) {
udp_port: None,
nat_enabled: false,
discovery_enabled: false,
- pin: true,
boot_nodes: Vec::new(),
use_secret: None,
ideal_peers: 0,
+ reserved_nodes: Vec::new(),
+ non_reserved_mode: ::util::network::NonReservedPeerMode::Accept,
};
let client_config = conf.client_config(&spec);
@@ -379,10 +399,11 @@ fn execute_import(conf: Configuration) {
udp_port: None,
nat_enabled: false,
discovery_enabled: false,
- pin: true,
boot_nodes: Vec::new(),
use_secret: None,
ideal_peers: 0,
+ reserved_nodes: Vec::new(),
+ non_reserved_mode: ::util::network::NonReservedPeerMode::Accept,
};
let client_config = conf.client_config(&spec);
@@ -478,7 +499,7 @@ fn execute_signer(conf: Configuration) {
}
fn execute_account_cli(conf: Configuration) {
- use ethcore::ethstore::{SecretStore, EthStore, import_accounts};
+ use ethcore::ethstore::{EthStore, import_accounts};
use ethcore::ethstore::dir::DiskDirectory;
use ethcore::account_provider::AccountProvider;
use rpassword::read_password;
@@ -524,6 +545,30 @@ fn execute_account_cli(conf: Configuration) {
}
}
+fn execute_wallet_cli(conf: Configuration) {
+ use ethcore::ethstore::{PresaleWallet, EthStore};
+ use ethcore::ethstore::dir::DiskDirectory;
+ use ethcore::account_provider::AccountProvider;
+
+ let wallet_path = conf.args.arg_path.first().unwrap();
+ let filename = conf.args.flag_password.first().unwrap();
+ let mut file = File::open(filename).unwrap_or_else(|_| die!("{} Unable to read password file.", filename));
+ let mut file_content = String::new();
+ file.read_to_string(&mut file_content).unwrap_or_else(|_| die!("{} Unable to read password file.", filename));
+
+ let dir = Box::new(DiskDirectory::create(conf.keys_path()).unwrap());
+ let iterations = conf.keys_iterations();
+ let store = AccountProvider::new(Box::new(EthStore::open_with_iterations(dir, iterations).unwrap()));
+
+ // remove eof
+ let pass = &file_content[..file_content.len() - 1];
+ let wallet = PresaleWallet::open(wallet_path).unwrap_or_else(|_| die!("Unable to open presale wallet."));
+ let kp = wallet.decrypt(pass).unwrap_or_else(|_| die!("Invalid password"));
+ let address = store.insert_account(kp.secret().clone(), pass).unwrap();
+
+ println!("Imported account: {}", address);
+}
+
fn wait_for_exit(
panic_handler: Arc,
_rpc_server: Option,
diff --git a/parity/migration.rs b/parity/migration.rs
index acfd32ffd..4198f7ed0 100644
--- a/parity/migration.rs
+++ b/parity/migration.rs
@@ -89,6 +89,7 @@ fn current_version(path: &PathBuf) -> Result {
/// Writes current database version to the file.
/// Creates a new file if the version file does not exist yet.
fn update_version(path: &PathBuf) -> Result<(), Error> {
+ try!(fs::create_dir_all(path));
let mut file = try!(File::create(version_file_path(path)));
try!(file.write_all(format!("{}", CURRENT_VERSION).as_bytes()));
Ok(())
@@ -151,8 +152,6 @@ fn migrate_database(version: u32, path: PathBuf, migrations: MigrationManager) -
return Ok(())
}
- println!("Migrating database {} from version {} to {}", path.to_string_lossy(), version, CURRENT_VERSION);
-
let temp_path = temp_database_path(&path);
let backup_path = backup_database_path(&path);
// remote the dir if it exists
@@ -163,6 +162,7 @@ fn migrate_database(version: u32, path: PathBuf, migrations: MigrationManager) -
let db_config = DatabaseConfig {
prefix_size: None,
max_open_files: 64,
+ cache_size: None,
};
// open old database
@@ -187,20 +187,26 @@ fn migrate_database(version: u32, path: PathBuf, migrations: MigrationManager) -
// remove backup
try!(fs::remove_dir_all(&backup_path));
- println!("Migration finished");
Ok(())
}
+fn exists(path: &PathBuf) -> bool {
+ fs::metadata(path).is_ok()
+}
+
/// Migrates the database.
pub fn migrate(path: &PathBuf) -> Result<(), Error> {
// read version file.
let version = try!(current_version(path));
// migrate the databases.
- if version != CURRENT_VERSION {
+ // main db directory may already exists, so let's check if we have blocks dir
+ if version != CURRENT_VERSION && exists(&blocks_database_path(path)) {
+ println!("Migrating database from version {} to {}", version, CURRENT_VERSION);
try!(migrate_database(version, blocks_database_path(path), try!(blocks_database_migrations())));
try!(migrate_database(version, extras_database_path(path), try!(extras_database_migrations())));
+ println!("Migration finished");
}
// update version file.
diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs
index bf21181a1..c0daaa926 100644
--- a/parity/rpc_apis.rs
+++ b/parity/rpc_apis.rs
@@ -25,6 +25,7 @@ use ethcore::client::Client;
use util::RotatingLogger;
use ethcore::account_provider::AccountProvider;
use util::network_settings::NetworkSettings;
+use util::network::NetworkService;
#[cfg(feature="rpc")]
pub use ethcore_rpc::ConfirmationsQueue;
@@ -89,6 +90,7 @@ pub struct Dependencies {
pub logger: Arc,
pub settings: Arc,
pub allow_pending_receipt_query: bool,
+ pub net_service: Arc