Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Calculate gas for deployment transaction #9840

Merged
merged 3 commits into from
Nov 28, 2018
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 31 additions & 7 deletions ethcore/private-tx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ use ethcore::executed::{Executed};
use transaction::{SignedTransaction, Transaction, Action, UnverifiedTransaction};
use ethcore::{contract_address as ethcore_contract_address};
use ethcore::client::{
Client, ChainNotify, ChainRoute, ChainMessageType, ClientIoMessage, BlockId, CallContract
Client, ChainNotify, ChainRoute, ChainMessageType, ClientIoMessage, BlockId,
CallContract, Call, BlockInfo
};
use ethcore::account_provider::AccountProvider;
use ethcore::miner::{self, Miner, MinerService, pool_client::NonceCache};
Expand Down Expand Up @@ -550,21 +551,44 @@ impl Provider where {
let state = self.client.state_at(block).ok_or(ErrorKind::StatePruned)?;
let nonce = state.nonce(&sender)?;
let executed = self.execute_private(source, TransactOptions::with_no_tracing(), block)?;
let gas: u64 = 650000 +
validators.len() as u64 * 30000 +
executed.code.as_ref().map_or(0, |c| c.len() as u64) * 8000 +
executed.state.len() as u64 * 8000;
let header = self.client.block_header(block)
.ok_or(ErrorKind::StatePruned)
.and_then(|h| h.decode().map_err(|_| ErrorKind::StateIncorrect).into())?;
let (executed_code, executed_state) = (executed.code.unwrap_or_default(), executed.state);
let tx_data = Self::generate_constructor(validators, executed_code.clone(), executed_state.clone());
let gas = match self.client.estimate_gas(&Transaction{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: missing space

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the deployment transaction the speed is not so important as it's one-time action. At the same time overestimation for the gas can (and actually is, see the corresponding bug) cause problems as wrapper contract is pretty complex and stores private contracts inside. In case, when the private contract is big enough, this overestimation exceeds gas_limit.

nonce: nonce,
action: Action::Create,
gas: u64::max_value().into(),
gas_price: gas_price,
value: source.value,
data: tx_data.clone(),
}.fake_sign(sender),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think indentation is a bit weird like this

&state,
&header) {
Ok(estimated_gas) => estimated_gas,
Err(_) => self.estimate_tx_gas(validators, &executed_code, &executed_state, &[]),
};
Ok((Transaction {
nonce: nonce,
action: Action::Create,
gas: gas.into(),
gas_price: gas_price,
value: source.value,
data: Self::generate_constructor(validators, executed.code.unwrap_or_default(), executed.state)
data: tx_data,
},
executed.contract_address))
}

fn estimate_tx_gas(&self, validators: &[Address], code: &Bytes, state: &Bytes, signatures: &[Signature]) -> U256 {
let default_gas = 650000 +
validators.len() as u64 * 30000 +
code.len() as u64 * 8000 +
signatures.len() as u64 * 50000 +
state.len() as u64 * 8000;
default_gas.into()
}

/// Create encrypted public contract deployment transaction. Returns updated encrypted state.
pub fn execute_private_transaction(&self, block: BlockId, source: &SignedTransaction) -> Result<Bytes, Error> {
if let Action::Create = source.action {
Expand All @@ -576,7 +600,7 @@ impl Provider where {

/// Create encrypted public transaction from private transaction.
pub fn public_transaction(&self, state: Bytes, source: &SignedTransaction, signatures: &[Signature], nonce: U256, gas_price: U256) -> Result<Transaction, Error> {
let gas: u64 = 650000 + state.len() as u64 * 8000 + signatures.len() as u64 * 50000;
let gas = self.estimate_tx_gas(&[], &Vec::new(), &state, signatures);
Ok(Transaction {
nonce: nonce,
action: source.action.clone(),
Expand Down