diff --git a/README.md b/README.md index 35f7fc4..44154e2 100644 --- a/README.md +++ b/README.md @@ -100,11 +100,6 @@ password = "foreign_password.txt" [authorities] required_signatures = 2 - -[transactions] -deposit_relay = { gas = 3000000 } -withdraw_relay = { gas = 3000000 } -withdraw_confirm = { gas = 3000000 } ``` #### Options @@ -133,9 +128,9 @@ withdraw_confirm = { gas = 3000000 } #### transaction options -- `transaction.deposit_relay.gas` - specify how much gas should be consumed by deposit relay -- `transaction.withdraw_confirm.gas` - specify how much gas should be consumed by withdraw confirm -- `transaction.withdraw_relay.gas` - specify how much gas should be consumed by withdraw relay +- `transaction.deposit_relay.gas` - specify how much gas should be consumed by deposit relay (optional, default: computed with `eth.estimateGas`) +- `transaction.withdraw_confirm.gas` - specify how much gas should be consumed by withdraw confirm (optional, default: computed with `eth.estimateGas`) +- `transaction.withdraw_relay.gas` - specify how much gas should be consumed by withdraw relay (optional, default: computed with `eth.estimateGas`) ### Database file format diff --git a/bridge/src/api.rs b/bridge/src/api.rs index cf31055..4035d09 100644 --- a/bridge/src/api.rs +++ b/bridge/src/api.rs @@ -142,6 +142,24 @@ pub fn call(transport: T, address: Address, payload: Bytes) -> Api } } +/// Imperative wrapper for web3 function. +pub fn estimate_gas(transport: T, sender: Option
, address: Address, payload: Bytes) -> ApiCall { + let future = api::Eth::new(transport).estimate_gas(CallRequest { + from: sender, + to: address, + gas: None, + gas_price: None, + value: None, + data: Some(payload), + }, None); + + ApiCall { + future, + message: "eth_estimateGas", + } +} + + /// Returns a eth_sign-compatible hash of data to sign. /// The data is prepended with special message to prevent /// chosen-plaintext attacks. diff --git a/bridge/src/bridge/nonce.rs b/bridge/src/bridge/nonce.rs index e9007db..27f2661 100644 --- a/bridge/src/bridge/nonce.rs +++ b/bridge/src/bridge/nonce.rs @@ -2,7 +2,7 @@ use futures::{Future, Async, Poll, future::{MapErr}}; use tokio_timer::Timeout; use web3::{self, Transport}; use web3::types::{U256, H256, Bytes}; -use ethcore_transaction::Transaction; +use ethcore_transaction::{Transaction, Action}; use api::{self, ApiCall}; use error::{Error, ErrorKind}; use config::Node; @@ -23,6 +23,12 @@ enum NonceCheckState { }, /// Nonce available Nonce(U256), + /// Request gas estimation + GasEstimateRequest { + future: Timeout>, + }, + /// Send transaction + SendTransaction, /// Transaction is in progress TransactionRequest { future: Timeout, @@ -90,6 +96,35 @@ impl Future for NonceCheck { }, NonceCheckState::Nonce(mut nonce) => { self.transaction.nonce = nonce; + match self.transaction.action { + Action::Call(address) if self.transaction.gas.is_zero() => { + NonceCheckState::GasEstimateRequest { + future: self.app.timer.timeout(api::estimate_gas(&self.transport, Some(self.node.account), address, Bytes(self.transaction.data.clone())), self.node.request_timeout) + } + }, + _ => NonceCheckState::SendTransaction, + } + }, + NonceCheckState::GasEstimateRequest { ref mut future } => { + match future.poll() { + Ok(Async::Ready(gas)) => { + self.transaction.gas = gas; + NonceCheckState::SendTransaction + }, + Ok(Async::NotReady) => return Ok(Async::NotReady), + Err(e) => { + match e { + Error(ErrorKind::Web3(web3::error::Error(web3::error::ErrorKind::Rpc(err), _)), _) => { + let hash = self.transaction.hash(Some(self.chain_id)); + info!("{} fails to pass eth.estimateGas on {}, skipping (error: {:?})", hash, self.node.rpc_host, err); + return Ok(Async::Ready(self.sender.ignore(hash))) + }, + e => return Err(From::from(e)), + } + }, + } + }, + NonceCheckState::SendTransaction => { match prepare_raw_transaction(self.transaction.clone(), &self.app, &self.node, self.chain_id) { Ok(tx) => NonceCheckState::TransactionRequest { future: self.app.timer.timeout(self.sender.send(tx), self.node.request_timeout) diff --git a/examples/config.toml b/examples/config.toml index f6f3cef..17dc7f6 100644 --- a/examples/config.toml +++ b/examples/config.toml @@ -19,8 +19,3 @@ default_gas_price = 5_000_000_000 # 5 GWEI [authorities] required_signatures = 1 - -[transactions] -home_deploy = { gas = 1000000 } -foreign_deploy = { gas = 3000000 } -deposit_relay = { gas = 100000 } diff --git a/integration-tests/bridge_config.toml b/integration-tests/bridge_config.toml index 96a9707..83279e0 100644 --- a/integration-tests/bridge_config.toml +++ b/integration-tests/bridge_config.toml @@ -33,6 +33,6 @@ required_signatures = 1 [transactions] home_deploy = { gas = 3000000 } foreign_deploy = { gas = 3000000 } -deposit_relay = { gas = 3000000 } -withdraw_relay = { gas = 3000000 } -withdraw_confirm = { gas = 3000000 } +#deposit_relay = { gas = 3000000 } +#withdraw_relay = { gas = 3000000 } +#withdraw_confirm = { gas = 3000000 }