errors, fees, and refunds

This commit is contained in:
debris 2016-01-10 12:29:35 +01:00
parent efa6c424c1
commit 9f06c2f2e6

View File

@ -55,6 +55,9 @@ impl Substate {
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
pub enum ExecutiveResult { pub enum ExecutiveResult {
Ok, Ok,
BlockGasLimitReached { gas_limit: U256, gas_used: U256, gas: U256 },
InvalidNonce { expected: U256, is: U256 },
NotEnoughCash { required: U256, is: U256 },
OutOfGas, OutOfGas,
InternalError InternalError
} }
@ -91,17 +94,40 @@ impl<'a> Executive<'a> {
/// This funtion should be used to execute transaction. /// This funtion should be used to execute transaction.
pub fn transact(e: &mut Executive<'a>, t: &Transaction) -> ExecutiveResult { pub fn transact(e: &mut Executive<'a>, t: &Transaction) -> ExecutiveResult {
// TODO: validate that we have enough funds // validate if transaction fits into given block
// TODO: validate nonce ? if e.info.gas_used + t.gas > e.info.gas_limit {
return ExecutiveResult::BlockGasLimitReached {
gas_limit: e.info.gas_limit,
gas_used: e.info.gas_used,
gas: t.gas
};
}
let sender = t.sender(); let sender = t.sender();
let nonce = e.state.nonce(&sender);
// validate transaction nonce
if t.nonce != nonce {
return ExecutiveResult::InvalidNonce { expected: nonce, is: t.nonce };
}
// TODO: we might need bigints here, or at least check overflows.
let balance = e.state.balance(&sender);
let gas_cost = t.gas * t.gas_price;
let total_cost = t.value + gas_cost;
// avoid unaffordable transactions
if balance < total_cost {
return ExecutiveResult::NotEnoughCash { required: total_cost, is: balance };
}
e.state.inc_nonce(&sender);
let mut substate = Substate::new(); let mut substate = Substate::new();
let res = match t.kind() { let res = match t.kind() {
TransactionKind::ContractCreation => { TransactionKind::ContractCreation => {
let params = EvmParams { let params = EvmParams {
address: contract_address(&sender, &t.nonce), address: contract_address(&sender, &nonce),
sender: sender.clone(), sender: sender.clone(),
origin: sender.clone(), origin: sender.clone(),
gas: t.gas, gas: t.gas,
@ -110,9 +136,7 @@ impl<'a> Executive<'a> {
code: t.data.clone(), code: t.data.clone(),
data: vec![], data: vec![],
}; };
e.state.inc_nonce(&params.address); Executive::call(e, &params, &mut substate)
unimplemented!()
//Executive::call(e, &params, &substate)
}, },
TransactionKind::MessageCall => { TransactionKind::MessageCall => {
let params = EvmParams { let params = EvmParams {
@ -125,13 +149,12 @@ impl<'a> Executive<'a> {
code: e.state.code(&t.to.clone().unwrap()).unwrap_or(vec![]), code: e.state.code(&t.to.clone().unwrap()).unwrap_or(vec![]),
data: t.data.clone(), data: t.data.clone(),
}; };
e.state.inc_nonce(&params.address);
Executive::create(e, &params, &mut substate) Executive::create(e, &params, &mut substate)
} }
}; };
// finalize here! // finalize here!
e.finalize(substate, U256::zero(), U256::zero()); e.finalize(substate, &sender, U256::zero(), U256::zero(), t.gas_price);
res res
} }
@ -207,15 +230,23 @@ impl<'a> Executive<'a> {
} }
/// Finalizes the transaction (does refunds and suicides). /// Finalizes the transaction (does refunds and suicides).
fn finalize(&mut self, substate: Substate, gas: U256, gas_used: U256) { fn finalize(&mut self, substate: Substate, sender: &Address, gas: U256, gas_left: U256, gas_price: U256) {
let schedule = self.engine.evm_schedule(self.info); let schedule = self.engine.evm_schedule(self.info);
// refunds from SSTORE nonzero -> zero // refunds from SSTORE nonzero -> zero
let sstore_refunds = U256::from(schedule.sstore_refund_gas) * substate.refunds_count; let sstore_refunds = U256::from(schedule.sstore_refund_gas) * substate.refunds_count;
// refunds from contract suicides // refunds from contract suicides
let suicide_refunds = U256::from(schedule.suicide_refund_gas) * U256::from(substate.suicides.len()); let suicide_refunds = U256::from(schedule.suicide_refund_gas) * U256::from(substate.suicides.len());
// real ammount to refund // real ammount to refund
let refund = cmp::min(sstore_refunds + suicide_refunds, (gas - gas_used) / U256::from(2)); let refund = cmp::min(sstore_refunds + suicide_refunds, (gas - gas_left) / U256::from(2)) + gas_left;
let refund_value = refund * gas_price;
self.state.add_balance(sender, &refund_value);
// fees earned by author
let fees = (gas - refund) * gas_price;
let author = &self.info.author;
self.state.add_balance(author, &fees);
// perform suicides // perform suicides
for address in substate.suicides.iter() { for address in substate.suicides.iter() {