Use U512s for ether cost calculation.

This commit is contained in:
Gav Wood 2016-01-12 17:40:34 +01:00
parent 5abffb518d
commit 08074ef397
3 changed files with 21 additions and 13 deletions

View File

@ -28,7 +28,7 @@ pub enum ExecutionError {
InvalidNonce { expected: U256, is: U256 }, InvalidNonce { expected: U256, is: 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: U256, is: U256 }, NotEnoughCash { required: U512, is: U512 },
/// Returned when internal evm error occurs. /// Returned when internal evm error occurs.
Internal Internal
} }

View File

@ -123,17 +123,17 @@ impl<'a> Executive<'a> {
// TODO: we might need bigints here, or at least check overflows. // TODO: we might need bigints here, or at least check overflows.
let balance = self.state.balance(&sender); let balance = self.state.balance(&sender);
let gas_cost = t.gas * t.gas_price; let gas_cost = U512::from(t.gas) * U512::from(t.gas_price);
let total_cost = t.value + gas_cost; let total_cost = U512::from(t.value) + gas_cost;
// avoid unaffordable transactions // avoid unaffordable transactions
if balance < total_cost { if U512::from(balance) < total_cost {
return Err(From::from(ExecutionError::NotEnoughCash { required: total_cost, is: balance })); return Err(From::from(ExecutionError::NotEnoughCash { required: total_cost, is: U512::from(balance) }));
} }
// NOTE: there can be no invalid transactions from this point. // NOTE: there can be no invalid transactions from this point.
self.state.inc_nonce(&sender); self.state.inc_nonce(&sender);
self.state.sub_balance(&sender, &gas_cost); self.state.sub_balance(&sender, &U256::from(gas_cost));
let mut substate = Substate::new(); let mut substate = Substate::new();
let backup = self.state.clone(); let backup = self.state.clone();

View File

@ -90,25 +90,33 @@ impl Transaction {
/// Returns transaction sender. /// Returns transaction sender.
pub fn sender(&self) -> Result<Address, Error> { Ok(From::from(try!(ec::recover(&self.signature(), &self.message_hash())).sha3())) } pub fn sender(&self) -> Result<Address, Error> { Ok(From::from(try!(ec::recover(&self.signature(), &self.message_hash())).sha3())) }
/// Signs the transaction as coming from `sender`.
pub fn sign(&mut self, secret: &Secret) {
let sig = ec::sign(secret, &self.message_hash());
let (r, s, v) = sig.unwrap().to_rsv();
self.r = r;
self.s = s;
self.v = v;
}
/// Get the transaction cost in gas for the given params. /// Get the transaction cost in gas for the given params.
pub fn gas_required_for(is_create: bool, data: &[u8], schedule: &Schedule) -> U256 { pub fn gas_required_for(is_create: bool, data: &[u8], schedule: &Schedule) -> u64 {
// CRITICAL TODO XXX FIX NEED BIGINT!!!!!
data.iter().fold( data.iter().fold(
U256::from(if is_create {schedule.tx_create_gas} else {schedule.tx_gas}), (if is_create {schedule.tx_create_gas} else {schedule.tx_gas}) as u64,
|g, b| g + U256::from(match *b { 0 => schedule.tx_data_zero_gas, _ => schedule.tx_data_non_zero_gas}) |g, b| g + (match *b { 0 => schedule.tx_data_zero_gas, _ => schedule.tx_data_non_zero_gas }) as u64
) )
} }
/// Get the transaction cost in gas for this transaction. /// Get the transaction cost in gas for this transaction.
pub fn gas_required(&self, schedule: &Schedule) -> U256 { pub fn gas_required(&self, schedule: &Schedule) -> u64 {
Self::gas_required_for(match self.action{Action::Create=>true, Action::Call(_)=>false}, &self.data, schedule) Self::gas_required_for(match self.action{Action::Create=>true, Action::Call(_)=>false}, &self.data, schedule)
} }
/// Do basic validation, checking for valid signature and minimum gas, /// Do basic validation, checking for valid signature and minimum gas,
pub fn validate(self, schedule: &Schedule) -> Result<Transaction, Error> { pub fn validate(self, schedule: &Schedule) -> Result<Transaction, Error> {
try!(self.sender()); try!(self.sender());
if self.gas < self.gas_required(&schedule) { if self.gas < U256::from(self.gas_required(&schedule)) {
Err(From::from(TransactionError::InvalidGasLimit(OutOfBounds{min: Some(self.gas_required(&schedule)), max: None, found: self.gas}))) Err(From::from(TransactionError::InvalidGasLimit(OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas})))
} else { } else {
Ok(self) Ok(self)
} }