vm: implement (*VM).AddGas

Calculating interop prices can be tricky. It is more convenitent to burn
gas inside interops where necessary parameters are popped.
This commit is contained in:
Evgenii Stratonikov 2020-06-09 12:23:14 +03:00
parent df958caf93
commit 7256efd1ed
4 changed files with 21 additions and 0 deletions

View file

@ -11,6 +11,9 @@ import (
// of 0.001 GAS = Fixed8(10^5).
const interopGasRatio = 100000
// StoragePrice is a price for storing 1 byte of storage.
const StoragePrice = 100000
// getPrice returns a price for executing op with the provided parameter.
// Some SYSCALLs have variable price depending on their arguments.
func getPrice(v *vm.VM, op opcode.Opcode, parameter []byte) util.Fixed8 {

View file

@ -11,6 +11,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
)
@ -73,6 +74,9 @@ func createContractStateFromVM(ic *interop.Context, v *vm.VM) (*state.Contract,
if len(manifestBytes) > manifest.MaxManifestSize {
return nil, errors.New("manifest is too big")
}
if !v.AddGas(util.Fixed8(StoragePrice * (len(script) + len(manifestBytes)))) {
return nil, errors.New("gas limit exceeded")
}
var m manifest.Manifest
r := io.NewBinReaderFromBuf(manifestBytes)
m.DecodeBinary(r)

View file

@ -136,6 +136,12 @@ func (v *VM) SetGasLimit(max util.Fixed8) {
v.gasLimit = max
}
// AddGas consumes specified amount of gas. It returns true iff gas limit wasn't exceeded.
func (v *VM) AddGas(gas util.Fixed8) bool {
v.gasConsumed += gas
return v.gasLimit == 0 || v.gasConsumed <= v.gasLimit
}
// Estack returns the evaluation stack so interop hooks can utilize this.
func (v *VM) Estack() *Stack {
return v.estack

View file

@ -98,6 +98,14 @@ func TestVM_SetPriceGetter(t *testing.T) {
})
}
func TestAddGas(t *testing.T) {
v := New()
v.SetGasLimit(10)
require.True(t, v.AddGas(5))
require.True(t, v.AddGas(5))
require.False(t, v.AddGas(5))
}
func TestBytesToPublicKey(t *testing.T) {
v := New()
cache := v.GetPublicKeys()