Merge pull request #1937 from nspcc-dev/burn-gas
Implement burning GAS and refueling
This commit is contained in:
commit
9a8d7f6a90
10 changed files with 202 additions and 2 deletions
|
@ -136,7 +136,9 @@ func TestNativeHelpersCompile(t *testing.T) {
|
||||||
{"unclaimedGas", []string{u160, "123"}},
|
{"unclaimedGas", []string{u160, "123"}},
|
||||||
{"unregisterCandidate", []string{pub}},
|
{"unregisterCandidate", []string{pub}},
|
||||||
}, nep17TestCases...))
|
}, nep17TestCases...))
|
||||||
runNativeTestCases(t, cs.GAS.ContractMD, "gas", nep17TestCases)
|
runNativeTestCases(t, cs.GAS.ContractMD, "gas", append([]nativeTestCase{
|
||||||
|
{"refuel", []string{u160, "123"}},
|
||||||
|
}, nep17TestCases...))
|
||||||
runNativeTestCases(t, cs.Oracle.ContractMD, "oracle", []nativeTestCase{
|
runNativeTestCases(t, cs.Oracle.ContractMD, "oracle", []nativeTestCase{
|
||||||
{"getPrice", nil},
|
{"getPrice", nil},
|
||||||
{"request", []string{`"url"`, "nil", `"callback"`, "nil", "123"}},
|
{"request", []string{`"url"`, "nil", `"callback"`, "nil", "123"}},
|
||||||
|
|
|
@ -68,6 +68,7 @@ func TestSyscallExecution(t *testing.T) {
|
||||||
"iterator.Create": {interopnames.SystemIteratorCreate, []string{pubs}, false},
|
"iterator.Create": {interopnames.SystemIteratorCreate, []string{pubs}, false},
|
||||||
"iterator.Next": {interopnames.SystemIteratorNext, []string{"iterator.Iterator{}"}, false},
|
"iterator.Next": {interopnames.SystemIteratorNext, []string{"iterator.Iterator{}"}, false},
|
||||||
"iterator.Value": {interopnames.SystemIteratorValue, []string{"iterator.Iterator{}"}, false},
|
"iterator.Value": {interopnames.SystemIteratorValue, []string{"iterator.Iterator{}"}, false},
|
||||||
|
"runtime.BurnGas": {interopnames.SystemRuntimeBurnGas, []string{"1"}, true},
|
||||||
"runtime.CheckWitness": {interopnames.SystemRuntimeCheckWitness, []string{b}, false},
|
"runtime.CheckWitness": {interopnames.SystemRuntimeCheckWitness, []string{b}, false},
|
||||||
"runtime.GasLeft": {interopnames.SystemRuntimeGasLeft, nil, false},
|
"runtime.GasLeft": {interopnames.SystemRuntimeGasLeft, nil, false},
|
||||||
"runtime.GetCallingScriptHash": {interopnames.SystemRuntimeGetCallingScriptHash, nil, false},
|
"runtime.GetCallingScriptHash": {interopnames.SystemRuntimeGetCallingScriptHash, nil, false},
|
||||||
|
|
|
@ -16,6 +16,7 @@ const (
|
||||||
SystemIteratorCreate = "System.Iterator.Create"
|
SystemIteratorCreate = "System.Iterator.Create"
|
||||||
SystemIteratorNext = "System.Iterator.Next"
|
SystemIteratorNext = "System.Iterator.Next"
|
||||||
SystemIteratorValue = "System.Iterator.Value"
|
SystemIteratorValue = "System.Iterator.Value"
|
||||||
|
SystemRuntimeBurnGas = "System.Runtime.BurnGas"
|
||||||
SystemRuntimeCheckWitness = "System.Runtime.CheckWitness"
|
SystemRuntimeCheckWitness = "System.Runtime.CheckWitness"
|
||||||
SystemRuntimeGasLeft = "System.Runtime.GasLeft"
|
SystemRuntimeGasLeft = "System.Runtime.GasLeft"
|
||||||
SystemRuntimeGetCallingScriptHash = "System.Runtime.GetCallingScriptHash"
|
SystemRuntimeGetCallingScriptHash = "System.Runtime.GetCallingScriptHash"
|
||||||
|
@ -55,6 +56,7 @@ var names = []string{
|
||||||
SystemIteratorCreate,
|
SystemIteratorCreate,
|
||||||
SystemIteratorNext,
|
SystemIteratorNext,
|
||||||
SystemIteratorValue,
|
SystemIteratorValue,
|
||||||
|
SystemRuntimeBurnGas,
|
||||||
SystemRuntimeCheckWitness,
|
SystemRuntimeCheckWitness,
|
||||||
SystemRuntimeGasLeft,
|
SystemRuntimeGasLeft,
|
||||||
SystemRuntimeGetCallingScriptHash,
|
SystemRuntimeGetCallingScriptHash,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
|
@ -99,3 +100,21 @@ func GetTime(ic *interop.Context) error {
|
||||||
ic.VM.Estack().PushVal(ic.Block.Timestamp)
|
ic.VM.Estack().PushVal(ic.Block.Timestamp)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BurnGas burns GAS to benefit NEO ecosystem.
|
||||||
|
func BurnGas(ic *interop.Context) error {
|
||||||
|
gas := ic.VM.Estack().Pop().BigInt()
|
||||||
|
if !gas.IsInt64() {
|
||||||
|
return errors.New("invalid GAS value")
|
||||||
|
}
|
||||||
|
|
||||||
|
g := gas.Int64()
|
||||||
|
if g <= 0 {
|
||||||
|
return errors.New("GAS must be positive")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ic.VM.AddGas(g) {
|
||||||
|
return errors.New("GAS limit exceeded")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
@ -346,6 +347,13 @@ func getTestContractState(bc *Blockchain) (*state.Contract, *state.Contract) {
|
||||||
emit.Opcodes(w.BinWriter, opcode.CALLT, 1, 0, opcode.RET)
|
emit.Opcodes(w.BinWriter, opcode.CALLT, 1, 0, opcode.RET)
|
||||||
callT2Off := w.Len()
|
callT2Off := w.Len()
|
||||||
emit.Opcodes(w.BinWriter, opcode.CALLT, 0, 0, opcode.RET)
|
emit.Opcodes(w.BinWriter, opcode.CALLT, 0, 0, opcode.RET)
|
||||||
|
refuelOff := w.Len()
|
||||||
|
emit.Opcodes(w.BinWriter, opcode.PUSH2, opcode.PACK)
|
||||||
|
emit.AppCallNoArgs(w.BinWriter, bc.contracts.GAS.Hash, "refuel", callflag.States|callflag.AllowNotify)
|
||||||
|
emit.Opcodes(w.BinWriter, opcode.DROP)
|
||||||
|
burnGasOff := w.Len()
|
||||||
|
emit.Syscall(w.BinWriter, interopnames.SystemRuntimeBurnGas)
|
||||||
|
emit.Opcodes(w.BinWriter, opcode.RET)
|
||||||
|
|
||||||
script := w.Bytes()
|
script := w.Bytes()
|
||||||
h := hash.Hash160(script)
|
h := hash.Hash160(script)
|
||||||
|
@ -506,8 +514,26 @@ func getTestContractState(bc *Blockchain) (*state.Contract, *state.Contract) {
|
||||||
Offset: callT2Off,
|
Offset: callT2Off,
|
||||||
ReturnType: smartcontract.IntegerType,
|
ReturnType: smartcontract.IntegerType,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "burnGas",
|
||||||
|
Offset: burnGasOff,
|
||||||
|
Parameters: []manifest.Parameter{
|
||||||
|
manifest.NewParameter("amount", smartcontract.IntegerType),
|
||||||
|
},
|
||||||
|
ReturnType: smartcontract.VoidType,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "refuelGas",
|
||||||
|
Offset: refuelOff,
|
||||||
|
Parameters: []manifest.Parameter{
|
||||||
|
manifest.NewParameter("account", smartcontract.Hash160Type),
|
||||||
|
manifest.NewParameter("gasRefuel", smartcontract.IntegerType),
|
||||||
|
manifest.NewParameter("gasBurn", smartcontract.IntegerType),
|
||||||
|
},
|
||||||
|
ReturnType: smartcontract.VoidType,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
m.Permissions = make([]manifest.Permission, 2)
|
m.Permissions = make([]manifest.Permission, 3)
|
||||||
m.Permissions[0].Contract.Type = manifest.PermissionHash
|
m.Permissions[0].Contract.Type = manifest.PermissionHash
|
||||||
m.Permissions[0].Contract.Value = bc.contracts.NEO.Hash
|
m.Permissions[0].Contract.Value = bc.contracts.NEO.Hash
|
||||||
m.Permissions[0].Methods.Add("balanceOf")
|
m.Permissions[0].Methods.Add("balanceOf")
|
||||||
|
@ -516,6 +542,10 @@ func getTestContractState(bc *Blockchain) (*state.Contract, *state.Contract) {
|
||||||
m.Permissions[1].Contract.Value = util.Uint160{}
|
m.Permissions[1].Contract.Value = util.Uint160{}
|
||||||
m.Permissions[1].Methods.Add("method")
|
m.Permissions[1].Methods.Add("method")
|
||||||
|
|
||||||
|
m.Permissions[2].Contract.Type = manifest.PermissionHash
|
||||||
|
m.Permissions[2].Contract.Value = bc.contracts.GAS.Hash
|
||||||
|
m.Permissions[2].Methods.Add("refuel")
|
||||||
|
|
||||||
cs := &state.Contract{
|
cs := &state.Contract{
|
||||||
ContractBase: state.ContractBase{
|
ContractBase: state.ContractBase{
|
||||||
Hash: h,
|
Hash: h,
|
||||||
|
@ -941,3 +971,37 @@ func TestLoadToken(t *testing.T) {
|
||||||
checkFAULTState(t, aer)
|
checkFAULTState(t, aer)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRuntimeBurnGas(t *testing.T) {
|
||||||
|
bc := newTestChain(t)
|
||||||
|
|
||||||
|
cs, _ := getTestContractState(bc)
|
||||||
|
require.NoError(t, bc.contracts.Management.PutContractState(bc.dao, cs))
|
||||||
|
|
||||||
|
const sysFee = 2_000000
|
||||||
|
|
||||||
|
t.Run("good", func(t *testing.T) {
|
||||||
|
aer, err := invokeContractMethod(bc, sysFee, cs.Hash, "burnGas", int64(1))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, vm.HaltState, aer.VMState)
|
||||||
|
|
||||||
|
t.Run("gas limit exceeded", func(t *testing.T) {
|
||||||
|
aer, err = invokeContractMethod(bc, aer.GasConsumed, cs.Hash, "burnGas", int64(2))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, vm.FaultState, aer.VMState)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
t.Run("too big integer", func(t *testing.T) {
|
||||||
|
gas := big.NewInt(math.MaxInt64)
|
||||||
|
gas.Add(gas, big.NewInt(1))
|
||||||
|
|
||||||
|
aer, err := invokeContractMethod(bc, sysFee, cs.Hash, "burnGas", gas)
|
||||||
|
require.NoError(t, err)
|
||||||
|
checkFAULTState(t, aer)
|
||||||
|
})
|
||||||
|
t.Run("zero GAS", func(t *testing.T) {
|
||||||
|
aer, err := invokeContractMethod(bc, sysFee, cs.Hash, "burnGas", int64(0))
|
||||||
|
require.NoError(t, err)
|
||||||
|
checkFAULTState(t, aer)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ var systemInterops = []interop.Function{
|
||||||
{Name: interopnames.SystemIteratorCreate, Func: iterator.Create, Price: 1 << 4, ParamCount: 1},
|
{Name: interopnames.SystemIteratorCreate, Func: iterator.Create, Price: 1 << 4, ParamCount: 1},
|
||||||
{Name: interopnames.SystemIteratorNext, Func: iterator.Next, Price: 1 << 15, ParamCount: 1},
|
{Name: interopnames.SystemIteratorNext, Func: iterator.Next, Price: 1 << 15, ParamCount: 1},
|
||||||
{Name: interopnames.SystemIteratorValue, Func: iterator.Value, Price: 1 << 4, ParamCount: 1},
|
{Name: interopnames.SystemIteratorValue, Func: iterator.Value, Price: 1 << 4, ParamCount: 1},
|
||||||
|
{Name: interopnames.SystemRuntimeBurnGas, Func: runtime.BurnGas, Price: 1 << 4, ParamCount: 1},
|
||||||
{Name: interopnames.SystemRuntimeCheckWitness, Func: runtime.CheckWitness, Price: 1 << 10,
|
{Name: interopnames.SystemRuntimeCheckWitness, Func: runtime.CheckWitness, Price: 1 << 10,
|
||||||
RequiredFlags: callflag.NoneFlag, ParamCount: 1},
|
RequiredFlags: callflag.NoneFlag, ParamCount: 1},
|
||||||
{Name: interopnames.SystemRuntimeGasLeft, Func: runtime.GasLeft, Price: 1 << 4},
|
{Name: interopnames.SystemRuntimeGasLeft, Func: runtime.GasLeft, Price: 1 << 4},
|
||||||
|
|
|
@ -2,14 +2,19 @@ package native
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GAS represents GAS native contract.
|
// GAS represents GAS native contract.
|
||||||
|
@ -38,6 +43,12 @@ func newGAS() *GAS {
|
||||||
|
|
||||||
g.nep17TokenNative = *nep17
|
g.nep17TokenNative = *nep17
|
||||||
|
|
||||||
|
desc := newDescriptor("refuel", smartcontract.VoidType,
|
||||||
|
manifest.NewParameter("account", smartcontract.Hash160Type),
|
||||||
|
manifest.NewParameter("amount", smartcontract.IntegerType))
|
||||||
|
md := newMethodAndPrice(g.refuel, 1<<15, callflag.States|callflag.AllowNotify)
|
||||||
|
g.AddMethod(md, desc)
|
||||||
|
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +79,24 @@ func (g *GAS) balanceFromBytes(si *state.StorageItem) (*big.Int, error) {
|
||||||
return &acc.Balance, err
|
return &acc.Balance, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *GAS) refuel(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||||
|
acc := toUint160(args[0])
|
||||||
|
gas := toBigInt(args[1])
|
||||||
|
|
||||||
|
if !gas.IsInt64() || gas.Sign() == -1 {
|
||||||
|
panic("invalid GAS value")
|
||||||
|
}
|
||||||
|
|
||||||
|
ok, err := runtime.CheckHashedWitness(ic, acc)
|
||||||
|
if !ok || err != nil {
|
||||||
|
panic(fmt.Errorf("%w: %v", ErrInvalidWitness, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
g.burn(ic, acc, gas)
|
||||||
|
ic.VM.GasLimit += gas.Int64()
|
||||||
|
return stackitem.Null{}
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize initializes GAS contract.
|
// Initialize initializes GAS contract.
|
||||||
func (g *GAS) Initialize(ic *interop.Context) error {
|
func (g *GAS) Initialize(ic *interop.Context) error {
|
||||||
if err := g.nep17TokenNative.Initialize(ic); err != nil {
|
if err := g.nep17TokenNative.Initialize(ic); err != nil {
|
||||||
|
|
70
pkg/core/native_gas_test.go
Normal file
70
pkg/core/native_gas_test.go
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/internal/random"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGAS_Refuel(t *testing.T) {
|
||||||
|
bc := newTestChain(t)
|
||||||
|
|
||||||
|
cs, _ := getTestContractState(bc)
|
||||||
|
require.NoError(t, bc.contracts.Management.PutContractState(bc.dao, cs))
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysFee = 10_000000
|
||||||
|
burnFee = sysFee + 12345678
|
||||||
|
)
|
||||||
|
|
||||||
|
accs := []*wallet.Account{
|
||||||
|
newAccountWithGAS(t, bc),
|
||||||
|
newAccountWithGAS(t, bc),
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("good, refuel from self", func(t *testing.T) {
|
||||||
|
before0 := bc.GetUtilityTokenBalance(accs[0].Contract.ScriptHash())
|
||||||
|
aer, err := invokeContractMethodGeneric(bc, sysFee, bc.contracts.GAS.Hash, "refuel",
|
||||||
|
accs[0], accs[0].Contract.ScriptHash(), int64(burnFee))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, vm.HaltState, aer.VMState)
|
||||||
|
|
||||||
|
after0 := bc.GetUtilityTokenBalance(accs[0].Contract.ScriptHash())
|
||||||
|
tx, _, _ := bc.GetTransaction(aer.Container)
|
||||||
|
require.Equal(t, before0, new(big.Int).Add(after0, big.NewInt(tx.SystemFee+tx.NetworkFee+burnFee)))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("good, refuel from other", func(t *testing.T) {
|
||||||
|
before0 := bc.GetUtilityTokenBalance(accs[0].Contract.ScriptHash())
|
||||||
|
before1 := bc.GetUtilityTokenBalance(accs[1].Contract.ScriptHash())
|
||||||
|
aer, err := invokeContractMethodGeneric(bc, sysFee, cs.Hash, "refuelGas",
|
||||||
|
accs, accs[1].Contract.ScriptHash(), int64(burnFee), int64(burnFee))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, vm.HaltState, aer.VMState)
|
||||||
|
|
||||||
|
after0 := bc.GetUtilityTokenBalance(accs[0].Contract.ScriptHash())
|
||||||
|
after1 := bc.GetUtilityTokenBalance(accs[1].Contract.ScriptHash())
|
||||||
|
|
||||||
|
tx, _, _ := bc.GetTransaction(aer.Container)
|
||||||
|
require.Equal(t, before0, new(big.Int).Add(after0, big.NewInt(tx.SystemFee+tx.NetworkFee)))
|
||||||
|
require.Equal(t, before1, new(big.Int).Add(after1, big.NewInt(burnFee)))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("bad, invalid witness", func(t *testing.T) {
|
||||||
|
aer, err := invokeContractMethodGeneric(bc, sysFee, cs.Hash, "refuelGas",
|
||||||
|
accs, random.Uint160(), int64(1), int64(1))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, vm.FaultState, aer.VMState)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("bad, invalid GAS amount", func(t *testing.T) {
|
||||||
|
aer, err := invokeContractMethodGeneric(bc, sysFee, cs.Hash, "refuelGas",
|
||||||
|
accs, accs[0].Contract.ScriptHash(), int64(0), int64(1))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, vm.FaultState, aer.VMState)
|
||||||
|
})
|
||||||
|
}
|
|
@ -37,3 +37,10 @@ func Transfer(from, to interop.Hash160, amount int, data interface{}) bool {
|
||||||
return contract.Call(interop.Hash160(Hash), "transfer",
|
return contract.Call(interop.Hash160(Hash), "transfer",
|
||||||
contract.All, from, to, amount, data).(bool)
|
contract.All, from, to, amount, data).(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Refuel makes some GAS from the provided account available
|
||||||
|
// for the current execution. It represents `refuel` method of GAS native contract.
|
||||||
|
func Refuel(from interop.Hash160, amount int) {
|
||||||
|
contract.Call(interop.Hash160(Hash), "refuel",
|
||||||
|
contract.States|contract.AllowNotify, from, amount)
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,11 @@ const (
|
||||||
Verification byte = 0x20
|
Verification byte = 0x20
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// BurnGas burns provided amount of GAS. It uses `System.Runtime.BurnGas` syscall.
|
||||||
|
func BurnGas(gas int) {
|
||||||
|
neogointernal.Syscall1NoReturn("System.Runtime.BurnGas", gas)
|
||||||
|
}
|
||||||
|
|
||||||
// CheckWitness verifies if the given script hash (160-bit BE value in a 20 byte
|
// CheckWitness verifies if the given script hash (160-bit BE value in a 20 byte
|
||||||
// slice) or key (compressed serialized 33-byte form) is one of the signers of
|
// slice) or key (compressed serialized 33-byte form) is one of the signers of
|
||||||
// this invocation. It uses `System.Runtime.CheckWitness` syscall.
|
// this invocation. It uses `System.Runtime.CheckWitness` syscall.
|
||||||
|
|
Loading…
Reference in a new issue