vm: set GAS limit

Make it possible to set maximum amount of GAS which can be spent
during execution.
This commit is contained in:
Evgenii Stratonikov 2020-01-20 14:49:07 +03:00
parent 0662a7e3c2
commit c22d09adad
2 changed files with 25 additions and 1 deletions

View file

@ -80,6 +80,7 @@ type VM struct {
size int size int
gasConsumed util.Fixed8 gasConsumed util.Fixed8
gasLimit util.Fixed8
// Public keys cache. // Public keys cache.
keys map[string]*keys.PublicKey keys map[string]*keys.PublicKey
@ -130,6 +131,12 @@ func (v *VM) GasConsumed() util.Fixed8 {
return v.gasConsumed return v.gasConsumed
} }
// SetGasLimit sets maximum amount of gas which v can spent.
// If max <= 0, no limit is imposed.
func (v *VM) SetGasLimit(max util.Fixed8) {
v.gasLimit = max
}
// Estack returns the evaluation stack so interop hooks can utilize this. // Estack returns the evaluation stack so interop hooks can utilize this.
func (v *VM) Estack() *Stack { func (v *VM) Estack() *Stack {
return v.estack return v.estack
@ -483,6 +490,9 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
if v.getPrice != nil && ctx.ip < len(ctx.prog) { if v.getPrice != nil && ctx.ip < len(ctx.prog) {
v.gasConsumed += v.getPrice(v, op, parameter) v.gasConsumed += v.getPrice(v, op, parameter)
if v.gasLimit > 0 && v.gasConsumed > v.gasLimit {
panic("gas limit is exceeded")
}
} }
if op >= opcode.PUSHBYTES1 && op <= opcode.PUSHBYTES75 { if op >= opcode.PUSHBYTES1 && op <= opcode.PUSHBYTES75 {

View file

@ -92,7 +92,21 @@ func TestVM_SetPriceGetter(t *testing.T) {
v.Load(prog) v.Load(prog)
runVM(t, v) runVM(t, v)
require.EqualValues(t, 9, v.gasConsumed) require.EqualValues(t, 9, v.GasConsumed())
})
t.Run("with sufficient gas limit", func(t *testing.T) {
v.Load(prog)
v.SetGasLimit(9)
runVM(t, v)
require.EqualValues(t, 9, v.GasConsumed())
})
t.Run("with small gas limit", func(t *testing.T) {
v.Load(prog)
v.SetGasLimit(8)
checkVMFailed(t, v)
}) })
} }