Merge pull request #99 from gavofyork/ext_u256
externalities use u256 instead of u64 for gas calculation
This commit is contained in:
commit
0fb68d3ecd
@ -6,7 +6,6 @@ use util::bytes::*;
|
|||||||
use evm::{Schedule, Error};
|
use evm::{Schedule, Error};
|
||||||
use env_info::*;
|
use env_info::*;
|
||||||
|
|
||||||
// TODO: replace all u64 with u256
|
|
||||||
pub trait Ext {
|
pub trait Ext {
|
||||||
/// Returns a value for given key.
|
/// Returns a value for given key.
|
||||||
fn sload(&self, key: &H256) -> H256;
|
fn sload(&self, key: &H256) -> H256;
|
||||||
@ -25,20 +24,20 @@ pub trait Ext {
|
|||||||
/// If contract creation is successfull, return gas_left and contract address,
|
/// If contract creation is successfull, return gas_left and contract address,
|
||||||
/// If depth is too big or transfer value exceeds balance, return None
|
/// If depth is too big or transfer value exceeds balance, return None
|
||||||
/// Otherwise return appropriate `Error`.
|
/// Otherwise return appropriate `Error`.
|
||||||
fn create(&mut self, gas: u64, value: &U256, code: &[u8]) -> Result<(u64, Option<Address>), Error>;
|
fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> Result<(U256, Option<Address>), Error>;
|
||||||
|
|
||||||
/// Message call.
|
/// Message call.
|
||||||
///
|
///
|
||||||
/// If call is successfull, returns gas left.
|
/// If call is successfull, returns gas left.
|
||||||
/// otherwise `Error`.
|
/// otherwise `Error`.
|
||||||
fn call(&mut self,
|
fn call(&mut self,
|
||||||
gas: u64,
|
gas: &U256,
|
||||||
call_gas: u64,
|
call_gas: &U256,
|
||||||
receive_address: &Address,
|
receive_address: &Address,
|
||||||
value: &U256,
|
value: &U256,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
code_address: &Address,
|
code_address: &Address,
|
||||||
output: &mut [u8]) -> Result<u64, Error>;
|
output: &mut [u8]) -> Result<U256, Error>;
|
||||||
|
|
||||||
/// Returns code at given address
|
/// Returns code at given address
|
||||||
fn extcode(&self, address: &Address) -> Vec<u8>;
|
fn extcode(&self, address: &Address) -> Vec<u8>;
|
||||||
@ -48,7 +47,7 @@ pub trait Ext {
|
|||||||
|
|
||||||
/// Should be called when transaction calls `RETURN` opcode.
|
/// Should be called when transaction calls `RETURN` opcode.
|
||||||
/// Returns gas_left if cost of returning the data is not too high.
|
/// Returns gas_left if cost of returning the data is not too high.
|
||||||
fn ret(&mut self, gas: u64, data: &[u8]) -> Result<u64, Error>;
|
fn ret(&mut self, gas: &U256, data: &[u8]) -> Result<U256, Error>;
|
||||||
|
|
||||||
/// Should be called when contract commits suicide.
|
/// Should be called when contract commits suicide.
|
||||||
/// Address to which funds should be refunded.
|
/// Address to which funds should be refunded.
|
||||||
|
@ -209,9 +209,9 @@ impl<'a> evmjit::Ext for ExtAdapter<'a> {
|
|||||||
init_size: u64,
|
init_size: u64,
|
||||||
address: *mut evmjit::H256) {
|
address: *mut evmjit::H256) {
|
||||||
unsafe {
|
unsafe {
|
||||||
match self.ext.create(*io_gas, &U256::from_jit(&*endowment), slice::from_raw_parts(init_beg, init_size as usize)) {
|
match self.ext.create(&U256::from(*io_gas), &U256::from_jit(&*endowment), slice::from_raw_parts(init_beg, init_size as usize)) {
|
||||||
Ok((gas_left, opt)) => {
|
Ok((gas_left, opt)) => {
|
||||||
*io_gas = gas_left;
|
*io_gas = gas_left.low_u64();
|
||||||
*address = match opt {
|
*address = match opt {
|
||||||
Some(addr) => addr.into_jit(),
|
Some(addr) => addr.into_jit(),
|
||||||
_ => Address::new().into_jit()
|
_ => Address::new().into_jit()
|
||||||
@ -240,8 +240,8 @@ impl<'a> evmjit::Ext for ExtAdapter<'a> {
|
|||||||
out_size: u64,
|
out_size: u64,
|
||||||
code_address: *const evmjit::H256) -> bool {
|
code_address: *const evmjit::H256) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let res = self.ext.call(*io_gas,
|
let res = self.ext.call(&U256::from(*io_gas),
|
||||||
call_gas,
|
&U256::from(call_gas),
|
||||||
&Address::from_jit(&*receive_address),
|
&Address::from_jit(&*receive_address),
|
||||||
&U256::from_jit(&*value),
|
&U256::from_jit(&*value),
|
||||||
slice::from_raw_parts(in_beg, in_size as usize),
|
slice::from_raw_parts(in_beg, in_size as usize),
|
||||||
@ -250,7 +250,7 @@ impl<'a> evmjit::Ext for ExtAdapter<'a> {
|
|||||||
|
|
||||||
match res {
|
match res {
|
||||||
Ok(gas_left) => {
|
Ok(gas_left) => {
|
||||||
*io_gas = gas_left;
|
*io_gas = gas_left.low_u64();
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
Err(err @ evm::Error::OutOfGas) => {
|
Err(err @ evm::Error::OutOfGas) => {
|
||||||
@ -345,7 +345,7 @@ impl evm::Evm for JitEvm {
|
|||||||
|
|
||||||
match res {
|
match res {
|
||||||
evmjit::ReturnCode::Stop => Ok(U256::from(context.gas_left())),
|
evmjit::ReturnCode::Stop => Ok(U256::from(context.gas_left())),
|
||||||
evmjit::ReturnCode::Return => ext.ret(context.gas_left(), context.output_data()).map(|gas_left| U256::from(gas_left)),
|
evmjit::ReturnCode::Return => ext.ret(&U256::from(context.gas_left()), context.output_data()),
|
||||||
evmjit::ReturnCode::Suicide => {
|
evmjit::ReturnCode::Suicide => {
|
||||||
ext.suicide(&Address::from_jit(&context.suicide_refund_address()));
|
ext.suicide(&Address::from_jit(&context.suicide_refund_address()));
|
||||||
Ok(U256::from(context.gas_left()))
|
Ok(U256::from(context.gas_left()))
|
||||||
|
@ -42,18 +42,18 @@ impl Ext for FakeExt {
|
|||||||
self.blockhashes.get(number).unwrap_or(&H256::new()).clone()
|
self.blockhashes.get(number).unwrap_or(&H256::new()).clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create(&mut self, _gas: u64, _value: &U256, _code: &[u8]) -> result::Result<(u64, Option<Address>), evm::Error> {
|
fn create(&mut self, _gas: &U256, _value: &U256, _code: &[u8]) -> result::Result<(U256, Option<Address>), evm::Error> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self,
|
fn call(&mut self,
|
||||||
_gas: u64,
|
_gas: &U256,
|
||||||
_call_gas: u64,
|
_call_gas: &U256,
|
||||||
_receive_address: &Address,
|
_receive_address: &Address,
|
||||||
_value: &U256,
|
_value: &U256,
|
||||||
_data: &[u8],
|
_data: &[u8],
|
||||||
_code_address: &Address,
|
_code_address: &Address,
|
||||||
_output: &mut [u8]) -> result::Result<u64, evm::Error> {
|
_output: &mut [u8]) -> result::Result<U256, evm::Error> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ impl Ext for FakeExt {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ret(&mut self, _gas: u64, _data: &[u8]) -> result::Result<u64, evm::Error> {
|
fn ret(&mut self, _gas: &U256, _data: &[u8]) -> result::Result<U256, evm::Error> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,10 +349,10 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create(&mut self, gas: u64, value: &U256, code: &[u8]) -> Result<(u64, Option<Address>), evm::Error> {
|
fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> Result<(U256, Option<Address>), evm::Error> {
|
||||||
// if balance is insufficient or we are to deep, return
|
// if balance is insufficient or we are to deep, return
|
||||||
if self.state.balance(&self.params.address) < *value || self.depth >= self.schedule.stack_limit {
|
if self.state.balance(&self.params.address) < *value || self.depth >= self.schedule.stack_limit {
|
||||||
return Ok((gas, None));
|
return Ok((*gas, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
// create new contract address
|
// create new contract address
|
||||||
@ -363,7 +363,7 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
address: address.clone(),
|
address: address.clone(),
|
||||||
sender: self.params.address.clone(),
|
sender: self.params.address.clone(),
|
||||||
origin: self.params.origin.clone(),
|
origin: self.params.origin.clone(),
|
||||||
gas: U256::from(gas),
|
gas: *gas,
|
||||||
gas_price: self.params.gas_price.clone(),
|
gas_price: self.params.gas_price.clone(),
|
||||||
value: value.clone(),
|
value: value.clone(),
|
||||||
code: code.to_vec(),
|
code: code.to_vec(),
|
||||||
@ -372,29 +372,29 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
|
|
||||||
let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.depth);
|
let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.depth);
|
||||||
ex.state.inc_nonce(&self.params.address);
|
ex.state.inc_nonce(&self.params.address);
|
||||||
ex.create(¶ms, self.substate).map(|gas_left| (gas_left.low_u64(), Some(address)))
|
ex.create(¶ms, self.substate).map(|gas_left| (gas_left, Some(address)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, gas: u64, call_gas: u64, receive_address: &Address, value: &U256, data: &[u8], code_address: &Address, output: &mut [u8]) -> Result<u64, evm::Error> {
|
fn call(&mut self, gas: &U256, call_gas: &U256, receive_address: &Address, value: &U256, data: &[u8], code_address: &Address, output: &mut [u8]) -> Result<U256, evm::Error> {
|
||||||
let mut gas_cost = call_gas;
|
let mut gas_cost = *call_gas;
|
||||||
let mut call_gas = call_gas;
|
let mut call_gas = *call_gas;
|
||||||
|
|
||||||
let is_call = receive_address == code_address;
|
let is_call = receive_address == code_address;
|
||||||
if is_call && !self.state.exists(&code_address) {
|
if is_call && !self.state.exists(&code_address) {
|
||||||
gas_cost = gas_cost + self.schedule.call_new_account_gas as u64;
|
gas_cost = gas_cost + U256::from(self.schedule.call_new_account_gas);
|
||||||
}
|
}
|
||||||
|
|
||||||
if *value > U256::zero() {
|
if *value > U256::zero() {
|
||||||
assert!(self.schedule.call_value_transfer_gas > self.schedule.call_stipend, "overflow possible");
|
assert!(self.schedule.call_value_transfer_gas > self.schedule.call_stipend, "overflow possible");
|
||||||
gas_cost = gas_cost + self.schedule.call_value_transfer_gas as u64;
|
gas_cost = gas_cost + U256::from(self.schedule.call_value_transfer_gas);
|
||||||
call_gas = call_gas + self.schedule.call_stipend as u64;
|
call_gas = call_gas + U256::from(self.schedule.call_stipend);
|
||||||
}
|
}
|
||||||
|
|
||||||
if gas_cost > gas {
|
if gas_cost > *gas {
|
||||||
return Err(evm::Error::OutOfGas)
|
return Err(evm::Error::OutOfGas)
|
||||||
}
|
}
|
||||||
|
|
||||||
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 to deep, return
|
||||||
if self.state.balance(&self.params.address) < *value || self.depth >= self.schedule.stack_limit {
|
if self.state.balance(&self.params.address) < *value || self.depth >= self.schedule.stack_limit {
|
||||||
@ -405,7 +405,7 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
address: receive_address.clone(),
|
address: receive_address.clone(),
|
||||||
sender: self.params.address.clone(),
|
sender: self.params.address.clone(),
|
||||||
origin: self.params.origin.clone(),
|
origin: self.params.origin.clone(),
|
||||||
gas: U256::from(call_gas),
|
gas: call_gas,
|
||||||
gas_price: self.params.gas_price.clone(),
|
gas_price: self.params.gas_price.clone(),
|
||||||
value: value.clone(),
|
value: value.clone(),
|
||||||
code: self.state.code(code_address).unwrap_or(vec![]),
|
code: self.state.code(code_address).unwrap_or(vec![]),
|
||||||
@ -413,35 +413,33 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.depth);
|
let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.depth);
|
||||||
ex.call(¶ms, self.substate, BytesRef::Fixed(output)).map(|gas_left| {
|
ex.call(¶ms, self.substate, BytesRef::Fixed(output))
|
||||||
gas + gas_left.low_u64()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extcode(&self, address: &Address) -> Vec<u8> {
|
fn extcode(&self, address: &Address) -> Vec<u8> {
|
||||||
self.state.code(address).unwrap_or(vec![])
|
self.state.code(address).unwrap_or(vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ret(&mut self, gas: u64, data: &[u8]) -> Result<u64, evm::Error> {
|
fn ret(&mut self, gas: &U256, data: &[u8]) -> Result<U256, evm::Error> {
|
||||||
match &mut self.output {
|
match &mut self.output {
|
||||||
&mut OutputPolicy::Return(BytesRef::Fixed(ref mut slice)) => unsafe {
|
&mut OutputPolicy::Return(BytesRef::Fixed(ref mut slice)) => unsafe {
|
||||||
let len = cmp::min(slice.len(), data.len());
|
let len = cmp::min(slice.len(), data.len());
|
||||||
ptr::copy(data.as_ptr(), slice.as_mut_ptr(), len);
|
ptr::copy(data.as_ptr(), slice.as_mut_ptr(), len);
|
||||||
Ok(gas)
|
Ok(*gas)
|
||||||
},
|
},
|
||||||
&mut OutputPolicy::Return(BytesRef::Flexible(ref mut vec)) => unsafe {
|
&mut OutputPolicy::Return(BytesRef::Flexible(ref mut vec)) => unsafe {
|
||||||
vec.clear();
|
vec.clear();
|
||||||
vec.reserve(data.len());
|
vec.reserve(data.len());
|
||||||
ptr::copy(data.as_ptr(), vec.as_mut_ptr(), data.len());
|
ptr::copy(data.as_ptr(), vec.as_mut_ptr(), data.len());
|
||||||
vec.set_len(data.len());
|
vec.set_len(data.len());
|
||||||
Ok(gas)
|
Ok(*gas)
|
||||||
},
|
},
|
||||||
&mut OutputPolicy::InitContract => {
|
&mut OutputPolicy::InitContract => {
|
||||||
let return_cost = data.len() as u64 * self.schedule.create_data_gas as u64;
|
let return_cost = U256::from(data.len()) * U256::from(self.schedule.create_data_gas);
|
||||||
if return_cost > gas {
|
if return_cost > *gas {
|
||||||
return match self.schedule.exceptional_failed_code_deposit {
|
return match self.schedule.exceptional_failed_code_deposit {
|
||||||
true => Err(evm::Error::OutOfGas),
|
true => Err(evm::Error::OutOfGas),
|
||||||
false => Ok(gas)
|
false => Ok(*gas)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut code = vec![];
|
let mut code = vec![];
|
||||||
@ -453,7 +451,7 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
let address = &self.params.address;
|
let address = &self.params.address;
|
||||||
self.state.init_code(address, code);
|
self.state.init_code(address, code);
|
||||||
self.substate.contracts_created.push(address.clone());
|
self.substate.contracts_created.push(address.clone());
|
||||||
Ok(gas - return_cost)
|
Ok(*gas - return_cost)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ impl<'a> Ext for TestExt<'a> {
|
|||||||
self.ext.blockhash(number)
|
self.ext.blockhash(number)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create(&mut self, gas: u64, value: &U256, code: &[u8]) -> Result<(u64, Option<Address>), evm::Error> {
|
fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> Result<(U256, Option<Address>), evm::Error> {
|
||||||
// in call and create we need to check if we exited with insufficient balance or max limit reached.
|
// in call and create we need to check if we exited with insufficient balance or max limit reached.
|
||||||
// in case of reaching max depth, we should store callcreates. Otherwise, ignore.
|
// in case of reaching max depth, we should store callcreates. Otherwise, ignore.
|
||||||
let res = self.ext.create(gas, value, code);
|
let res = self.ext.create(gas, value, code);
|
||||||
@ -82,7 +82,7 @@ impl<'a> Ext for TestExt<'a> {
|
|||||||
self.callcreates.push(CallCreate {
|
self.callcreates.push(CallCreate {
|
||||||
data: code.to_vec(),
|
data: code.to_vec(),
|
||||||
destination: address.clone(),
|
destination: address.clone(),
|
||||||
_gas_limit: U256::from(gas),
|
_gas_limit: *gas,
|
||||||
value: *value
|
value: *value
|
||||||
});
|
});
|
||||||
Ok((gas_left, Some(address)))
|
Ok((gas_left, Some(address)))
|
||||||
@ -94,7 +94,7 @@ impl<'a> Ext for TestExt<'a> {
|
|||||||
data: code.to_vec(),
|
data: code.to_vec(),
|
||||||
// TODO: address is not stored here?
|
// TODO: address is not stored here?
|
||||||
destination: Address::new(),
|
destination: Address::new(),
|
||||||
_gas_limit: U256::from(gas),
|
_gas_limit: *gas,
|
||||||
value: *value
|
value: *value
|
||||||
});
|
});
|
||||||
Ok((gas_left, Some(address)))
|
Ok((gas_left, Some(address)))
|
||||||
@ -104,13 +104,13 @@ impl<'a> Ext for TestExt<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self,
|
fn call(&mut self,
|
||||||
gas: u64,
|
gas: &U256,
|
||||||
call_gas: u64,
|
call_gas: &U256,
|
||||||
receive_address: &Address,
|
receive_address: &Address,
|
||||||
value: &U256,
|
value: &U256,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
code_address: &Address,
|
code_address: &Address,
|
||||||
output: &mut [u8]) -> Result<u64, evm::Error> {
|
output: &mut [u8]) -> Result<U256, evm::Error> {
|
||||||
let res = self.ext.call(gas, call_gas, receive_address, value, data, code_address, output);
|
let res = self.ext.call(gas, call_gas, receive_address, value, data, code_address, output);
|
||||||
let ext = &self.ext;
|
let ext = &self.ext;
|
||||||
match res {
|
match res {
|
||||||
@ -118,7 +118,7 @@ impl<'a> Ext for TestExt<'a> {
|
|||||||
self.callcreates.push(CallCreate {
|
self.callcreates.push(CallCreate {
|
||||||
data: data.to_vec(),
|
data: data.to_vec(),
|
||||||
destination: receive_address.clone(),
|
destination: receive_address.clone(),
|
||||||
_gas_limit: U256::from(call_gas),
|
_gas_limit: *call_gas,
|
||||||
value: *value
|
value: *value
|
||||||
});
|
});
|
||||||
Ok(gas_left)
|
Ok(gas_left)
|
||||||
@ -135,7 +135,7 @@ impl<'a> Ext for TestExt<'a> {
|
|||||||
self.ext.log(topics, data)
|
self.ext.log(topics, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ret(&mut self, gas: u64, data: &[u8]) -> Result<u64, evm::Error> {
|
fn ret(&mut self, gas: &U256, data: &[u8]) -> Result<U256, evm::Error> {
|
||||||
self.ext.ret(gas, data)
|
self.ext.ret(gas, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user