dispatcher abstraction, port most things to it
This commit is contained in:
		
							parent
							
								
									4bb45c4f64
								
							
						
					
					
						commit
						e73ea80954
					
				@ -472,6 +472,12 @@ impl PendingTransaction {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Deref for PendingTransaction {
 | 
				
			||||||
 | 
						type Target = SignedTransaction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn deref(&self) -> &SignedTransaction { &self.transaction }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<SignedTransaction> for PendingTransaction {
 | 
					impl From<SignedTransaction> for PendingTransaction {
 | 
				
			||||||
	fn from(t: SignedTransaction) -> Self {
 | 
						fn from(t: SignedTransaction) -> Self {
 | 
				
			||||||
		PendingTransaction {
 | 
							PendingTransaction {
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use std::fmt::Debug;
 | 
					use std::fmt::Debug;
 | 
				
			||||||
use std::ops::Deref;
 | 
					use std::ops::Deref;
 | 
				
			||||||
 | 
					use std::sync::Weak;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use futures::{future, Future, BoxFuture};
 | 
				
			||||||
use rlp;
 | 
					use rlp;
 | 
				
			||||||
use util::{Address, H520, H256, U256, Uint, Bytes};
 | 
					use util::{Address, H520, H256, U256, Uint, Bytes};
 | 
				
			||||||
use util::bytes::ToPretty;
 | 
					use util::bytes::ToPretty;
 | 
				
			||||||
@ -38,6 +41,118 @@ use v1::types::{
 | 
				
			|||||||
	DecryptRequest as RpcDecryptRequest,
 | 
						DecryptRequest as RpcDecryptRequest,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Has the capability to dispatch, sign, and decrypt.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Requires a clone implementation, with the implication that it be cheap;
 | 
				
			||||||
 | 
					/// usually just bumping a reference count or two.
 | 
				
			||||||
 | 
					pub trait Dispatcher: Send + Sync + Clone {
 | 
				
			||||||
 | 
						// TODO: when ATC exist, use zero-cost
 | 
				
			||||||
 | 
						// type Out<T>: IntoFuture<T, Error>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// Fill optional fields of a transaction request, fetching gas price but not nonce.
 | 
				
			||||||
 | 
						fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address)
 | 
				
			||||||
 | 
							-> BoxFuture<FilledTransactionRequest, Error>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// Sign the given transaction request without dispatching, fetching appropriate nonce.
 | 
				
			||||||
 | 
						fn sign(&self, accounts: &AccountProvider, filled: FilledTransactionRequest, password: SignWith)
 | 
				
			||||||
 | 
							-> BoxFuture<WithToken<SignedTransaction>, Error>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// "Dispatch" a local transaction.
 | 
				
			||||||
 | 
						fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result<H256, Error>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// A dispatcher which uses references to a client and miner in order to sign
 | 
				
			||||||
 | 
					/// requests locally.
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub struct FullDispatcher<C, M> {
 | 
				
			||||||
 | 
						client: Weak<C>,
 | 
				
			||||||
 | 
						miner: Weak<M>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<C, M> FullDispatcher<C, M> {
 | 
				
			||||||
 | 
						/// Create a `FullDispatcher` from weak references to a client and miner.
 | 
				
			||||||
 | 
						pub fn new(client: Weak<C>, miner: Weak<M>) -> Self {
 | 
				
			||||||
 | 
							FullDispatcher {
 | 
				
			||||||
 | 
								client: client,
 | 
				
			||||||
 | 
								miner: miner,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<C, M> Clone for FullDispatcher<C, M> {
 | 
				
			||||||
 | 
						fn clone(&self) -> Self {
 | 
				
			||||||
 | 
							FullDispatcher {
 | 
				
			||||||
 | 
								client: self.client.clone(),
 | 
				
			||||||
 | 
								miner: self.miner.clone(),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<C: MiningBlockChainClient, M: MinerService> Dispatcher for FullDispatcher<C, M> {
 | 
				
			||||||
 | 
						fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address)
 | 
				
			||||||
 | 
							-> BoxFuture<FilledTransactionRequest, Error>
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							let inner = move || {
 | 
				
			||||||
 | 
								let (client, miner) = (take_weak!(self.client), take_weak!(self.miner));
 | 
				
			||||||
 | 
								Ok(FilledTransactionRequest {
 | 
				
			||||||
 | 
									from: request.from.unwrap_or(default_sender),
 | 
				
			||||||
 | 
									used_default_from: request.from.is_none(),
 | 
				
			||||||
 | 
									to: request.to,
 | 
				
			||||||
 | 
									nonce: request.nonce,
 | 
				
			||||||
 | 
									gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(client, miner)),
 | 
				
			||||||
 | 
									gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()),
 | 
				
			||||||
 | 
									value: request.value.unwrap_or_else(|| 0.into()),
 | 
				
			||||||
 | 
									data: request.data.unwrap_or_else(Vec::new),
 | 
				
			||||||
 | 
									condition: request.condition,
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							future::done(inner()).boxed()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn sign(&self, accounts: &AccountProvider, filled: FilledTransactionRequest, password: SignWith)
 | 
				
			||||||
 | 
							-> BoxFuture<WithToken<SignedTransaction>, Error>
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							let inner = move || {
 | 
				
			||||||
 | 
								let (client, miner) = (take_weak!(self.client), take_weak!(self.miner));
 | 
				
			||||||
 | 
								let network_id = client.signing_network_id();
 | 
				
			||||||
 | 
								let address = filled.from;
 | 
				
			||||||
 | 
								let signed_transaction = {
 | 
				
			||||||
 | 
									let t = Transaction {
 | 
				
			||||||
 | 
										nonce: filled.nonce
 | 
				
			||||||
 | 
											.or_else(|| miner
 | 
				
			||||||
 | 
												.last_nonce(&filled.from)
 | 
				
			||||||
 | 
												.map(|nonce| nonce + U256::one()))
 | 
				
			||||||
 | 
											.unwrap_or_else(|| client.latest_nonce(&filled.from)),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										action: filled.to.map_or(Action::Create, Action::Call),
 | 
				
			||||||
 | 
										gas: filled.gas,
 | 
				
			||||||
 | 
										gas_price: filled.gas_price,
 | 
				
			||||||
 | 
										value: filled.value,
 | 
				
			||||||
 | 
										data: filled.data,
 | 
				
			||||||
 | 
									};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									let hash = t.hash(network_id);
 | 
				
			||||||
 | 
									let signature = signature(accounts, address, hash, password)?;
 | 
				
			||||||
 | 
									signature.map(|sig| {
 | 
				
			||||||
 | 
										SignedTransaction::new(t.with_signature(sig, network_id))
 | 
				
			||||||
 | 
											.expect("Transaction was signed by AccountsProvider; it never produces invalid signatures; qed")
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
								Ok(signed_transaction)
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							future::done(inner()).boxed()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result<H256, Error> {
 | 
				
			||||||
 | 
							let hash = signed_transaction.transaction.hash();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							take_weak!(self.miner).import_own_transaction(take_weak!(self.client), signed_transaction)
 | 
				
			||||||
 | 
								.map_err(errors::from_transaction_error)
 | 
				
			||||||
 | 
								.map(|_| hash)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub const DEFAULT_MAC: [u8; 2] = [0, 0];
 | 
					pub const DEFAULT_MAC: [u8; 2] = [0, 0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type AccountToken = String;
 | 
					type AccountToken = String;
 | 
				
			||||||
@ -83,6 +198,14 @@ impl<T: Debug> WithToken<T> {
 | 
				
			|||||||
			WithToken::Yes(v, _) => v,
 | 
								WithToken::Yes(v, _) => v,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// Convert the `WithToken` into a tuple.
 | 
				
			||||||
 | 
						pub fn into_tuple(self) -> (T, Option<AccountToken>) {
 | 
				
			||||||
 | 
							match self {
 | 
				
			||||||
 | 
								WithToken::No(v) => (v, None),
 | 
				
			||||||
 | 
								WithToken::Yes(v, token) => (v, Some(token))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T: Debug> From<(T, AccountToken)> for WithToken<T> {
 | 
					impl<T: Debug> From<(T, AccountToken)> for WithToken<T> {
 | 
				
			||||||
@ -91,26 +214,44 @@ impl<T: Debug> From<(T, AccountToken)> for WithToken<T> {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn execute<C, M>(client: &C, miner: &M, accounts: &AccountProvider, payload: ConfirmationPayload, pass: SignWith) -> Result<WithToken<ConfirmationResponse>, Error>
 | 
					impl<T: Debug> From<(T, Option<AccountToken>)> for WithToken<T> {
 | 
				
			||||||
	where C: MiningBlockChainClient, M: MinerService
 | 
						fn from(tuple: (T, Option<AccountToken>)) -> Self {
 | 
				
			||||||
{
 | 
							match tuple.1 {
 | 
				
			||||||
 | 
								Some(token) => WithToken::Yes(tuple.0, token),
 | 
				
			||||||
 | 
								None => WithToken::No(tuple.0),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn execute<D: Dispatcher>(
 | 
				
			||||||
 | 
						dispatcher: D,
 | 
				
			||||||
 | 
						accounts: &AccountProvider,
 | 
				
			||||||
 | 
						payload: ConfirmationPayload,
 | 
				
			||||||
 | 
						pass: SignWith
 | 
				
			||||||
 | 
					) -> BoxFuture<WithToken<ConfirmationResponse>, Error> {
 | 
				
			||||||
	match payload {
 | 
						match payload {
 | 
				
			||||||
		ConfirmationPayload::SendTransaction(request) => {
 | 
							ConfirmationPayload::SendTransaction(request) => {
 | 
				
			||||||
			sign_and_dispatch(client, miner, accounts, request, pass)
 | 
								let condition = request.condition.clone();
 | 
				
			||||||
				.map(|result| result
 | 
								dispatcher.sign(accounts, request, pass)
 | 
				
			||||||
					.map(RpcH256::from)
 | 
									.map(move |v| v.map(move |tx| PendingTransaction::new(tx, condition)))
 | 
				
			||||||
					.map(ConfirmationResponse::SendTransaction)
 | 
									.map(WithToken::into_tuple)
 | 
				
			||||||
				)
 | 
									.map(|(tx, token)| (tx, token, dispatcher))
 | 
				
			||||||
 | 
									.and_then(|(tx, tok, dispatcher)| {
 | 
				
			||||||
 | 
										dispatcher.dispatch_transaction(tx)
 | 
				
			||||||
 | 
											.map(RpcH256::from)
 | 
				
			||||||
 | 
											.map(ConfirmationResponse::SendTransaction)
 | 
				
			||||||
 | 
											.map(move |h| WithToken::from((h, tok)))
 | 
				
			||||||
 | 
									}).boxed()
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		ConfirmationPayload::SignTransaction(request) => {
 | 
							ConfirmationPayload::SignTransaction(request) => {
 | 
				
			||||||
			sign_no_dispatch(client, miner, accounts, request, pass)
 | 
								dispatcher.sign(accounts, request, pass)
 | 
				
			||||||
				.map(|result| result
 | 
									.map(|result| result
 | 
				
			||||||
					.map(RpcRichRawTransaction::from)
 | 
										.map(RpcRichRawTransaction::from)
 | 
				
			||||||
					.map(ConfirmationResponse::SignTransaction)
 | 
										.map(ConfirmationResponse::SignTransaction)
 | 
				
			||||||
				)
 | 
									).boxed()
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		ConfirmationPayload::Signature(address, data) => {
 | 
							ConfirmationPayload::Signature(address, data) => {
 | 
				
			||||||
			signature(accounts, address, data.sha3(), pass)
 | 
								let res = signature(accounts, address, data.sha3(), pass)
 | 
				
			||||||
				.map(|result| result
 | 
									.map(|result| result
 | 
				
			||||||
					.map(|rsv| {
 | 
										.map(|rsv| {
 | 
				
			||||||
						let mut vrs = [0u8; 65];
 | 
											let mut vrs = [0u8; 65];
 | 
				
			||||||
@ -122,14 +263,16 @@ pub fn execute<C, M>(client: &C, miner: &M, accounts: &AccountProvider, payload:
 | 
				
			|||||||
					})
 | 
										})
 | 
				
			||||||
					.map(RpcH520::from)
 | 
										.map(RpcH520::from)
 | 
				
			||||||
					.map(ConfirmationResponse::Signature)
 | 
										.map(ConfirmationResponse::Signature)
 | 
				
			||||||
				)
 | 
									);
 | 
				
			||||||
 | 
								future::done(res).boxed()
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		ConfirmationPayload::Decrypt(address, data) => {
 | 
							ConfirmationPayload::Decrypt(address, data) => {
 | 
				
			||||||
			decrypt(accounts, address, data, pass)
 | 
								let res = decrypt(accounts, address, data, pass)
 | 
				
			||||||
				.map(|result| result
 | 
									.map(|result| result
 | 
				
			||||||
					.map(RpcBytes)
 | 
										.map(RpcBytes)
 | 
				
			||||||
					.map(ConfirmationResponse::Decrypt)
 | 
										.map(ConfirmationResponse::Decrypt)
 | 
				
			||||||
				)
 | 
									);
 | 
				
			||||||
 | 
								future::done(res).boxed()
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -156,105 +299,34 @@ fn decrypt(accounts: &AccountProvider, address: Address, msg: Bytes, password: S
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn dispatch_transaction<C, M>(client: &C, miner: &M, signed_transaction: PendingTransaction) -> Result<H256, Error>
 | 
					/// Extract default gas price from a client and miner.
 | 
				
			||||||
	where C: MiningBlockChainClient, M: MinerService {
 | 
					 | 
				
			||||||
	let hash = signed_transaction.transaction.hash();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	miner.import_own_transaction(client, signed_transaction)
 | 
					 | 
				
			||||||
		.map_err(errors::from_transaction_error)
 | 
					 | 
				
			||||||
		.map(|_| hash)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub fn sign_no_dispatch<C, M>(client: &C, miner: &M, accounts: &AccountProvider, filled: FilledTransactionRequest, password: SignWith) -> Result<WithToken<SignedTransaction>, Error>
 | 
					 | 
				
			||||||
	where C: MiningBlockChainClient, M: MinerService {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let network_id = client.signing_network_id();
 | 
					 | 
				
			||||||
	let address = filled.from;
 | 
					 | 
				
			||||||
	let signed_transaction = {
 | 
					 | 
				
			||||||
		let t = Transaction {
 | 
					 | 
				
			||||||
			nonce: filled.nonce
 | 
					 | 
				
			||||||
				.or_else(|| miner
 | 
					 | 
				
			||||||
					.last_nonce(&filled.from)
 | 
					 | 
				
			||||||
					.map(|nonce| nonce + U256::one()))
 | 
					 | 
				
			||||||
				.unwrap_or_else(|| client.latest_nonce(&filled.from)),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			action: filled.to.map_or(Action::Create, Action::Call),
 | 
					 | 
				
			||||||
			gas: filled.gas,
 | 
					 | 
				
			||||||
			gas_price: filled.gas_price,
 | 
					 | 
				
			||||||
			value: filled.value,
 | 
					 | 
				
			||||||
			data: filled.data,
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		let hash = t.hash(network_id);
 | 
					 | 
				
			||||||
		let signature = signature(accounts, address, hash, password)?;
 | 
					 | 
				
			||||||
		signature.map(|sig| {
 | 
					 | 
				
			||||||
			SignedTransaction::new(t.with_signature(sig, network_id))
 | 
					 | 
				
			||||||
				.expect("Transaction was signed by AccountsProvider; it never produces invalid signatures; qed")
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	Ok(signed_transaction)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub fn sign_and_dispatch<C, M>(client: &C, miner: &M, accounts: &AccountProvider, filled: FilledTransactionRequest, password: SignWith) -> Result<WithToken<H256>, Error>
 | 
					 | 
				
			||||||
	where C: MiningBlockChainClient, M: MinerService
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let network_id = client.signing_network_id();
 | 
					 | 
				
			||||||
	let condition = filled.condition.clone();
 | 
					 | 
				
			||||||
	let signed_transaction = sign_no_dispatch(client, miner, accounts, filled, password)?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let (signed_transaction, token) = match signed_transaction {
 | 
					 | 
				
			||||||
		WithToken::No(signed_transaction) => (signed_transaction, None),
 | 
					 | 
				
			||||||
		WithToken::Yes(signed_transaction, token) => (signed_transaction, Some(token)),
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	trace!(target: "miner", "send_transaction: dispatching tx: {} for network ID {:?}", rlp::encode(&signed_transaction).to_vec().pretty(), network_id);
 | 
					 | 
				
			||||||
	let pending_transaction = PendingTransaction::new(signed_transaction, condition.map(Into::into));
 | 
					 | 
				
			||||||
	dispatch_transaction(&*client, &*miner, pending_transaction).map(|hash| {
 | 
					 | 
				
			||||||
		match token {
 | 
					 | 
				
			||||||
			Some(ref token) => WithToken::Yes(hash, token.clone()),
 | 
					 | 
				
			||||||
			None => WithToken::No(hash),
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub fn fill_optional_fields<C, M>(request: TransactionRequest, default_sender: Address, client: &C, miner: &M) -> FilledTransactionRequest
 | 
					 | 
				
			||||||
	where C: MiningBlockChainClient, M: MinerService
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	FilledTransactionRequest {
 | 
					 | 
				
			||||||
		from: request.from.unwrap_or(default_sender),
 | 
					 | 
				
			||||||
		used_default_from: request.from.is_none(),
 | 
					 | 
				
			||||||
		to: request.to,
 | 
					 | 
				
			||||||
		nonce: request.nonce,
 | 
					 | 
				
			||||||
		gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(client, miner)),
 | 
					 | 
				
			||||||
		gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()),
 | 
					 | 
				
			||||||
		value: request.value.unwrap_or_else(|| 0.into()),
 | 
					 | 
				
			||||||
		data: request.data.unwrap_or_else(Vec::new),
 | 
					 | 
				
			||||||
		condition: request.condition,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub fn default_gas_price<C, M>(client: &C, miner: &M) -> U256
 | 
					pub fn default_gas_price<C, M>(client: &C, miner: &M) -> U256
 | 
				
			||||||
	where C: MiningBlockChainClient, M: MinerService
 | 
						where C: MiningBlockChainClient, M: MinerService
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	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, default_account: Address, client: &C, miner: &M) -> ConfirmationPayload
 | 
					/// Convert RPC confirmation payload to signer confirmation payload.
 | 
				
			||||||
	where C: MiningBlockChainClient, M: MinerService {
 | 
					/// May need to resolve in the future to fetch things like gas price.
 | 
				
			||||||
 | 
					pub fn from_rpc<D>(payload: RpcConfirmationPayload, default_account: Address, dispatcher: &D) -> BoxFuture<ConfirmationPayload, Error>
 | 
				
			||||||
 | 
						where D: Dispatcher
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
	match payload {
 | 
						match payload {
 | 
				
			||||||
		RpcConfirmationPayload::SendTransaction(request) => {
 | 
							RpcConfirmationPayload::SendTransaction(request) => {
 | 
				
			||||||
			ConfirmationPayload::SendTransaction(fill_optional_fields(request.into(), default_account, client, miner))
 | 
								dispatcher.fill_optional_fields(request.into(), default_account)
 | 
				
			||||||
 | 
									.map(ConfirmationPayload::SendTransaction)
 | 
				
			||||||
 | 
									.boxed()
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		RpcConfirmationPayload::SignTransaction(request) => {
 | 
							RpcConfirmationPayload::SignTransaction(request) => {
 | 
				
			||||||
			ConfirmationPayload::SignTransaction(fill_optional_fields(request.into(), default_account, client, miner))
 | 
								dispatcher.fill_optional_fields(request.into(), default_account)
 | 
				
			||||||
 | 
									.map(ConfirmationPayload::SignTransaction)
 | 
				
			||||||
 | 
									.boxed()
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		RpcConfirmationPayload::Decrypt(RpcDecryptRequest { address, msg }) => {
 | 
							RpcConfirmationPayload::Decrypt(RpcDecryptRequest { address, msg }) => {
 | 
				
			||||||
			ConfirmationPayload::Decrypt(address.into(), msg.into())
 | 
								future::ok(ConfirmationPayload::Decrypt(address.into(), msg.into())).boxed()
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		RpcConfirmationPayload::Signature(RpcSignRequest { address, data }) => {
 | 
							RpcConfirmationPayload::Signature(RpcSignRequest { address, data }) => {
 | 
				
			||||||
			ConfirmationPayload::Signature(address.into(), data.into())
 | 
								future::ok(ConfirmationPayload::Signature(address.into(), data.into())).boxed()
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -16,15 +16,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
//! Ethereum rpc interface implementation.
 | 
					//! Ethereum rpc interface implementation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
macro_rules! take_weak {
 | 
					 | 
				
			||||||
	($weak: expr) => {
 | 
					 | 
				
			||||||
		match $weak.upgrade() {
 | 
					 | 
				
			||||||
			Some(arc) => arc,
 | 
					 | 
				
			||||||
			None => return Err(Error::internal_error())
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
mod eth;
 | 
					mod eth;
 | 
				
			||||||
mod eth_filter;
 | 
					mod eth_filter;
 | 
				
			||||||
mod net;
 | 
					mod net;
 | 
				
			||||||
 | 
				
			|||||||
@ -20,46 +20,37 @@ use std::sync::{Arc, Weak};
 | 
				
			|||||||
use ethcore::account_provider::AccountProvider;
 | 
					use ethcore::account_provider::AccountProvider;
 | 
				
			||||||
use ethcore::client::MiningBlockChainClient;
 | 
					use ethcore::client::MiningBlockChainClient;
 | 
				
			||||||
use ethcore::miner::MinerService;
 | 
					use ethcore::miner::MinerService;
 | 
				
			||||||
use util::{Address, U128, Uint};
 | 
					use ethcore::transaction::PendingTransaction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use futures::{self, Future, BoxFuture};
 | 
					use util::{Address, U128, Uint, ToPretty};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use futures::{self, future, Future, BoxFuture};
 | 
				
			||||||
use jsonrpc_core::Error;
 | 
					use jsonrpc_core::Error;
 | 
				
			||||||
use v1::helpers::errors;
 | 
					use v1::helpers::errors;
 | 
				
			||||||
use v1::helpers::dispatch::{self, sign_and_dispatch};
 | 
					use v1::helpers::dispatch::{Dispatcher, SignWith};
 | 
				
			||||||
use v1::traits::Personal;
 | 
					use v1::traits::Personal;
 | 
				
			||||||
use v1::types::{H160 as RpcH160, H256 as RpcH256, U128 as RpcU128, TransactionRequest};
 | 
					use v1::types::{H160 as RpcH160, H256 as RpcH256, U128 as RpcU128, TransactionRequest};
 | 
				
			||||||
use v1::metadata::Metadata;
 | 
					use v1::metadata::Metadata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Account management (personal) rpc implementation.
 | 
					/// Account management (personal) rpc implementation.
 | 
				
			||||||
pub struct PersonalClient<C, M> where
 | 
					pub struct PersonalClient<D: Dispatcher> {
 | 
				
			||||||
	C: MiningBlockChainClient,
 | 
					 | 
				
			||||||
	M: MinerService,
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	accounts: Weak<AccountProvider>,
 | 
						accounts: Weak<AccountProvider>,
 | 
				
			||||||
	client: Weak<C>,
 | 
						dispatcher: D,
 | 
				
			||||||
	miner: Weak<M>,
 | 
					 | 
				
			||||||
	allow_perm_unlock: bool,
 | 
						allow_perm_unlock: bool,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<C, M> PersonalClient<C, M> where
 | 
					impl<D: Dispatcher> PersonalClient<D> {
 | 
				
			||||||
	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>, dispatcher: D, allow_perm_unlock: bool) -> Self {
 | 
				
			||||||
		PersonalClient {
 | 
							PersonalClient {
 | 
				
			||||||
			accounts: Arc::downgrade(store),
 | 
								accounts: Arc::downgrade(store),
 | 
				
			||||||
			client: Arc::downgrade(client),
 | 
								dispatcher: dispatcher,
 | 
				
			||||||
			miner: Arc::downgrade(miner),
 | 
					 | 
				
			||||||
			allow_perm_unlock: allow_perm_unlock,
 | 
								allow_perm_unlock: allow_perm_unlock,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<C, M> Personal for PersonalClient<C, M> where
 | 
					impl<D: Dispatcher + 'static> Personal for PersonalClient<D> {
 | 
				
			||||||
	C: MiningBlockChainClient + 'static,
 | 
					 | 
				
			||||||
	M: MinerService + 'static,
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	type Metadata = Metadata;
 | 
						type Metadata = Metadata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn accounts(&self) -> Result<Vec<RpcH160>, Error> {
 | 
						fn accounts(&self) -> Result<Vec<RpcH160>, Error> {
 | 
				
			||||||
@ -106,28 +97,41 @@ impl<C, M> Personal for PersonalClient<C, M> where
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn send_transaction(&self, meta: Metadata, request: TransactionRequest, password: String) -> BoxFuture<RpcH256, Error> {
 | 
						fn send_transaction(&self, meta: Metadata, request: TransactionRequest, password: String) -> BoxFuture<RpcH256, Error> {
 | 
				
			||||||
		let sign_and_send = move || {
 | 
							let setup = || {
 | 
				
			||||||
			let client = take_weak!(self.client);
 | 
								let dispatcher = self.dispatcher.clone();
 | 
				
			||||||
			let miner = take_weak!(self.miner);
 | 
					 | 
				
			||||||
			let accounts = take_weak!(self.accounts);
 | 
								let accounts = take_weak!(self.accounts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			let default_account = match request.from {
 | 
								Ok((accounts, dispatcher))
 | 
				
			||||||
				Some(ref account) => account.clone().into(),
 | 
					 | 
				
			||||||
				None => accounts
 | 
					 | 
				
			||||||
					.default_address(meta.dapp_id.unwrap_or_default().into())
 | 
					 | 
				
			||||||
					.map_err(|e| errors::account("Cannot find default account.", e))?,
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			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()
 | 
							future::done(setup())
 | 
				
			||||||
 | 
								.and_then(move |(accounts, dispatcher)| {
 | 
				
			||||||
 | 
									let default = match request.from.as_ref() {
 | 
				
			||||||
 | 
										Some(account) => Ok(account.clone().into()),
 | 
				
			||||||
 | 
										None => accounts
 | 
				
			||||||
 | 
											.default_address(meta.dapp_id.unwrap_or_default().into())
 | 
				
			||||||
 | 
											.map_err(|e| errors::account("Cannot find default account.", e)),
 | 
				
			||||||
 | 
									};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									let dis = dispatcher.clone();
 | 
				
			||||||
 | 
									future::done(default)
 | 
				
			||||||
 | 
										.and_then(move |default| dis.fill_optional_fields(request.into(), default))
 | 
				
			||||||
 | 
										.map(move |tx| (tx, accounts, dispatcher))
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								.and_then(move |(filled, accounts, dispatcher)| {
 | 
				
			||||||
 | 
									let condition = filled.condition.clone().map(Into::into);
 | 
				
			||||||
 | 
									dispatcher.sign(&accounts, filled, SignWith::Password(password))
 | 
				
			||||||
 | 
										.map(|tx| tx.into_value())
 | 
				
			||||||
 | 
										.map(move |tx| PendingTransaction::new(tx, condition))
 | 
				
			||||||
 | 
										.map(move |tx| (tx, dispatcher))
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								.and_then(move |(pending_tx, dispatcher)| {
 | 
				
			||||||
 | 
									let network_id = pending_tx.network_id();
 | 
				
			||||||
 | 
									trace!(target: "miner", "send_transaction: dispatching tx: {} for network ID {:?}",
 | 
				
			||||||
 | 
										::rlp::encode(&*pending_tx).to_vec().pretty(), network_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									dispatcher.dispatch_transaction(pending_tx).map(Into::into)
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								.boxed()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -24,13 +24,14 @@ use ethcore::account_provider::AccountProvider;
 | 
				
			|||||||
use ethcore::miner::MinerService;
 | 
					use ethcore::miner::MinerService;
 | 
				
			||||||
use ethcore::client::MiningBlockChainClient;
 | 
					use ethcore::client::MiningBlockChainClient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use futures::{self, BoxFuture, Future};
 | 
					use futures::{self, future, BoxFuture, Future};
 | 
				
			||||||
use jsonrpc_core::Error;
 | 
					use jsonrpc_core::Error;
 | 
				
			||||||
use v1::helpers::{
 | 
					use v1::helpers::{
 | 
				
			||||||
	errors, dispatch,
 | 
						errors,
 | 
				
			||||||
	DefaultAccount,
 | 
						DefaultAccount,
 | 
				
			||||||
	SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, SignerService
 | 
						SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, SignerService
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					use v1::helpers::dispatch::{self, Dispatcher};
 | 
				
			||||||
use v1::metadata::Metadata;
 | 
					use v1::metadata::Metadata;
 | 
				
			||||||
use v1::traits::{EthSigning, ParitySigning};
 | 
					use v1::traits::{EthSigning, ParitySigning};
 | 
				
			||||||
use v1::types::{
 | 
					use v1::types::{
 | 
				
			||||||
@ -50,105 +51,97 @@ enum DispatchResult {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Implementation of functions that require signing when no trusted signer is used.
 | 
					/// Implementation of functions that require signing when no trusted signer is used.
 | 
				
			||||||
pub struct SigningQueueClient<C, M> where C: MiningBlockChainClient, M: MinerService {
 | 
					pub struct SigningQueueClient<D> {
 | 
				
			||||||
	signer: Weak<SignerService>,
 | 
						signer: Weak<SignerService>,
 | 
				
			||||||
	accounts: Weak<AccountProvider>,
 | 
						accounts: Weak<AccountProvider>,
 | 
				
			||||||
	client: Weak<C>,
 | 
						dispatcher: D,
 | 
				
			||||||
	miner: Weak<M>,
 | 
						pending: Arc<Mutex<TransientHashMap<U256, ConfirmationPromise>>>,
 | 
				
			||||||
 | 
					 | 
				
			||||||
	pending: Mutex<TransientHashMap<U256, ConfirmationPromise>>,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<C, M> SigningQueueClient<C, M> where
 | 
					fn handle_dispatch<OnResponse>(res: Result<DispatchResult, Error>, on_response: OnResponse)
 | 
				
			||||||
	C: MiningBlockChainClient,
 | 
						where OnResponse: FnOnce(Result<RpcConfirmationResponse, Error>) + Send + 'static
 | 
				
			||||||
	M: MinerService,
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						match res {
 | 
				
			||||||
 | 
							Ok(DispatchResult::Value(result)) => on_response(Ok(result)),
 | 
				
			||||||
 | 
							Ok(DispatchResult::Promise(promise)) => {
 | 
				
			||||||
 | 
								promise.wait_for_result(move |result| {
 | 
				
			||||||
 | 
									on_response(result.unwrap_or_else(|| Err(errors::request_rejected())))
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Err(e) => on_response(Err(e)),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<D: Dispatcher> SigningQueueClient<D> {
 | 
				
			||||||
	/// Creates a new signing queue client given shared signing queue.
 | 
						/// Creates a new signing queue client given shared signing queue.
 | 
				
			||||||
	pub fn new(signer: &Arc<SignerService>, client: &Arc<C>, miner: &Arc<M>, accounts: &Arc<AccountProvider>) -> Self {
 | 
						pub fn new(signer: &Arc<SignerService>, dispatcher: D, accounts: &Arc<AccountProvider>) -> Self {
 | 
				
			||||||
		SigningQueueClient {
 | 
							SigningQueueClient {
 | 
				
			||||||
			signer: Arc::downgrade(signer),
 | 
								signer: Arc::downgrade(signer),
 | 
				
			||||||
			accounts: Arc::downgrade(accounts),
 | 
								accounts: Arc::downgrade(accounts),
 | 
				
			||||||
			client: Arc::downgrade(client),
 | 
								dispatcher: dispatcher,
 | 
				
			||||||
			miner: Arc::downgrade(miner),
 | 
								pending: Arc::new(Mutex::new(TransientHashMap::new(MAX_PENDING_DURATION))),
 | 
				
			||||||
			pending: Mutex::new(TransientHashMap::new(MAX_PENDING_DURATION)),
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn handle_dispatch<OnResponse>(&self, res: Result<DispatchResult, Error>, on_response: OnResponse)
 | 
						fn dispatch(&self, payload: RpcConfirmationPayload, default_account: DefaultAccount) -> BoxFuture<DispatchResult, Error> {
 | 
				
			||||||
		where OnResponse: FnOnce(Result<RpcConfirmationResponse, Error>) + Send + 'static
 | 
							let setup = || {
 | 
				
			||||||
	{
 | 
								let accounts = take_weak!(self.accounts);
 | 
				
			||||||
		match res {
 | 
								let default_account = match default_account {
 | 
				
			||||||
			Ok(DispatchResult::Value(result)) => on_response(Ok(result)),
 | 
									DefaultAccount::Provided(acc) => acc,
 | 
				
			||||||
			Ok(DispatchResult::Promise(promise)) => {
 | 
									DefaultAccount::ForDapp(dapp) => accounts.default_address(dapp).ok().unwrap_or_default(),
 | 
				
			||||||
				promise.wait_for_result(move |result| {
 | 
								};
 | 
				
			||||||
					on_response(result.unwrap_or_else(|| Err(errors::request_rejected())))
 | 
					 | 
				
			||||||
				})
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			Err(e) => on_response(Err(e)),
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn add_to_queue(&self, payload: ConfirmationPayload) -> Result<DispatchResult, Error> {
 | 
								(self.dispatcher.clone(), accounts, default_account)
 | 
				
			||||||
		let client = take_weak!(self.client);
 | 
					 | 
				
			||||||
		let miner = take_weak!(self.miner);
 | 
					 | 
				
			||||||
		let accounts = take_weak!(self.accounts);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		let sender = payload.sender();
 | 
					 | 
				
			||||||
		if accounts.is_unlocked(sender) {
 | 
					 | 
				
			||||||
			return dispatch::execute(&*client, &*miner, &*accounts, payload, dispatch::SignWith::Nothing)
 | 
					 | 
				
			||||||
				.map(|v| v.into_value())
 | 
					 | 
				
			||||||
				.map(DispatchResult::Value);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		take_weak!(self.signer).add_request(payload)
 | 
					 | 
				
			||||||
			.map(DispatchResult::Promise)
 | 
					 | 
				
			||||||
			.map_err(|_| errors::request_rejected_limit())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fn dispatch(&self, payload: RpcConfirmationPayload, default_account: DefaultAccount) -> Result<DispatchResult, Error> {
 | 
					 | 
				
			||||||
		let client = take_weak!(self.client);
 | 
					 | 
				
			||||||
		let miner = take_weak!(self.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)
 | 
							let weak_signer = self.signer.clone();
 | 
				
			||||||
 | 
							future::done(setup)
 | 
				
			||||||
 | 
								.and_then(move |(dispatcher, accounts, default_account)| {
 | 
				
			||||||
 | 
									dispatch::from_rpc(payload, default_account, &dispatcher)
 | 
				
			||||||
 | 
										.and_then(move |payload| {
 | 
				
			||||||
 | 
											let sender = payload.sender();
 | 
				
			||||||
 | 
											if accounts.is_unlocked(sender) {
 | 
				
			||||||
 | 
												dispatch::execute(dispatcher, &accounts, payload, dispatch::SignWith::Nothing)
 | 
				
			||||||
 | 
													.boxed()
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
												future::lazy(move || take_weak!(weak_signer).add_request(payload))
 | 
				
			||||||
 | 
													.map(DispatchResult::Promise)
 | 
				
			||||||
 | 
													.map_err(|_| errors::request_rejected_limit())
 | 
				
			||||||
 | 
													.boxed()
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								.boxed()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<C: 'static, M: 'static> ParitySigning for SigningQueueClient<C, M> where
 | 
					impl<D: Dispatcher + 'static> ParitySigning for SigningQueueClient<D> {
 | 
				
			||||||
	C: MiningBlockChainClient,
 | 
					 | 
				
			||||||
	M: MinerService,
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	type Metadata = Metadata;
 | 
						type Metadata = Metadata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn post_sign(&self, address: RpcH160, data: RpcBytes) -> Result<RpcEither<RpcU256, RpcConfirmationResponse>, Error> {
 | 
						fn post_sign(&self, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcEither<RpcU256, RpcConfirmationResponse>, Error> {
 | 
				
			||||||
 | 
							let pending = self.pending.clone();
 | 
				
			||||||
		self.dispatch(RpcConfirmationPayload::Signature((address.clone(), data).into()), DefaultAccount::Provided(address.into()))
 | 
							self.dispatch(RpcConfirmationPayload::Signature((address.clone(), data).into()), DefaultAccount::Provided(address.into()))
 | 
				
			||||||
			.map(|result| match result {
 | 
								.map(move |result| match result {
 | 
				
			||||||
				DispatchResult::Value(v) => RpcEither::Or(v),
 | 
									DispatchResult::Value(v) => RpcEither::Or(v),
 | 
				
			||||||
				DispatchResult::Promise(promise) => {
 | 
									DispatchResult::Promise(promise) => {
 | 
				
			||||||
					let id = promise.id();
 | 
										let id = promise.id();
 | 
				
			||||||
					self.pending.lock().insert(id, promise);
 | 
										pending.lock().insert(id, promise);
 | 
				
			||||||
					RpcEither::Either(id.into())
 | 
										RpcEither::Either(id.into())
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn post_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcEither<RpcU256, RpcConfirmationResponse>, Error> {
 | 
						fn post_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcEither<RpcU256, RpcConfirmationResponse>, Error> {
 | 
				
			||||||
		let post_transaction = move || {
 | 
							let pending = self.pending.clone();
 | 
				
			||||||
			self.dispatch(RpcConfirmationPayload::SendTransaction(request), meta.into())
 | 
							self.dispatch(RpcConfirmationPayload::SendTransaction(request), meta.into())
 | 
				
			||||||
				.map(|result| match result {
 | 
								.map(move |result| match result {
 | 
				
			||||||
					DispatchResult::Value(v) => RpcEither::Or(v),
 | 
									DispatchResult::Value(v) => RpcEither::Or(v),
 | 
				
			||||||
					DispatchResult::Promise(promise) => {
 | 
									DispatchResult::Promise(promise) => {
 | 
				
			||||||
						let id = promise.id();
 | 
										let id = promise.id();
 | 
				
			||||||
						self.pending.lock().insert(id, promise);
 | 
										pending.lock().insert(id, promise);
 | 
				
			||||||
						RpcEither::Either(id.into())
 | 
										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> {
 | 
				
			||||||
@ -170,67 +163,78 @@ impl<C: 'static, M: 'static> ParitySigning for SigningQueueClient<C, M> where
 | 
				
			|||||||
		let res = self.dispatch(RpcConfirmationPayload::Decrypt((address.clone(), data).into()), address.into());
 | 
							let res = 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
 | 
					 | 
				
			||||||
		self.handle_dispatch(res, |response| {
 | 
					 | 
				
			||||||
			match response {
 | 
					 | 
				
			||||||
				Ok(RpcConfirmationResponse::Decrypt(data)) => ready.complete(Ok(data)),
 | 
					 | 
				
			||||||
				Err(e) => ready.complete(Err(e)),
 | 
					 | 
				
			||||||
				e => ready.complete(Err(errors::internal("Unexpected result.", e))),
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
 | 
							// when dispatch is complete
 | 
				
			||||||
 | 
							res.then(move |res| {
 | 
				
			||||||
 | 
								// register callback via the oneshot sender.
 | 
				
			||||||
 | 
								handle_dispatch(res, move |response| {
 | 
				
			||||||
 | 
									match response {
 | 
				
			||||||
 | 
										Ok(RpcConfirmationResponse::Decrypt(data)) => ready.complete(Ok(data)),
 | 
				
			||||||
 | 
										Err(e) => ready.complete(Err(e)),
 | 
				
			||||||
 | 
										e => ready.complete(Err(errors::internal("Unexpected result.", e))),
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// and wait for that to resolve.
 | 
				
			||||||
 | 
								p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
 | 
				
			||||||
 | 
							}).boxed()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<C: 'static, M: 'static> EthSigning for SigningQueueClient<C, M> where
 | 
					impl<D: Dispatcher + 'static> EthSigning for SigningQueueClient<D> {
 | 
				
			||||||
	C: MiningBlockChainClient,
 | 
					 | 
				
			||||||
	M: MinerService,
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	type Metadata = Metadata;
 | 
						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.dispatch(RpcConfirmationPayload::Signature((address.clone(), data).into()), address.into());
 | 
							let res = 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| {
 | 
					 | 
				
			||||||
			match response {
 | 
					 | 
				
			||||||
				Ok(RpcConfirmationResponse::Signature(signature)) => ready.complete(Ok(signature)),
 | 
					 | 
				
			||||||
				Err(e) => ready.complete(Err(e)),
 | 
					 | 
				
			||||||
				e => ready.complete(Err(errors::internal("Unexpected result.", e))),
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
 | 
							res.then(move |res| {
 | 
				
			||||||
 | 
								handle_dispatch(res, move |response| {
 | 
				
			||||||
 | 
									match response {
 | 
				
			||||||
 | 
										Ok(RpcConfirmationResponse::Signature(sig)) => ready.complete(Ok(sig)),
 | 
				
			||||||
 | 
										Err(e) => ready.complete(Err(e)),
 | 
				
			||||||
 | 
										e => ready.complete(Err(errors::internal("Unexpected result.", e))),
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
 | 
				
			||||||
 | 
							}).boxed()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn send_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcH256, Error> {
 | 
						fn send_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcH256, Error> {
 | 
				
			||||||
		let res = self.dispatch(RpcConfirmationPayload::SendTransaction(request), meta.into());
 | 
							let res = self.dispatch(RpcConfirmationPayload::SendTransaction(request), meta.into());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let (ready, p) = futures::oneshot();
 | 
							let (ready, p) = futures::oneshot();
 | 
				
			||||||
		self.handle_dispatch(res, |response| {
 | 
					 | 
				
			||||||
			match response {
 | 
					 | 
				
			||||||
				Ok(RpcConfirmationResponse::SendTransaction(hash)) => ready.complete(Ok(hash)),
 | 
					 | 
				
			||||||
				Err(e) => ready.complete(Err(e)),
 | 
					 | 
				
			||||||
				e => ready.complete(Err(errors::internal("Unexpected result.", e))),
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
 | 
							res.then(move |res| {
 | 
				
			||||||
 | 
								handle_dispatch(res, move |response| {
 | 
				
			||||||
 | 
									match response {
 | 
				
			||||||
 | 
										Ok(RpcConfirmationResponse::SendTransaction(hash)) => ready.complete(Ok(hash)),
 | 
				
			||||||
 | 
										Err(e) => ready.complete(Err(e)),
 | 
				
			||||||
 | 
										e => ready.complete(Err(errors::internal("Unexpected result.", e))),
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
 | 
				
			||||||
 | 
							}).boxed()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn sign_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction, Error> {
 | 
						fn sign_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction, Error> {
 | 
				
			||||||
		let res = self.dispatch(RpcConfirmationPayload::SignTransaction(request), meta.into());
 | 
							let res = self.dispatch(RpcConfirmationPayload::SignTransaction(request), meta.into());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let (ready, p) = futures::oneshot();
 | 
							let (ready, p) = futures::oneshot();
 | 
				
			||||||
		self.handle_dispatch(res, |response| {
 | 
					 | 
				
			||||||
			match response {
 | 
					 | 
				
			||||||
				Ok(RpcConfirmationResponse::SignTransaction(tx)) => ready.complete(Ok(tx)),
 | 
					 | 
				
			||||||
				Err(e) => ready.complete(Err(e)),
 | 
					 | 
				
			||||||
				e => ready.complete(Err(errors::internal("Unexpected result.", e))),
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
 | 
							res.then(move |res| {
 | 
				
			||||||
 | 
								handle_dispatch(res, move |response| {
 | 
				
			||||||
 | 
									match response {
 | 
				
			||||||
 | 
										Ok(RpcConfirmationResponse::SignTransaction(tx)) => ready.complete(Ok(tx)),
 | 
				
			||||||
 | 
										Err(e) => ready.complete(Err(e)),
 | 
				
			||||||
 | 
										e => ready.complete(Err(errors::internal("Unexpected result.", e))),
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
 | 
				
			||||||
 | 
							}).boxed()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -22,9 +22,10 @@ use ethcore::account_provider::AccountProvider;
 | 
				
			|||||||
use ethcore::miner::MinerService;
 | 
					use ethcore::miner::MinerService;
 | 
				
			||||||
use ethcore::client::MiningBlockChainClient;
 | 
					use ethcore::client::MiningBlockChainClient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use futures::{self, BoxFuture, Future};
 | 
					use futures::{self, future, BoxFuture, Future};
 | 
				
			||||||
use jsonrpc_core::Error;
 | 
					use jsonrpc_core::Error;
 | 
				
			||||||
use v1::helpers::{errors, dispatch, DefaultAccount};
 | 
					use v1::helpers::{errors, DefaultAccount};
 | 
				
			||||||
 | 
					use v1::helpers::dispatch::{self, Dispatcher};
 | 
				
			||||||
use v1::metadata::Metadata;
 | 
					use v1::metadata::Metadata;
 | 
				
			||||||
use v1::traits::{EthSigning, ParitySigning};
 | 
					use v1::traits::{EthSigning, ParitySigning};
 | 
				
			||||||
use v1::types::{
 | 
					use v1::types::{
 | 
				
			||||||
@ -38,106 +39,100 @@ use v1::types::{
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Implementation of functions that require signing when no trusted signer is used.
 | 
					/// Implementation of functions that require signing when no trusted signer is used.
 | 
				
			||||||
pub struct SigningUnsafeClient<C, M> where
 | 
					pub struct SigningUnsafeClient<D> {
 | 
				
			||||||
	C: MiningBlockChainClient,
 | 
					 | 
				
			||||||
	M: MinerService,
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	accounts: Weak<AccountProvider>,
 | 
						accounts: Weak<AccountProvider>,
 | 
				
			||||||
	client: Weak<C>,
 | 
						dispatcher: D,
 | 
				
			||||||
	miner: Weak<M>,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<C, M> SigningUnsafeClient<C, M> where
 | 
					impl<D: Dispatcher> SigningUnsafeClient<D> {
 | 
				
			||||||
	C: MiningBlockChainClient,
 | 
					 | 
				
			||||||
	M: MinerService,
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/// Creates new SigningUnsafeClient.
 | 
						/// Creates new SigningUnsafeClient.
 | 
				
			||||||
	pub fn new(client: &Arc<C>, accounts: &Arc<AccountProvider>, miner: &Arc<M>)
 | 
						pub fn new(accounts: &Arc<AccountProvider>, dispatcher: D) -> Self {
 | 
				
			||||||
		-> Self {
 | 
					 | 
				
			||||||
		SigningUnsafeClient {
 | 
							SigningUnsafeClient {
 | 
				
			||||||
			client: Arc::downgrade(client),
 | 
					 | 
				
			||||||
			miner: Arc::downgrade(miner),
 | 
					 | 
				
			||||||
			accounts: Arc::downgrade(accounts),
 | 
								accounts: Arc::downgrade(accounts),
 | 
				
			||||||
 | 
								dispatcher: dispatcher,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn handle(&self, payload: RpcConfirmationPayload, account: DefaultAccount) -> Result<RpcConfirmationResponse, Error> {
 | 
						fn handle(&self, payload: RpcConfirmationPayload, account: DefaultAccount) -> BoxFuture<RpcConfirmationResponse, Error> {
 | 
				
			||||||
		let client = take_weak!(self.client);
 | 
							let setup = move || {
 | 
				
			||||||
		let miner = take_weak!(self.miner);
 | 
								let accounts = take_weak!(self.accounts);
 | 
				
			||||||
		let accounts = take_weak!(self.accounts);
 | 
								let default_account = match account {
 | 
				
			||||||
 | 
									DefaultAccount::Provided(acc) => acc,
 | 
				
			||||||
 | 
									DefaultAccount::ForDapp(dapp) => accounts.default_address(dapp).ok().unwrap_or_default(),
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let default_account = match account {
 | 
								(accounts, default_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)
 | 
							let dis = self.dispatcher.clone();
 | 
				
			||||||
			.map(|v| v.into_value())
 | 
							future::done(setup())
 | 
				
			||||||
 | 
								.and_then(move |(accounts, default)| {
 | 
				
			||||||
 | 
									dispatch::from_rpc(payload, default, &dis)
 | 
				
			||||||
 | 
										.and_then(|payload| {
 | 
				
			||||||
 | 
											dispatch::execute(&dis, &accounts, payload, dispatch::SignWith::Nothing)
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
										.map(|v| v.into_value())
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								.boxed()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<C: 'static, M: 'static> EthSigning for SigningUnsafeClient<C, M> where
 | 
					impl<D: Dispatcher + 'static> EthSigning for SigningUnsafeClient<D>
 | 
				
			||||||
	C: MiningBlockChainClient,
 | 
					 | 
				
			||||||
	M: MinerService,
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	type Metadata = Metadata;
 | 
						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.clone(), data).into()), address.into()) {
 | 
							self.handle(RpcConfirmationPayload::Signature((address.clone(), data).into()), address.into())
 | 
				
			||||||
			Ok(RpcConfirmationResponse::Signature(signature)) => Ok(signature),
 | 
								.then(|res| match res {
 | 
				
			||||||
			Err(e) => Err(e),
 | 
									Ok(RpcConfirmationResponse::Signature(signature)) => Ok(signature),
 | 
				
			||||||
			e => Err(errors::internal("Unexpected result", e)),
 | 
									Err(e) => Err(e),
 | 
				
			||||||
		};
 | 
									e => Err(errors::internal("Unexpected result", e)),
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
		futures::done(result).boxed()
 | 
								.boxed()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn send_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcH256, Error> {
 | 
						fn send_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcH256, Error> {
 | 
				
			||||||
		let result = match self.handle(RpcConfirmationPayload::SendTransaction(request), meta.into()) {
 | 
							self.handle(RpcConfirmationPayload::SendTransaction(request), meta.into())
 | 
				
			||||||
			Ok(RpcConfirmationResponse::SendTransaction(hash)) => Ok(hash),
 | 
								.then(|res| match res {
 | 
				
			||||||
			Err(e) => Err(e),
 | 
									Ok(RpcConfirmationResponse::SendTransaction(hash)) => Ok(hash),
 | 
				
			||||||
			e => Err(errors::internal("Unexpected result", e)),
 | 
									Err(e) => Err(e),
 | 
				
			||||||
		};
 | 
									e => Err(errors::internal("Unexpected result", e)),
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
		futures::done(result).boxed()
 | 
								.boxed()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn sign_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction, Error> {
 | 
						fn sign_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction, Error> {
 | 
				
			||||||
		let result = match self.handle(RpcConfirmationPayload::SignTransaction(request), meta.into()) {
 | 
							self.handle(RpcConfirmationPayload::SignTransaction(request), meta.into())
 | 
				
			||||||
			Ok(RpcConfirmationResponse::SignTransaction(tx)) => Ok(tx),
 | 
								.then(|res| match res {
 | 
				
			||||||
			Err(e) => Err(e),
 | 
									Ok(RpcConfirmationResponse::SignTransaction(tx)) => Ok(tx),
 | 
				
			||||||
			e => Err(errors::internal("Unexpected result", e)),
 | 
									Err(e) => Err(e),
 | 
				
			||||||
		};
 | 
									e => Err(errors::internal("Unexpected result", e)),
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
		futures::done(result).boxed()
 | 
								.boxed()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<C: 'static, M: 'static> ParitySigning for SigningUnsafeClient<C, M> where
 | 
					impl<D: Dispatcher + 'static> ParitySigning for SigningUnsafeClient<D> {
 | 
				
			||||||
	C: MiningBlockChainClient,
 | 
					 | 
				
			||||||
	M: MinerService,
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	type Metadata = Metadata;
 | 
						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.clone(), data).into()), address.into()) {
 | 
							self.handle(RpcConfirmationPayload::Decrypt((address.clone(), data).into()), address.into())
 | 
				
			||||||
			Ok(RpcConfirmationResponse::Decrypt(data)) => Ok(data),
 | 
								.then(|res| match res {
 | 
				
			||||||
			Err(e) => Err(e),
 | 
									Ok(RpcConfirmationResponse::Decrypt(data)) => Ok(data),
 | 
				
			||||||
			e => Err(errors::internal("Unexpected result", e)),
 | 
									Err(e) => Err(e),
 | 
				
			||||||
		};
 | 
									e => Err(errors::internal("Unexpected result", e)),
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
		futures::done(result).boxed()
 | 
								.boxed()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn post_sign(&self, _: RpcH160, _: RpcBytes) -> Result<RpcEither<RpcU256, RpcConfirmationResponse>, Error> {
 | 
						fn post_sign(&self, _: RpcH160, _: RpcBytes) -> 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())
 | 
							future::err(errors::signer_disabled()).boxed()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn post_transaction(&self, _: Metadata, _: RpcTransactionRequest) -> BoxFuture<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.
 | 
				
			||||||
		futures::done(Err(errors::signer_disabled())).boxed()
 | 
							future::err((errors::signer_disabled())).boxed()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn check_request(&self, _: RpcU256) -> Result<Option<RpcConfirmationResponse>, Error> {
 | 
						fn check_request(&self, _: RpcU256) -> Result<Option<RpcConfirmationResponse>, Error> {
 | 
				
			||||||
 | 
				
			|||||||
@ -18,6 +18,15 @@
 | 
				
			|||||||
//!
 | 
					//!
 | 
				
			||||||
//! Compliant with ethereum rpc.
 | 
					//! Compliant with ethereum rpc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					macro_rules! take_weak {
 | 
				
			||||||
 | 
						($weak: expr) => {
 | 
				
			||||||
 | 
							match $weak.upgrade() {
 | 
				
			||||||
 | 
								Some(arc) => arc,
 | 
				
			||||||
 | 
								None => return Err(Error::internal_error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[macro_use]
 | 
					#[macro_use]
 | 
				
			||||||
mod helpers;
 | 
					mod helpers;
 | 
				
			||||||
mod impls;
 | 
					mod impls;
 | 
				
			||||||
 | 
				
			|||||||
@ -27,8 +27,8 @@ build_rpc_trait! {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		/// 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(async, name = "parity_postSign")]
 | 
				
			||||||
		fn post_sign(&self, H160, Bytes) -> Result<Either<U256, ConfirmationResponse>, Error>;
 | 
							fn post_sign(&self, H160, Bytes) -> BoxFuture<Either<U256, ConfirmationResponse>, Error>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// 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.
 | 
				
			||||||
 | 
				
			|||||||
@ -164,7 +164,7 @@ mod tests {
 | 
				
			|||||||
			logs_bloom: H2048::default(),
 | 
								logs_bloom: H2048::default(),
 | 
				
			||||||
			timestamp: U256::default(),
 | 
								timestamp: U256::default(),
 | 
				
			||||||
			difficulty: U256::default(),
 | 
								difficulty: U256::default(),
 | 
				
			||||||
			total_difficulty: U256::default(),
 | 
								total_difficulty: Some(U256::default()),
 | 
				
			||||||
			seal_fields: vec![Bytes::default(), Bytes::default()],
 | 
								seal_fields: vec![Bytes::default(), Bytes::default()],
 | 
				
			||||||
			uncles: vec![],
 | 
								uncles: vec![],
 | 
				
			||||||
			transactions: BlockTransactions::Hashes(vec![].into()),
 | 
								transactions: BlockTransactions::Hashes(vec![].into()),
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user