Gas usage implementation (#123)

* Set up gas consumption based on gas limit

* Convert evm gas meter to be infinite since being ignored

* Remove unnecessary declaration

* Update fees paid to validators to be function of gas limit and price instead of just gas

* added nonce check for node tx execution

* Increment account nonce after mempool check

* Remove unnecessary nonce increment
This commit is contained in:
Austin Abell
2019-10-19 08:14:38 +09:00
committed by GitHub
parent dc25d847c3
commit 9802cbc98e
3 changed files with 131 additions and 64 deletions
+5 -1
View File
@@ -117,7 +117,11 @@ func (am AppModule) BeginBlock(ctx sdk.Context, bl abci.RequestBeginBlock) {
// EndBlock function for module at end of block
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
_, err := am.keeper.csdb.Commit(true)
// Gas costs are handled within msg handler so costs should be ignored
ebCtx := ctx.WithBlockGasMeter(sdk.NewInfiniteGasMeter())
// Commit state objects to KV store
_, err := am.keeper.csdb.WithContext(ebCtx).Commit(true)
if err != nil {
panic(err)
}
+17 -31
View File
@@ -31,6 +31,9 @@ type StateTransition struct {
func (st StateTransition) TransitionCSDB(ctx sdk.Context) (sdk.Result, *big.Int) {
contractCreation := st.Recipient == nil
// This gas limit the the transaction gas limit with intrinsic gas subtracted
gasLimit := ctx.GasMeter().Limit()
// Create context for evm
context := vm.Context{
CanTransfer: core.CanTransfer,
@@ -40,11 +43,17 @@ func (st StateTransition) TransitionCSDB(ctx sdk.Context) (sdk.Result, *big.Int)
BlockNumber: big.NewInt(ctx.BlockHeight()),
Time: big.NewInt(time.Now().Unix()),
Difficulty: big.NewInt(0x30000), // unused
GasLimit: ctx.GasMeter().Limit(),
GasLimit: gasLimit,
GasPrice: ctx.MinGasPrices().AmountOf(emint.DenomDefault).Int,
}
vmenv := vm.NewEVM(context, st.Csdb.WithContext(ctx), GenerateChainConfig(st.ChainID), vm.Config{})
// This gas meter is set up to consume gas from gaskv during evm execution and be ignored
evmGasMeter := sdk.NewInfiniteGasMeter()
vmenv := vm.NewEVM(
context, st.Csdb.WithContext(ctx.WithGasMeter(evmGasMeter)),
GenerateChainConfig(st.ChainID), vm.Config{},
)
var (
leftOverGas uint64
@@ -54,11 +63,11 @@ func (st StateTransition) TransitionCSDB(ctx sdk.Context) (sdk.Result, *big.Int)
)
if contractCreation {
_, addr, leftOverGas, vmerr = vmenv.Create(senderRef, st.Payload, st.GasLimit, st.Amount)
_, addr, leftOverGas, vmerr = vmenv.Create(senderRef, st.Payload, gasLimit, st.Amount)
} else {
// Increment the nonce for the next transaction
st.Csdb.SetNonce(st.Sender, st.Csdb.GetNonce(st.Sender)+1)
_, leftOverGas, vmerr = vmenv.Call(senderRef, *st.Recipient, st.Payload, st.GasLimit, st.Amount)
_, leftOverGas, vmerr = vmenv.Call(senderRef, *st.Recipient, st.Payload, gasLimit, st.Amount)
}
// handle errors
@@ -66,15 +75,13 @@ func (st StateTransition) TransitionCSDB(ctx sdk.Context) (sdk.Result, *big.Int)
return emint.ErrVMExecution(vmerr.Error()).Result(), nil
}
// Refund remaining gas from tx (Check these values and ensure gas is being consumed correctly)
refundGas(st.Csdb, &leftOverGas, st.GasLimit, context.GasPrice, st.Sender)
// add balance for the processor of the tx (determine who rewards are being processed to)
// TODO: Double check nothing needs to be done here
// Refunds would happen here, if intended in future
st.Csdb.Finalise(true) // Change to depend on config
// TODO: Consume gas from sender
// Consume gas from evm execution
// Out of gas check does not need to be done here since it is done within the EVM execution
ctx.GasMeter().ConsumeGas(gasLimit-leftOverGas, "EVM execution consumption")
// Generate bloom filter to be saved in tx receipt data
bloomInt := big.NewInt(0)
@@ -90,24 +97,3 @@ func (st StateTransition) TransitionCSDB(ctx sdk.Context) (sdk.Result, *big.Int)
return sdk.Result{Data: returnData, GasUsed: st.GasLimit - leftOverGas}, bloomInt
}
func refundGas(
st vm.StateDB, gasRemaining *uint64, initialGas uint64, gasPrice *big.Int,
from common.Address,
) {
// Apply refund counter, capped to half of the used gas.
refund := (initialGas - *gasRemaining) / 2
if refund > st.GetRefund() {
refund = st.GetRefund()
}
*gasRemaining += refund
// // Return ETH for remaining gas, exchanged at the original rate.
// remaining := new(big.Int).Mul(new(big.Int).SetUint64(*gasRemaining), gasPrice)
// st.AddBalance(from, remaining)
// // Also return remaining gas to the block gas counter so it is
// // available for the next transaction.
// TODO: Return gas to block gas meter?
// st.gp.AddGas(st.gas)
}