From 37a2ee98de1ec086df6851565821970250c3a68e Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 22 Oct 2016 14:24:02 +0100 Subject: [PATCH] Additional RPCs for password management (#2779) * Add personal_testPassword and stub for personal_changePassword * Add change-password functionality. * Address grumble. * Update tests. * Update build. --- ethcore/src/account_provider.rs | 14 ++++++++++++++ rpc/src/v1/impls/personal.rs | 31 +++++++++++++++++++++++++++++-- rpc/src/v1/traits/personal.rs | 10 ++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/ethcore/src/account_provider.rs b/ethcore/src/account_provider.rs index 5c1398e02..7a4958ddc 100644 --- a/ethcore/src/account_provider.rs +++ b/ethcore/src/account_provider.rs @@ -265,6 +265,20 @@ impl AccountProvider { Ok(()) } + /// Returns `true` if the password for `account` is `password`. `false` if not. + pub fn test_password(&self, account: &Address, password: String) -> Result { + match self.sstore.sign(&account, &password, &Default::default()) { + Ok(_) => Ok(true), + Err(SSError::InvalidPassword) => Ok(false), + Err(e) => Err(Error::SStore(e)), + } + } + + /// Changes the password of `account` from `password` to `new_password`. Fails if incorrect `password` given. + pub fn change_password(&self, account: &Address, password: String, new_password: String) -> Result<(), Error> { + self.sstore.change_password(&account, &password, &new_password).map_err(Error::SStore) + } + /// Helper method used for unlocking accounts. fn unlock_account(&self, account: Address, password: String, unlock: Unlock) -> Result<(), Error> { // verify password by signing dump message diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index 0830effd5..fde5f10b2 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -119,7 +119,7 @@ impl Personal for PersonalClient where C: MiningBl fn unlock_account(&self, params: Params) -> Result { try!(self.active()); from_params::<(RpcH160, String, Option)>(params).and_then( - |(account, account_pass, duration)|{ + |(account, account_pass, duration)| { let account: Address = account.into(); let store = take_weak!(self.accounts); let r = match (self.allow_perm_unlock, duration) { @@ -132,7 +132,34 @@ impl Personal for PersonalClient where C: MiningBl Ok(_) => Ok(Value::Bool(true)), Err(_) => Ok(Value::Bool(false)), } - }) + } + ) + } + + fn test_password(&self, params: Params) -> Result { + try!(self.active()); + from_params::<(RpcH160, String)>(params).and_then( + |(account, password)| { + let account: Address = account.into(); + take_weak!(self.accounts) + .test_password(&account, password) + .map(|b| Value::Bool(b)) + .map_err(|e| errors::account("Could not fetch account info.", e)) + } + ) + } + + fn change_password(&self, params: Params) -> Result { + try!(self.active()); + from_params::<(RpcH160, String, String)>(params).and_then( + |(account, password, new_password)| { + let account: Address = account.into(); + take_weak!(self.accounts) + .change_password(&account, password, new_password) + .map(|_| Value::Null) + .map_err(|e| errors::account("Could not fetch account info.", e)) + } + ) } fn sign_and_send_transaction(&self, params: Params) -> Result { diff --git a/rpc/src/v1/traits/personal.rs b/rpc/src/v1/traits/personal.rs index 988091958..cf955447f 100644 --- a/rpc/src/v1/traits/personal.rs +++ b/rpc/src/v1/traits/personal.rs @@ -39,6 +39,14 @@ pub trait Personal: Sized + Send + Sync + 'static { /// Unlocks specified account for use (can only be one unlocked account at one moment) fn unlock_account(&self, _: Params) -> Result; + /// Returns true if given `password` would unlock given `account`. + /// Arguments: `account`, `password`. + fn test_password(&self, _: Params) -> Result; + + /// Changes an account's password. + /// Arguments: `account`, `password`, `new_password`. + fn change_password(&self, _: Params) -> Result; + /// Sends transaction and signs it in single call. The account is not unlocked in such case. fn sign_and_send_transaction(&self, _: Params) -> Result; @@ -69,6 +77,8 @@ pub trait Personal: Sized + Send + Sync + 'static { delegate.add_method("personal_newAccountFromPhrase", Personal::new_account_from_phrase); delegate.add_method("personal_newAccountFromWallet", Personal::new_account_from_wallet); delegate.add_method("personal_unlockAccount", Personal::unlock_account); + delegate.add_method("personal_testPassword", Personal::test_password); + delegate.add_method("personal_changePassword", Personal::change_password); delegate.add_method("personal_signAndSendTransaction", Personal::sign_and_send_transaction); delegate.add_method("personal_setAccountName", Personal::set_account_name); delegate.add_method("personal_setAccountMeta", Personal::set_account_meta);