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:
parent
4a404a6f33
commit
9fb2be8f2b
@ -50,30 +50,33 @@ struct AccountData {
|
|||||||
password: String,
|
password: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `AccountProvider` errors.
|
/// Signing error
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum SignError {
|
||||||
/// Returned when account is not unlocked.
|
/// Account is not unlocked
|
||||||
NotUnlocked,
|
NotUnlocked,
|
||||||
/// Returned when signing fails.
|
/// Low-level error from store
|
||||||
SStore(SSError),
|
SStore(SSError)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for SignError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
match *self {
|
match *self {
|
||||||
Error::NotUnlocked => write!(f, "Account is locked"),
|
SignError::NotUnlocked => write!(f, "Account is locked"),
|
||||||
Error::SStore(ref e) => write!(f, "{}", e),
|
SignError::SStore(ref e) => write!(f, "{}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SSError> for Error {
|
impl From<SSError> for SignError {
|
||||||
fn from(e: SSError) -> Self {
|
fn from(e: SSError) -> Self {
|
||||||
Error::SStore(e)
|
SignError::SStore(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `AccountProvider` errors.
|
||||||
|
pub type Error = SSError;
|
||||||
|
|
||||||
/// Dapp identifier
|
/// Dapp identifier
|
||||||
#[derive(Default, Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
#[derive(Default, Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||||
pub struct DappId(String);
|
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.
|
/// Sets addresses visile for dapp.
|
||||||
pub fn set_dapps_addresses(&self, dapp: DappId, addresses: Vec<Address>) -> Result<(), Error> {
|
pub fn set_dapps_addresses(&self, dapp: DappId, addresses: Vec<Address>) -> Result<(), Error> {
|
||||||
self.dapps_settings.write().set_accounts(dapp, addresses);
|
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.
|
/// 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> {
|
pub fn change_password(&self, account: &Address, password: String, new_password: String) -> Result<(), Error> {
|
||||||
self.sstore.change_password(&StoreAccountRef::root(address.clone()), &password, &new_password).map_err(Error::SStore)
|
self.sstore.change_password(&StoreAccountRef::root(account.clone()), &password, &new_password)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper method used for unlocking accounts.
|
/// Helper method used for unlocking accounts.
|
||||||
@ -316,16 +327,16 @@ impl AccountProvider {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn password(&self, account: &StoreAccountRef) -> Result<String, Error> {
|
fn password(&self, account: &StoreAccountRef) -> Result<String, SignError> {
|
||||||
let mut unlocked = self.unlocked.write();
|
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 {
|
if let Unlock::Temp = data.unlock {
|
||||||
unlocked.remove(account).expect("data exists: so key must exist: qed");
|
unlocked.remove(account).expect("data exists: so key must exist: qed");
|
||||||
}
|
}
|
||||||
if let Unlock::Timed(ref end) = data.unlock {
|
if let Unlock::Timed(ref end) = data.unlock {
|
||||||
if Instant::now() > *end {
|
if Instant::now() > *end {
|
||||||
unlocked.remove(account).expect("data exists: so key must exist: qed");
|
unlocked.remove(account).expect("data exists: so key must exist: qed");
|
||||||
return Err(Error::NotUnlocked);
|
return Err(SignError::NotUnlocked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(data.password.clone())
|
Ok(data.password.clone())
|
||||||
@ -354,14 +365,14 @@ impl AccountProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Signs the message. If password is not provided the account must be unlocked.
|
/// 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 account = StoreAccountRef::root(address);
|
||||||
let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?;
|
let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?;
|
||||||
Ok(self.sstore.sign(&account, &password, &message)?)
|
Ok(self.sstore.sign(&account, &password, &message)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signs given message with supplied token. Returns a token to use in next signing within this session.
|
/// 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 account = StoreAccountRef::root(address);
|
||||||
let is_std_password = self.sstore.test_password(&account, &token)?;
|
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.
|
/// 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])
|
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 account = StoreAccountRef::root(address);
|
||||||
let is_std_password = self.sstore.test_password(&account, &token)?;
|
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.
|
/// 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 account = StoreAccountRef::root(address);
|
||||||
let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?;
|
let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?;
|
||||||
Ok(self.sstore.decrypt(&account, &password, shared_mac, message)?)
|
Ok(self.sstore.decrypt(&account, &password, shared_mac, message)?)
|
||||||
|
@ -47,7 +47,7 @@ impl EngineSigner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sign a consensus message hash.
|
/// 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)
|
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 {
|
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 {
|
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) {
|
fn increment_view(&self, n: View) {
|
||||||
@ -309,7 +309,7 @@ impl Tendermint {
|
|||||||
fn has_enough_future_step_votes(&self, vote_step: &VoteStep) -> bool {
|
fn has_enough_future_step_votes(&self, vote_step: &VoteStep) -> bool {
|
||||||
if vote_step.view > self.view.load(AtomicOrdering::SeqCst) {
|
if vote_step.view > self.view.load(AtomicOrdering::SeqCst) {
|
||||||
let step_votes = self.votes.count_round_votes(vote_step);
|
let step_votes = self.votes.count_round_votes(vote_step);
|
||||||
self.is_above_threshold(step_votes)
|
self.is_above_threshold(step_votes)
|
||||||
} else {
|
} else {
|
||||||
false
|
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 mi = message_info_rlp(&VoteStep::new(height, view, step), block_hash);
|
||||||
let m = message_full_rlp(&signer(mi.sha3()).unwrap().into(), &mi);
|
let m = message_full_rlp(&signer(mi.sha3()).unwrap().into(), &mi);
|
||||||
engine.handle_message(&m).unwrap();
|
engine.handle_message(&m).unwrap();
|
||||||
|
@ -26,7 +26,7 @@ use types::block_import_error::BlockImportError;
|
|||||||
use snapshot::Error as SnapshotError;
|
use snapshot::Error as SnapshotError;
|
||||||
use engines::EngineError;
|
use engines::EngineError;
|
||||||
use ethkey::Error as EthkeyError;
|
use ethkey::Error as EthkeyError;
|
||||||
use account_provider::Error as AccountsError;
|
use account_provider::SignError as AccountsError;
|
||||||
|
|
||||||
pub use types::executed::{ExecutionError, CallError};
|
pub use types::executed::{ExecutionError, CallError};
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ use std::time::{Instant, Duration};
|
|||||||
|
|
||||||
use util::*;
|
use util::*;
|
||||||
use util::using_queue::{UsingQueue, GetAction};
|
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 state::{State, CleanupMode};
|
||||||
use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockId, CallAnalytics, TransactionId};
|
use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockId, CallAnalytics, TransactionId};
|
||||||
use client::TransactionImportResult;
|
use client::TransactionImportResult;
|
||||||
|
@ -83,7 +83,7 @@ pub trait MinerService : Send + Sync {
|
|||||||
fn set_author(&self, author: Address);
|
fn set_author(&self, author: Address);
|
||||||
|
|
||||||
/// Set info necessary to sign consensus messages.
|
/// 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.
|
/// Get the extra_data that we will seal blocks with.
|
||||||
fn extra_data(&self) -> Bytes;
|
fn extra_data(&self) -> Bytes;
|
||||||
|
@ -210,11 +210,12 @@ pub fn sign_and_dispatch<C, M>(client: &C, miner: &M, accounts: &AccountProvider
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_optional_fields<C, M>(request: TransactionRequest, client: &C, miner: &M) -> FilledTransactionRequest
|
pub fn fill_optional_fields<C, M>(request: TransactionRequest, default_sender: Address, client: &C, miner: &M) -> FilledTransactionRequest
|
||||||
where C: MiningBlockChainClient, M: MinerService
|
where C: MiningBlockChainClient, M: MinerService
|
||||||
{
|
{
|
||||||
FilledTransactionRequest {
|
FilledTransactionRequest {
|
||||||
from: request.from,
|
from: request.from.unwrap_or(default_sender),
|
||||||
|
used_default_from: request.from.is_none(),
|
||||||
to: request.to,
|
to: request.to,
|
||||||
nonce: request.nonce,
|
nonce: request.nonce,
|
||||||
gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(client, miner)),
|
gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(client, miner)),
|
||||||
@ -231,15 +232,15 @@ pub fn default_gas_price<C, M>(client: &C, miner: &M) -> U256
|
|||||||
client.gas_price_median(100).unwrap_or_else(|| miner.sensible_gas_price())
|
client.gas_price_median(100).unwrap_or_else(|| miner.sensible_gas_price())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_rpc<C, M>(payload: RpcConfirmationPayload, client: &C, miner: &M) -> ConfirmationPayload
|
pub fn from_rpc<C, M>(payload: RpcConfirmationPayload, default_account: Address, client: &C, miner: &M) -> ConfirmationPayload
|
||||||
where C: MiningBlockChainClient, M: MinerService {
|
where C: MiningBlockChainClient, M: MinerService {
|
||||||
|
|
||||||
match payload {
|
match payload {
|
||||||
RpcConfirmationPayload::SendTransaction(request) => {
|
RpcConfirmationPayload::SendTransaction(request) => {
|
||||||
ConfirmationPayload::SendTransaction(fill_optional_fields(request.into(), client, miner))
|
ConfirmationPayload::SendTransaction(fill_optional_fields(request.into(), default_account, client, miner))
|
||||||
},
|
},
|
||||||
RpcConfirmationPayload::SignTransaction(request) => {
|
RpcConfirmationPayload::SignTransaction(request) => {
|
||||||
ConfirmationPayload::SignTransaction(fill_optional_fields(request.into(), client, miner))
|
ConfirmationPayload::SignTransaction(fill_optional_fields(request.into(), default_account, client, miner))
|
||||||
},
|
},
|
||||||
RpcConfirmationPayload::Decrypt(RpcDecryptRequest { address, msg }) => {
|
RpcConfirmationPayload::Decrypt(RpcDecryptRequest { address, msg }) => {
|
||||||
ConfirmationPayload::Decrypt(address.into(), msg.into())
|
ConfirmationPayload::Decrypt(address.into(), msg.into())
|
||||||
|
@ -23,7 +23,7 @@ macro_rules! rpc_unimplemented {
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use rlp::DecoderError;
|
use rlp::DecoderError;
|
||||||
use ethcore::error::{Error as EthcoreError, CallError, TransactionError};
|
use ethcore::error::{Error as EthcoreError, CallError, TransactionError};
|
||||||
use ethcore::account_provider::{Error as AccountError};
|
use ethcore::account_provider::{SignError as AccountError};
|
||||||
use jsonrpc_core::{Error, ErrorCode, Value};
|
use jsonrpc_core::{Error, ErrorCode, Value};
|
||||||
|
|
||||||
mod codes {
|
mod codes {
|
||||||
|
@ -29,7 +29,11 @@ mod network_settings;
|
|||||||
|
|
||||||
pub use self::poll_manager::PollManager;
|
pub use self::poll_manager::PollManager;
|
||||||
pub use self::poll_filter::{PollFilter, limit_logs};
|
pub use self::poll_filter::{PollFilter, limit_logs};
|
||||||
pub use self::requests::{TransactionRequest, FilledTransactionRequest, ConfirmationRequest, ConfirmationPayload, CallRequest};
|
pub use self::requests::{
|
||||||
pub use self::signing_queue::{ConfirmationsQueue, ConfirmationPromise, ConfirmationResult, SigningQueue, QueueEvent};
|
TransactionRequest, FilledTransactionRequest, ConfirmationRequest, ConfirmationPayload, CallRequest,
|
||||||
|
};
|
||||||
|
pub use self::signing_queue::{
|
||||||
|
ConfirmationsQueue, ConfirmationPromise, ConfirmationResult, SigningQueue, QueueEvent, DefaultAccount,
|
||||||
|
};
|
||||||
pub use self::signer::SignerService;
|
pub use self::signer::SignerService;
|
||||||
pub use self::network_settings::NetworkSettings;
|
pub use self::network_settings::NetworkSettings;
|
||||||
|
@ -20,7 +20,7 @@ use util::{Address, U256, Bytes};
|
|||||||
#[derive(Debug, Clone, Default, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Default, Eq, PartialEq, Hash)]
|
||||||
pub struct TransactionRequest {
|
pub struct TransactionRequest {
|
||||||
/// Sender
|
/// Sender
|
||||||
pub from: Address,
|
pub from: Option<Address>,
|
||||||
/// Recipient
|
/// Recipient
|
||||||
pub to: Option<Address>,
|
pub to: Option<Address>,
|
||||||
/// Gas Price
|
/// Gas Price
|
||||||
@ -42,6 +42,8 @@ pub struct TransactionRequest {
|
|||||||
pub struct FilledTransactionRequest {
|
pub struct FilledTransactionRequest {
|
||||||
/// Sender
|
/// Sender
|
||||||
pub from: Address,
|
pub from: Address,
|
||||||
|
/// Indicates if the sender was filled by default value.
|
||||||
|
pub used_default_from: bool,
|
||||||
/// Recipient
|
/// Recipient
|
||||||
pub to: Option<Address>,
|
pub to: Option<Address>,
|
||||||
/// Gas Price
|
/// Gas Price
|
||||||
@ -61,7 +63,7 @@ pub struct FilledTransactionRequest {
|
|||||||
impl From<FilledTransactionRequest> for TransactionRequest {
|
impl From<FilledTransactionRequest> for TransactionRequest {
|
||||||
fn from(r: FilledTransactionRequest) -> Self {
|
fn from(r: FilledTransactionRequest) -> Self {
|
||||||
TransactionRequest {
|
TransactionRequest {
|
||||||
from: r.from,
|
from: Some(r.from),
|
||||||
to: r.to,
|
to: r.to,
|
||||||
gas_price: Some(r.gas_price),
|
gas_price: Some(r.gas_price),
|
||||||
gas: Some(r.gas),
|
gas: Some(r.gas),
|
||||||
|
@ -19,13 +19,36 @@ use std::cell::RefCell;
|
|||||||
use std::sync::{mpsc, Arc};
|
use std::sync::{mpsc, Arc};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use jsonrpc_core;
|
use jsonrpc_core;
|
||||||
use util::{Mutex, RwLock, U256};
|
use util::{Mutex, RwLock, U256, Address};
|
||||||
|
use ethcore::account_provider::DappId;
|
||||||
use v1::helpers::{ConfirmationRequest, ConfirmationPayload};
|
use v1::helpers::{ConfirmationRequest, ConfirmationPayload};
|
||||||
use v1::types::ConfirmationResponse;
|
use v1::metadata::Metadata;
|
||||||
|
use v1::types::{ConfirmationResponse, H160 as RpcH160};
|
||||||
|
|
||||||
/// Result that can be returned from JSON RPC.
|
/// Result that can be returned from JSON RPC.
|
||||||
pub type RpcResult = Result<ConfirmationResponse, jsonrpc_core::Error>;
|
pub type RpcResult = Result<ConfirmationResponse, jsonrpc_core::Error>;
|
||||||
|
|
||||||
|
|
||||||
|
/// Type of default account
|
||||||
|
pub enum DefaultAccount {
|
||||||
|
/// Default account is known
|
||||||
|
Provided(Address),
|
||||||
|
/// Should use default account for dapp
|
||||||
|
ForDapp(DappId),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Metadata> for DefaultAccount {
|
||||||
|
fn from(meta: Metadata) -> Self {
|
||||||
|
DefaultAccount::ForDapp(meta.dapp_id.unwrap_or_default().into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RpcH160> for DefaultAccount {
|
||||||
|
fn from(address: RpcH160) -> Self {
|
||||||
|
DefaultAccount::Provided(address.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Possible events happening in the queue that can be listened to.
|
/// Possible events happening in the queue that can be listened to.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum QueueEvent {
|
pub enum QueueEvent {
|
||||||
@ -319,6 +342,7 @@ mod test {
|
|||||||
fn request() -> ConfirmationPayload {
|
fn request() -> ConfirmationPayload {
|
||||||
ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
||||||
from: Address::from(1),
|
from: Address::from(1),
|
||||||
|
used_default_from: false,
|
||||||
to: Some(Address::from(2)),
|
to: Some(Address::from(2)),
|
||||||
gas_price: 0.into(),
|
gas_price: 0.into(),
|
||||||
gas: 10_000.into(),
|
gas: 10_000.into(),
|
||||||
|
@ -45,15 +45,15 @@ use ethsync::{SyncProvider};
|
|||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use jsonrpc_macros::Trailing;
|
use jsonrpc_macros::Trailing;
|
||||||
|
|
||||||
|
use v1::helpers::{CallRequest as CRequest, errors, limit_logs};
|
||||||
|
use v1::helpers::dispatch::{dispatch_transaction, default_gas_price};
|
||||||
|
use v1::helpers::block_import::is_major_importing;
|
||||||
use v1::traits::Eth;
|
use v1::traits::Eth;
|
||||||
use v1::types::{
|
use v1::types::{
|
||||||
RichBlock, Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo,
|
RichBlock, Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo,
|
||||||
Transaction, CallRequest, Index, Filter, Log, Receipt, Work,
|
Transaction, CallRequest, Index, Filter, Log, Receipt, Work,
|
||||||
H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256,
|
H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256,
|
||||||
};
|
};
|
||||||
use v1::helpers::{CallRequest as CRequest, errors, limit_logs};
|
|
||||||
use v1::helpers::dispatch::{dispatch_transaction, default_gas_price};
|
|
||||||
use v1::helpers::block_import::is_major_importing;
|
|
||||||
use v1::metadata::Metadata;
|
use v1::metadata::Metadata;
|
||||||
|
|
||||||
const EXTRA_INFO_PROOF: &'static str = "Object exists in in blockchain (fetched earlier), extra_info is always available if object exists; qed";
|
const EXTRA_INFO_PROOF: &'static str = "Object exists in in blockchain (fetched earlier), extra_info is always available if object exists; qed";
|
||||||
|
@ -35,6 +35,8 @@ use updater::{Service as UpdateService};
|
|||||||
|
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use jsonrpc_macros::Trailing;
|
use jsonrpc_macros::Trailing;
|
||||||
|
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
|
||||||
|
use v1::helpers::dispatch::DEFAULT_MAC;
|
||||||
use v1::metadata::Metadata;
|
use v1::metadata::Metadata;
|
||||||
use v1::traits::Parity;
|
use v1::traits::Parity;
|
||||||
use v1::types::{
|
use v1::types::{
|
||||||
@ -44,8 +46,6 @@ use v1::types::{
|
|||||||
BlockNumber, ConsensusCapability, VersionInfo,
|
BlockNumber, ConsensusCapability, VersionInfo,
|
||||||
OperationsInfo, DappId, ChainStatus,
|
OperationsInfo, DappId, ChainStatus,
|
||||||
};
|
};
|
||||||
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
|
|
||||||
use v1::helpers::dispatch::DEFAULT_MAC;
|
|
||||||
|
|
||||||
/// Parity implementation.
|
/// Parity implementation.
|
||||||
pub struct ParityClient<C, M, S: ?Sized, U> where
|
pub struct ParityClient<C, M, S: ?Sized, U> where
|
||||||
|
@ -24,9 +24,9 @@ use ethcore::account_provider::AccountProvider;
|
|||||||
use ethcore::client::MiningBlockChainClient;
|
use ethcore::client::MiningBlockChainClient;
|
||||||
|
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
|
use v1::helpers::errors;
|
||||||
use v1::traits::ParityAccounts;
|
use v1::traits::ParityAccounts;
|
||||||
use v1::types::{H160 as RpcH160, H256 as RpcH256, DappId};
|
use v1::types::{H160 as RpcH160, H256 as RpcH256, DappId};
|
||||||
use v1::helpers::errors;
|
|
||||||
|
|
||||||
/// Account management (personal) rpc implementation.
|
/// Account management (personal) rpc implementation.
|
||||||
pub struct ParityAccountsClient<C> where C: MiningBlockChainClient {
|
pub struct ParityAccountsClient<C> where C: MiningBlockChainClient {
|
||||||
|
@ -22,21 +22,29 @@ use ethcore::client::MiningBlockChainClient;
|
|||||||
use ethcore::miner::MinerService;
|
use ethcore::miner::MinerService;
|
||||||
use util::{Address, U128, Uint};
|
use util::{Address, U128, Uint};
|
||||||
|
|
||||||
|
use futures::{self, Future, BoxFuture};
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use v1::traits::Personal;
|
|
||||||
use v1::types::{H160 as RpcH160, H256 as RpcH256, U128 as RpcU128, TransactionRequest};
|
|
||||||
use v1::helpers::errors;
|
use v1::helpers::errors;
|
||||||
use v1::helpers::dispatch::{self, sign_and_dispatch};
|
use v1::helpers::dispatch::{self, sign_and_dispatch};
|
||||||
|
use v1::traits::Personal;
|
||||||
|
use v1::types::{H160 as RpcH160, H256 as RpcH256, U128 as RpcU128, TransactionRequest};
|
||||||
|
use v1::metadata::Metadata;
|
||||||
|
|
||||||
/// Account management (personal) rpc implementation.
|
/// Account management (personal) rpc implementation.
|
||||||
pub struct PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
pub struct PersonalClient<C, M> where
|
||||||
|
C: MiningBlockChainClient,
|
||||||
|
M: MinerService,
|
||||||
|
{
|
||||||
accounts: Weak<AccountProvider>,
|
accounts: Weak<AccountProvider>,
|
||||||
client: Weak<C>,
|
client: Weak<C>,
|
||||||
miner: Weak<M>,
|
miner: Weak<M>,
|
||||||
allow_perm_unlock: bool,
|
allow_perm_unlock: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M> PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
impl<C, M> PersonalClient<C, M> where
|
||||||
|
C: MiningBlockChainClient,
|
||||||
|
M: MinerService,
|
||||||
|
{
|
||||||
/// Creates new PersonalClient
|
/// Creates new PersonalClient
|
||||||
pub fn new(store: &Arc<AccountProvider>, client: &Arc<C>, miner: &Arc<M>, allow_perm_unlock: bool) -> Self {
|
pub fn new(store: &Arc<AccountProvider>, client: &Arc<C>, miner: &Arc<M>, allow_perm_unlock: bool) -> Self {
|
||||||
PersonalClient {
|
PersonalClient {
|
||||||
@ -54,7 +62,12 @@ impl<C, M> PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: 'static, M: 'static> Personal for PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
impl<C, M> Personal for PersonalClient<C, M> where
|
||||||
|
C: MiningBlockChainClient + 'static,
|
||||||
|
M: MinerService + 'static,
|
||||||
|
{
|
||||||
|
type Metadata = Metadata;
|
||||||
|
|
||||||
fn accounts(&self) -> Result<Vec<RpcH160>, Error> {
|
fn accounts(&self) -> Result<Vec<RpcH160>, Error> {
|
||||||
self.active()?;
|
self.active()?;
|
||||||
|
|
||||||
@ -102,19 +115,30 @@ impl<C: 'static, M: 'static> Personal for PersonalClient<C, M> where C: MiningBl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_transaction(&self, request: TransactionRequest, password: String) -> Result<RpcH256, Error> {
|
fn send_transaction(&self, meta: Metadata, request: TransactionRequest, password: String) -> BoxFuture<RpcH256, Error> {
|
||||||
self.active()?;
|
let sign_and_send = move || {
|
||||||
let client = take_weak!(self.client);
|
self.active()?;
|
||||||
let miner = take_weak!(self.miner);
|
let client = take_weak!(self.client);
|
||||||
let accounts = take_weak!(self.accounts);
|
let miner = take_weak!(self.miner);
|
||||||
|
let accounts = take_weak!(self.accounts);
|
||||||
|
|
||||||
let request = dispatch::fill_optional_fields(request.into(), &*client, &*miner);
|
let default_account = match request.from {
|
||||||
sign_and_dispatch(
|
Some(ref account) => account.clone().into(),
|
||||||
&*client,
|
None => accounts
|
||||||
&*miner,
|
.default_address(meta.dapp_id.unwrap_or_default().into())
|
||||||
&*accounts,
|
.map_err(|e| errors::account("Cannot find default account.", e))?,
|
||||||
request,
|
};
|
||||||
dispatch::SignWith::Password(password)
|
|
||||||
).map(|v| v.into_value().into())
|
let request = dispatch::fill_optional_fields(request.into(), default_account, &*client, &*miner);
|
||||||
|
sign_and_dispatch(
|
||||||
|
&*client,
|
||||||
|
&*miner,
|
||||||
|
&*accounts,
|
||||||
|
request,
|
||||||
|
dispatch::SignWith::Password(password)
|
||||||
|
).map(|v| v.into_value().into())
|
||||||
|
};
|
||||||
|
|
||||||
|
futures::done(sign_and_send()).boxed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,10 @@ use ethcore::transaction::{SignedTransaction, PendingTransaction};
|
|||||||
use ethcore::miner::MinerService;
|
use ethcore::miner::MinerService;
|
||||||
|
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use v1::traits::Signer;
|
|
||||||
use v1::types::{TransactionModification, ConfirmationRequest, ConfirmationResponse, ConfirmationResponseWithToken, U256, Bytes};
|
|
||||||
use v1::helpers::{errors, SignerService, SigningQueue, ConfirmationPayload};
|
use v1::helpers::{errors, SignerService, SigningQueue, ConfirmationPayload};
|
||||||
use v1::helpers::dispatch::{self, dispatch_transaction, WithToken};
|
use v1::helpers::dispatch::{self, dispatch_transaction, WithToken};
|
||||||
|
use v1::traits::Signer;
|
||||||
|
use v1::types::{TransactionModification, ConfirmationRequest, ConfirmationResponse, ConfirmationResponseWithToken, U256, Bytes};
|
||||||
|
|
||||||
/// Transactions confirmation (personal) rpc implementation.
|
/// Transactions confirmation (personal) rpc implementation.
|
||||||
pub struct SignerClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
pub struct SignerClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||||
|
@ -28,8 +28,10 @@ use futures::{self, BoxFuture, Future};
|
|||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use v1::helpers::{
|
use v1::helpers::{
|
||||||
errors, dispatch,
|
errors, dispatch,
|
||||||
|
DefaultAccount,
|
||||||
SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, SignerService
|
SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, SignerService
|
||||||
};
|
};
|
||||||
|
use v1::metadata::Metadata;
|
||||||
use v1::traits::{EthSigning, ParitySigning};
|
use v1::traits::{EthSigning, ParitySigning};
|
||||||
use v1::types::{
|
use v1::types::{
|
||||||
H160 as RpcH160, H256 as RpcH256, U256 as RpcU256, Bytes as RpcBytes, H520 as RpcH520,
|
H160 as RpcH160, H256 as RpcH256, U256 as RpcU256, Bytes as RpcBytes, H520 as RpcH520,
|
||||||
@ -42,7 +44,7 @@ use v1::types::{
|
|||||||
|
|
||||||
const MAX_PENDING_DURATION: u64 = 60 * 60;
|
const MAX_PENDING_DURATION: u64 = 60 * 60;
|
||||||
|
|
||||||
pub enum DispatchResult {
|
enum DispatchResult {
|
||||||
Promise(ConfirmationPromise),
|
Promise(ConfirmationPromise),
|
||||||
Value(RpcConfirmationResponse),
|
Value(RpcConfirmationResponse),
|
||||||
}
|
}
|
||||||
@ -109,11 +111,15 @@ impl<C, M> SigningQueueClient<C, M> where
|
|||||||
.map_err(|_| errors::request_rejected_limit())
|
.map_err(|_| errors::request_rejected_limit())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dispatch(&self, payload: RpcConfirmationPayload) -> Result<DispatchResult, Error> {
|
fn dispatch(&self, payload: RpcConfirmationPayload, default_account: DefaultAccount) -> Result<DispatchResult, Error> {
|
||||||
let client = take_weak!(self.client);
|
let client = take_weak!(self.client);
|
||||||
let miner = take_weak!(self.miner);
|
let miner = take_weak!(self.miner);
|
||||||
|
|
||||||
let payload = dispatch::from_rpc(payload, &*client, &*miner);
|
let default_account = match default_account {
|
||||||
|
DefaultAccount::Provided(acc) => acc,
|
||||||
|
DefaultAccount::ForDapp(dapp) => take_weak!(self.accounts).default_address(dapp).ok().unwrap_or_default(),
|
||||||
|
};
|
||||||
|
let payload = dispatch::from_rpc(payload, default_account, &*client, &*miner);
|
||||||
self.add_to_queue(payload)
|
self.add_to_queue(payload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,9 +128,11 @@ impl<C: 'static, M: 'static> ParitySigning for SigningQueueClient<C, M> where
|
|||||||
C: MiningBlockChainClient,
|
C: MiningBlockChainClient,
|
||||||
M: MinerService,
|
M: MinerService,
|
||||||
{
|
{
|
||||||
|
type Metadata = Metadata;
|
||||||
|
|
||||||
fn post_sign(&self, address: RpcH160, data: RpcBytes) -> Result<RpcEither<RpcU256, RpcConfirmationResponse>, Error> {
|
fn post_sign(&self, address: RpcH160, data: RpcBytes) -> Result<RpcEither<RpcU256, RpcConfirmationResponse>, Error> {
|
||||||
self.active()?;
|
self.active()?;
|
||||||
self.dispatch(RpcConfirmationPayload::Signature((address, data).into()))
|
self.dispatch(RpcConfirmationPayload::Signature((address.clone(), data).into()), DefaultAccount::Provided(address.into()))
|
||||||
.map(|result| match result {
|
.map(|result| match result {
|
||||||
DispatchResult::Value(v) => RpcEither::Or(v),
|
DispatchResult::Value(v) => RpcEither::Or(v),
|
||||||
DispatchResult::Promise(promise) => {
|
DispatchResult::Promise(promise) => {
|
||||||
@ -135,17 +143,20 @@ impl<C: 'static, M: 'static> ParitySigning for SigningQueueClient<C, M> where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_transaction(&self, request: RpcTransactionRequest) -> Result<RpcEither<RpcU256, RpcConfirmationResponse>, Error> {
|
fn post_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcEither<RpcU256, RpcConfirmationResponse>, Error> {
|
||||||
self.active()?;
|
let post_transaction = move || {
|
||||||
self.dispatch(RpcConfirmationPayload::SendTransaction(request))
|
self.active()?;
|
||||||
.map(|result| match result {
|
self.dispatch(RpcConfirmationPayload::SendTransaction(request), meta.into())
|
||||||
DispatchResult::Value(v) => RpcEither::Or(v),
|
.map(|result| match result {
|
||||||
DispatchResult::Promise(promise) => {
|
DispatchResult::Value(v) => RpcEither::Or(v),
|
||||||
let id = promise.id();
|
DispatchResult::Promise(promise) => {
|
||||||
self.pending.lock().insert(id, promise);
|
let id = promise.id();
|
||||||
RpcEither::Either(id.into())
|
self.pending.lock().insert(id, promise);
|
||||||
},
|
RpcEither::Either(id.into())
|
||||||
})
|
},
|
||||||
|
})
|
||||||
|
};
|
||||||
|
futures::done(post_transaction()).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_request(&self, id: RpcU256) -> Result<Option<RpcConfirmationResponse>, Error> {
|
fn check_request(&self, id: RpcU256) -> Result<Option<RpcConfirmationResponse>, Error> {
|
||||||
@ -166,7 +177,7 @@ impl<C: 'static, M: 'static> ParitySigning for SigningQueueClient<C, M> where
|
|||||||
|
|
||||||
fn decrypt_message(&self, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcBytes, Error> {
|
fn decrypt_message(&self, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcBytes, Error> {
|
||||||
let res = self.active()
|
let res = self.active()
|
||||||
.and_then(|_| self.dispatch(RpcConfirmationPayload::Decrypt((address, data).into())));
|
.and_then(|_| self.dispatch(RpcConfirmationPayload::Decrypt((address.clone(), data).into()), address.into()));
|
||||||
|
|
||||||
let (ready, p) = futures::oneshot();
|
let (ready, p) = futures::oneshot();
|
||||||
// TODO [todr] typed handle_dispatch
|
// TODO [todr] typed handle_dispatch
|
||||||
@ -186,8 +197,11 @@ impl<C: 'static, M: 'static> EthSigning for SigningQueueClient<C, M> where
|
|||||||
C: MiningBlockChainClient,
|
C: MiningBlockChainClient,
|
||||||
M: MinerService,
|
M: MinerService,
|
||||||
{
|
{
|
||||||
|
type Metadata = Metadata;
|
||||||
|
|
||||||
fn sign(&self, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcH520, Error> {
|
fn sign(&self, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcH520, Error> {
|
||||||
let res = self.active().and_then(|_| self.dispatch(RpcConfirmationPayload::Signature((address, data).into())));
|
let res = self.active()
|
||||||
|
.and_then(|_| self.dispatch(RpcConfirmationPayload::Signature((address.clone(), data).into()), address.into()));
|
||||||
|
|
||||||
let (ready, p) = futures::oneshot();
|
let (ready, p) = futures::oneshot();
|
||||||
self.handle_dispatch(res, |response| {
|
self.handle_dispatch(res, |response| {
|
||||||
@ -201,8 +215,9 @@ impl<C: 'static, M: 'static> EthSigning for SigningQueueClient<C, M> where
|
|||||||
p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
|
p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_transaction(&self, request: RpcTransactionRequest) -> BoxFuture<RpcH256, Error> {
|
fn send_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcH256, Error> {
|
||||||
let res = self.active().and_then(|_| self.dispatch(RpcConfirmationPayload::SendTransaction(request)));
|
let res = self.active()
|
||||||
|
.and_then(|_| self.dispatch(RpcConfirmationPayload::SendTransaction(request), meta.into()));
|
||||||
|
|
||||||
let (ready, p) = futures::oneshot();
|
let (ready, p) = futures::oneshot();
|
||||||
self.handle_dispatch(res, |response| {
|
self.handle_dispatch(res, |response| {
|
||||||
@ -216,8 +231,8 @@ impl<C: 'static, M: 'static> EthSigning for SigningQueueClient<C, M> where
|
|||||||
p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
|
p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign_transaction(&self, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction, Error> {
|
fn sign_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction, Error> {
|
||||||
let res = self.active().and_then(|_| self.dispatch(RpcConfirmationPayload::SignTransaction(request)));
|
let res = self.active().and_then(|_| self.dispatch(RpcConfirmationPayload::SignTransaction(request), meta.into()));
|
||||||
|
|
||||||
let (ready, p) = futures::oneshot();
|
let (ready, p) = futures::oneshot();
|
||||||
self.handle_dispatch(res, |response| {
|
self.handle_dispatch(res, |response| {
|
||||||
|
@ -24,8 +24,8 @@ use ethcore::client::MiningBlockChainClient;
|
|||||||
|
|
||||||
use futures::{self, BoxFuture, Future};
|
use futures::{self, BoxFuture, Future};
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use v1::helpers::errors;
|
use v1::helpers::{errors, dispatch, DefaultAccount};
|
||||||
use v1::helpers::dispatch;
|
use v1::metadata::Metadata;
|
||||||
use v1::traits::{EthSigning, ParitySigning};
|
use v1::traits::{EthSigning, ParitySigning};
|
||||||
use v1::types::{
|
use v1::types::{
|
||||||
U256 as RpcU256,
|
U256 as RpcU256,
|
||||||
@ -68,13 +68,17 @@ impl<C, M> SigningUnsafeClient<C, M> where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle(&self, payload: RpcConfirmationPayload) -> Result<RpcConfirmationResponse, Error> {
|
fn handle(&self, payload: RpcConfirmationPayload, account: DefaultAccount) -> Result<RpcConfirmationResponse, Error> {
|
||||||
self.active()?;
|
self.active()?;
|
||||||
let client = take_weak!(self.client);
|
let client = take_weak!(self.client);
|
||||||
let miner = take_weak!(self.miner);
|
let miner = take_weak!(self.miner);
|
||||||
let accounts = take_weak!(self.accounts);
|
let accounts = take_weak!(self.accounts);
|
||||||
|
|
||||||
let payload = dispatch::from_rpc(payload, &*client, &*miner);
|
let default_account = match account {
|
||||||
|
DefaultAccount::Provided(acc) => acc,
|
||||||
|
DefaultAccount::ForDapp(dapp) => accounts.default_address(dapp).ok().unwrap_or_default(),
|
||||||
|
};
|
||||||
|
let payload = dispatch::from_rpc(payload, default_account, &*client, &*miner);
|
||||||
dispatch::execute(&*client, &*miner, &*accounts, payload, dispatch::SignWith::Nothing)
|
dispatch::execute(&*client, &*miner, &*accounts, payload, dispatch::SignWith::Nothing)
|
||||||
.map(|v| v.into_value())
|
.map(|v| v.into_value())
|
||||||
}
|
}
|
||||||
@ -84,8 +88,10 @@ impl<C: 'static, M: 'static> EthSigning for SigningUnsafeClient<C, M> where
|
|||||||
C: MiningBlockChainClient,
|
C: MiningBlockChainClient,
|
||||||
M: MinerService,
|
M: MinerService,
|
||||||
{
|
{
|
||||||
|
type Metadata = Metadata;
|
||||||
|
|
||||||
fn sign(&self, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcH520, Error> {
|
fn sign(&self, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcH520, Error> {
|
||||||
let result = match self.handle(RpcConfirmationPayload::Signature((address, data).into())) {
|
let result = match self.handle(RpcConfirmationPayload::Signature((address.clone(), data).into()), address.into()) {
|
||||||
Ok(RpcConfirmationResponse::Signature(signature)) => Ok(signature),
|
Ok(RpcConfirmationResponse::Signature(signature)) => Ok(signature),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
e => Err(errors::internal("Unexpected result", e)),
|
e => Err(errors::internal("Unexpected result", e)),
|
||||||
@ -94,8 +100,8 @@ impl<C: 'static, M: 'static> EthSigning for SigningUnsafeClient<C, M> where
|
|||||||
futures::done(result).boxed()
|
futures::done(result).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_transaction(&self, request: RpcTransactionRequest) -> BoxFuture<RpcH256, Error> {
|
fn send_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcH256, Error> {
|
||||||
let result = match self.handle(RpcConfirmationPayload::SendTransaction(request)) {
|
let result = match self.handle(RpcConfirmationPayload::SendTransaction(request), meta.into()) {
|
||||||
Ok(RpcConfirmationResponse::SendTransaction(hash)) => Ok(hash),
|
Ok(RpcConfirmationResponse::SendTransaction(hash)) => Ok(hash),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
e => Err(errors::internal("Unexpected result", e)),
|
e => Err(errors::internal("Unexpected result", e)),
|
||||||
@ -104,8 +110,8 @@ impl<C: 'static, M: 'static> EthSigning for SigningUnsafeClient<C, M> where
|
|||||||
futures::done(result).boxed()
|
futures::done(result).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign_transaction(&self, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction, Error> {
|
fn sign_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction, Error> {
|
||||||
let result = match self.handle(RpcConfirmationPayload::SignTransaction(request)) {
|
let result = match self.handle(RpcConfirmationPayload::SignTransaction(request), meta.into()) {
|
||||||
Ok(RpcConfirmationResponse::SignTransaction(tx)) => Ok(tx),
|
Ok(RpcConfirmationResponse::SignTransaction(tx)) => Ok(tx),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
e => Err(errors::internal("Unexpected result", e)),
|
e => Err(errors::internal("Unexpected result", e)),
|
||||||
@ -119,8 +125,10 @@ impl<C: 'static, M: 'static> ParitySigning for SigningUnsafeClient<C, M> where
|
|||||||
C: MiningBlockChainClient,
|
C: MiningBlockChainClient,
|
||||||
M: MinerService,
|
M: MinerService,
|
||||||
{
|
{
|
||||||
|
type Metadata = Metadata;
|
||||||
|
|
||||||
fn decrypt_message(&self, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcBytes, Error> {
|
fn decrypt_message(&self, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcBytes, Error> {
|
||||||
let result = match self.handle(RpcConfirmationPayload::Decrypt((address, data).into())) {
|
let result = match self.handle(RpcConfirmationPayload::Decrypt((address.clone(), data).into()), address.into()) {
|
||||||
Ok(RpcConfirmationResponse::Decrypt(data)) => Ok(data),
|
Ok(RpcConfirmationResponse::Decrypt(data)) => Ok(data),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
e => Err(errors::internal("Unexpected result", e)),
|
e => Err(errors::internal("Unexpected result", e)),
|
||||||
@ -134,9 +142,9 @@ impl<C: 'static, M: 'static> ParitySigning for SigningUnsafeClient<C, M> where
|
|||||||
Err(errors::signer_disabled())
|
Err(errors::signer_disabled())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_transaction(&self, _: RpcTransactionRequest) -> Result<RpcEither<RpcU256, RpcConfirmationResponse>, Error> {
|
fn post_transaction(&self, _: Metadata, _: RpcTransactionRequest) -> BoxFuture<RpcEither<RpcU256, RpcConfirmationResponse>, Error> {
|
||||||
// We don't support this in non-signer mode.
|
// We don't support this in non-signer mode.
|
||||||
Err(errors::signer_disabled())
|
futures::done(Err(errors::signer_disabled())).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_request(&self, _: RpcU256) -> Result<Option<RpcConfirmationResponse>, Error> {
|
fn check_request(&self, _: RpcU256) -> Result<Option<RpcConfirmationResponse>, Error> {
|
||||||
|
@ -25,7 +25,7 @@ use ethcore::header::BlockNumber;
|
|||||||
use ethcore::transaction::{UnverifiedTransaction, SignedTransaction, PendingTransaction};
|
use ethcore::transaction::{UnverifiedTransaction, SignedTransaction, PendingTransaction};
|
||||||
use ethcore::receipt::{Receipt, RichReceipt};
|
use ethcore::receipt::{Receipt, RichReceipt};
|
||||||
use ethcore::miner::{MinerService, MinerStatus, TransactionImportResult, LocalTransactionStatus};
|
use ethcore::miner::{MinerService, MinerStatus, TransactionImportResult, LocalTransactionStatus};
|
||||||
use ethcore::account_provider::Error as AccountError;
|
use ethcore::account_provider::SignError as AccountError;
|
||||||
|
|
||||||
/// Test miner service.
|
/// Test miner service.
|
||||||
pub struct TestMinerService {
|
pub struct TestMinerService {
|
||||||
|
@ -19,14 +19,14 @@ use std::str::FromStr;
|
|||||||
use jsonrpc_core::IoHandler;
|
use jsonrpc_core::IoHandler;
|
||||||
use util::{U256, Uint, Address};
|
use util::{U256, Uint, Address};
|
||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
use v1::{PersonalClient, Personal};
|
use v1::{PersonalClient, Personal, Metadata};
|
||||||
use v1::tests::helpers::TestMinerService;
|
use v1::tests::helpers::TestMinerService;
|
||||||
use ethcore::client::TestBlockChainClient;
|
use ethcore::client::TestBlockChainClient;
|
||||||
use ethcore::transaction::{Action, Transaction};
|
use ethcore::transaction::{Action, Transaction};
|
||||||
|
|
||||||
struct PersonalTester {
|
struct PersonalTester {
|
||||||
accounts: Arc<AccountProvider>,
|
accounts: Arc<AccountProvider>,
|
||||||
io: IoHandler,
|
io: IoHandler<Metadata>,
|
||||||
miner: Arc<TestMinerService>,
|
miner: Arc<TestMinerService>,
|
||||||
// these unused fields are necessary to keep the data alive
|
// these unused fields are necessary to keep the data alive
|
||||||
// as the handler has only weak pointers.
|
// as the handler has only weak pointers.
|
||||||
|
@ -26,13 +26,14 @@ use rlp::encode;
|
|||||||
use serde_json;
|
use serde_json;
|
||||||
use jsonrpc_core::IoHandler;
|
use jsonrpc_core::IoHandler;
|
||||||
use v1::{SignerClient, Signer};
|
use v1::{SignerClient, Signer};
|
||||||
|
use v1::metadata::Metadata;
|
||||||
use v1::tests::helpers::TestMinerService;
|
use v1::tests::helpers::TestMinerService;
|
||||||
use v1::helpers::{SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload};
|
use v1::helpers::{SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload};
|
||||||
|
|
||||||
struct SignerTester {
|
struct SignerTester {
|
||||||
signer: Arc<SignerService>,
|
signer: Arc<SignerService>,
|
||||||
accounts: Arc<AccountProvider>,
|
accounts: Arc<AccountProvider>,
|
||||||
io: IoHandler,
|
io: IoHandler<Metadata>,
|
||||||
miner: Arc<TestMinerService>,
|
miner: Arc<TestMinerService>,
|
||||||
// these unused fields are necessary to keep the data alive
|
// these unused fields are necessary to keep the data alive
|
||||||
// as the handler has only weak pointers.
|
// as the handler has only weak pointers.
|
||||||
@ -77,6 +78,7 @@ fn should_return_list_of_items_to_confirm() {
|
|||||||
let tester = signer_tester();
|
let tester = signer_tester();
|
||||||
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
||||||
from: Address::from(1),
|
from: Address::from(1),
|
||||||
|
used_default_from: false,
|
||||||
to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
|
to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
|
||||||
gas_price: U256::from(10_000),
|
gas_price: U256::from(10_000),
|
||||||
gas: U256::from(10_000_000),
|
gas: U256::from(10_000_000),
|
||||||
@ -107,6 +109,7 @@ fn should_reject_transaction_from_queue_without_dispatching() {
|
|||||||
let tester = signer_tester();
|
let tester = signer_tester();
|
||||||
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
||||||
from: Address::from(1),
|
from: Address::from(1),
|
||||||
|
used_default_from: false,
|
||||||
to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
|
to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
|
||||||
gas_price: U256::from(10_000),
|
gas_price: U256::from(10_000),
|
||||||
gas: U256::from(10_000_000),
|
gas: U256::from(10_000_000),
|
||||||
@ -133,6 +136,7 @@ fn should_not_remove_transaction_if_password_is_invalid() {
|
|||||||
let tester = signer_tester();
|
let tester = signer_tester();
|
||||||
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
||||||
from: Address::from(1),
|
from: Address::from(1),
|
||||||
|
used_default_from: false,
|
||||||
to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
|
to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
|
||||||
gas_price: U256::from(10_000),
|
gas_price: U256::from(10_000),
|
||||||
gas: U256::from(10_000_000),
|
gas: U256::from(10_000_000),
|
||||||
@ -176,6 +180,7 @@ fn should_confirm_transaction_and_dispatch() {
|
|||||||
let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap();
|
let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap();
|
||||||
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
||||||
from: address,
|
from: address,
|
||||||
|
used_default_from: false,
|
||||||
to: Some(recipient),
|
to: Some(recipient),
|
||||||
gas_price: U256::from(10_000),
|
gas_price: U256::from(10_000),
|
||||||
gas: U256::from(10_000_000),
|
gas: U256::from(10_000_000),
|
||||||
@ -221,6 +226,7 @@ fn should_alter_the_sender_and_nonce() {
|
|||||||
let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap();
|
let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap();
|
||||||
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
||||||
from: 0.into(),
|
from: 0.into(),
|
||||||
|
used_default_from: false,
|
||||||
to: Some(recipient),
|
to: Some(recipient),
|
||||||
gas_price: U256::from(10_000),
|
gas_price: U256::from(10_000),
|
||||||
gas: U256::from(10_000_000),
|
gas: U256::from(10_000_000),
|
||||||
@ -270,6 +276,7 @@ fn should_confirm_transaction_with_token() {
|
|||||||
let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap();
|
let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap();
|
||||||
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
||||||
from: address,
|
from: address,
|
||||||
|
used_default_from: false,
|
||||||
to: Some(recipient),
|
to: Some(recipient),
|
||||||
gas_price: U256::from(10_000),
|
gas_price: U256::from(10_000),
|
||||||
gas: U256::from(10_000_000),
|
gas: U256::from(10_000_000),
|
||||||
@ -318,6 +325,7 @@ fn should_confirm_transaction_with_rlp() {
|
|||||||
let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap();
|
let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap();
|
||||||
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
||||||
from: address,
|
from: address,
|
||||||
|
used_default_from: false,
|
||||||
to: Some(recipient),
|
to: Some(recipient),
|
||||||
gas_price: U256::from(10_000),
|
gas_price: U256::from(10_000),
|
||||||
gas: U256::from(10_000_000),
|
gas: U256::from(10_000_000),
|
||||||
@ -365,6 +373,7 @@ fn should_return_error_when_sender_does_not_match() {
|
|||||||
let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap();
|
let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap();
|
||||||
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest {
|
||||||
from: Address::default(),
|
from: Address::default(),
|
||||||
|
used_default_from: false,
|
||||||
to: Some(recipient),
|
to: Some(recipient),
|
||||||
gas_price: U256::from(10_000),
|
gas_price: U256::from(10_000),
|
||||||
gas: U256::from(10_000_000),
|
gas: U256::from(10_000_000),
|
||||||
|
@ -24,6 +24,8 @@ use v1::types::{Bytes, H160, H256, H520, TransactionRequest, RichRawTransaction}
|
|||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
/// Signing methods implementation relying on unlocked accounts.
|
/// Signing methods implementation relying on unlocked accounts.
|
||||||
pub trait EthSigning {
|
pub trait EthSigning {
|
||||||
|
type Metadata;
|
||||||
|
|
||||||
/// Signs the hash of data with given address signature.
|
/// Signs the hash of data with given address signature.
|
||||||
#[rpc(async, name = "eth_sign")]
|
#[rpc(async, name = "eth_sign")]
|
||||||
fn sign(&self, H160, Bytes) -> BoxFuture<H520, Error>;
|
fn sign(&self, H160, Bytes) -> BoxFuture<H520, Error>;
|
||||||
@ -31,13 +33,13 @@ build_rpc_trait! {
|
|||||||
/// Sends transaction; will block waiting for signer to return the
|
/// Sends transaction; will block waiting for signer to return the
|
||||||
/// transaction hash.
|
/// transaction hash.
|
||||||
/// If Signer is disable it will require the account to be unlocked.
|
/// If Signer is disable it will require the account to be unlocked.
|
||||||
#[rpc(async, name = "eth_sendTransaction")]
|
#[rpc(meta, name = "eth_sendTransaction")]
|
||||||
fn send_transaction(&self, TransactionRequest) -> BoxFuture<H256, Error>;
|
fn send_transaction(&self, Self::Metadata, TransactionRequest) -> BoxFuture<H256, Error>;
|
||||||
|
|
||||||
/// Signs transactions without dispatching it to the network.
|
/// Signs transactions without dispatching it to the network.
|
||||||
/// Returns signed transaction RLP representation and the transaction itself.
|
/// Returns signed transaction RLP representation and the transaction itself.
|
||||||
/// It can be later submitted using `eth_sendRawTransaction/eth_submitTransaction`.
|
/// It can be later submitted using `eth_sendRawTransaction/eth_submitTransaction`.
|
||||||
#[rpc(async, name = "eth_signTransaction")]
|
#[rpc(meta, name = "eth_signTransaction")]
|
||||||
fn sign_transaction(&self, TransactionRequest) -> BoxFuture<RichRawTransaction, Error>;
|
fn sign_transaction(&self, Self::Metadata, TransactionRequest) -> BoxFuture<RichRawTransaction, Error>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ use v1::types::{U256, H160, Bytes, ConfirmationResponse, TransactionRequest, Eit
|
|||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
/// Signing methods implementation.
|
/// Signing methods implementation.
|
||||||
pub trait ParitySigning {
|
pub trait ParitySigning {
|
||||||
|
type Metadata;
|
||||||
|
|
||||||
/// Posts sign request asynchronously.
|
/// Posts sign request asynchronously.
|
||||||
/// Will return a confirmation ID for later use with check_transaction.
|
/// Will return a confirmation ID for later use with check_transaction.
|
||||||
#[rpc(name = "parity_postSign")]
|
#[rpc(name = "parity_postSign")]
|
||||||
@ -30,8 +32,8 @@ build_rpc_trait! {
|
|||||||
|
|
||||||
/// Posts transaction asynchronously.
|
/// Posts transaction asynchronously.
|
||||||
/// Will return a transaction ID for later use with check_transaction.
|
/// Will return a transaction ID for later use with check_transaction.
|
||||||
#[rpc(name = "parity_postTransaction")]
|
#[rpc(meta, name = "parity_postTransaction")]
|
||||||
fn post_transaction(&self, TransactionRequest) -> Result<Either<U256, ConfirmationResponse>, Error>;
|
fn post_transaction(&self, Self::Metadata, TransactionRequest) -> BoxFuture<Either<U256, ConfirmationResponse>, Error>;
|
||||||
|
|
||||||
/// Checks the progress of a previously posted request (transaction/sign).
|
/// Checks the progress of a previously posted request (transaction/sign).
|
||||||
/// Should be given a valid send_transaction ID.
|
/// Should be given a valid send_transaction ID.
|
||||||
|
@ -17,11 +17,15 @@
|
|||||||
//! Personal rpc interface.
|
//! Personal rpc interface.
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
|
|
||||||
|
use futures::BoxFuture;
|
||||||
|
|
||||||
use v1::types::{U128, H160, H256, TransactionRequest};
|
use v1::types::{U128, H160, H256, TransactionRequest};
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
/// Personal rpc interface. Safe (read-only) functions.
|
/// Personal rpc interface. Safe (read-only) functions.
|
||||||
pub trait Personal {
|
pub trait Personal {
|
||||||
|
type Metadata;
|
||||||
|
|
||||||
/// Lists all stored accounts
|
/// Lists all stored accounts
|
||||||
#[rpc(name = "personal_listAccounts")]
|
#[rpc(name = "personal_listAccounts")]
|
||||||
fn accounts(&self) -> Result<Vec<H160>, Error>;
|
fn accounts(&self) -> Result<Vec<H160>, Error>;
|
||||||
@ -36,7 +40,7 @@ build_rpc_trait! {
|
|||||||
fn unlock_account(&self, H160, String, Option<U128>) -> Result<bool, Error>;
|
fn unlock_account(&self, H160, String, Option<U128>) -> Result<bool, Error>;
|
||||||
|
|
||||||
/// Sends transaction and signs it in single call. The account is not unlocked in such case.
|
/// Sends transaction and signs it in single call. The account is not unlocked in such case.
|
||||||
#[rpc(name = "personal_sendTransaction")]
|
#[rpc(meta, name = "personal_sendTransaction")]
|
||||||
fn send_transaction(&self, TransactionRequest, String) -> Result<H256, Error>;
|
fn send_transaction(&self, Self::Metadata, TransactionRequest, String) -> BoxFuture<H256, Error>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,6 +267,7 @@ mod tests {
|
|||||||
id: 15.into(),
|
id: 15.into(),
|
||||||
payload: helpers::ConfirmationPayload::SendTransaction(helpers::FilledTransactionRequest {
|
payload: helpers::ConfirmationPayload::SendTransaction(helpers::FilledTransactionRequest {
|
||||||
from: 0.into(),
|
from: 0.into(),
|
||||||
|
used_default_from: false,
|
||||||
to: None,
|
to: None,
|
||||||
gas: 15_000.into(),
|
gas: 15_000.into(),
|
||||||
gas_price: 10_000.into(),
|
gas_price: 10_000.into(),
|
||||||
@ -292,6 +293,7 @@ mod tests {
|
|||||||
id: 15.into(),
|
id: 15.into(),
|
||||||
payload: helpers::ConfirmationPayload::SignTransaction(helpers::FilledTransactionRequest {
|
payload: helpers::ConfirmationPayload::SignTransaction(helpers::FilledTransactionRequest {
|
||||||
from: 0.into(),
|
from: 0.into(),
|
||||||
|
used_default_from: false,
|
||||||
to: None,
|
to: None,
|
||||||
gas: 15_000.into(),
|
gas: 15_000.into(),
|
||||||
gas_price: 10_000.into(),
|
gas_price: 10_000.into(),
|
||||||
|
@ -27,7 +27,7 @@ use std::fmt;
|
|||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct TransactionRequest {
|
pub struct TransactionRequest {
|
||||||
/// Sender
|
/// Sender
|
||||||
pub from: H160,
|
pub from: Option<H160>,
|
||||||
/// Recipient
|
/// Recipient
|
||||||
pub to: Option<H160>,
|
pub to: Option<H160>,
|
||||||
/// Gas Price
|
/// Gas Price
|
||||||
@ -86,7 +86,7 @@ impl fmt::Display for TransactionRequest {
|
|||||||
impl From<helpers::TransactionRequest> for TransactionRequest {
|
impl From<helpers::TransactionRequest> for TransactionRequest {
|
||||||
fn from(r: helpers::TransactionRequest) -> Self {
|
fn from(r: helpers::TransactionRequest) -> Self {
|
||||||
TransactionRequest {
|
TransactionRequest {
|
||||||
from: r.from.into(),
|
from: r.from.map(Into::into),
|
||||||
to: r.to.map(Into::into),
|
to: r.to.map(Into::into),
|
||||||
gas_price: r.gas_price.map(Into::into),
|
gas_price: r.gas_price.map(Into::into),
|
||||||
gas: r.gas.map(Into::into),
|
gas: r.gas.map(Into::into),
|
||||||
@ -101,7 +101,7 @@ impl From<helpers::TransactionRequest> for TransactionRequest {
|
|||||||
impl From<helpers::FilledTransactionRequest> for TransactionRequest {
|
impl From<helpers::FilledTransactionRequest> for TransactionRequest {
|
||||||
fn from(r: helpers::FilledTransactionRequest) -> Self {
|
fn from(r: helpers::FilledTransactionRequest) -> Self {
|
||||||
TransactionRequest {
|
TransactionRequest {
|
||||||
from: r.from.into(),
|
from: Some(r.from.into()),
|
||||||
to: r.to.map(Into::into),
|
to: r.to.map(Into::into),
|
||||||
gas_price: Some(r.gas_price.into()),
|
gas_price: Some(r.gas_price.into()),
|
||||||
gas: Some(r.gas.into()),
|
gas: Some(r.gas.into()),
|
||||||
@ -116,7 +116,7 @@ impl From<helpers::FilledTransactionRequest> for TransactionRequest {
|
|||||||
impl Into<helpers::TransactionRequest> for TransactionRequest {
|
impl Into<helpers::TransactionRequest> for TransactionRequest {
|
||||||
fn into(self) -> helpers::TransactionRequest {
|
fn into(self) -> helpers::TransactionRequest {
|
||||||
helpers::TransactionRequest {
|
helpers::TransactionRequest {
|
||||||
from: self.from.into(),
|
from: self.from.map(Into::into),
|
||||||
to: self.to.map(Into::into),
|
to: self.to.map(Into::into),
|
||||||
gas_price: self.gas_price.map(Into::into),
|
gas_price: self.gas_price.map(Into::into),
|
||||||
gas: self.gas.map(Into::into),
|
gas: self.gas.map(Into::into),
|
||||||
@ -152,7 +152,7 @@ mod tests {
|
|||||||
let deserialized: TransactionRequest = serde_json::from_str(s).unwrap();
|
let deserialized: TransactionRequest = serde_json::from_str(s).unwrap();
|
||||||
|
|
||||||
assert_eq!(deserialized, TransactionRequest {
|
assert_eq!(deserialized, TransactionRequest {
|
||||||
from: H160::from(1),
|
from: Some(H160::from(1)),
|
||||||
to: Some(H160::from(2)),
|
to: Some(H160::from(2)),
|
||||||
gas_price: Some(U256::from(1)),
|
gas_price: Some(U256::from(1)),
|
||||||
gas: Some(U256::from(2)),
|
gas: Some(U256::from(2)),
|
||||||
@ -176,7 +176,7 @@ mod tests {
|
|||||||
let deserialized: TransactionRequest = serde_json::from_str(s).unwrap();
|
let deserialized: TransactionRequest = serde_json::from_str(s).unwrap();
|
||||||
|
|
||||||
assert_eq!(deserialized, TransactionRequest {
|
assert_eq!(deserialized, TransactionRequest {
|
||||||
from: H160::from_str("b60e8dd61c5d32be8058bb8eb970870f07233155").unwrap(),
|
from: Some(H160::from_str("b60e8dd61c5d32be8058bb8eb970870f07233155").unwrap()),
|
||||||
to: Some(H160::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
|
to: Some(H160::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
|
||||||
gas_price: Some(U256::from_str("9184e72a000").unwrap()),
|
gas_price: Some(U256::from_str("9184e72a000").unwrap()),
|
||||||
gas: Some(U256::from_str("76c0").unwrap()),
|
gas: Some(U256::from_str("76c0").unwrap()),
|
||||||
@ -193,7 +193,7 @@ mod tests {
|
|||||||
let deserialized: TransactionRequest = serde_json::from_str(s).unwrap();
|
let deserialized: TransactionRequest = serde_json::from_str(s).unwrap();
|
||||||
|
|
||||||
assert_eq!(deserialized, TransactionRequest {
|
assert_eq!(deserialized, TransactionRequest {
|
||||||
from: H160::from(1).into(),
|
from: Some(H160::from(1).into()),
|
||||||
to: None,
|
to: None,
|
||||||
gas_price: None,
|
gas_price: None,
|
||||||
gas: None,
|
gas: None,
|
||||||
@ -217,7 +217,7 @@ mod tests {
|
|||||||
let deserialized: TransactionRequest = serde_json::from_str(s).unwrap();
|
let deserialized: TransactionRequest = serde_json::from_str(s).unwrap();
|
||||||
|
|
||||||
assert_eq!(deserialized, TransactionRequest {
|
assert_eq!(deserialized, TransactionRequest {
|
||||||
from: H160::from_str("b5f7502a2807cb23615c7456055e1d65b2508625").unwrap(),
|
from: Some(H160::from_str("b5f7502a2807cb23615c7456055e1d65b2508625").unwrap()),
|
||||||
to: Some(H160::from_str("895d32f2db7d01ebb50053f9e48aacf26584fe40").unwrap()),
|
to: Some(H160::from_str("895d32f2db7d01ebb50053f9e48aacf26584fe40").unwrap()),
|
||||||
gas_price: Some(U256::from_str("0ba43b7400").unwrap()),
|
gas_price: Some(U256::from_str("0ba43b7400").unwrap()),
|
||||||
gas: Some(U256::from_str("2fd618").unwrap()),
|
gas: Some(U256::from_str("2fd618").unwrap()),
|
||||||
|
Loading…
Reference in New Issue
Block a user