Merge branch 'master' of github.com:gavofyork/ethcore into client
This commit is contained in:
commit
d80fe310a3
@ -20,16 +20,19 @@ pub struct OutOfBounds<T: fmt::Debug> {
|
|||||||
/// Result of executing the transaction.
|
/// Result of executing the transaction.
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
pub enum ExecutionError {
|
pub enum ExecutionError {
|
||||||
|
/// Returned when there gas paid for transaction execution is
|
||||||
|
/// lower than base gas required.
|
||||||
|
NotEnoughBaseGas { required: U256, got: U256 },
|
||||||
/// Returned when block (gas_used + gas) > gas_limit.
|
/// Returned when block (gas_used + gas) > gas_limit.
|
||||||
///
|
///
|
||||||
/// If gas =< gas_limit, upstream may try to execute the transaction
|
/// If gas =< gas_limit, upstream may try to execute the transaction
|
||||||
/// in next block.
|
/// in next block.
|
||||||
BlockGasLimitReached { gas_limit: U256, gas_used: U256, gas: U256 },
|
BlockGasLimitReached { gas_limit: U256, gas_used: U256, gas: U256 },
|
||||||
/// Returned when transaction nonce does not match state nonce.
|
/// Returned when transaction nonce does not match state nonce.
|
||||||
InvalidNonce { expected: U256, is: U256 },
|
InvalidNonce { expected: U256, got: U256 },
|
||||||
/// Returned when cost of transaction (value + gas_price * gas) exceeds
|
/// Returned when cost of transaction (value + gas_price * gas) exceeds
|
||||||
/// current sender balance.
|
/// current sender balance.
|
||||||
NotEnoughCash { required: U512, is: U512 },
|
NotEnoughCash { required: U512, got: U512 },
|
||||||
/// Returned when internal evm error occurs.
|
/// Returned when internal evm error occurs.
|
||||||
Internal
|
Internal
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,6 @@ pub struct Substate {
|
|||||||
logs: Vec<LogEntry>,
|
logs: Vec<LogEntry>,
|
||||||
/// Refund counter of SSTORE nonzero->zero.
|
/// Refund counter of SSTORE nonzero->zero.
|
||||||
refunds_count: U256,
|
refunds_count: U256,
|
||||||
/// True if transaction, or one of its subcalls runs out of gas.
|
|
||||||
excepted: bool,
|
|
||||||
/// Created contracts.
|
/// Created contracts.
|
||||||
contracts_created: Vec<Address>
|
contracts_created: Vec<Address>
|
||||||
}
|
}
|
||||||
@ -34,7 +32,6 @@ impl Substate {
|
|||||||
suicides: HashSet::new(),
|
suicides: HashSet::new(),
|
||||||
logs: vec![],
|
logs: vec![],
|
||||||
refunds_count: U256::zero(),
|
refunds_count: U256::zero(),
|
||||||
excepted: false,
|
|
||||||
contracts_created: vec![]
|
contracts_created: vec![]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,11 +40,8 @@ impl Substate {
|
|||||||
self.suicides.extend(s.suicides.into_iter());
|
self.suicides.extend(s.suicides.into_iter());
|
||||||
self.logs.extend(s.logs.into_iter());
|
self.logs.extend(s.logs.into_iter());
|
||||||
self.refunds_count = self.refunds_count + s.refunds_count;
|
self.refunds_count = self.refunds_count + s.refunds_count;
|
||||||
self.excepted |= s.excepted;
|
|
||||||
self.contracts_created.extend(s.contracts_created.into_iter());
|
self.contracts_created.extend(s.contracts_created.into_iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn excepted(&self) -> bool { self.excepted }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transaction execution receipt.
|
/// Transaction execution receipt.
|
||||||
@ -68,8 +62,6 @@ pub struct Executed {
|
|||||||
pub cumulative_gas_used: U256,
|
pub cumulative_gas_used: U256,
|
||||||
/// Vector of logs generated by transaction.
|
/// Vector of logs generated by transaction.
|
||||||
pub logs: Vec<LogEntry>,
|
pub logs: Vec<LogEntry>,
|
||||||
/// Execution ended running out of gas.
|
|
||||||
pub excepted: bool,
|
|
||||||
/// Addresses of contracts created during execution of transaction.
|
/// Addresses of contracts created during execution of transaction.
|
||||||
/// Ordered from earliest creation.
|
/// Ordered from earliest creation.
|
||||||
///
|
///
|
||||||
@ -117,11 +109,18 @@ impl<'a> Executive<'a> {
|
|||||||
let sender = try!(t.sender());
|
let sender = try!(t.sender());
|
||||||
let nonce = self.state.nonce(&sender);
|
let nonce = self.state.nonce(&sender);
|
||||||
|
|
||||||
// TODO: error on base gas required
|
let schedule = self.engine.schedule(self.info);
|
||||||
|
let base_gas_required = U256::from(t.gas_required(&schedule));
|
||||||
|
|
||||||
|
if t.gas < base_gas_required {
|
||||||
|
return Err(From::from(ExecutionError::NotEnoughBaseGas { required: base_gas_required, got: t.gas }));
|
||||||
|
}
|
||||||
|
|
||||||
|
let init_gas = t.gas - base_gas_required;
|
||||||
|
|
||||||
// validate transaction nonce
|
// validate transaction nonce
|
||||||
if t.nonce != nonce {
|
if t.nonce != nonce {
|
||||||
return Err(From::from(ExecutionError::InvalidNonce { expected: nonce, is: 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
|
||||||
@ -140,7 +139,7 @@ impl<'a> Executive<'a> {
|
|||||||
|
|
||||||
// avoid unaffordable transactions
|
// avoid unaffordable transactions
|
||||||
if U512::from(balance) < total_cost {
|
if U512::from(balance) < total_cost {
|
||||||
return Err(From::from(ExecutionError::NotEnoughCash { required: total_cost, is: U512::from(balance) }));
|
return Err(From::from(ExecutionError::NotEnoughCash { required: total_cost, got: U512::from(balance) }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: there can be no invalid transactions from this point.
|
// NOTE: there can be no invalid transactions from this point.
|
||||||
@ -149,9 +148,6 @@ impl<'a> Executive<'a> {
|
|||||||
|
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
|
|
||||||
let schedule = self.engine.schedule(self.info);
|
|
||||||
let init_gas = t.gas - U256::from(t.gas_required(&schedule));
|
|
||||||
|
|
||||||
let res = match t.action() {
|
let res = match t.action() {
|
||||||
&Action::Create => {
|
&Action::Create => {
|
||||||
let params = ActionParams {
|
let params = ActionParams {
|
||||||
@ -207,7 +203,10 @@ impl<'a> Executive<'a> {
|
|||||||
Ok(params.gas - cost)
|
Ok(params.gas - cost)
|
||||||
},
|
},
|
||||||
// just drain the whole gas
|
// just drain the whole gas
|
||||||
false => Ok(U256::zero())
|
false => {
|
||||||
|
self.state.revert(backup);
|
||||||
|
Err(evm::Error::OutOfGas)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if params.code.len() > 0 {
|
} else if params.code.len() > 0 {
|
||||||
// if destination is a contract, do normal message call
|
// if destination is a contract, do normal message call
|
||||||
@ -293,7 +292,6 @@ impl<'a> Executive<'a> {
|
|||||||
refunded: refund,
|
refunded: refund,
|
||||||
cumulative_gas_used: self.info.gas_used + gas_used,
|
cumulative_gas_used: self.info.gas_used + gas_used,
|
||||||
logs: substate.logs,
|
logs: substate.logs,
|
||||||
excepted: substate.excepted,
|
|
||||||
contracts_created: substate.contracts_created
|
contracts_created: substate.contracts_created
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -304,7 +302,6 @@ impl<'a> Executive<'a> {
|
|||||||
refunded: U256::zero(),
|
refunded: U256::zero(),
|
||||||
cumulative_gas_used: self.info.gas_used + t.gas,
|
cumulative_gas_used: self.info.gas_used + t.gas,
|
||||||
logs: vec![],
|
logs: vec![],
|
||||||
excepted: true,
|
|
||||||
contracts_created: vec![]
|
contracts_created: vec![]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -315,7 +312,6 @@ impl<'a> Executive<'a> {
|
|||||||
// TODO: handle other evm::Errors same as OutOfGas once they are implemented
|
// TODO: handle other evm::Errors same as OutOfGas once they are implemented
|
||||||
match result {
|
match result {
|
||||||
&Err(evm::Error::OutOfGas) => {
|
&Err(evm::Error::OutOfGas) => {
|
||||||
substate.excepted = true;
|
|
||||||
self.state.revert(backup);
|
self.state.revert(backup);
|
||||||
},
|
},
|
||||||
&Ok(_) | &Err(evm::Error::Internal) => substate.accrue(un_substate)
|
&Ok(_) | &Err(evm::Error::Internal) => substate.accrue(un_substate)
|
||||||
@ -461,7 +457,7 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
|
|
||||||
let gas = *gas - gas_cost;
|
let gas = *gas - gas_cost;
|
||||||
|
|
||||||
// if balance is insufficient or we are to deep, return
|
// if balance is insufficient or we are too deep, return
|
||||||
if self.state.balance(&self.params.address) < *value || self.depth >= self.schedule.max_depth {
|
if self.state.balance(&self.params.address) < *value || self.depth >= self.schedule.max_depth {
|
||||||
return Ok((gas + call_gas, true));
|
return Ok((gas + call_gas, true));
|
||||||
}
|
}
|
||||||
@ -899,7 +895,6 @@ mod tests {
|
|||||||
assert_eq!(executed.refunded, U256::from(58_699));
|
assert_eq!(executed.refunded, U256::from(58_699));
|
||||||
assert_eq!(executed.cumulative_gas_used, U256::from(41_301));
|
assert_eq!(executed.cumulative_gas_used, U256::from(41_301));
|
||||||
assert_eq!(executed.logs.len(), 0);
|
assert_eq!(executed.logs.len(), 0);
|
||||||
assert_eq!(executed.excepted, false);
|
|
||||||
assert_eq!(executed.contracts_created.len(), 0);
|
assert_eq!(executed.contracts_created.len(), 0);
|
||||||
assert_eq!(state.balance(&sender), U256::from(1));
|
assert_eq!(state.balance(&sender), U256::from(1));
|
||||||
assert_eq!(state.balance(&contract), U256::from(17));
|
assert_eq!(state.balance(&contract), U256::from(17));
|
||||||
@ -946,8 +941,8 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Err(Error::Execution(ExecutionError::InvalidNonce { expected, is }))
|
Err(Error::Execution(ExecutionError::InvalidNonce { expected, got }))
|
||||||
if expected == U256::zero() && is == U256::one() => (),
|
if expected == U256::zero() && got == U256::one() => (),
|
||||||
_ => assert!(false, "Expected invalid nonce error.")
|
_ => assert!(false, "Expected invalid nonce error.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -997,8 +992,8 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Err(Error::Execution(ExecutionError::NotEnoughCash { required , is }))
|
Err(Error::Execution(ExecutionError::NotEnoughCash { required , got }))
|
||||||
if required == U512::from(100_018) && is == U512::from(100_017) => (),
|
if required == U512::from(100_018) && got == U512::from(100_017) => (),
|
||||||
_ => assert!(false, "Expected not enough cash error. {:?}", res)
|
_ => assert!(false, "Expected not enough cash error. {:?}", res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,7 @@ impl PodAccount {
|
|||||||
let mut stream = RlpStream::new_list(4);
|
let mut stream = RlpStream::new_list(4);
|
||||||
stream.append(&self.nonce);
|
stream.append(&self.nonce);
|
||||||
stream.append(&self.balance);
|
stream.append(&self.balance);
|
||||||
// TODO.
|
stream.append(&sec_trie_root(self.storage.iter().map(|(k, v)| (k.to_vec(), encode(&U256::from(v.as_slice())))).collect()));
|
||||||
stream.append(&SHA3_NULL_RLP);
|
|
||||||
stream.append(&self.code.sha3());
|
stream.append(&self.code.sha3());
|
||||||
stream.out()
|
stream.out()
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,6 @@ use pod_state::*;
|
|||||||
use state_diff::*;
|
use state_diff::*;
|
||||||
use ethereum;
|
use ethereum;
|
||||||
|
|
||||||
fn flush(s: String) {
|
|
||||||
::std::io::stdout().write(s.as_bytes()).unwrap();
|
|
||||||
::std::io::stdout().flush().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||||
let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid");
|
let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid");
|
||||||
let mut failed = Vec::new();
|
let mut failed = Vec::new();
|
||||||
@ -39,14 +34,12 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
|||||||
|
|
||||||
//println!("Transaction: {:?}", t);
|
//println!("Transaction: {:?}", t);
|
||||||
//println!("Env: {:?}", env);
|
//println!("Env: {:?}", env);
|
||||||
|
let calc_post = sec_trie_root(post.get().iter().map(|(k, v)| (k.to_vec(), v.rlp())).collect());
|
||||||
|
|
||||||
{
|
if fail_unless(post_state_root == calc_post) {
|
||||||
let mut s = State::new_temp();
|
println!("!!! {}: Trie root mismatch (got: {}, expect: {}):", name, calc_post, post_state_root);
|
||||||
s.populate_from(post.clone());
|
println!("!!! Post:\n{}", post);
|
||||||
s.commit();
|
} else {
|
||||||
assert_eq!(&post_state_root, s.root());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut s = State::new_temp();
|
let mut s = State::new_temp();
|
||||||
s.populate_from(pre);
|
s.populate_from(pre);
|
||||||
s.commit();
|
s.commit();
|
||||||
@ -68,6 +61,7 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if !fail {
|
if !fail {
|
||||||
flush(format!("ok\n"));
|
flush(format!("ok\n"));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user