From a5299bdb1a19f5eb6cf0dc8745b5786165dfe52c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 6 Jun 2017 18:06:40 +0200 Subject: [PATCH 01/15] Unlocking with secrets. --- ethcore/src/account_provider/mod.rs | 51 ++++++++++++++++++++++------- ethstore/src/account/mod.rs | 1 + ethstore/src/ethstore.rs | 6 +++- ethstore/src/lib.rs | 3 ++ ethstore/src/secret_store.rs | 10 ++++++ parity/cli/mod.rs | 4 +++ parity/cli/usage.txt | 2 ++ parity/configuration.rs | 1 + parity/params.rs | 2 ++ parity/run.rs | 1 + 10 files changed, 69 insertions(+), 12 deletions(-) diff --git a/ethcore/src/account_provider/mod.rs b/ethcore/src/account_provider/mod.rs index 0ecbf3b17..5bb5f823e 100755 --- a/ethcore/src/account_provider/mod.rs +++ b/ethcore/src/account_provider/mod.rs @@ -26,7 +26,7 @@ use std::time::{Instant, Duration}; use util::{RwLock}; use ethstore::{ SimpleSecretStore, SecretStore, Error as SSError, EthStore, EthMultiStore, - random_string, SecretVaultRef, StoreAccountRef, + random_string, SecretVaultRef, StoreAccountRef, OpaqueSecret, }; use ethstore::dir::MemoryDirectory; use ethstore::ethkey::{Address, Message, Public, Secret, Random, Generator}; @@ -36,10 +36,10 @@ pub use ethstore::ethkey::Signature; pub use ethstore::{Derivation, IndexDerivation, KeyFile}; /// Type of unlock. -#[derive(Clone)] +#[derive(Clone, PartialEq)] enum Unlock { /// If account is unlocked temporarily, it should be locked after first usage. - Temp, + OneTime, /// Account unlocked permantently can always sign message. /// Use with caution. Perm, @@ -116,8 +116,13 @@ type AccountToken = String; /// Account management. /// Responsible for unlocking accounts. pub struct AccountProvider { + /// For performance reasons some methods can re-use unlocked secrets. + unlocked_secrets: RwLock>, + /// Unlocked account data. unlocked: RwLock>, + /// Address book. address_book: RwLock, + /// Dapps settings. dapps_settings: RwLock, /// Accounts on disk sstore: Box, @@ -125,6 +130,8 @@ pub struct AccountProvider { transient_sstore: EthMultiStore, /// Accounts in hardware wallets. hardware_store: Option, + /// When unlocking permanently on for some time store a raw secret instead of password. + fast_unlock: bool, } /// Account management settings. @@ -133,6 +140,8 @@ pub struct AccountProviderSettings { pub enable_hardware_wallets: bool, /// Use the classic chain key on the hardware wallet. pub hardware_wallet_classic_key: bool, + /// Use fast, but unsafe unlock + pub fast_unlock: bool, } impl Default for AccountProviderSettings { @@ -140,6 +149,7 @@ impl Default for AccountProviderSettings { AccountProviderSettings { enable_hardware_wallets: false, hardware_wallet_classic_key: false, + fast_unlock: true, } } } @@ -158,24 +168,28 @@ impl AccountProvider { } } AccountProvider { + unlocked_secrets: RwLock::new(HashMap::new()), unlocked: RwLock::new(HashMap::new()), address_book: RwLock::new(AddressBook::new(&sstore.local_path())), dapps_settings: RwLock::new(DappsSettingsStore::new(&sstore.local_path())), sstore: sstore, transient_sstore: transient_sstore(), hardware_store: hardware_store, + fast_unlock: settings.fast_unlock, } } /// Creates not disk backed provider. pub fn transient_provider() -> Self { AccountProvider { + unlocked_secrets: RwLock::new(HashMap::new()), unlocked: RwLock::new(HashMap::new()), address_book: RwLock::new(AddressBook::transient()), dapps_settings: RwLock::new(DappsSettingsStore::transient()), sstore: Box::new(EthStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")), transient_sstore: transient_sstore(), hardware_store: None, + fast_unlock: false, } } @@ -509,10 +523,7 @@ impl AccountProvider { /// Helper method used for unlocking accounts. fn unlock_account(&self, address: Address, password: String, unlock: Unlock) -> Result<(), Error> { - // verify password by signing dump message - // result may be discarded let account = self.sstore.account_ref(&address)?; - let _ = self.sstore.sign(&account, &password, &Default::default())?; // check if account is already unlocked pernamently, if it is, do nothing let mut unlocked = self.unlocked.write(); @@ -522,6 +533,16 @@ impl AccountProvider { } } + if self.fast_unlock && unlock != Unlock::OneTime { + // verify password and get the secret + let secret = self.sstore.raw_secret(&account, &password)?; + self.unlocked_secrets.write().insert(account.clone(), secret); + } else { + // verify password by signing dump message + // result may be discarded + let _ = self.sstore.sign(&account, &password, &Default::default())?; + } + let data = AccountData { unlock: unlock, password: password, @@ -534,7 +555,7 @@ impl AccountProvider { fn password(&self, account: &StoreAccountRef) -> Result { let mut unlocked = self.unlocked.write(); let data = unlocked.get(account).ok_or(SignError::NotUnlocked)?.clone(); - if let Unlock::Temp = data.unlock { + if let Unlock::OneTime = data.unlock { unlocked.remove(account).expect("data exists: so key must exist: qed"); } if let Unlock::Timed(ref end) = data.unlock { @@ -553,7 +574,7 @@ impl AccountProvider { /// Unlocks account temporarily (for one signing). pub fn unlock_account_temporarily(&self, account: Address, password: String) -> Result<(), Error> { - self.unlock_account(account, password, Unlock::Temp) + self.unlock_account(account, password, Unlock::OneTime) } /// Unlocks account temporarily with a timeout. @@ -564,16 +585,24 @@ impl AccountProvider { /// Checks if given account is unlocked pub fn is_unlocked(&self, address: Address) -> bool { let unlocked = self.unlocked.read(); + let unlocked_secrets = self.unlocked_secrets.read(); self.sstore.account_ref(&address) - .map(|r| unlocked.get(&r).is_some()) + .map(|r| unlocked.get(&r).is_some() || unlocked_secrets.get(&r).is_some()) .unwrap_or(false) } /// Signs the message. If password is not provided the account must be unlocked. pub fn sign(&self, address: Address, password: Option, message: Message) -> Result { let account = self.sstore.account_ref(&address)?; - let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?; - Ok(self.sstore.sign(&account, &password, &message)?) + match self.unlocked_secrets.read().get(&account) { + Some(secret) => { + Ok(self.sstore.sign_with_secret(&secret, &message)?) + }, + None => { + let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?; + Ok(self.sstore.sign(&account, &password, &message)?) + } + } } /// Signs message using the derived secret. If password is not provided the account must be unlocked. diff --git a/ethstore/src/account/mod.rs b/ethstore/src/account/mod.rs index 1ea19a265..c352ffe78 100755 --- a/ethstore/src/account/mod.rs +++ b/ethstore/src/account/mod.rs @@ -25,3 +25,4 @@ pub use self::crypto::Crypto; pub use self::kdf::{Kdf, Pbkdf2, Scrypt, Prf}; pub use self::safe_account::SafeAccount; pub use self::version::Version; + diff --git a/ethstore/src/ethstore.rs b/ethstore/src/ethstore.rs index 7c4ebfd95..246671990 100755 --- a/ethstore/src/ethstore.rs +++ b/ethstore/src/ethstore.rs @@ -26,7 +26,7 @@ use dir::{KeyDirectory, VaultKeyDirectory, VaultKey, SetKeyError}; use account::SafeAccount; use presale::PresaleWallet; use json::{self, Uuid, OpaqueKeyFile}; -use {import, Error, SimpleSecretStore, SecretStore, SecretVaultRef, StoreAccountRef, Derivation}; +use {import, Error, SimpleSecretStore, SecretStore, SecretVaultRef, StoreAccountRef, Derivation, OpaqueSecret}; /// Accounts store. pub struct EthStore { @@ -140,6 +140,10 @@ impl SimpleSecretStore for EthStore { } impl SecretStore for EthStore { + fn raw_secret(&self, account: &StoreAccountRef, password: &str) -> Result { + Ok(OpaqueSecret(self.get(account)?.crypto.secret(password)?)) + } + fn import_presale(&self, vault: SecretVaultRef, json: &[u8], password: &str) -> Result { let json_wallet = json::PresaleWallet::load(json).map_err(|_| Error::InvalidKeyFile("Invalid JSON format".to_owned()))?; let wallet = PresaleWallet::from(json_wallet); diff --git a/ethstore/src/lib.rs b/ethstore/src/lib.rs index 00a06a3e5..13ad4e013 100755 --- a/ethstore/src/lib.rs +++ b/ethstore/src/lib.rs @@ -66,3 +66,6 @@ pub use self::secret_store::{ }; pub use self::random::random_string; pub use self::parity_wordlist::random_phrase; + +/// A opaque wrapper for secret. +pub struct OpaqueSecret(::ethkey::Secret); diff --git a/ethstore/src/secret_store.rs b/ethstore/src/secret_store.rs index b292f0ef4..2deae023e 100755 --- a/ethstore/src/secret_store.rs +++ b/ethstore/src/secret_store.rs @@ -20,6 +20,7 @@ use ethkey::{Address, Message, Signature, Secret, Public}; use Error; use json::{Uuid, OpaqueKeyFile}; use bigint::hash::H256; +use OpaqueSecret; /// Key directory reference #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] @@ -88,6 +89,15 @@ pub trait SimpleSecretStore: Send + Sync { /// Secret Store API pub trait SecretStore: SimpleSecretStore { + + /// Returns a raw opaque Secret that can be later used to sign a message. + fn raw_secret(&self, account: &StoreAccountRef, password: &str) -> Result; + + /// Signs a message with raw secret. + fn sign_with_secret(&self, secret: &OpaqueSecret, message: &Message) -> Result { + Ok(::ethkey::sign(&secret.0, message)?) + } + /// Imports presale wallet fn import_presale(&self, vault: SecretVaultRef, json: &[u8], password: &str) -> Result; /// Imports existing JSON wallet diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index cd8f14add..59d3c9fc7 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -114,6 +114,8 @@ usage! { or |c: &Config| otry!(c.account).keys_iterations.clone(), flag_no_hardware_wallets: bool = false, or |c: &Config| otry!(c.account).disable_hardware.clone(), + flag_fast_unlock: bool = false, + or |c: &Config| otry!(c.account).fast_unlock.clone(), flag_force_ui: bool = false, @@ -424,6 +426,7 @@ struct Account { password: Option>, keys_iterations: Option, disable_hardware: Option, + fast_unlock: Option, } #[derive(Default, Debug, PartialEq, RustcDecodable)] @@ -927,6 +930,7 @@ mod tests { password: Some(vec!["passwdfile path".into()]), keys_iterations: None, disable_hardware: None, + fast_unlock: None, }), ui: Some(Ui { force: None, diff --git a/parity/cli/usage.txt b/parity/cli/usage.txt index 99f6c7304..5dc2f8404 100644 --- a/parity/cli/usage.txt +++ b/parity/cli/usage.txt @@ -99,6 +99,8 @@ Account Options: deriving key from the password (bigger is more secure) (default: {flag_keys_iterations}). --no-hardware-wallets Disables hardware wallet support. (default: {flag_no_hardware_wallets}) + --fast-unlock Use way faster unlocking mode. This setting causes raw secrets to be stored + unprotected in memory. (default: {flag_fast_unlock}) UI Options: --force-ui Enable Trusted UI WebSocket endpoint, diff --git a/parity/configuration.rs b/parity/configuration.rs index c211b29d5..214c00cbb 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -497,6 +497,7 @@ impl Configuration { password_files: self.args.flag_password.clone(), unlocked_accounts: to_addresses(&self.args.flag_unlock)?, enable_hardware_wallets: !self.args.flag_no_hardware_wallets, + enable_fast_unlock: self.args.flag_fast_unlock, }; Ok(cfg) diff --git a/parity/params.rs b/parity/params.rs index 85019b3e7..20a24ee1c 100644 --- a/parity/params.rs +++ b/parity/params.rs @@ -180,6 +180,7 @@ pub struct AccountsConfig { pub password_files: Vec, pub unlocked_accounts: Vec
, pub enable_hardware_wallets: bool, + pub enable_fast_unlock: bool, } impl Default for AccountsConfig { @@ -190,6 +191,7 @@ impl Default for AccountsConfig { password_files: Vec::new(), unlocked_accounts: Vec::new(), enable_hardware_wallets: true, + enable_fast_unlock: false, } } } diff --git a/parity/run.rs b/parity/run.rs index 352f11c5d..b543ab7f4 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -777,6 +777,7 @@ fn prepare_account_provider(spec: &SpecType, dirs: &Directories, data_dir: &str, let account_settings = AccountProviderSettings { enable_hardware_wallets: cfg.enable_hardware_wallets, hardware_wallet_classic_key: spec == &SpecType::Classic, + fast_unlock: cfg.enable_fast_unlock, }; let account_provider = AccountProvider::new( Box::new(EthStore::open_with_iterations(dir, cfg.iterations).map_err(|e| format!("Could not open keys directory: {}", e))?), From 139ee17d39c8285b5a3b7b56fd43a08e53abf55d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 6 Jun 2017 18:45:33 +0200 Subject: [PATCH 02/15] Small typos. --- ethstore/src/lib.rs | 2 +- parity/cli/usage.txt | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ethstore/src/lib.rs b/ethstore/src/lib.rs index 13ad4e013..06a8259de 100755 --- a/ethstore/src/lib.rs +++ b/ethstore/src/lib.rs @@ -67,5 +67,5 @@ pub use self::secret_store::{ pub use self::random::random_string; pub use self::parity_wordlist::random_phrase; -/// A opaque wrapper for secret. +/// An opaque wrapper for secret. pub struct OpaqueSecret(::ethkey::Secret); diff --git a/parity/cli/usage.txt b/parity/cli/usage.txt index 5dc2f8404..40be1856f 100644 --- a/parity/cli/usage.txt +++ b/parity/cli/usage.txt @@ -99,8 +99,9 @@ Account Options: deriving key from the password (bigger is more secure) (default: {flag_keys_iterations}). --no-hardware-wallets Disables hardware wallet support. (default: {flag_no_hardware_wallets}) - --fast-unlock Use way faster unlocking mode. This setting causes raw secrets to be stored - unprotected in memory. (default: {flag_fast_unlock}) + --fast-unlock Use drasticly faster unlocking mode. This setting causes + raw secrets to be stored unprotected in memory, + so use with care. (default: {flag_fast_unlock}) UI Options: --force-ui Enable Trusted UI WebSocket endpoint, From c2a8415f7883a9e026182c9647fe7df42ef25c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 8 Jun 2017 09:20:50 +0200 Subject: [PATCH 03/15] Fix test. --- parity/cli/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index 59d3c9fc7..5aea26000 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -710,6 +710,7 @@ mod tests { flag_password: vec!["~/.safe/password.file".into()], flag_keys_iterations: 10240u32, flag_no_hardware_wallets: false, + flag_fast_unlock: false, flag_force_ui: false, flag_no_ui: false, From ae8ff941f9cea592c58bcf27bbd9a5351c3e491c Mon Sep 17 00:00:00 2001 From: 5chdn <5chdn@users.noreply.github.com> Date: Thu, 8 Jun 2017 14:10:35 +0200 Subject: [PATCH 04/15] Fix terminology distributed -> decentralized --- js/src/dapps/dappreg/Application/application.js | 2 +- js/src/dapps/dappreg/ModalDelete/modalDelete.js | 2 +- js/src/dapps/dappreg/ModalRegister/modalRegister.js | 2 +- js/src/i18n/_default/extension.js | 2 +- js/src/i18n/_default/settings.js | 4 ++-- js/src/i18n/_default/tabBar.js | 2 +- js/src/i18n/zh-Hant-TW/extension.js | 2 +- js/src/i18n/zh-Hant-TW/settings.js | 4 ++-- js/src/i18n/zh-Hant-TW/tabBar.js | 2 +- js/src/i18n/zh/extension.js | 2 +- js/src/i18n/zh/settings.js | 4 ++-- js/src/i18n/zh/tabBar.js | 2 +- js/src/modals/FirstRun/TnC/tnc.js | 2 +- js/src/views/Application/Extension/extension.js | 2 +- js/src/views/Application/TabBar/tabBar.js | 2 +- js/src/views/Settings/Views/views.js | 4 ++-- 16 files changed, 20 insertions(+), 20 deletions(-) diff --git a/js/src/dapps/dappreg/Application/application.js b/js/src/dapps/dappreg/Application/application.js index 4c3a567c2..b33aa0b96 100644 --- a/js/src/dapps/dappreg/Application/application.js +++ b/js/src/dapps/dappreg/Application/application.js @@ -42,7 +42,7 @@ export default class Application extends Component { return (
- DAPP REGISTRY, a global view of distributed applications available on the network. Putting the puzzle together. + DAPP REGISTRY, a global view of decentralized applications available on the network. Putting the puzzle together.
diff --git a/js/src/dapps/dappreg/ModalDelete/modalDelete.js b/js/src/dapps/dappreg/ModalDelete/modalDelete.js index e64c315fa..20ca64067 100644 --- a/js/src/dapps/dappreg/ModalDelete/modalDelete.js +++ b/js/src/dapps/dappreg/ModalDelete/modalDelete.js @@ -43,7 +43,7 @@ export default class ModalDelete extends Component { secondary >
- You are about to remove a distributed application from the registry, + You are about to remove a decentralized application from the registry, the details of this application is given below. Removal does not return any fees, however the application will not be available to users anymore.
diff --git a/js/src/dapps/dappreg/ModalRegister/modalRegister.js b/js/src/dapps/dappreg/ModalRegister/modalRegister.js index 0c8bd0b9a..ee4d2a374 100644 --- a/js/src/dapps/dappreg/ModalRegister/modalRegister.js +++ b/js/src/dapps/dappreg/ModalRegister/modalRegister.js @@ -50,7 +50,7 @@ export default class ModalRegister extends Component { secondary >
- You are about to register a new distributed application on the network, the details of + You are about to register a new decentralized application on the network, the details of this application is given below. This will require a non-refundable fee of { api.util.fromWei(this.dappsStore.fee).toFormat(3) } ETH
diff --git a/js/src/i18n/_default/extension.js b/js/src/i18n/_default/extension.js index 88ba33674..baa2efd4e 100644 --- a/js/src/i18n/_default/extension.js +++ b/js/src/i18n/_default/extension.js @@ -16,5 +16,5 @@ export default { install: `Install the extension now`, - intro: `Parity now has an extension available for Chrome that allows safe browsing of Ethereum-enabled distributed applications. It is highly recommended that you install this extension to further enhance your Parity experience.` + intro: `Parity now has an extension available for Chrome that allows safe browsing of Ethereum-enabled decentralized applications. It is highly recommended that you install this extension to further enhance your Parity experience.` }; diff --git a/js/src/i18n/_default/settings.js b/js/src/i18n/_default/settings.js index 3e475e087..ea447e4a9 100644 --- a/js/src/i18n/_default/settings.js +++ b/js/src/i18n/_default/settings.js @@ -69,7 +69,7 @@ export default { label: `Addressbook` }, apps: { - description: `Distributed applications that interact with the underlying network. Add applications, manage you application portfolio and interact with application from around the network.`, + description: `Decentralized applications that interact with the underlying network. Add applications, manage you application portfolio and interact with application from around the network.`, label: `Applications` }, contracts: { @@ -85,7 +85,7 @@ export default { label: `Settings` }, signer: { - description: `The secure transaction management area of the application where you can approve any outgoing transactions made from the application as well as those placed into the queue by distributed applications.`, + description: `The secure transaction management area of the application where you can approve any outgoing transactions made from the application as well as those placed into the queue by decentralized applications.`, label: `Signer` }, status: { diff --git a/js/src/i18n/_default/tabBar.js b/js/src/i18n/_default/tabBar.js index 1692a1997..b704879e0 100644 --- a/js/src/i18n/_default/tabBar.js +++ b/js/src/i18n/_default/tabBar.js @@ -16,6 +16,6 @@ export default { tooltip: { - overview: `navigate between the different parts and views of the application, switching between an account view, token view and distributed application view` + overview: `navigate between the different parts and views of the application, switching between an account view, token view and decentralized application view` } }; diff --git a/js/src/i18n/zh-Hant-TW/extension.js b/js/src/i18n/zh-Hant-TW/extension.js index 5c0987038..0f017aa0f 100644 --- a/js/src/i18n/zh-Hant-TW/extension.js +++ b/js/src/i18n/zh-Hant-TW/extension.js @@ -17,6 +17,6 @@ export default { install: `現在就安裝這個擴充套件`, // Install the extension now intro: `Parity現在有一個Chrome的擴充套件,可以安全的瀏覽以太坊所支援的分散式應用。我們強烈推薦你安裝這個擴充套件來進一步提升你的Parity使用體驗。` - // Parity now has an extension available for Chrome that allows safe browsing of Ethereum-enabled distributed applications. + // Parity now has an extension available for Chrome that allows safe browsing of Ethereum-enabled decentralized applications. // It is highly recommended that you install this extension to further enhance your Parity experience. }; diff --git a/js/src/i18n/zh-Hant-TW/settings.js b/js/src/i18n/zh-Hant-TW/settings.js index bf026c384..8841279dc 100644 --- a/js/src/i18n/zh-Hant-TW/settings.js +++ b/js/src/i18n/zh-Hant-TW/settings.js @@ -82,7 +82,7 @@ export default { }, apps: { description: `與整個底層網路交流的分散式應用。新增應用,管理你的應用庫和與網路上的其他應用進行互動。`, - // Distributed applications that interact with the underlying network. Add applications, manage you application portfolio and + // Decentralized applications that interact with the underlying network. Add applications, manage you application portfolio and // interact with application from around the network. label: `應用` // Applications }, @@ -108,7 +108,7 @@ export default { signer: { description: `這個應用安全交易管理區域,你可以通過任何從本應用和其他分散式應用發起的即將傳送的交易`, // The secure transaction management area of the application where you can approve any outgoing transactions made - // from the application as well as those placed into the queue by distributed applications. + // from the application as well as those placed into the queue by decentralized applications. label: `Signer` // Signer }, status: { diff --git a/js/src/i18n/zh-Hant-TW/tabBar.js b/js/src/i18n/zh-Hant-TW/tabBar.js index 73ccabf96..482c230fb 100644 --- a/js/src/i18n/zh-Hant-TW/tabBar.js +++ b/js/src/i18n/zh-Hant-TW/tabBar.js @@ -17,6 +17,6 @@ export default { tooltip: { overview: `在應用的不同部分和不同介面進行導航,在帳戶介面、代幣介面和分散式應用介面之間切換。` - // navigate between the different parts and views of the application, switching between an account view, token view and distributed application view + // navigate between the different parts and views of the application, switching between an account view, token view and decentralized application view } }; diff --git a/js/src/i18n/zh/extension.js b/js/src/i18n/zh/extension.js index e79c03667..609b76bcf 100644 --- a/js/src/i18n/zh/extension.js +++ b/js/src/i18n/zh/extension.js @@ -17,6 +17,6 @@ export default { install: `现在就安装这个扩展`, // Install the extension now intro: `Parity现在有一个Chrome的扩展,可以安全的浏览以太坊所支持的分布式应用。我们强烈推荐你安装这个扩展来进一步提升你的Parity使用体验。` - // Parity now has an extension available for Chrome that allows safe browsing of Ethereum-enabled distributed applications. + // Parity now has an extension available for Chrome that allows safe browsing of Ethereum-enabled decentralized applications. // It is highly recommended that you install this extension to further enhance your Parity experience. }; diff --git a/js/src/i18n/zh/settings.js b/js/src/i18n/zh/settings.js index 3630caa45..4081a06d6 100644 --- a/js/src/i18n/zh/settings.js +++ b/js/src/i18n/zh/settings.js @@ -82,7 +82,7 @@ export default { }, apps: { description: `与整个底层网络交流的分布式应用。添加应用,管理你的应用库和与网络上的其他应用进行交互。`, - // Distributed applications that interact with the underlying network. Add applications, manage you application portfolio and + // Decentralized applications that interact with the underlying network. Add applications, manage you application portfolio and // interact with application from around the network. label: `应用` // Applications }, @@ -108,7 +108,7 @@ export default { signer: { description: `这个应用安全交易管理区域,你可以通过任何从本应用和其他分布式应用发起的即将发送的交易`, // The secure transaction management area of the application where you can approve any outgoing transactions made - // from the application as well as those placed into the queue by distributed applications. + // from the application as well as those placed into the queue by decentralized applications. label: `Signer` // Signer }, status: { diff --git a/js/src/i18n/zh/tabBar.js b/js/src/i18n/zh/tabBar.js index 7521c1b33..08a0a816f 100644 --- a/js/src/i18n/zh/tabBar.js +++ b/js/src/i18n/zh/tabBar.js @@ -17,6 +17,6 @@ export default { tooltip: { overview: `在应用的不同部分和不同界面进行导航,在账户界面、代币界面和分布式应用界面之间切换。` - // navigate between the different parts and views of the application, switching between an account view, token view and distributed application view + // navigate between the different parts and views of the application, switching between an account view, token view and decentralized application view } }; diff --git a/js/src/modals/FirstRun/TnC/tnc.js b/js/src/modals/FirstRun/TnC/tnc.js index 51b70f8dc..b2d6de9de 100644 --- a/js/src/modals/FirstRun/TnC/tnc.js +++ b/js/src/modals/FirstRun/TnC/tnc.js @@ -64,7 +64,7 @@ export default class TnC extends Component {

As with other cryptocurrencies, the blockchain used by Parity is susceptible to mining attacks, including but not limited to double-spend attacks, majority mining power attacks, “selfish-mining” attacks, and race condition attacks. Any successful attacks present a risk to the Ethereum ecosystem, expected proper execution and sequencing of ETH transactions, and expected proper execution and sequencing of contract computations. Despite the efforts of the EthCore and the EthCore Team, known or novel mining attacks may be successful.

Risk of Rapid Adoption and Insufficiency of Computational Application Processing Power on the Ethereum Network

-

If Parity is rapidly adopted, the demand for transaction processing and distributed application computations could rise dramatically and at a pace that exceeds the rate with which ETH miners can bring online additional mining power. Under such a scenario, the entire Ethereum ecosystem could become destabilized, due to the increased cost of running distributed applications. In turn, this could dampen interest in the Ethereum ecosystem and ETH. Insufficiency of computational resources and an associated rise in the price of ETH could result in businesses being unable to acquire scarce computational resources to run their distributed applications. This would represent revenue losses to businesses or worst case, cause businesses to cease operations because such operations have become uneconomical due to distortions in the crypto-economy.

+

If Parity is rapidly adopted, the demand for transaction processing and decentralized application computations could rise dramatically and at a pace that exceeds the rate with which ETH miners can bring online additional mining power. Under such a scenario, the entire Ethereum ecosystem could become destabilized, due to the increased cost of running decentralized applications. In turn, this could dampen interest in the Ethereum ecosystem and ETH. Insufficiency of computational resources and an associated rise in the price of ETH could result in businesses being unable to acquire scarce computational resources to run their decentralized applications. This would represent revenue losses to businesses or worst case, cause businesses to cease operations because such operations have become uneconomical due to distortions in the crypto-economy.

Risk of temporary network incoherence

We recommend any groups handling large or important transactions to maintain a voluntary 24 hour waiting period on any ether deposited. In case the integrity of the network is at risk due to issues in the clients, we will endeavour to publish patches in a timely fashion to address the issues. We will endeavour to provide solutions within the voluntary 24 hour waiting period.

diff --git a/js/src/views/Application/Extension/extension.js b/js/src/views/Application/Extension/extension.js index 0c033225b..e7a0da7fb 100644 --- a/js/src/views/Application/Extension/extension.js +++ b/js/src/views/Application/Extension/extension.js @@ -44,7 +44,7 @@ export default class Extension extends Component {

diff --git a/js/src/views/Application/TabBar/tabBar.js b/js/src/views/Application/TabBar/tabBar.js index d136029e9..e421c41e2 100644 --- a/js/src/views/Application/TabBar/tabBar.js +++ b/js/src/views/Application/TabBar/tabBar.js @@ -53,7 +53,7 @@ class TabBar extends Component { text={ } /> diff --git a/js/src/views/Settings/Views/views.js b/js/src/views/Settings/Views/views.js index 42a21c9ea..072670b0a 100644 --- a/js/src/views/Settings/Views/views.js +++ b/js/src/views/Settings/Views/views.js @@ -97,7 +97,7 @@ class Views extends Component { />, ) } @@ -130,7 +130,7 @@ class Views extends Component { />, ) } From cd3a1c1a94ed99819c6b9512d1af9b5b7f5830ef Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Fri, 9 Jun 2017 01:26:46 +0800 Subject: [PATCH 05/15] use rust 1.18's new feature to boost the purge performance --- README.md | 2 +- util/src/memorydb.rs | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b286055b2..07f0423f1 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ below to build from source. ## Build dependencies -**Parity requires Rust version 1.17.0 to build** +**Parity requires Rust version 1.18.0 to build** We recommend installing Rust through [rustup](https://www.rustup.rs/). If you don't already have rustup, you can install it like this: diff --git a/util/src/memorydb.rs b/util/src/memorydb.rs index 1feca9cba..bd96347ab 100644 --- a/util/src/memorydb.rs +++ b/util/src/memorydb.rs @@ -103,11 +103,7 @@ impl MemoryDB { /// Purge all zero-referenced data from the database. pub fn purge(&mut self) { - let empties: Vec<_> = self.data.iter() - .filter(|&(_, &(_, rc))| rc == 0) - .map(|(k, _)| k.clone()) - .collect(); - for empty in empties { self.data.remove(&empty); } + self.data.retain(|_, &mut (_, rc)| rc != 0); } /// Return the internal map of hashes to data, clearing the current state. From 4f63377ff2e552ae616f74bd2904fd6639822a12 Mon Sep 17 00:00:00 2001 From: Bas Date: Fri, 9 Jun 2017 12:21:11 +0200 Subject: [PATCH 06/15] Fix terminology distributed -> decentralized for Dutch i18n (#5802) --- js/src/i18n/nl/extension.js | 2 +- js/src/i18n/nl/settings.js | 4 ++-- js/src/i18n/nl/tabBar.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/js/src/i18n/nl/extension.js b/js/src/i18n/nl/extension.js index 73d765807..fbc12210b 100644 --- a/js/src/i18n/nl/extension.js +++ b/js/src/i18n/nl/extension.js @@ -16,5 +16,5 @@ export default { install: `Installeer de extensie nu`, - intro: `Parity heeft nu een extensie voor Chrome beschikbaar waarmee je veillig Ethereum-enabled gedistribueerde applicaties kunt bekijken. Het wordt ten zeerste aanbevolen om deze extensie te installeren om je Parity ervaring nog beter te maken.` + intro: `Parity heeft nu een extensie voor Chrome beschikbaar waarmee je veillig Ethereum-enabled decentrale applicaties kunt bekijken. Het wordt ten zeerste aanbevolen om deze extensie te installeren om je Parity ervaring nog beter te maken.` }; diff --git a/js/src/i18n/nl/settings.js b/js/src/i18n/nl/settings.js index f6705df78..f436d39c6 100644 --- a/js/src/i18n/nl/settings.js +++ b/js/src/i18n/nl/settings.js @@ -69,7 +69,7 @@ export default { label: `Adresboek` }, apps: { - description: `Gedistibueerde applicaties die gebruik maken van het onderliggende Ethereum netwerk. Voeg applicaties toe, beheer je applicatie portfolio en maak gebruik van applicaties op het wereldwijde netwerk.`, + description: `Decentrale applicaties die gebruik maken van het onderliggende Ethereum netwerk. Voeg applicaties toe, beheer je applicatie portfolio en maak gebruik van applicaties op het wereldwijde netwerk.`, label: `Applicaties` }, contracts: { @@ -85,7 +85,7 @@ export default { label: `Instellingen` }, signer: { - description: `Het beveiligde transactie beheergebied van de applicatie waar je elke uitgaande transactie die je hebt gemaakt met Parity evenals de transacties die in de wachtrij zijn geplaatst door gedistribueerde applicaties kan goedkeuren.`, + description: `Het beveiligde transactie beheergebied van de applicatie waar je goedkeuring kunt verlenen aan elke uitgaande transactie die je hebt gemaakt met Parity evenals de transacties die in de wachtrij zijn geplaatst door decentrale applicaties.`, label: `Signer` }, status: { diff --git a/js/src/i18n/nl/tabBar.js b/js/src/i18n/nl/tabBar.js index ae1cb1c52..378b536c9 100644 --- a/js/src/i18n/nl/tabBar.js +++ b/js/src/i18n/nl/tabBar.js @@ -16,6 +16,6 @@ export default { tooltip: { - overview: `navigeer tussen de verschillende onderdelen en weergaven in de applicatie, wissel tussen de account weergave, token weergave en gedistribueerde applicatie weergave` + overview: `navigeer tussen de verschillende onderdelen en weergaven in de applicatie, wissel tussen de account weergave, token weergave en decentrale applicatie weergave` } }; From efc46e78f17cbf6d3f6bfedc517fb78077b16143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 14 Jun 2017 12:06:15 +0200 Subject: [PATCH 07/15] Fix description of AccountProvider setting. --- ethcore/src/account_provider/mod.rs | 17 +++++++++-------- parity/run.rs | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/ethcore/src/account_provider/mod.rs b/ethcore/src/account_provider/mod.rs index 4c099ed85..20d1b5ad8 100755 --- a/ethcore/src/account_provider/mod.rs +++ b/ethcore/src/account_provider/mod.rs @@ -130,8 +130,9 @@ pub struct AccountProvider { transient_sstore: EthMultiStore, /// Accounts in hardware wallets. hardware_store: Option, - /// When unlocking permanently on for some time store a raw secret instead of password. - fast_unlock: bool, + /// When unlocking account permanently we additionally keep a raw secret in memory + /// to increase the performance of transaction signing. + unlock_keep_secret: bool, /// Disallowed accounts. blacklisted_accounts: Vec

, } @@ -142,8 +143,8 @@ pub struct AccountProviderSettings { pub enable_hardware_wallets: bool, /// Use the classic chain key on the hardware wallet. pub hardware_wallet_classic_key: bool, - /// Use fast, but unsafe unlock - pub fast_unlock: bool, + /// Store raw account secret when unlocking the account permanently. + pub unlock_keep_secret: bool, /// Disallowed accounts. pub blacklisted_accounts: Vec
, } @@ -153,7 +154,7 @@ impl Default for AccountProviderSettings { AccountProviderSettings { enable_hardware_wallets: false, hardware_wallet_classic_key: false, - fast_unlock: true, + unlock_keep_secret: false, blacklisted_accounts: vec![], } } @@ -187,7 +188,7 @@ impl AccountProvider { sstore: sstore, transient_sstore: transient_sstore(), hardware_store: hardware_store, - fast_unlock: settings.fast_unlock, + unlock_keep_secret: settings.unlock_keep_secret, blacklisted_accounts: settings.blacklisted_accounts, } } @@ -202,7 +203,7 @@ impl AccountProvider { sstore: Box::new(EthStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")), transient_sstore: transient_sstore(), hardware_store: None, - fast_unlock: false, + unlock_keep_secret: false, blacklisted_accounts: vec![], } } @@ -561,7 +562,7 @@ impl AccountProvider { } } - if self.fast_unlock && unlock != Unlock::OneTime { + if self.unlock_keep_secret && unlock != Unlock::OneTime { // verify password and get the secret let secret = self.sstore.raw_secret(&account, &password)?; self.unlocked_secrets.write().insert(account.clone(), secret); diff --git a/parity/run.rs b/parity/run.rs index 54a2e0d2e..fcbeb5f1f 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -777,7 +777,7 @@ fn prepare_account_provider(spec: &SpecType, dirs: &Directories, data_dir: &str, let account_settings = AccountProviderSettings { enable_hardware_wallets: cfg.enable_hardware_wallets, hardware_wallet_classic_key: spec == &SpecType::Classic, - fast_unlock: cfg.enable_fast_unlock, + unlock_keep_secret: cfg.enable_fast_unlock, blacklisted_accounts: match *spec { SpecType::Morden | SpecType::Ropsten | SpecType::Kovan | SpecType::Dev => vec![], _ => vec![ From ba35d69831a634ffef74f25cbd60fc7bf1c17c0c Mon Sep 17 00:00:00 2001 From: Rocco Stanzione Date: Thu, 15 Jun 2017 20:06:46 -0500 Subject: [PATCH 08/15] Typos in token deploy dapp ui --- js/src/dapps/tokendeploy/Application/pages.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/src/dapps/tokendeploy/Application/pages.js b/js/src/dapps/tokendeploy/Application/pages.js index 432b5636c..2839cb4d1 100644 --- a/js/src/dapps/tokendeploy/Application/pages.js +++ b/js/src/dapps/tokendeploy/Application/pages.js @@ -19,19 +19,19 @@ const PAGES = [ path: 'overview', title: 'Overview', byline: 'Display all the current information relating to your own deployed tokens', - description: 'View the total number of tokens in circulation, the number of different tokens associated with your accounts as well as the types of tokens created by you. In addition view the balances associated with your accounts in reltion to the total in circulation.' + description: 'View the total number of tokens in circulation, the number of different tokens associated with your accounts, as well as the types of tokens created by you. In addition, view the balances associated with your accounts in relation to the total in circulation.' }, { path: 'transfer', title: 'Transfer', byline: 'Send tokens associated with your accounts to other addresses', - description: 'Send any tokens created byt you or received from others. In addition have a bird\'s eye view of all events relating to token transfers, be it yours, created byt others, either local or globally available on the network.' + description: 'Send any tokens created by you or received from others. In addition, have a bird\'s eye view of all events relating to token transfers, be it yours, created by others, either local or globally available on the network.' }, { path: 'deploy', title: 'Deploy', byline: 'Deploy a new token to the network', - description: 'Token registration has never been this easy. Select the name for your token, the TLA and the number of tokens in circulation. Start sending the tokens to contacts right from this interface. Optionally you can register the token with the Token Registry which would allow you to transaction in tokens from anywhere these transactions are allowed.' + description: 'Token registration has never been this easy. Select the name for your token, the TLA and the number of tokens in circulation. Start sending the tokens to contacts right from this interface. Optionally you can register the token with the Token Registry which would allow you to transact in tokens from anywhere these transactions are allowed.' } ]; From 649de53382de1c50e84512333146617c17cef092 Mon Sep 17 00:00:00 2001 From: maciejhirsz Date: Fri, 16 Jun 2017 16:29:15 +0200 Subject: [PATCH 09/15] Allow IPFS server to accept POST requests --- ipfs/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ipfs/src/lib.rs b/ipfs/src/lib.rs index eeac2431b..104c7db19 100644 --- a/ipfs/src/lib.rs +++ b/ipfs/src/lib.rs @@ -77,11 +77,11 @@ impl IpfsHandler { /// Implement Hyper's HTTP handler impl Handler for IpfsHandler { fn on_request(&mut self, req: Request) -> Next { - if *req.method() != Method::Get { - return Next::write(); + match *req.method() { + Method::Get | Method::Post => {}, + _ => return Next::write() } - if !http::is_host_allowed(&req, &self.allowed_hosts) { self.out = Out::Bad("Disallowed Host header"); From 42dcdde4e812271298b7741f4cfec32744e8e4aa Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Fri, 16 Jun 2017 17:30:14 +0000 Subject: [PATCH 10/15] [ci skip] js-precompiled 20170616-172546 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cbb9237a8..ace76b1f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1803,7 +1803,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/paritytech/js-precompiled.git#e0cdec722ff2d32de6308638710fc4eb8a07253e" +source = "git+https://github.com/paritytech/js-precompiled.git#bebd4fc6ab48574cc976f3570357359f6e831a71" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index d45df6d3f..77b643da8 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.90", + "version": "1.7.91", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From 3111421866542cba4d4d20fa9e983eac5aaa3ac3 Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Sat, 17 Jun 2017 22:03:12 +0300 Subject: [PATCH 11/15] Update .gitlab-ci.yml snap update --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f12dd1aff..ff03eb79e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -71,13 +71,13 @@ linux-snap: - triggers script: - export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n") - - cd scripts + - cd snap - rm -rf *snap - sed -i 's/master/'"$VER"'/g' snapcraft.yaml - echo "Version:"$VER - snapcraft - ls - - cp parity_master_amd64.snap parity_"$VER"_amd64.snap + - cp "parity_"$CI_BUILD"_REF_NAME_amd64.snap" "parity_"$VER"_amd64.snap" - md5sum "parity_"$VER"_amd64.snap" > "parity_"$VER"_amd64.snap.md5" - aws configure set aws_access_key_id $s3_key - aws configure set aws_secret_access_key $s3_secret From ca27234a592e0157aea4a48f93bb2caf10bb8249 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Sat, 17 Jun 2017 21:18:52 +0200 Subject: [PATCH 12/15] minor optimizations of the modexp builtin --- ethcore/src/builtin.rs | 69 +++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index d567701d3..90190ac8e 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -111,7 +111,7 @@ impl Builtin { pub fn cost(&self, input: &[u8]) -> U256 { self.pricer.cost(input) } /// Simple forwarder for execute. - pub fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { + pub fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { self.native.execute(input, output) } @@ -288,9 +288,11 @@ impl Impl for ModexpImpl { let exp = read_num(exp_len); let modulus = read_num(mod_len); - // calculate modexp: exponentiation by squaring. + // calculate modexp: exponentiation by squaring. the `num` crate has pow, but not modular. fn modexp(mut base: BigUint, mut exp: BigUint, modulus: BigUint) -> BigUint { - match (base == BigUint::zero(), exp == BigUint::zero()) { + use num::Integer; + + match (base.is_zero(), exp.is_zero()) { (_, true) => return BigUint::one(), // n^0 % m (true, false) => return BigUint::zero(), // 0^n % m, n>0 (false, false) if modulus <= BigUint::one() => return BigUint::zero(), // a^b % 1 = 0. @@ -301,10 +303,9 @@ impl Impl for ModexpImpl { base = base % &modulus; // fast path for base divisible by modulus. - if base == BigUint::zero() { return result } - while exp != BigUint::zero() { - // exp has to be on the right here to avoid move. - if BigUint::one() & &exp == BigUint::one() { + if base.is_zero() { return result } + while !exp.is_zero() { + if exp.is_odd() { result = (result * &base) % &modulus; } @@ -331,22 +332,22 @@ impl Impl for ModexpImpl { fn read_fr(reader: &mut io::Chain<&[u8], io::Repeat>) -> Result<::bn::Fr, Error> { let mut buf = [0u8; 32]; - + reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); ::bn::Fr::from_slice(&buf[0..32]).map_err(|_| Error::from("Invalid field element")) } fn read_point(reader: &mut io::Chain<&[u8], io::Repeat>) -> Result<::bn::G1, Error> { use bn::{Fq, AffineG1, G1, Group}; - + let mut buf = [0u8; 32]; - + reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); let px = Fq::from_slice(&buf[0..32]).map_err(|_| Error::from("Invalid point x coordinate"))?; reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); let py = Fq::from_slice(&buf[0..32]).map_err(|_| Error::from("Invalid point x coordinate"))?; - + Ok( if px == Fq::zero() && py == Fq::zero() { G1::zero() @@ -374,7 +375,7 @@ impl Impl for Bn128AddImpl { output.write(0, &write_buf); Ok(()) - } + } } impl Impl for Bn128MulImpl { @@ -394,7 +395,7 @@ impl Impl for Bn128MulImpl { } output.write(0, &write_buf); Ok(()) - } + } } mod bn128_gen { @@ -420,13 +421,13 @@ mod bn128_gen { .expect("a valid field element"), Fq::from_str("4082367875863433681332203403145435568316851327593401208105741076214120093531") .expect("a valid field element"), - ), + ), ).expect("the generator P2(10857046999023057135944570762232829481370756359578518086990519993285655852781 + 11559732032986387107991004021392285783925812861821192530917403151452391805634i, 8495653923123431417604973247489272438418190587263600148770280649306958101930 + 4082367875863433681332203403145435568316851327593401208105741076214120093531i) is a valid curve point")); - } + } lazy_static! { pub static ref P1_P2_PAIRING: Gt = pairing(P1.clone(), P2.clone()); - } + } } impl Impl for Bn128PairingImpl { @@ -438,8 +439,8 @@ impl Impl for Bn128PairingImpl { use bn::{AffineG1, AffineG2, Fq, Fq2, pairing, G1, G2, Gt}; let elements = input.len() / 192; // (a, b_a, b_b - each 64-byte affine coordinates) - if input.len() % 192 != 0 { - return Err("Invalid input length, must be multiple of 192 (3 * (32*2))".into()) + if input.len() % 192 != 0 { + return Err("Invalid input length, must be multiple of 192 (3 * (32*2))".into()) } let ret_val = if input.len() == 0 { U256::one() @@ -459,11 +460,11 @@ impl Impl for Bn128PairingImpl { .map_err(|_| Error::from("Invalid b argument imaginary coeff y coordinate"))?; let b_a_x = Fq::from_slice(&input[idx*192+128..idx*192+160]) - .map_err(|_| Error::from("Invalid b argument real coeff x coordinate"))?; + .map_err(|_| Error::from("Invalid b argument real coeff x coordinate"))?; let b_a_y = Fq::from_slice(&input[idx*192+160..idx*192+192]) - .map_err(|_| Error::from("Invalid b argument real coeff y coordinate"))?; - + .map_err(|_| Error::from("Invalid b argument real coeff y coordinate"))?; + vals.push(( G1::from( AffineG1::new(a_x, a_y).map_err(|_| Error::from("Invalid a argument - not on curve"))? @@ -719,7 +720,7 @@ mod tests { pricer: Box::new(Linear { base: 0, word: 0 }), native: ethereum_builtin("bn128_add"), activate_at: 0, - }; + }; // zero-points additions { @@ -738,7 +739,7 @@ mod tests { f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); assert_eq!(output, expected); - } + } // no input, should not fail @@ -754,7 +755,7 @@ mod tests { f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); assert_eq!(output, expected); - } + } // should fail - point not on curve { @@ -769,7 +770,7 @@ mod tests { let res = f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])); assert!(res.is_err(), "There should be built-in error here"); - } + } } @@ -781,7 +782,7 @@ mod tests { pricer: Box::new(Linear { base: 0, word: 0 }), native: ethereum_builtin("bn128_mul"), activate_at: 0, - }; + }; // zero-point multiplication { @@ -799,7 +800,7 @@ mod tests { f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); assert_eq!(output, expected); - } + } // should fail - point not on curve { @@ -813,7 +814,7 @@ mod tests { let res = f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])); assert!(res.is_err(), "There should be built-in error here"); - } + } } fn builtin_pairing() -> Builtin { @@ -826,12 +827,12 @@ mod tests { fn empty_test(f: Builtin, expected: Vec) { let mut empty = [0u8; 0]; - let input = BytesRef::Fixed(&mut empty); + let input = BytesRef::Fixed(&mut empty); let mut output = vec![0u8; expected.len()]; f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); - assert_eq!(output, expected); + assert_eq!(output, expected); } fn error_test(f: Builtin, input: &[u8], msg_contains: Option<&str>) { @@ -851,12 +852,12 @@ mod tests { fn bytes(s: &'static str) -> Vec { FromHex::from_hex(s).expect("static str should contain valid hex bytes") } - + #[test] fn bn128_pairing_empty() { // should not fail, because empty input is a valid input of 0 elements empty_test( - builtin_pairing(), + builtin_pairing(), bytes("0000000000000000000000000000000000000000000000000000000000000001"), ); } @@ -890,7 +891,7 @@ mod tests { ), Some("Invalid input length"), ); - } + } #[test] #[should_panic] @@ -953,4 +954,4 @@ mod tests { b.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); assert_eq!(i, o); } -} \ No newline at end of file +} From 4efd673c19daaa51e371c2662fdc1401aa0cdd8e Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Sat, 27 May 2017 11:32:49 +0800 Subject: [PATCH 13/15] add a bit clarification to HashDB's remove() interface --- util/src/hashdb.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/util/src/hashdb.rs b/util/src/hashdb.rs index 8217413ef..ca4120702 100644 --- a/util/src/hashdb.rs +++ b/util/src/hashdb.rs @@ -86,7 +86,7 @@ pub trait HashDB: AsHashDB + Send + Sync { fn emplace(&mut self, key: H256, value: DBValue); /// Remove a datum previously inserted. Insertions can be "owed" such that the same number of `insert()`s may - /// happen without the data being eventually being inserted into the DB. + /// happen without the data being eventually being inserted into the DB. It can be "owed" more than once. /// /// # Examples /// ```rust @@ -100,6 +100,10 @@ pub trait HashDB: AsHashDB + Send + Sync { /// let key = &d.sha3(); /// m.remove(key); // OK - we now owe an insertion. /// assert!(!m.contains(key)); + /// m.remove(key); // OK - we now owe two insertions. + /// assert!(!m.contains(key)); + /// m.insert(d); // OK - still owed. + /// assert!(!m.contains(key)); /// m.insert(d); // OK - now it's "empty" again. /// assert!(!m.contains(key)); /// m.insert(d); // OK - now we've From ce8f8f40d7e7a7fa8a59518257ef48fde9b7c807 Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Sat, 27 May 2017 11:33:18 +0800 Subject: [PATCH 14/15] move MemoryDB's tests into tests module --- util/src/memorydb.rs | 85 +++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/util/src/memorydb.rs b/util/src/memorydb.rs index 1feca9cba..ab62b2c57 100644 --- a/util/src/memorydb.rs +++ b/util/src/memorydb.rs @@ -250,46 +250,51 @@ impl HashDB for MemoryDB { } } -#[test] -fn memorydb_remove_and_purge() { - let hello_bytes = b"Hello world!"; - let hello_key = hello_bytes.sha3(); +#[cfg(test)] +mod tests { + use super::*; - let mut m = MemoryDB::new(); - m.remove(&hello_key); - assert_eq!(m.raw(&hello_key).unwrap().1, -1); - m.purge(); - assert_eq!(m.raw(&hello_key).unwrap().1, -1); - m.insert(hello_bytes); - assert_eq!(m.raw(&hello_key).unwrap().1, 0); - m.purge(); - assert_eq!(m.raw(&hello_key), None); + #[test] + fn memorydb_remove_and_purge() { + let hello_bytes = b"Hello world!"; + let hello_key = hello_bytes.sha3(); - let mut m = MemoryDB::new(); - assert!(m.remove_and_purge(&hello_key).is_none()); - assert_eq!(m.raw(&hello_key).unwrap().1, -1); - m.insert(hello_bytes); - m.insert(hello_bytes); - assert_eq!(m.raw(&hello_key).unwrap().1, 1); - assert_eq!(&*m.remove_and_purge(&hello_key).unwrap(), hello_bytes); - assert_eq!(m.raw(&hello_key), None); - assert!(m.remove_and_purge(&hello_key).is_none()); -} - -#[test] -fn consolidate() { - let mut main = MemoryDB::new(); - let mut other = MemoryDB::new(); - let remove_key = other.insert(b"doggo"); - main.remove(&remove_key); - - let insert_key = other.insert(b"arf"); - main.emplace(insert_key, DBValue::from_slice(b"arf")); - - main.consolidate(other); - - let overlay = main.drain(); - - assert_eq!(overlay.get(&remove_key).unwrap(), &(DBValue::from_slice(b"doggo"), 0)); - assert_eq!(overlay.get(&insert_key).unwrap(), &(DBValue::from_slice(b"arf"), 2)); + let mut m = MemoryDB::new(); + m.remove(&hello_key); + assert_eq!(m.raw(&hello_key).unwrap().1, -1); + m.purge(); + assert_eq!(m.raw(&hello_key).unwrap().1, -1); + m.insert(hello_bytes); + assert_eq!(m.raw(&hello_key).unwrap().1, 0); + m.purge(); + assert_eq!(m.raw(&hello_key), None); + + let mut m = MemoryDB::new(); + assert!(m.remove_and_purge(&hello_key).is_none()); + assert_eq!(m.raw(&hello_key).unwrap().1, -1); + m.insert(hello_bytes); + m.insert(hello_bytes); + assert_eq!(m.raw(&hello_key).unwrap().1, 1); + assert_eq!(&*m.remove_and_purge(&hello_key).unwrap(), hello_bytes); + assert_eq!(m.raw(&hello_key), None); + assert!(m.remove_and_purge(&hello_key).is_none()); + } + + #[test] + fn consolidate() { + let mut main = MemoryDB::new(); + let mut other = MemoryDB::new(); + let remove_key = other.insert(b"doggo"); + main.remove(&remove_key); + + let insert_key = other.insert(b"arf"); + main.emplace(insert_key, DBValue::from_slice(b"arf")); + + main.consolidate(other); + + let overlay = main.drain(); + + assert_eq!(overlay.get(&remove_key).unwrap(), &(DBValue::from_slice(b"doggo"), 0)); + assert_eq!(overlay.get(&insert_key).unwrap(), &(DBValue::from_slice(b"arf"), 2)); + } } From 1efa7e7b1000e99f84cb580e06bfaf0b5dbb0dcf Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Wed, 31 May 2017 01:06:25 +0800 Subject: [PATCH 15/15] add one more test case for consolidate, both are negative --- util/src/memorydb.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/util/src/memorydb.rs b/util/src/memorydb.rs index ab62b2c57..e046943a4 100644 --- a/util/src/memorydb.rs +++ b/util/src/memorydb.rs @@ -290,11 +290,17 @@ mod tests { let insert_key = other.insert(b"arf"); main.emplace(insert_key, DBValue::from_slice(b"arf")); + let negative_remove_key = other.insert(b"negative"); + other.remove(&negative_remove_key); // ref cnt: 0 + other.remove(&negative_remove_key); // ref cnt: -1 + main.remove(&negative_remove_key); // ref cnt: -1 + main.consolidate(other); let overlay = main.drain(); assert_eq!(overlay.get(&remove_key).unwrap(), &(DBValue::from_slice(b"doggo"), 0)); assert_eq!(overlay.get(&insert_key).unwrap(), &(DBValue::from_slice(b"arf"), 2)); + assert_eq!(overlay.get(&negative_remove_key).unwrap(), &(DBValue::from_slice(b"negative"), -2)); } }