Fixed eth_call nonce and gas handling
This commit is contained in:
parent
d01a79f58f
commit
9b7c48110a
@ -38,7 +38,7 @@ use block_queue::{BlockQueue, BlockQueueInfo};
|
|||||||
use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute};
|
use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute};
|
||||||
use client::{BlockId, TransactionId, UncleId, ClientConfig, BlockChainClient};
|
use client::{BlockId, TransactionId, UncleId, ClientConfig, BlockChainClient};
|
||||||
use env_info::EnvInfo;
|
use env_info::EnvInfo;
|
||||||
use executive::{Executive, Executed, contract_address};
|
use executive::{Executive, Executed, TransactOptions, contract_address};
|
||||||
use receipt::LocalizedReceipt;
|
use receipt::LocalizedReceipt;
|
||||||
pub use blockchain::CacheSize as BlockChainCacheSize;
|
pub use blockchain::CacheSize as BlockChainCacheSize;
|
||||||
|
|
||||||
@ -418,7 +418,8 @@ impl<V> BlockChainClient for Client<V> where V: Verifier {
|
|||||||
// give the sender max balance
|
// give the sender max balance
|
||||||
state.sub_balance(&sender, &balance);
|
state.sub_balance(&sender, &balance);
|
||||||
state.add_balance(&sender, &U256::max_value());
|
state.add_balance(&sender, &U256::max_value());
|
||||||
Executive::new(&mut state, &env_info, self.engine.deref().deref()).transact(t, false)
|
let options = TransactOptions { tracing: false, check_nonce: false };
|
||||||
|
Executive::new(&mut state, &env_info, self.engine.deref().deref()).transact(t, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO [todr] Should be moved to miner crate eventually.
|
// TODO [todr] Should be moved to miner crate eventually.
|
||||||
|
@ -36,6 +36,14 @@ pub fn contract_address(address: &Address, nonce: &U256) -> Address {
|
|||||||
From::from(stream.out().sha3())
|
From::from(stream.out().sha3())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Transaction execution options.
|
||||||
|
pub struct TransactOptions {
|
||||||
|
/// Enable call tracing.
|
||||||
|
pub tracing: bool,
|
||||||
|
/// Check transaction nonce before execution.
|
||||||
|
pub check_nonce: bool,
|
||||||
|
}
|
||||||
|
|
||||||
/// Transaction execution receipt.
|
/// Transaction execution receipt.
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct Executed {
|
pub struct Executed {
|
||||||
@ -110,7 +118,7 @@ impl<'a> Executive<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This funtion should be used to execute transaction.
|
/// This funtion should be used to execute transaction.
|
||||||
pub fn transact(&'a mut self, t: &SignedTransaction, tracing: bool) -> Result<Executed, Error> {
|
pub fn transact(&'a mut self, t: &SignedTransaction, options: TransactOptions) -> Result<Executed, Error> {
|
||||||
let sender = try!(t.sender());
|
let sender = try!(t.sender());
|
||||||
let nonce = self.state.nonce(&sender);
|
let nonce = self.state.nonce(&sender);
|
||||||
|
|
||||||
@ -124,9 +132,11 @@ impl<'a> Executive<'a> {
|
|||||||
let init_gas = t.gas - base_gas_required;
|
let init_gas = t.gas - base_gas_required;
|
||||||
|
|
||||||
// validate transaction nonce
|
// validate transaction nonce
|
||||||
|
if options.check_nonce {
|
||||||
if t.nonce != nonce {
|
if t.nonce != nonce {
|
||||||
return Err(From::from(ExecutionError::InvalidNonce { expected: nonce, got: t.nonce }));
|
return Err(From::from(ExecutionError::InvalidNonce { expected: nonce, got: t.nonce }));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// validate if transaction fits into given block
|
// validate if transaction fits into given block
|
||||||
if self.info.gas_used + t.gas > self.info.gas_limit {
|
if self.info.gas_used + t.gas > self.info.gas_limit {
|
||||||
@ -151,7 +161,7 @@ impl<'a> Executive<'a> {
|
|||||||
self.state.inc_nonce(&sender);
|
self.state.inc_nonce(&sender);
|
||||||
self.state.sub_balance(&sender, &U256::from(gas_cost));
|
self.state.sub_balance(&sender, &U256::from(gas_cost));
|
||||||
|
|
||||||
let mut substate = Substate::new(tracing);
|
let mut substate = Substate::new(options.tracing);
|
||||||
|
|
||||||
let (gas_left, output) = match t.action {
|
let (gas_left, output) = match t.action {
|
||||||
Action::Create => {
|
Action::Create => {
|
||||||
@ -881,7 +891,8 @@ mod tests {
|
|||||||
|
|
||||||
let executed = {
|
let executed = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
ex.transact(&t, false).unwrap()
|
let opts = TransactOptions { check_nonce: true, tracing: false };
|
||||||
|
ex.transact(&t, opts).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(executed.gas, U256::from(100_000));
|
assert_eq!(executed.gas, U256::from(100_000));
|
||||||
@ -914,7 +925,8 @@ mod tests {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
ex.transact(&t, false)
|
let opts = TransactOptions { check_nonce: true, tracing: false };
|
||||||
|
ex.transact(&t, opts)
|
||||||
};
|
};
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
@ -945,7 +957,8 @@ mod tests {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
ex.transact(&t, false)
|
let opts = TransactOptions { check_nonce: true, tracing: false };
|
||||||
|
ex.transact(&t, opts)
|
||||||
};
|
};
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
@ -978,7 +991,8 @@ mod tests {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
ex.transact(&t, false)
|
let opts = TransactOptions { check_nonce: true, tracing: false };
|
||||||
|
ex.transact(&t, opts)
|
||||||
};
|
};
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
@ -1011,7 +1025,8 @@ mod tests {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
ex.transact(&t, false)
|
let opts = TransactOptions { check_nonce: true, tracing: false };
|
||||||
|
ex.transact(&t, opts)
|
||||||
};
|
};
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
use common::*;
|
use common::*;
|
||||||
use engine::Engine;
|
use engine::Engine;
|
||||||
use executive::Executive;
|
use executive::{Executive, TransactOptions};
|
||||||
use account_db::*;
|
use account_db::*;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[cfg(feature = "json-tests")]
|
#[cfg(feature = "json-tests")]
|
||||||
@ -220,7 +220,8 @@ impl State {
|
|||||||
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &SignedTransaction, tracing: bool) -> ApplyResult {
|
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &SignedTransaction, tracing: bool) -> ApplyResult {
|
||||||
// let old = self.to_pod();
|
// let old = self.to_pod();
|
||||||
|
|
||||||
let e = try!(Executive::new(self, env_info, engine).transact(t, tracing));
|
let options = TransactOptions { tracing: tracing, check_nonce: true };
|
||||||
|
let e = try!(Executive::new(self, env_info, engine).transact(t, options));
|
||||||
|
|
||||||
// TODO uncomment once to_pod() works correctly.
|
// TODO uncomment once to_pod() works correctly.
|
||||||
// trace!("Applied transaction. Diff:\n{}\n", StateDiff::diff_pod(&old, &self.to_pod()));
|
// trace!("Applied transaction. Diff:\n{}\n", StateDiff::diff_pod(&old, &self.to_pod()));
|
||||||
|
@ -43,6 +43,10 @@ fn default_gas() -> U256 {
|
|||||||
U256::from(21_000)
|
U256::from(21_000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_call_gas() -> U256 {
|
||||||
|
U256::from(50_000_000)
|
||||||
|
}
|
||||||
|
|
||||||
/// Eth rpc implementation.
|
/// Eth rpc implementation.
|
||||||
pub struct EthClient<C, S, A, M, EM = ExternalMiner>
|
pub struct EthClient<C, S, A, M, EM = ExternalMiner>
|
||||||
where C: BlockChainClient,
|
where C: BlockChainClient,
|
||||||
@ -175,7 +179,7 @@ impl<C, S, A, M, EM> EthClient<C, S, A, M, EM>
|
|||||||
Ok(EthTransaction {
|
Ok(EthTransaction {
|
||||||
nonce: request.nonce.unwrap_or_else(|| client.nonce(&from)),
|
nonce: request.nonce.unwrap_or_else(|| client.nonce(&from)),
|
||||||
action: request.to.map_or(Action::Create, Action::Call),
|
action: request.to.map_or(Action::Create, Action::Call),
|
||||||
gas: request.gas.unwrap_or_else(default_gas),
|
gas: request.gas.unwrap_or_else(default_call_gas),
|
||||||
gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()),
|
gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()),
|
||||||
value: request.value.unwrap_or_else(U256::zero),
|
value: request.value.unwrap_or_else(U256::zero),
|
||||||
data: request.data.map_or_else(Vec::new, |d| d.to_vec())
|
data: request.data.map_or_else(Vec::new, |d| d.to_vec())
|
||||||
|
Loading…
Reference in New Issue
Block a user