errors, fees, and refunds
This commit is contained in:
parent
efa6c424c1
commit
9f06c2f2e6
@ -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 {
|
||||||
let sender = t.sender();
|
gas_limit: e.info.gas_limit,
|
||||||
|
gas_used: e.info.gas_used,
|
||||||
|
gas: t.gas
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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(¶ms.address);
|
Executive::call(e, ¶ms, &mut substate)
|
||||||
unimplemented!()
|
|
||||||
//Executive::call(e, ¶ms, &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(¶ms.address);
|
|
||||||
Executive::create(e, ¶ms, &mut substate)
|
Executive::create(e, ¶ms, &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() {
|
||||||
|
Loading…
Reference in New Issue
Block a user