fix (light/provider) : Make read_only executions read-only (#9591)
				
					
				
			* `ExecutionsRequest` from light-clients as read-only This changes so all `ExecutionRequests` from light-clients are executed as read-only which the `virtual``flag == true ensures. This boost up the current transaction to always succeed Note, this only affects `eth_estimateGas` and `eth_call` AFAIK. * grumbles(revert renaming) : TransactionProof * grumbles(trace) : remove incorrect trace * grumbles(state/prove_tx) : explicit `virt` Remove the boolean flag to determine that a `state::prove_transaction` whether it should be executed in a virtual context or not. Because of that also rename the function to `state::prove_transction_virtual` to make more clear
This commit is contained in:
		
							parent
							
								
									dc14cce7a9
								
							
						
					
					
						commit
						5b54442a48
					
				@ -2381,14 +2381,13 @@ impl ProvingBlockChainClient for Client {
 | 
			
		||||
		env_info.gas_limit = transaction.gas.clone();
 | 
			
		||||
		let mut jdb = self.state_db.read().journal_db().boxed_clone();
 | 
			
		||||
 | 
			
		||||
		state::prove_transaction(
 | 
			
		||||
		state::prove_transaction_virtual(
 | 
			
		||||
			jdb.as_hashdb_mut(),
 | 
			
		||||
			header.state_root().clone(),
 | 
			
		||||
			&transaction,
 | 
			
		||||
			self.engine.machine(),
 | 
			
		||||
			&env_info,
 | 
			
		||||
			self.factories.clone(),
 | 
			
		||||
			false,
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -877,14 +877,13 @@ impl Spec {
 | 
			
		||||
				data: d,
 | 
			
		||||
			}.fake_sign(from);
 | 
			
		||||
 | 
			
		||||
			let res = ::state::prove_transaction(
 | 
			
		||||
			let res = ::state::prove_transaction_virtual(
 | 
			
		||||
				db.as_hashdb_mut(),
 | 
			
		||||
				*genesis.state_root(),
 | 
			
		||||
				&tx,
 | 
			
		||||
				self.engine.machine(),
 | 
			
		||||
				&env_info,
 | 
			
		||||
				factories.clone(),
 | 
			
		||||
				true,
 | 
			
		||||
			);
 | 
			
		||||
 | 
			
		||||
			res.map(|(out, proof)| {
 | 
			
		||||
 | 
			
		||||
@ -224,17 +224,16 @@ pub fn check_proof(
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Prove a transaction on the given state.
 | 
			
		||||
/// Prove a `virtual` transaction on the given state.
 | 
			
		||||
/// Returns `None` when the transacion could not be proved,
 | 
			
		||||
/// and a proof otherwise.
 | 
			
		||||
pub fn prove_transaction<H: AsHashDB<KeccakHasher> + Send + Sync>(
 | 
			
		||||
pub fn prove_transaction_virtual<H: AsHashDB<KeccakHasher> + Send + Sync>(
 | 
			
		||||
	db: H,
 | 
			
		||||
	root: H256,
 | 
			
		||||
	transaction: &SignedTransaction,
 | 
			
		||||
	machine: &Machine,
 | 
			
		||||
	env_info: &EnvInfo,
 | 
			
		||||
	factories: Factories,
 | 
			
		||||
	virt: bool,
 | 
			
		||||
) -> Option<(Bytes, Vec<DBValue>)> {
 | 
			
		||||
	use self::backend::Proving;
 | 
			
		||||
 | 
			
		||||
@ -252,7 +251,7 @@ pub fn prove_transaction<H: AsHashDB<KeccakHasher> + Send + Sync>(
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	let options = TransactOptions::with_no_tracing().dont_check_nonce().save_output_from_contract();
 | 
			
		||||
	match state.execute(env_info, machine, transaction, options, virt) {
 | 
			
		||||
	match state.execute(env_info, machine, transaction, options, true) {
 | 
			
		||||
		Err(ExecutionError::Internal(_)) => None,
 | 
			
		||||
		Err(e) => {
 | 
			
		||||
			trace!(target: "state", "Proved call failed: {}", e);
 | 
			
		||||
 | 
			
		||||
@ -191,7 +191,7 @@ impl LightFetch {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Helper for getting proved execution.
 | 
			
		||||
	pub fn proved_execution(&self, req: CallRequest, num: Trailing<BlockNumber>) -> impl Future<Item = ExecutionResult, Error = Error> + Send {
 | 
			
		||||
	pub fn proved_read_only_execution(&self, req: CallRequest, num: Trailing<BlockNumber>) -> impl Future<Item = ExecutionResult, Error = Error> + Send {
 | 
			
		||||
		const DEFAULT_GAS_PRICE: u64 = 21_000;
 | 
			
		||||
		// starting gas when gas not provided.
 | 
			
		||||
		const START_GAS: u64 = 50_000;
 | 
			
		||||
@ -256,14 +256,14 @@ impl LightFetch {
 | 
			
		||||
				_ => return Either::A(future::err(errors::unknown_block())),
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			Either::B(execute_tx(gas_known, ExecuteParams {
 | 
			
		||||
				from: from,
 | 
			
		||||
				tx: tx,
 | 
			
		||||
				hdr: hdr,
 | 
			
		||||
				env_info: env_info,
 | 
			
		||||
			Either::B(execute_read_only_tx(gas_known, ExecuteParams {
 | 
			
		||||
				from,
 | 
			
		||||
				tx,
 | 
			
		||||
				hdr,
 | 
			
		||||
				env_info,
 | 
			
		||||
				engine: client.engine().clone(),
 | 
			
		||||
				on_demand: on_demand,
 | 
			
		||||
				sync: sync,
 | 
			
		||||
				on_demand,
 | 
			
		||||
				sync,
 | 
			
		||||
			}))
 | 
			
		||||
		}))
 | 
			
		||||
	}
 | 
			
		||||
@ -608,10 +608,10 @@ struct ExecuteParams {
 | 
			
		||||
 | 
			
		||||
// has a peer execute the transaction with given params. If `gas_known` is false,
 | 
			
		||||
// this will double the gas on each `OutOfGas` error.
 | 
			
		||||
fn execute_tx(gas_known: bool, params: ExecuteParams) -> impl Future<Item = ExecutionResult, Error = Error> + Send {
 | 
			
		||||
fn execute_read_only_tx(gas_known: bool, params: ExecuteParams) -> impl Future<Item = ExecutionResult, Error = Error> + Send {
 | 
			
		||||
	if !gas_known {
 | 
			
		||||
		Box::new(future::loop_fn(params, |mut params| {
 | 
			
		||||
			execute_tx(true, params.clone()).and_then(move |res| {
 | 
			
		||||
			execute_read_only_tx(true, params.clone()).and_then(move |res| {
 | 
			
		||||
				match res {
 | 
			
		||||
					Ok(executed) => {
 | 
			
		||||
						// TODO: how to distinguish between actual OOG and
 | 
			
		||||
 | 
			
		||||
@ -381,7 +381,7 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn call(&self, req: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<Bytes> {
 | 
			
		||||
		Box::new(self.fetcher().proved_execution(req, num).and_then(|res| {
 | 
			
		||||
		Box::new(self.fetcher().proved_read_only_execution(req, num).and_then(|res| {
 | 
			
		||||
			match res {
 | 
			
		||||
				Ok(exec) => Ok(exec.output.into()),
 | 
			
		||||
				Err(e) => Err(errors::execution(e)),
 | 
			
		||||
@ -391,7 +391,7 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
 | 
			
		||||
 | 
			
		||||
	fn estimate_gas(&self, req: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256> {
 | 
			
		||||
		// TODO: binary chop for more accurate estimates.
 | 
			
		||||
		Box::new(self.fetcher().proved_execution(req, num).and_then(|res| {
 | 
			
		||||
		Box::new(self.fetcher().proved_read_only_execution(req, num).and_then(|res| {
 | 
			
		||||
			match res {
 | 
			
		||||
				Ok(exec) => Ok((exec.refunded + exec.gas_used).into()),
 | 
			
		||||
				Err(e) => Err(errors::execution(e)),
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user