Optional from field in Transaction Requests (#4332)
* Infering default account when sending transactions if not provided * Fixing test * Fixing tests code * Fixes. * More fixes. * Final fix.
This commit is contained in:
@@ -50,30 +50,33 @@ struct AccountData {
|
||||
password: String,
|
||||
}
|
||||
|
||||
/// `AccountProvider` errors.
|
||||
/// Signing error
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Returned when account is not unlocked.
|
||||
pub enum SignError {
|
||||
/// Account is not unlocked
|
||||
NotUnlocked,
|
||||
/// Returned when signing fails.
|
||||
SStore(SSError),
|
||||
/// Low-level error from store
|
||||
SStore(SSError)
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
impl fmt::Display for SignError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
Error::NotUnlocked => write!(f, "Account is locked"),
|
||||
Error::SStore(ref e) => write!(f, "{}", e),
|
||||
SignError::NotUnlocked => write!(f, "Account is locked"),
|
||||
SignError::SStore(ref e) => write!(f, "{}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SSError> for Error {
|
||||
impl From<SSError> for SignError {
|
||||
fn from(e: SSError) -> Self {
|
||||
Error::SStore(e)
|
||||
SignError::SStore(e)
|
||||
}
|
||||
}
|
||||
|
||||
/// `AccountProvider` errors.
|
||||
pub type Error = SSError;
|
||||
|
||||
/// Dapp identifier
|
||||
#[derive(Default, Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||
pub struct DappId(String);
|
||||
@@ -218,6 +221,14 @@ impl AccountProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns default account for particular dapp falling back to other allowed accounts if necessary.
|
||||
pub fn default_address(&self, dapp: DappId) -> Result<Address, Error> {
|
||||
self.dapps_addresses(dapp)?
|
||||
.get(0)
|
||||
.cloned()
|
||||
.ok_or(SSError::InvalidAccount)
|
||||
}
|
||||
|
||||
/// Sets addresses visile for dapp.
|
||||
pub fn set_dapps_addresses(&self, dapp: DappId, addresses: Vec<Address>) -> Result<(), Error> {
|
||||
self.dapps_settings.write().set_accounts(dapp, addresses);
|
||||
@@ -288,8 +299,8 @@ impl AccountProvider {
|
||||
}
|
||||
|
||||
/// Changes the password of `account` from `password` to `new_password`. Fails if incorrect `password` given.
|
||||
pub fn change_password(&self, address: &Address, password: String, new_password: String) -> Result<(), Error> {
|
||||
self.sstore.change_password(&StoreAccountRef::root(address.clone()), &password, &new_password).map_err(Error::SStore)
|
||||
pub fn change_password(&self, account: &Address, password: String, new_password: String) -> Result<(), Error> {
|
||||
self.sstore.change_password(&StoreAccountRef::root(account.clone()), &password, &new_password)
|
||||
}
|
||||
|
||||
/// Helper method used for unlocking accounts.
|
||||
@@ -316,16 +327,16 @@ impl AccountProvider {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn password(&self, account: &StoreAccountRef) -> Result<String, Error> {
|
||||
fn password(&self, account: &StoreAccountRef) -> Result<String, SignError> {
|
||||
let mut unlocked = self.unlocked.write();
|
||||
let data = unlocked.get(account).ok_or(Error::NotUnlocked)?.clone();
|
||||
let data = unlocked.get(account).ok_or(SignError::NotUnlocked)?.clone();
|
||||
if let Unlock::Temp = data.unlock {
|
||||
unlocked.remove(account).expect("data exists: so key must exist: qed");
|
||||
}
|
||||
if let Unlock::Timed(ref end) = data.unlock {
|
||||
if Instant::now() > *end {
|
||||
unlocked.remove(account).expect("data exists: so key must exist: qed");
|
||||
return Err(Error::NotUnlocked);
|
||||
return Err(SignError::NotUnlocked);
|
||||
}
|
||||
}
|
||||
Ok(data.password.clone())
|
||||
@@ -354,14 +365,14 @@ impl AccountProvider {
|
||||
}
|
||||
|
||||
/// Signs the message. If password is not provided the account must be unlocked.
|
||||
pub fn sign(&self, address: Address, password: Option<String>, message: Message) -> Result<Signature, Error> {
|
||||
pub fn sign(&self, address: Address, password: Option<String>, message: Message) -> Result<Signature, SignError> {
|
||||
let account = StoreAccountRef::root(address);
|
||||
let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?;
|
||||
Ok(self.sstore.sign(&account, &password, &message)?)
|
||||
}
|
||||
|
||||
/// Signs given message with supplied token. Returns a token to use in next signing within this session.
|
||||
pub fn sign_with_token(&self, address: Address, token: AccountToken, message: Message) -> Result<(Signature, AccountToken), Error> {
|
||||
pub fn sign_with_token(&self, address: Address, token: AccountToken, message: Message) -> Result<(Signature, AccountToken), SignError> {
|
||||
let account = StoreAccountRef::root(address);
|
||||
let is_std_password = self.sstore.test_password(&account, &token)?;
|
||||
|
||||
@@ -383,7 +394,7 @@ impl AccountProvider {
|
||||
|
||||
/// Decrypts a message with given token. Returns a token to use in next operation for this account.
|
||||
pub fn decrypt_with_token(&self, address: Address, token: AccountToken, shared_mac: &[u8], message: &[u8])
|
||||
-> Result<(Vec<u8>, AccountToken), Error>
|
||||
-> Result<(Vec<u8>, AccountToken), SignError>
|
||||
{
|
||||
let account = StoreAccountRef::root(address);
|
||||
let is_std_password = self.sstore.test_password(&account, &token)?;
|
||||
@@ -405,7 +416,7 @@ impl AccountProvider {
|
||||
}
|
||||
|
||||
/// Decrypts a message. If password is not provided the account must be unlocked.
|
||||
pub fn decrypt(&self, address: Address, password: Option<String>, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, Error> {
|
||||
pub fn decrypt(&self, address: Address, password: Option<String>, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, SignError> {
|
||||
let account = StoreAccountRef::root(address);
|
||||
let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?;
|
||||
Ok(self.sstore.decrypt(&account, &password, shared_mac, message)?)
|
||||
|
||||
@@ -47,7 +47,7 @@ impl EngineSigner {
|
||||
}
|
||||
|
||||
/// Sign a consensus message hash.
|
||||
pub fn sign(&self, hash: H256) -> Result<Signature, account_provider::Error> {
|
||||
pub fn sign(&self, hash: H256) -> Result<Signature, account_provider::SignError> {
|
||||
self.account_provider.lock().sign(*self.address.read(), self.password.read().clone(), hash)
|
||||
}
|
||||
|
||||
|
||||
@@ -283,11 +283,11 @@ impl Tendermint {
|
||||
}
|
||||
|
||||
fn is_height(&self, message: &ConsensusMessage) -> bool {
|
||||
message.vote_step.is_height(self.height.load(AtomicOrdering::SeqCst))
|
||||
message.vote_step.is_height(self.height.load(AtomicOrdering::SeqCst))
|
||||
}
|
||||
|
||||
fn is_view(&self, message: &ConsensusMessage) -> bool {
|
||||
message.vote_step.is_view(self.height.load(AtomicOrdering::SeqCst), self.view.load(AtomicOrdering::SeqCst))
|
||||
message.vote_step.is_view(self.height.load(AtomicOrdering::SeqCst), self.view.load(AtomicOrdering::SeqCst))
|
||||
}
|
||||
|
||||
fn increment_view(&self, n: View) {
|
||||
@@ -309,7 +309,7 @@ impl Tendermint {
|
||||
fn has_enough_future_step_votes(&self, vote_step: &VoteStep) -> bool {
|
||||
if vote_step.view > self.view.load(AtomicOrdering::SeqCst) {
|
||||
let step_votes = self.votes.count_round_votes(vote_step);
|
||||
self.is_above_threshold(step_votes)
|
||||
self.is_above_threshold(step_votes)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@@ -673,7 +673,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn vote<F>(engine: &Engine, signer: F, height: usize, view: usize, step: Step, block_hash: Option<H256>) -> Bytes where F: FnOnce(H256) -> Result<H520, ::account_provider::Error> {
|
||||
fn vote<F>(engine: &Engine, signer: F, height: usize, view: usize, step: Step, block_hash: Option<H256>) -> Bytes where F: FnOnce(H256) -> Result<H520, ::account_provider::SignError> {
|
||||
let mi = message_info_rlp(&VoteStep::new(height, view, step), block_hash);
|
||||
let m = message_full_rlp(&signer(mi.sha3()).unwrap().into(), &mi);
|
||||
engine.handle_message(&m).unwrap();
|
||||
|
||||
@@ -26,7 +26,7 @@ use types::block_import_error::BlockImportError;
|
||||
use snapshot::Error as SnapshotError;
|
||||
use engines::EngineError;
|
||||
use ethkey::Error as EthkeyError;
|
||||
use account_provider::Error as AccountsError;
|
||||
use account_provider::SignError as AccountsError;
|
||||
|
||||
pub use types::executed::{ExecutionError, CallError};
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ use std::time::{Instant, Duration};
|
||||
|
||||
use util::*;
|
||||
use util::using_queue::{UsingQueue, GetAction};
|
||||
use account_provider::{AccountProvider, Error as AccountError};
|
||||
use account_provider::{AccountProvider, SignError as AccountError};
|
||||
use state::{State, CleanupMode};
|
||||
use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockId, CallAnalytics, TransactionId};
|
||||
use client::TransactionImportResult;
|
||||
|
||||
@@ -83,7 +83,7 @@ pub trait MinerService : Send + Sync {
|
||||
fn set_author(&self, author: Address);
|
||||
|
||||
/// Set info necessary to sign consensus messages.
|
||||
fn set_engine_signer(&self, address: Address, password: String) -> Result<(), ::account_provider::Error>;
|
||||
fn set_engine_signer(&self, address: Address, password: String) -> Result<(), ::account_provider::SignError>;
|
||||
|
||||
/// Get the extra_data that we will seal blocks with.
|
||||
fn extra_data(&self) -> Bytes;
|
||||
|
||||
Reference in New Issue
Block a user