diff --git a/Cargo.lock b/Cargo.lock index 21f5b45cea..5ce4568a10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -419,6 +419,7 @@ version = "0.1.0" dependencies = [ "codechain-core 0.1.0", "codechain-key 0.1.0", + "codechain-keystore 0.1.0", "codechain-logger 0.1.0", "codechain-network 0.1.0", "codechain-state 0.1.0", diff --git a/keystore/src/error.rs b/keystore/src/error.rs index b1d5b4cb31..b9782e945e 100644 --- a/keystore/src/error.rs +++ b/keystore/src/error.rs @@ -37,6 +37,8 @@ pub enum Error { InvalidKeyFile(String), /// Account creation failed. CreationFailed, + /// Account already exists. + AlreadyExists, /// `ckeys` error CKey(CKeyError), /// `CCrypto` error @@ -55,6 +57,7 @@ impl fmt::Display for Error { Error::InvalidMessage => "Invalid message".into(), Error::InvalidKeyFile(ref reason) => format!("Invalid key file: {}", reason), Error::CreationFailed => "Account creation failed".into(), + Error::AlreadyExists => "Account already exists".into(), Error::CKey(ref err) => err.to_string(), Error::CCrypto(ref err) => err.to_string(), Error::Custom(ref s) => s.clone(), diff --git a/keystore/src/keystore.rs b/keystore/src/keystore.rs index 2666d38674..96e0440de7 100644 --- a/keystore/src/keystore.rs +++ b/keystore/src/keystore.rs @@ -64,7 +64,11 @@ impl KeyStore { impl SimpleSecretStore for KeyStore { fn insert_account(&self, secret: Secret, password: &Password) -> Result { - self.store.insert_account(secret, password) + let keypair = KeyPair::from_private(secret.into()).map_err(|_| Error::CreationFailed)?; + match self.has_account(&keypair.address())? { + true => Err(Error::AlreadyExists), + false => self.store.insert_account(secret, password), + } } fn accounts(&self) -> Result, Error> { @@ -345,10 +349,10 @@ impl SimpleSecretStore for KeyMultiStore { } fn has_account(&self, account: &Address) -> Result { - let mut accounts = self.get_accounts(account)?.into_iter(); - match accounts.next() { - Some(_) => Ok(true), - None => Ok(false), + match self.get_accounts(account) { + Ok(_) => Ok(true), + Err(Error::InvalidAccount) => Ok(false), + Err(e) => Err(e), } } diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 60b7aec82e..e4b4510156 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -8,6 +8,7 @@ authors = ["CodeChain Team "] [dependencies] codechain-core = { path = "../core" } codechain-key = { path = "../key" } +codechain-keystore = { path = "../keystore" } codechain-logger = { path = "../util/logger" } codechain-network = { path = "../network" } codechain-state = { path = "../state" } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 84f47de00d..5086edddee 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -18,6 +18,7 @@ extern crate codechain_core as ccore; #[macro_use] extern crate codechain_logger as clogger; extern crate codechain_key as ckey; +extern crate codechain_keystore as ckeystore; extern crate codechain_network as cnetwork; extern crate codechain_state as cstate; extern crate codechain_types as ctypes; diff --git a/rpc/src/v1/errors.rs b/rpc/src/v1/errors.rs index f27d4bf0f9..33b79ed32e 100644 --- a/rpc/src/v1/errors.rs +++ b/rpc/src/v1/errors.rs @@ -19,6 +19,7 @@ use std::fmt; use ccore::AccountProviderError; use ccore::Error as CoreError; use ckey::Error as KeyError; +use ckeystore::Error as KeystoreError; use cnetwork::control::Error as NetworkControlError; use cstate::StateError; use ctypes::parcel::Error as ParcelError; @@ -43,6 +44,11 @@ mod codes { pub const TOO_LOW_FEE: i64 = -32033; pub const TOO_CHEAP_TO_REPLACE: i64 = -32034; pub const INVALID_NONCE: i64 = -32035; + pub const KEYSTORE_ERROR: i64 = -32040; + pub const KEY_ERROR: i64 = -32041; + pub const ALREADY_EXISTS: i64 = -32042; + pub const WRONG_PASSWORD: i64 = -32043; + pub const NO_SUCH_ACCOUNT: i64 = -32044; pub const UNKNOWN_ERROR: i64 = -32099; } @@ -148,10 +154,39 @@ pub fn rlp(error: DecoderError) -> Error { } pub fn account_provider(error: AccountProviderError) -> Error { - Error { - code: ErrorCode::ServerError(codes::ACCOUNT_PROVIDER_ERROR), - message: "AccountProvider error".into(), - data: Some(Value::String(format!("{:?}", error))), + match error { + AccountProviderError::KeystoreError(error) => match error { + KeystoreError::InvalidAccount => Error { + code: ErrorCode::ServerError(codes::NO_SUCH_ACCOUNT), + message: "No Such Account".into(), + data: Some(Value::String(format!("{:?}", error))), + }, + KeystoreError::InvalidPassword => Error { + code: ErrorCode::ServerError(codes::WRONG_PASSWORD), + message: "Wrong Password".into(), + data: Some(Value::String(format!("{:?}", error))), + }, + KeystoreError::AlreadyExists => Error { + code: ErrorCode::ServerError(codes::ALREADY_EXISTS), + message: "Already Exists".into(), + data: Some(Value::String(format!("{:?}", error))), + }, + _ => Error { + code: ErrorCode::ServerError(codes::KEYSTORE_ERROR), + message: "Keystore Error".into(), + data: Some(Value::String(format!("{:?}", error))), + }, + }, + AccountProviderError::KeyError(_) => Error { + code: ErrorCode::ServerError(codes::KEY_ERROR), + message: "Key Error".into(), + data: Some(Value::String(format!("{:?}", error))), + }, + _ => Error { + code: ErrorCode::ServerError(codes::ACCOUNT_PROVIDER_ERROR), + message: "AccountProvider Error".into(), + data: Some(Value::String(format!("{:?}", error))), + }, } }