forked from TrueCloudLab/neoneo-go
Merge pull request #1040 from nspcc-dev/feature/neo_to_system
Move interops from Neo.* to System.*
This commit is contained in:
commit
c044bdc731
24 changed files with 125 additions and 531 deletions
|
@ -898,23 +898,23 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
c.currentSwitch = label
|
c.currentSwitch = label
|
||||||
|
|
||||||
ast.Walk(c, n.X)
|
ast.Walk(c, n.X)
|
||||||
emit.Syscall(c.prog.BinWriter, "Neo.Iterator.Create")
|
emit.Syscall(c.prog.BinWriter, "System.Iterator.Create")
|
||||||
|
|
||||||
c.pushStackLabel(label, 1)
|
c.pushStackLabel(label, 1)
|
||||||
c.setLabel(start)
|
c.setLabel(start)
|
||||||
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
||||||
emit.Syscall(c.prog.BinWriter, "Neo.Enumerator.Next")
|
emit.Syscall(c.prog.BinWriter, "System.Enumerator.Next")
|
||||||
emit.Jmp(c.prog.BinWriter, opcode.JMPIFNOTL, end)
|
emit.Jmp(c.prog.BinWriter, opcode.JMPIFNOTL, end)
|
||||||
|
|
||||||
if n.Key != nil {
|
if n.Key != nil {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
||||||
emit.Syscall(c.prog.BinWriter, "Neo.Iterator.Key")
|
emit.Syscall(c.prog.BinWriter, "System.Iterator.Key")
|
||||||
c.emitStoreVar(n.Key.(*ast.Ident).Name)
|
c.emitStoreVar(n.Key.(*ast.Ident).Name)
|
||||||
}
|
}
|
||||||
if n.Value != nil {
|
if n.Value != nil {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
||||||
emit.Syscall(c.prog.BinWriter, "Neo.Enumerator.Value")
|
emit.Syscall(c.prog.BinWriter, "System.Enumerator.Value")
|
||||||
c.emitStoreVar(n.Value.(*ast.Ident).Name)
|
c.emitStoreVar(n.Value.(*ast.Ident).Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1092,7 +1092,7 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.THROW)
|
emit.Opcode(c.prog.BinWriter, opcode.THROW)
|
||||||
} else if isString(c.typeInfo.Types[arg].Type) {
|
} else if isString(c.typeInfo.Types[arg].Type) {
|
||||||
ast.Walk(c, arg)
|
ast.Walk(c, arg)
|
||||||
emit.Syscall(c.prog.BinWriter, "Neo.Runtime.Log")
|
emit.Syscall(c.prog.BinWriter, "System.Runtime.Log")
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.THROW)
|
emit.Opcode(c.prog.BinWriter, opcode.THROW)
|
||||||
} else {
|
} else {
|
||||||
c.prog.Err = errors.New("panic should have string or nil argument")
|
c.prog.Err = errors.New("panic should have string or nil argument")
|
||||||
|
|
|
@ -55,7 +55,7 @@ func getPanicSource(need bool, message string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func logGetter(logs *[]string) vm.InteropGetterFunc {
|
func logGetter(logs *[]string) vm.InteropGetterFunc {
|
||||||
logID := emit.InteropNameToID([]byte("Neo.Runtime.Log"))
|
logID := emit.InteropNameToID([]byte("System.Runtime.Log"))
|
||||||
return func(id uint32) *vm.InteropFuncPrice {
|
return func(id uint32) *vm.InteropFuncPrice {
|
||||||
if id != logID {
|
if id != logID {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,59 +1,40 @@
|
||||||
package compiler
|
package compiler
|
||||||
|
|
||||||
var syscalls = map[string]map[string]string{
|
var syscalls = map[string]map[string]string{
|
||||||
"account": {
|
|
||||||
"GetBalance": "Neo.Account.GetBalance",
|
|
||||||
"GetScriptHash": "Neo.Account.GetScriptHash",
|
|
||||||
"GetVotes": "Neo.Account.GetVotes",
|
|
||||||
"IsStandard": "Neo.Account.IsStandard",
|
|
||||||
},
|
|
||||||
"crypto": {
|
"crypto": {
|
||||||
"ECDsaVerify": "Neo.Crypto.ECDsaVerify",
|
"ECDsaVerify": "Neo.Crypto.ECDsaVerify",
|
||||||
},
|
},
|
||||||
"enumerator": {
|
"enumerator": {
|
||||||
"Concat": "Neo.Enumerator.Concat",
|
"Concat": "System.Enumerator.Concat",
|
||||||
"Create": "Neo.Enumerator.Create",
|
"Create": "System.Enumerator.Create",
|
||||||
"Next": "Neo.Enumerator.Next",
|
"Next": "System.Enumerator.Next",
|
||||||
"Value": "Neo.Enumerator.Value",
|
"Value": "System.Enumerator.Value",
|
||||||
},
|
},
|
||||||
"storage": {
|
"storage": {
|
||||||
"ConvertContextToReadOnly": "Neo.StorageContext.AsReadOnly",
|
"ConvertContextToReadOnly": "System.Storage.AsReadOnly",
|
||||||
"Delete": "Neo.Storage.Delete",
|
"Delete": "System.Storage.Delete",
|
||||||
"Find": "Neo.Storage.Find",
|
"Find": "System.Storage.Find",
|
||||||
"Get": "Neo.Storage.Get",
|
"Get": "System.Storage.Get",
|
||||||
"GetContext": "Neo.Storage.GetContext",
|
"GetContext": "System.Storage.GetContext",
|
||||||
"GetReadOnlyContext": "Neo.Storage.GetReadOnlyContext",
|
"GetReadOnlyContext": "System.Storage.GetReadOnlyContext",
|
||||||
"Put": "Neo.Storage.Put",
|
"Put": "System.Storage.Put",
|
||||||
},
|
},
|
||||||
"runtime": {
|
"runtime": {
|
||||||
"GetTrigger": "Neo.Runtime.GetTrigger",
|
"GetTrigger": "System.Runtime.GetTrigger",
|
||||||
"CheckWitness": "Neo.Runtime.CheckWitness",
|
"CheckWitness": "System.Runtime.CheckWitness",
|
||||||
"Notify": "Neo.Runtime.Notify",
|
"Notify": "System.Runtime.Notify",
|
||||||
"Log": "Neo.Runtime.Log",
|
"Log": "System.Runtime.Log",
|
||||||
"GetTime": "Neo.Runtime.GetTime",
|
"GetTime": "System.Runtime.GetTime",
|
||||||
"Serialize": "Neo.Runtime.Serialize",
|
"Serialize": "System.Runtime.Serialize",
|
||||||
"Deserialize": "Neo.Runtime.Deserialize",
|
"Deserialize": "System.Runtime.Deserialize",
|
||||||
},
|
},
|
||||||
"blockchain": {
|
"blockchain": {
|
||||||
"GetAccount": "Neo.Blockchain.GetAccount",
|
|
||||||
"GetBlock": "System.Blockchain.GetBlock",
|
"GetBlock": "System.Blockchain.GetBlock",
|
||||||
"GetContract": "Neo.Blockchain.GetContract",
|
"GetContract": "System.Blockchain.GetContract",
|
||||||
"GetHeader": "Neo.Blockchain.GetHeader",
|
"GetHeight": "System.Blockchain.GetHeight",
|
||||||
"GetHeight": "Neo.Blockchain.GetHeight",
|
|
||||||
"GetTransaction": "System.Blockchain.GetTransaction",
|
"GetTransaction": "System.Blockchain.GetTransaction",
|
||||||
"GetTransactionFromBlock": "System.Blockchain.GetTransactionFromBlock",
|
"GetTransactionFromBlock": "System.Blockchain.GetTransactionFromBlock",
|
||||||
"GetTransactionHeight": "System.Blockchain.GetTransactionHeight",
|
"GetTransactionHeight": "System.Blockchain.GetTransactionHeight",
|
||||||
"GetValidators": "Neo.Blockchain.GetValidators",
|
|
||||||
},
|
|
||||||
"header": {
|
|
||||||
"GetIndex": "Neo.Header.GetIndex",
|
|
||||||
"GetHash": "Neo.Header.GetHash",
|
|
||||||
"GetPrevHash": "Neo.Header.GetPrevHash",
|
|
||||||
"GetTimestamp": "Neo.Header.GetTimestamp",
|
|
||||||
"GetVersion": "Neo.Header.GetVersion",
|
|
||||||
"GetMerkleRoot": "Neo.Header.GetMerkleRoot",
|
|
||||||
"GetConsensusData": "Neo.Header.GetConsensusData",
|
|
||||||
"GetNextConsensus": "Neo.Header.GetNextConsensus",
|
|
||||||
},
|
},
|
||||||
"contract": {
|
"contract": {
|
||||||
"GetScript": "Neo.Contract.GetScript",
|
"GetScript": "Neo.Contract.GetScript",
|
||||||
|
@ -70,15 +51,12 @@ var syscalls = map[string]map[string]string{
|
||||||
"GetExecutingScriptHash": "System.ExecutionEngine.GetExecutingScriptHash",
|
"GetExecutingScriptHash": "System.ExecutionEngine.GetExecutingScriptHash",
|
||||||
},
|
},
|
||||||
"iterator": {
|
"iterator": {
|
||||||
"Concat": "Neo.Iterator.Concat",
|
"Concat": "System.Iterator.Concat",
|
||||||
"Create": "Neo.Iterator.Create",
|
"Create": "System.Iterator.Create",
|
||||||
"Key": "Neo.Iterator.Key",
|
"Key": "System.Iterator.Key",
|
||||||
"Keys": "Neo.Iterator.Keys",
|
"Keys": "System.Iterator.Keys",
|
||||||
"Next": "Neo.Iterator.Next",
|
"Next": "System.Enumerator.Next",
|
||||||
"Value": "Neo.Iterator.Value",
|
"Value": "System.Enumerator.Value",
|
||||||
"Values": "Neo.Iterator.Values",
|
"Values": "System.Iterator.Values",
|
||||||
},
|
|
||||||
"witness": {
|
|
||||||
"GetVerificationScript": "Neo.Witness.GetVerificationScript",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,10 +82,10 @@ func newStoragePlugin() *storagePlugin {
|
||||||
mem: make(map[string][]byte),
|
mem: make(map[string][]byte),
|
||||||
interops: make(map[uint32]vm.InteropFunc),
|
interops: make(map[uint32]vm.InteropFunc),
|
||||||
}
|
}
|
||||||
s.interops[emit.InteropNameToID([]byte("Neo.Storage.Get"))] = s.Get
|
s.interops[emit.InteropNameToID([]byte("System.Storage.Get"))] = s.Get
|
||||||
s.interops[emit.InteropNameToID([]byte("Neo.Storage.Put"))] = s.Put
|
s.interops[emit.InteropNameToID([]byte("System.Storage.Put"))] = s.Put
|
||||||
s.interops[emit.InteropNameToID([]byte("Neo.Storage.GetContext"))] = s.GetContext
|
s.interops[emit.InteropNameToID([]byte("System.Storage.GetContext"))] = s.GetContext
|
||||||
s.interops[emit.InteropNameToID([]byte("Neo.Runtime.Notify"))] = s.Notify
|
s.interops[emit.InteropNameToID([]byte("System.Runtime.Notify"))] = s.Notify
|
||||||
return s
|
return s
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,7 +265,7 @@ func TestSubscriptions(t *testing.T) {
|
||||||
|
|
||||||
script := io.NewBufBinWriter()
|
script := io.NewBufBinWriter()
|
||||||
emit.Bytes(script.BinWriter, []byte("yay!"))
|
emit.Bytes(script.BinWriter, []byte("yay!"))
|
||||||
emit.Syscall(script.BinWriter, "Neo.Runtime.Notify")
|
emit.Syscall(script.BinWriter, "System.Runtime.Notify")
|
||||||
require.NoError(t, script.Err)
|
require.NoError(t, script.Err)
|
||||||
txGood1 := transaction.New(script.Bytes(), 0)
|
txGood1 := transaction.New(script.Bytes(), 0)
|
||||||
txGood1.Sender = neoOwner
|
txGood1.Sender = neoOwner
|
||||||
|
@ -276,7 +276,7 @@ func TestSubscriptions(t *testing.T) {
|
||||||
// Reset() reuses the script buffer and we need to keep scripts.
|
// Reset() reuses the script buffer and we need to keep scripts.
|
||||||
script = io.NewBufBinWriter()
|
script = io.NewBufBinWriter()
|
||||||
emit.Bytes(script.BinWriter, []byte("nay!"))
|
emit.Bytes(script.BinWriter, []byte("nay!"))
|
||||||
emit.Syscall(script.BinWriter, "Neo.Runtime.Notify")
|
emit.Syscall(script.BinWriter, "System.Runtime.Notify")
|
||||||
emit.Opcode(script.BinWriter, opcode.THROW)
|
emit.Opcode(script.BinWriter, opcode.THROW)
|
||||||
require.NoError(t, script.Err)
|
require.NoError(t, script.Err)
|
||||||
txBad := transaction.New(script.Bytes(), 0)
|
txBad := transaction.New(script.Bytes(), 0)
|
||||||
|
@ -287,7 +287,7 @@ func TestSubscriptions(t *testing.T) {
|
||||||
|
|
||||||
script = io.NewBufBinWriter()
|
script = io.NewBufBinWriter()
|
||||||
emit.Bytes(script.BinWriter, []byte("yay! yay! yay!"))
|
emit.Bytes(script.BinWriter, []byte("yay! yay! yay!"))
|
||||||
emit.Syscall(script.BinWriter, "Neo.Runtime.Notify")
|
emit.Syscall(script.BinWriter, "System.Runtime.Notify")
|
||||||
require.NoError(t, script.Err)
|
require.NoError(t, script.Err)
|
||||||
txGood2 := transaction.New(script.Bytes(), 0)
|
txGood2 := transaction.New(script.Bytes(), 0)
|
||||||
txGood2.Sender = neoOwner
|
txGood2.Sender = neoOwner
|
||||||
|
|
|
@ -8,10 +8,8 @@ import (
|
||||||
|
|
||||||
"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/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
"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"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
)
|
)
|
||||||
|
@ -27,109 +25,6 @@ const (
|
||||||
MaxContractStringLen = 252
|
MaxContractStringLen = 252
|
||||||
)
|
)
|
||||||
|
|
||||||
// headerGetVersion returns version from the header.
|
|
||||||
func headerGetVersion(ic *interop.Context, v *vm.VM) error {
|
|
||||||
header, err := popHeaderFromVM(v)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
v.Estack().PushVal(header.Version)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// headerGetMerkleRoot returns version from the header.
|
|
||||||
func headerGetMerkleRoot(ic *interop.Context, v *vm.VM) error {
|
|
||||||
header, err := popHeaderFromVM(v)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
v.Estack().PushVal(header.MerkleRoot.BytesBE())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// headerGetNextConsensus returns version from the header.
|
|
||||||
func headerGetNextConsensus(ic *interop.Context, v *vm.VM) error {
|
|
||||||
header, err := popHeaderFromVM(v)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
v.Estack().PushVal(header.NextConsensus.BytesBE())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// witnessGetVerificationScript returns current witness' script.
|
|
||||||
func witnessGetVerificationScript(ic *interop.Context, v *vm.VM) error {
|
|
||||||
witInterface := v.Estack().Pop().Value()
|
|
||||||
wit, ok := witInterface.(*transaction.Witness)
|
|
||||||
if !ok {
|
|
||||||
return errors.New("value is not a witness")
|
|
||||||
}
|
|
||||||
// It's important not to share wit.VerificationScript slice with the code running in VM.
|
|
||||||
script := make([]byte, len(wit.VerificationScript))
|
|
||||||
copy(script, wit.VerificationScript)
|
|
||||||
v.Estack().PushVal(script)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// bcGetAccount returns or creates an account.
|
|
||||||
func bcGetAccount(ic *interop.Context, v *vm.VM) error {
|
|
||||||
accbytes := v.Estack().Pop().Bytes()
|
|
||||||
acchash, err := util.Uint160DecodeBytesBE(accbytes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
acc, err := ic.DAO.GetAccountStateOrNew(acchash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
v.Estack().PushVal(stackitem.NewInterop(acc))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// accountGetBalance returns balance for a given account.
|
|
||||||
func accountGetBalance(ic *interop.Context, v *vm.VM) error {
|
|
||||||
accInterface := v.Estack().Pop().Value()
|
|
||||||
acc, ok := accInterface.(*state.Account)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("%T is not an account state", acc)
|
|
||||||
}
|
|
||||||
asbytes := v.Estack().Pop().Bytes()
|
|
||||||
ashash, err := util.Uint256DecodeBytesBE(asbytes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
balance, ok := acc.GetBalanceValues()[ashash]
|
|
||||||
if !ok {
|
|
||||||
balance = util.Fixed8(0)
|
|
||||||
}
|
|
||||||
v.Estack().PushVal(int64(balance))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// accountGetScriptHash returns script hash of a given account.
|
|
||||||
func accountGetScriptHash(ic *interop.Context, v *vm.VM) error {
|
|
||||||
accInterface := v.Estack().Pop().Value()
|
|
||||||
acc, ok := accInterface.(*state.Account)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("%T is not an account state", acc)
|
|
||||||
}
|
|
||||||
v.Estack().PushVal(acc.ScriptHash.BytesBE())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// accountIsStandard checks whether given account is standard.
|
|
||||||
func accountIsStandard(ic *interop.Context, v *vm.VM) error {
|
|
||||||
accbytes := v.Estack().Pop().Bytes()
|
|
||||||
acchash, err := util.Uint160DecodeBytesBE(accbytes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
contract, err := ic.DAO.GetContractState(acchash)
|
|
||||||
res := err != nil || vm.IsStandardContract(contract.Script)
|
|
||||||
v.Estack().PushVal(res)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// storageFind finds stored key-value pair.
|
// storageFind finds stored key-value pair.
|
||||||
func storageFind(ic *interop.Context, v *vm.VM) error {
|
func storageFind(ic *interop.Context, v *vm.VM) error {
|
||||||
stcInterface := v.Estack().Pop().Value()
|
stcInterface := v.Estack().Pop().Value()
|
||||||
|
|
|
@ -2,7 +2,6 @@ package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||||
|
@ -136,64 +135,6 @@ func TestStorageFind(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHeaderGetVersion(t *testing.T) {
|
|
||||||
v, block, context, chain := createVMAndPushBlock(t)
|
|
||||||
defer chain.Close()
|
|
||||||
|
|
||||||
err := headerGetVersion(context, v)
|
|
||||||
require.NoError(t, err)
|
|
||||||
value := v.Estack().Pop().Value().(*big.Int)
|
|
||||||
require.Equal(t, uint64(block.Version), value.Uint64())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHeaderGetVersion_Negative(t *testing.T) {
|
|
||||||
v := vm.New()
|
|
||||||
block := newDumbBlock()
|
|
||||||
chain := newTestChain(t)
|
|
||||||
defer chain.Close()
|
|
||||||
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), block, nil)
|
|
||||||
v.Estack().PushVal(stackitem.NewBool(false))
|
|
||||||
|
|
||||||
err := headerGetVersion(context, v)
|
|
||||||
require.Errorf(t, err, "value is not a header or block")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHeaderGetMerkleRoot(t *testing.T) {
|
|
||||||
v, block, context, chain := createVMAndPushBlock(t)
|
|
||||||
defer chain.Close()
|
|
||||||
|
|
||||||
err := headerGetMerkleRoot(context, v)
|
|
||||||
require.NoError(t, err)
|
|
||||||
value := v.Estack().Pop().Value()
|
|
||||||
require.Equal(t, block.MerkleRoot.BytesBE(), value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHeaderGetNextConsensus(t *testing.T) {
|
|
||||||
v, block, context, chain := createVMAndPushBlock(t)
|
|
||||||
defer chain.Close()
|
|
||||||
|
|
||||||
err := headerGetNextConsensus(context, v)
|
|
||||||
require.NoError(t, err)
|
|
||||||
value := v.Estack().Pop().Value()
|
|
||||||
require.Equal(t, block.NextConsensus.BytesBE(), value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWitnessGetVerificationScript(t *testing.T) {
|
|
||||||
v := vm.New()
|
|
||||||
script := []byte{byte(opcode.PUSHM1), byte(opcode.RET)}
|
|
||||||
witness := transaction.Witness{InvocationScript: nil, VerificationScript: script}
|
|
||||||
|
|
||||||
chain := newTestChain(t)
|
|
||||||
defer chain.Close()
|
|
||||||
|
|
||||||
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), nil, nil)
|
|
||||||
v.Estack().PushVal(stackitem.NewInterop(&witness))
|
|
||||||
err := witnessGetVerificationScript(context, v)
|
|
||||||
require.NoError(t, err)
|
|
||||||
value := v.Estack().Pop().Value().([]byte)
|
|
||||||
require.Equal(t, witness.VerificationScript, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestECDSAVerify(t *testing.T) {
|
func TestECDSAVerify(t *testing.T) {
|
||||||
priv, err := keys.NewPrivateKey()
|
priv, err := keys.NewPrivateKey()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -270,17 +211,6 @@ func TestECDSAVerify(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccountGetScriptHash(t *testing.T) {
|
|
||||||
v, accState, context, chain := createVMAndAccState(t)
|
|
||||||
defer chain.Close()
|
|
||||||
v.Estack().PushVal(stackitem.NewInterop(accState))
|
|
||||||
|
|
||||||
err := accountGetScriptHash(context, v)
|
|
||||||
require.NoError(t, err)
|
|
||||||
hash := v.Estack().Pop().Value()
|
|
||||||
require.Equal(t, accState.ScriptHash.BytesBE(), hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContractGetScript(t *testing.T) {
|
func TestContractGetScript(t *testing.T) {
|
||||||
v, contractState, context, chain := createVMAndContractState(t)
|
v, contractState, context, chain := createVMAndContractState(t)
|
||||||
defer chain.Close()
|
defer chain.Close()
|
||||||
|
|
|
@ -98,21 +98,6 @@ func bcGetContract(ic *interop.Context, v *vm.VM) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// bcGetHeader returns block header.
|
|
||||||
func bcGetHeader(ic *interop.Context, v *vm.VM) error {
|
|
||||||
hash, err := getBlockHashFromElement(ic.Chain, v.Estack().Pop())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
header, err := ic.Chain.GetHeader(hash)
|
|
||||||
if err != nil {
|
|
||||||
v.Estack().PushVal([]byte{})
|
|
||||||
} else {
|
|
||||||
v.Estack().PushVal(stackitem.NewInterop(header))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// bcGetHeight returns blockchain height.
|
// bcGetHeight returns blockchain height.
|
||||||
func bcGetHeight(ic *interop.Context, v *vm.VM) error {
|
func bcGetHeight(ic *interop.Context, v *vm.VM) error {
|
||||||
v.Estack().PushVal(ic.Chain.BlockHeight())
|
v.Estack().PushVal(ic.Chain.BlockHeight())
|
||||||
|
|
|
@ -64,7 +64,6 @@ func getInteropFromSlice(ic *interop.Context, slice []interop.Function) func(uin
|
||||||
var systemInterops = []interop.Function{
|
var systemInterops = []interop.Function{
|
||||||
{Name: "System.Blockchain.GetBlock", Func: bcGetBlock, Price: 250},
|
{Name: "System.Blockchain.GetBlock", Func: bcGetBlock, Price: 250},
|
||||||
{Name: "System.Blockchain.GetContract", Func: bcGetContract, Price: 100},
|
{Name: "System.Blockchain.GetContract", Func: bcGetContract, Price: 100},
|
||||||
{Name: "System.Blockchain.GetHeader", Func: bcGetHeader, Price: 100},
|
|
||||||
{Name: "System.Blockchain.GetHeight", Func: bcGetHeight, Price: 1},
|
{Name: "System.Blockchain.GetHeight", Func: bcGetHeight, Price: 1},
|
||||||
{Name: "System.Blockchain.GetTransaction", Func: bcGetTransaction, Price: 100},
|
{Name: "System.Blockchain.GetTransaction", Func: bcGetTransaction, Price: 100},
|
||||||
{Name: "System.Blockchain.GetTransactionFromBlock", Func: bcGetTransactionFromBlock, Price: 100},
|
{Name: "System.Blockchain.GetTransactionFromBlock", Func: bcGetTransactionFromBlock, Price: 100},
|
||||||
|
@ -73,14 +72,19 @@ var systemInterops = []interop.Function{
|
||||||
{Name: "System.Contract.CallEx", Func: contractCallEx, Price: 1},
|
{Name: "System.Contract.CallEx", Func: contractCallEx, Price: 1},
|
||||||
{Name: "System.Contract.Destroy", Func: contractDestroy, Price: 1},
|
{Name: "System.Contract.Destroy", Func: contractDestroy, Price: 1},
|
||||||
{Name: "System.Contract.GetStorageContext", Func: contractGetStorageContext, Price: 1},
|
{Name: "System.Contract.GetStorageContext", Func: contractGetStorageContext, Price: 1},
|
||||||
|
{Name: "System.Enumerator.Concat", Func: enumerator.Concat, Price: 1},
|
||||||
|
{Name: "System.Enumerator.Create", Func: enumerator.Create, Price: 1},
|
||||||
|
{Name: "System.Enumerator.Next", Func: enumerator.Next, Price: 1},
|
||||||
|
{Name: "System.Enumerator.Value", Func: enumerator.Value, Price: 1},
|
||||||
{Name: "System.ExecutionEngine.GetCallingScriptHash", Func: engineGetCallingScriptHash, Price: 1},
|
{Name: "System.ExecutionEngine.GetCallingScriptHash", Func: engineGetCallingScriptHash, Price: 1},
|
||||||
{Name: "System.ExecutionEngine.GetEntryScriptHash", Func: engineGetEntryScriptHash, Price: 1},
|
{Name: "System.ExecutionEngine.GetEntryScriptHash", Func: engineGetEntryScriptHash, Price: 1},
|
||||||
{Name: "System.ExecutionEngine.GetExecutingScriptHash", Func: engineGetExecutingScriptHash, Price: 1},
|
{Name: "System.ExecutionEngine.GetExecutingScriptHash", Func: engineGetExecutingScriptHash, Price: 1},
|
||||||
{Name: "System.ExecutionEngine.GetScriptContainer", Func: engineGetScriptContainer, Price: 1},
|
{Name: "System.ExecutionEngine.GetScriptContainer", Func: engineGetScriptContainer, Price: 1},
|
||||||
{Name: "System.Header.GetHash", Func: headerGetHash, Price: 1},
|
{Name: "System.Iterator.Concat", Func: iterator.Concat, Price: 1},
|
||||||
{Name: "System.Header.GetIndex", Func: headerGetIndex, Price: 1},
|
{Name: "System.Iterator.Create", Func: iterator.Create, Price: 1},
|
||||||
{Name: "System.Header.GetPrevHash", Func: headerGetPrevHash, Price: 1},
|
{Name: "System.Iterator.Key", Func: iterator.Key, Price: 1},
|
||||||
{Name: "System.Header.GetTimestamp", Func: headerGetTimestamp, Price: 1},
|
{Name: "System.Iterator.Keys", Func: iterator.Keys, Price: 1},
|
||||||
|
{Name: "System.Iterator.Values", Func: iterator.Values, Price: 1},
|
||||||
{Name: "System.Runtime.CheckWitness", Func: runtime.CheckWitness, Price: 200},
|
{Name: "System.Runtime.CheckWitness", Func: runtime.CheckWitness, Price: 200},
|
||||||
{Name: "System.Runtime.Deserialize", Func: runtimeDeserialize, Price: 1},
|
{Name: "System.Runtime.Deserialize", Func: runtimeDeserialize, Price: 1},
|
||||||
{Name: "System.Runtime.GetTime", Func: runtimeGetTime, Price: 1},
|
{Name: "System.Runtime.GetTime", Func: runtimeGetTime, Price: 1},
|
||||||
|
@ -90,22 +94,16 @@ var systemInterops = []interop.Function{
|
||||||
{Name: "System.Runtime.Platform", Func: runtimePlatform, Price: 1},
|
{Name: "System.Runtime.Platform", Func: runtimePlatform, Price: 1},
|
||||||
{Name: "System.Runtime.Serialize", Func: runtimeSerialize, Price: 1},
|
{Name: "System.Runtime.Serialize", Func: runtimeSerialize, Price: 1},
|
||||||
{Name: "System.Storage.Delete", Func: storageDelete, Price: 100},
|
{Name: "System.Storage.Delete", Func: storageDelete, Price: 100},
|
||||||
|
{Name: "System.Storage.Find", Func: storageFind, Price: 1},
|
||||||
{Name: "System.Storage.Get", Func: storageGet, Price: 100},
|
{Name: "System.Storage.Get", Func: storageGet, Price: 100},
|
||||||
{Name: "System.Storage.GetContext", Func: storageGetContext, Price: 1},
|
{Name: "System.Storage.GetContext", Func: storageGetContext, Price: 1},
|
||||||
{Name: "System.Storage.GetReadOnlyContext", Func: storageGetReadOnlyContext, Price: 1},
|
{Name: "System.Storage.GetReadOnlyContext", Func: storageGetReadOnlyContext, Price: 1},
|
||||||
{Name: "System.Storage.Put", Func: storagePut, Price: 0}, // These don't have static price in C# code.
|
{Name: "System.Storage.Put", Func: storagePut, Price: 0}, // These don't have static price in C# code.
|
||||||
{Name: "System.Storage.PutEx", Func: storagePutEx, Price: 0},
|
{Name: "System.Storage.PutEx", Func: storagePutEx, Price: 0},
|
||||||
{Name: "System.StorageContext.AsReadOnly", Func: storageContextAsReadOnly, Price: 1},
|
{Name: "System.Storage.AsReadOnly", Func: storageContextAsReadOnly, Price: 1},
|
||||||
}
|
}
|
||||||
|
|
||||||
var neoInterops = []interop.Function{
|
var neoInterops = []interop.Function{
|
||||||
{Name: "Neo.Account.GetBalance", Func: accountGetBalance, Price: 1},
|
|
||||||
{Name: "Neo.Account.GetScriptHash", Func: accountGetScriptHash, Price: 1},
|
|
||||||
{Name: "Neo.Account.IsStandard", Func: accountIsStandard, Price: 100},
|
|
||||||
{Name: "Neo.Blockchain.GetAccount", Func: bcGetAccount, Price: 100},
|
|
||||||
{Name: "Neo.Blockchain.GetContract", Func: bcGetContract, Price: 100},
|
|
||||||
{Name: "Neo.Blockchain.GetHeader", Func: bcGetHeader, Price: 100},
|
|
||||||
{Name: "Neo.Blockchain.GetHeight", Func: bcGetHeight, Price: 1},
|
|
||||||
{Name: "Neo.Contract.Create", Func: contractCreate, Price: 0},
|
{Name: "Neo.Contract.Create", Func: contractCreate, Price: 0},
|
||||||
{Name: "Neo.Contract.Destroy", Func: contractDestroy, Price: 1},
|
{Name: "Neo.Contract.Destroy", Func: contractDestroy, Price: 1},
|
||||||
{Name: "Neo.Contract.GetScript", Func: contractGetScript, Price: 1},
|
{Name: "Neo.Contract.GetScript", Func: contractGetScript, Price: 1},
|
||||||
|
@ -115,42 +113,7 @@ var neoInterops = []interop.Function{
|
||||||
{Name: "Neo.Crypto.ECDsaVerify", Func: crypto.ECDSAVerify, Price: 1},
|
{Name: "Neo.Crypto.ECDsaVerify", Func: crypto.ECDSAVerify, Price: 1},
|
||||||
{Name: "Neo.Crypto.ECDsaCheckMultiSig", Func: crypto.ECDSACheckMultisig, Price: 1},
|
{Name: "Neo.Crypto.ECDsaCheckMultiSig", Func: crypto.ECDSACheckMultisig, Price: 1},
|
||||||
{Name: "Neo.Crypto.SHA256", Func: crypto.Sha256, Price: 1},
|
{Name: "Neo.Crypto.SHA256", Func: crypto.Sha256, Price: 1},
|
||||||
{Name: "Neo.Enumerator.Concat", Func: enumerator.Concat, Price: 1},
|
|
||||||
{Name: "Neo.Enumerator.Create", Func: enumerator.Create, Price: 1},
|
|
||||||
{Name: "Neo.Enumerator.Next", Func: enumerator.Next, Price: 1},
|
|
||||||
{Name: "Neo.Enumerator.Value", Func: enumerator.Value, Price: 1},
|
|
||||||
{Name: "Neo.Header.GetHash", Func: headerGetHash, Price: 1},
|
|
||||||
{Name: "Neo.Header.GetIndex", Func: headerGetIndex, Price: 1},
|
|
||||||
{Name: "Neo.Header.GetMerkleRoot", Func: headerGetMerkleRoot, Price: 1},
|
|
||||||
{Name: "Neo.Header.GetNextConsensus", Func: headerGetNextConsensus, Price: 1},
|
|
||||||
{Name: "Neo.Header.GetPrevHash", Func: headerGetPrevHash, Price: 1},
|
|
||||||
{Name: "Neo.Header.GetTimestamp", Func: headerGetTimestamp, Price: 1},
|
|
||||||
{Name: "Neo.Header.GetVersion", Func: headerGetVersion, Price: 1},
|
|
||||||
{Name: "Neo.Iterator.Concat", Func: iterator.Concat, Price: 1},
|
|
||||||
{Name: "Neo.Iterator.Create", Func: iterator.Create, Price: 1},
|
|
||||||
{Name: "Neo.Iterator.Key", Func: iterator.Key, Price: 1},
|
|
||||||
{Name: "Neo.Iterator.Keys", Func: iterator.Keys, Price: 1},
|
|
||||||
{Name: "Neo.Iterator.Values", Func: iterator.Values, Price: 1},
|
|
||||||
{Name: "Neo.Native.Deploy", Func: native.Deploy, Price: 1},
|
{Name: "Neo.Native.Deploy", Func: native.Deploy, Price: 1},
|
||||||
{Name: "Neo.Runtime.CheckWitness", Func: runtime.CheckWitness, Price: 200},
|
|
||||||
{Name: "Neo.Runtime.Deserialize", Func: runtimeDeserialize, Price: 1},
|
|
||||||
{Name: "Neo.Runtime.GetTime", Func: runtimeGetTime, Price: 1},
|
|
||||||
{Name: "Neo.Runtime.GetTrigger", Func: runtimeGetTrigger, Price: 1},
|
|
||||||
{Name: "Neo.Runtime.Log", Func: runtimeLog, Price: 1},
|
|
||||||
{Name: "Neo.Runtime.Notify", Func: runtimeNotify, Price: 1},
|
|
||||||
{Name: "Neo.Runtime.Serialize", Func: runtimeSerialize, Price: 1},
|
|
||||||
{Name: "Neo.Storage.Delete", Func: storageDelete, Price: 100},
|
|
||||||
{Name: "Neo.Storage.Find", Func: storageFind, Price: 1},
|
|
||||||
{Name: "Neo.Storage.Get", Func: storageGet, Price: 100},
|
|
||||||
{Name: "Neo.Storage.GetContext", Func: storageGetContext, Price: 1},
|
|
||||||
{Name: "Neo.Storage.GetReadOnlyContext", Func: storageGetReadOnlyContext, Price: 1},
|
|
||||||
{Name: "Neo.Storage.Put", Func: storagePut, Price: 0},
|
|
||||||
{Name: "Neo.StorageContext.AsReadOnly", Func: storageContextAsReadOnly, Price: 1},
|
|
||||||
{Name: "Neo.Witness.GetVerificationScript", Func: witnessGetVerificationScript, Price: 100},
|
|
||||||
|
|
||||||
// Aliases.
|
|
||||||
{Name: "Neo.Iterator.Next", Func: enumerator.Next, Price: 1},
|
|
||||||
{Name: "Neo.Iterator.Value", Func: enumerator.Value, Price: 1},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// initIDinInteropsSlice initializes IDs from names in one given
|
// initIDinInteropsSlice initializes IDs from names in one given
|
||||||
|
|
|
@ -32,25 +32,15 @@ func TestUnexpectedNonInterops(t *testing.T) {
|
||||||
|
|
||||||
// All of these functions expect an interop item on the stack.
|
// All of these functions expect an interop item on the stack.
|
||||||
funcs := []func(*interop.Context, *vm.VM) error{
|
funcs := []func(*interop.Context, *vm.VM) error{
|
||||||
accountGetBalance,
|
|
||||||
accountGetScriptHash,
|
|
||||||
contractGetScript,
|
contractGetScript,
|
||||||
contractGetStorageContext,
|
contractGetStorageContext,
|
||||||
contractIsPayable,
|
contractIsPayable,
|
||||||
headerGetHash,
|
|
||||||
headerGetIndex,
|
|
||||||
headerGetMerkleRoot,
|
|
||||||
headerGetNextConsensus,
|
|
||||||
headerGetPrevHash,
|
|
||||||
headerGetTimestamp,
|
|
||||||
headerGetVersion,
|
|
||||||
storageContextAsReadOnly,
|
storageContextAsReadOnly,
|
||||||
storageDelete,
|
storageDelete,
|
||||||
storageFind,
|
storageFind,
|
||||||
storageGet,
|
storageGet,
|
||||||
storagePut,
|
storagePut,
|
||||||
storagePutEx,
|
storagePutEx,
|
||||||
witnessGetVerificationScript,
|
|
||||||
}
|
}
|
||||||
for _, f := range funcs {
|
for _, f := range funcs {
|
||||||
for k, v := range vals {
|
for k, v := range vals {
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
Package account provides getter functions for Account interop structure.
|
|
||||||
To use these functions you need to get an Account first via blockchain.GetAccount
|
|
||||||
call.
|
|
||||||
*/
|
|
||||||
package account
|
|
||||||
|
|
||||||
// Account represents NEO account type that is used in interop functions, it's
|
|
||||||
// an opaque data structure that you can get data from only using functions from
|
|
||||||
// this package. It's similar in function to the Account class in the Neo .net
|
|
||||||
// framework.
|
|
||||||
type Account struct{}
|
|
||||||
|
|
||||||
// GetScriptHash returns the script hash of the given Account (20 bytes in BE
|
|
||||||
// representation). It uses `Neo.Account.GetBalance` syscall internally.
|
|
||||||
func GetScriptHash(a Account) []byte {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetVotes returns current votes of the given account represented as a slice of
|
|
||||||
// public keys. Keys are serialized into byte slices in their compressed form (33
|
|
||||||
// bytes long each). This function uses `Neo.Account.GetVotes` syscall
|
|
||||||
// internally.
|
|
||||||
func GetVotes(a Account) [][]byte {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBalance returns current balance of the given asset (by its ID, 256 bit
|
|
||||||
// hash in BE form) for the given account. Only native UTXO assets can be
|
|
||||||
// queiried via this function, for NEP-5 ones use respective contract calls.
|
|
||||||
// The value returned is represented as an integer with original value multiplied
|
|
||||||
// by 10⁸ so you can work with fractional parts of the balance too. This function
|
|
||||||
// uses `Neo.Account.GetBalance` syscall internally.
|
|
||||||
func GetBalance(a Account, assetID []byte) int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsStandard checks whether given account uses standard (CHECKSIG or
|
|
||||||
// CHECKMULTISIG) contract. It only works for deployed contracts and uses
|
|
||||||
// `Neo.Account.IsStandard` syscall internally.
|
|
||||||
func IsStandard(a Account) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
|
@ -4,9 +4,7 @@ Package blockchain provides functions to access various blockchain data.
|
||||||
package blockchain
|
package blockchain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/account"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/header"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Transaction represents a NEO transaction. It's similar to Transaction class
|
// Transaction represents a NEO transaction. It's similar to Transaction class
|
||||||
|
@ -63,19 +61,11 @@ type Block struct {
|
||||||
// Note that when transaction is being run as a part of new block this block is
|
// Note that when transaction is being run as a part of new block this block is
|
||||||
// considered as not yet accepted (persisted) and thus you'll get an index of
|
// considered as not yet accepted (persisted) and thus you'll get an index of
|
||||||
// the previous (already accepted) block. This function uses
|
// the previous (already accepted) block. This function uses
|
||||||
// `Neo.Blockchain.GetHeight` syscall.
|
// `System.Blockchain.GetHeight` syscall.
|
||||||
func GetHeight() int {
|
func GetHeight() int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHeader returns header found by the given hash (256 bit hash in BE format
|
|
||||||
// represented as a slice of 32 bytes) or index (integer). Refer to the `header`
|
|
||||||
// package for possible uses of returned structure. This function uses
|
|
||||||
// `Neo.Blockchain.GetHeader` syscall.
|
|
||||||
func GetHeader(heightOrHash interface{}) header.Header {
|
|
||||||
return header.Header{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBlock returns block found by the given hash or index (with the same
|
// GetBlock returns block found by the given hash or index (with the same
|
||||||
// encoding as for GetHeader). This function uses `System.Blockchain.GetBlock`
|
// encoding as for GetHeader). This function uses `System.Blockchain.GetBlock`
|
||||||
// syscall.
|
// syscall.
|
||||||
|
@ -108,22 +98,7 @@ func GetTransactionHeight(hash []byte) int {
|
||||||
// GetContract returns contract found by the given script hash (160 bit in BE
|
// GetContract returns contract found by the given script hash (160 bit in BE
|
||||||
// format represented as a slice of 20 bytes). Refer to the `contract` package
|
// format represented as a slice of 20 bytes). Refer to the `contract` package
|
||||||
// for details on how to use the returned structure. This function uses
|
// for details on how to use the returned structure. This function uses
|
||||||
// `Neo.Blockchain.GetContract` syscall.
|
// `System.Blockchain.GetContract` syscall.
|
||||||
func GetContract(scriptHash []byte) contract.Contract {
|
func GetContract(scriptHash []byte) contract.Contract {
|
||||||
return contract.Contract{}
|
return contract.Contract{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAccount returns account found by the given script hash (160 bit in BE
|
|
||||||
// format represented as a slice of 20 bytes). Refer to the `account` package
|
|
||||||
// for details on how to use the returned structure. This function uses
|
|
||||||
// `Neo.Blockchain.GetAccount` syscall.
|
|
||||||
func GetAccount(scriptHash []byte) account.Account {
|
|
||||||
return account.Account{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetValidators returns a slice of current validators public keys represented
|
|
||||||
// as a compressed serialized byte slice (33 bytes long). This function uses
|
|
||||||
// `Neo.Blockchain.GetValidators` syscall.
|
|
||||||
func GetValidators() [][]byte {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ type Enumerator struct{}
|
||||||
|
|
||||||
// Create creates a new enumerator from the given items (slice or structure).
|
// Create creates a new enumerator from the given items (slice or structure).
|
||||||
// New enumerator points at index -1 of its items, so the user of it has to
|
// New enumerator points at index -1 of its items, so the user of it has to
|
||||||
// advance it first with Next. This function uses `Neo.Enumerator.Create`
|
// advance it first with Next. This function uses `System.Enumerator.Create`
|
||||||
// syscall.
|
// syscall.
|
||||||
func Create(items []interface{}) Enumerator {
|
func Create(items []interface{}) Enumerator {
|
||||||
return Enumerator{}
|
return Enumerator{}
|
||||||
|
@ -20,13 +20,13 @@ func Create(items []interface{}) Enumerator {
|
||||||
// Next moves position of the given enumerator by one and returns a bool that
|
// Next moves position of the given enumerator by one and returns a bool that
|
||||||
// tells whether there is a new value present in this new position. If it is,
|
// tells whether there is a new value present in this new position. If it is,
|
||||||
// you can use Value to get it, if not then there are no more values in this
|
// you can use Value to get it, if not then there are no more values in this
|
||||||
// enumerator. This function uses `Neo.Enumerator.Next` syscall.
|
// enumerator. This function uses `System.Enumerator.Next` syscall.
|
||||||
func Next(e Enumerator) bool {
|
func Next(e Enumerator) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value returns current enumerator's item value, it's only valid to call it
|
// Value returns current enumerator's item value, it's only valid to call it
|
||||||
// after Next returning true. This function uses `Neo.Enumerator.Value` syscall.
|
// after Next returning true. This function uses `System.Enumerator.Value` syscall.
|
||||||
func Value(e Enumerator) interface{} {
|
func Value(e Enumerator) interface{} {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ func Value(e Enumerator) interface{} {
|
||||||
// a first and then continue with b. Enumerator positions are not reset for a
|
// a first and then continue with b. Enumerator positions are not reset for a
|
||||||
// and b, so if any of them was already advanced by Next the resulting
|
// and b, so if any of them was already advanced by Next the resulting
|
||||||
// Enumerator will point at this new position and never go back to previous
|
// Enumerator will point at this new position and never go back to previous
|
||||||
// values. This function uses `Neo.Enumerator.Concat` syscall.
|
// values. This function uses `System.Enumerator.Concat` syscall.
|
||||||
func Concat(a, b Enumerator) Enumerator {
|
func Concat(a, b Enumerator) Enumerator {
|
||||||
return Enumerator{}
|
return Enumerator{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
/*
|
|
||||||
Package header contains functions working with block headers.
|
|
||||||
*/
|
|
||||||
package header
|
|
||||||
|
|
||||||
// Header represents Neo block header type, it's an opaque data structure that
|
|
||||||
// can be used by functions from this package. You can create it with
|
|
||||||
// blockchain.GetHeader. In its function it's similar to the Header class
|
|
||||||
// of the Neo .net framework.
|
|
||||||
type Header struct{}
|
|
||||||
|
|
||||||
// GetIndex returns the index (height) of the given header. It uses
|
|
||||||
// `Neo.Header.GetIndex` syscall.
|
|
||||||
func GetIndex(h Header) int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHash returns the hash (256-bit BE value packed into 32 byte slice) of the
|
|
||||||
// given header (which also is a hash of the block). It uses `Neo.Header.GetHash`
|
|
||||||
// syscall.
|
|
||||||
func GetHash(h Header) []byte {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPrevHash returns the hash (256-bit BE value packed into 32 byte slice) of
|
|
||||||
// the previous block stored in the given header. It uses `Neo.Header.GetPrevHash`
|
|
||||||
// syscall.
|
|
||||||
func GetPrevHash(h Header) []byte {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTimestamp returns the timestamp of the given header. It uses
|
|
||||||
// `Neo.Header.GetTimestamp` syscall.
|
|
||||||
func GetTimestamp(h Header) int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetVersion returns the version of the given header. It uses
|
|
||||||
// `Neo.Header.GetVersion` syscall.
|
|
||||||
func GetVersion(h Header) int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMerkleRoot returns the Merkle root (256-bit BE value packed into 32 byte
|
|
||||||
// slice) of the given header. It uses `Neo.Header.GetMerkleRoot` syscall.
|
|
||||||
func GetMerkleRoot(h Header) []byte {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetConsensusData returns the consensus data (nonce) of the given header.
|
|
||||||
// It uses `Neo.Header.GetConsensusData` syscall.
|
|
||||||
func GetConsensusData(h Header) int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetNextConsensus returns the next consensus field (verification script hash,
|
|
||||||
// 160-bit BE value packed into 20 byte slice) of the given header. It uses
|
|
||||||
// `Neo.Header.GetNextConsensus` syscall.
|
|
||||||
func GetNextConsensus(h Header) []byte {
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -13,7 +13,7 @@ type Iterator struct{}
|
||||||
|
|
||||||
// Create creates an iterator from the given items (array, struct or map). A new
|
// Create creates an iterator from the given items (array, struct or map). A new
|
||||||
// iterator is set to point at element -1, so to access its first element you
|
// iterator is set to point at element -1, so to access its first element you
|
||||||
// need to call Next first. This function uses `Neo.Iterator.Create` syscall.
|
// need to call Next first. This function uses `System.Iterator.Create` syscall.
|
||||||
func Create(items []interface{}) Iterator {
|
func Create(items []interface{}) Iterator {
|
||||||
return Iterator{}
|
return Iterator{}
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,13 @@ func Create(items []interface{}) Iterator {
|
||||||
// Iterator will point at this new position and never go back to previous
|
// Iterator will point at this new position and never go back to previous
|
||||||
// key-value pairs. Concatenated iterators also remain completely independent
|
// key-value pairs. Concatenated iterators also remain completely independent
|
||||||
// in results they return, so if both contain the same key you'll receive this
|
// in results they return, so if both contain the same key you'll receive this
|
||||||
// key twice when iterating. This function uses `Neo.Iterator.Concat` syscall.
|
// key twice when iterating. This function uses `System.Iterator.Concat` syscall.
|
||||||
func Concat(a, b Iterator) Iterator {
|
func Concat(a, b Iterator) Iterator {
|
||||||
return Iterator{}
|
return Iterator{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key returns iterator's key at current position. It's only valid to call after
|
// Key returns iterator's key at current position. It's only valid to call after
|
||||||
// successful Next call. This function uses `Neo.Iterator.Key` syscall.
|
// successful Next call. This function uses `System.Iterator.Key` syscall.
|
||||||
func Key(it Iterator) interface{} {
|
func Key(it Iterator) interface{} {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -38,20 +38,20 @@ func Key(it Iterator) interface{} {
|
||||||
// Keys returns Enumerator ranging over keys or the given Iterator. Note that
|
// Keys returns Enumerator ranging over keys or the given Iterator. Note that
|
||||||
// this Enumerator is actually directly tied to the underlying Iterator, so that
|
// this Enumerator is actually directly tied to the underlying Iterator, so that
|
||||||
// advancing it with Next will actually advance the Iterator too. This function
|
// advancing it with Next will actually advance the Iterator too. This function
|
||||||
// uses `Neo.Iterator.Keys` syscall.
|
// uses `System.Iterator.Keys` syscall.
|
||||||
func Keys(it Iterator) enumerator.Enumerator {
|
func Keys(it Iterator) enumerator.Enumerator {
|
||||||
return enumerator.Enumerator{}
|
return enumerator.Enumerator{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next advances the iterator returning true if it is was successful (and you
|
// Next advances the iterator returning true if it is was successful (and you
|
||||||
// can use Key or Value) and false otherwise (and there are no more elements in
|
// can use Key or Value) and false otherwise (and there are no more elements in
|
||||||
// this Iterator). This function uses `Neo.Iterator.Next` syscall.
|
// this Iterator). This function uses `System.Enumerator.Next` syscall.
|
||||||
func Next(it Iterator) bool {
|
func Next(it Iterator) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value returns iterator's current value. It's only valid to call after
|
// Value returns iterator's current value. It's only valid to call after
|
||||||
// successful Next call. This function uses `Neo.Iterator.Value` syscall.
|
// successful Next call. This function uses `System.Enumerator.Value` syscall.
|
||||||
func Value(it Iterator) interface{} {
|
func Value(it Iterator) interface{} {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ func Value(it Iterator) interface{} {
|
||||||
// Values returns Enumerator ranging over values or the given Iterator. Note that
|
// Values returns Enumerator ranging over values or the given Iterator. Note that
|
||||||
// this Enumerator is actually directly tied to the underlying Iterator, so that
|
// this Enumerator is actually directly tied to the underlying Iterator, so that
|
||||||
// advancing it with Next will actually advance the Iterator too. This function
|
// advancing it with Next will actually advance the Iterator too. This function
|
||||||
// uses `Neo.Iterator.Values` syscall.
|
// uses `System.Iterator.Values` syscall.
|
||||||
func Values(it Iterator) enumerator.Enumerator {
|
func Values(it Iterator) enumerator.Enumerator {
|
||||||
return enumerator.Enumerator{}
|
return enumerator.Enumerator{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,14 @@ package runtime
|
||||||
|
|
||||||
// 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 `Neo.Runtime.CheckWitness` syscall.
|
// this invocation. It uses `System.Runtime.CheckWitness` syscall.
|
||||||
func CheckWitness(hashOrKey []byte) bool {
|
func CheckWitness(hashOrKey []byte) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log instructs VM to log the given message. It's mostly used for debugging
|
// Log instructs VM to log the given message. It's mostly used for debugging
|
||||||
// purposes as these messages are not saved anywhere normally and usually are
|
// purposes as these messages are not saved anywhere normally and usually are
|
||||||
// only visible in the VM logs. This function uses `Neo.Runtime.Log` syscall.
|
// only visible in the VM logs. This function uses `System.Runtime.Log` syscall.
|
||||||
func Log(message string) {}
|
func Log(message string) {}
|
||||||
|
|
||||||
// Notify sends a notification (collecting all arguments in an array) to the
|
// Notify sends a notification (collecting all arguments in an array) to the
|
||||||
|
@ -21,14 +21,14 @@ func Log(message string) {}
|
||||||
// notification is saved in application log. It's intended to be used as a
|
// notification is saved in application log. It's intended to be used as a
|
||||||
// part of contract's API to external systems, these events can be monitored
|
// part of contract's API to external systems, these events can be monitored
|
||||||
// from outside and act upon accordingly. This function uses
|
// from outside and act upon accordingly. This function uses
|
||||||
// `Neo.Runtime.Notify` syscall.
|
// `System.Runtime.Notify` syscall.
|
||||||
func Notify(arg ...interface{}) {}
|
func Notify(arg ...interface{}) {}
|
||||||
|
|
||||||
// GetTime returns the timestamp of the most recent block. Note that when running
|
// GetTime returns the timestamp of the most recent block. Note that when running
|
||||||
// script in test mode this would be the last accepted (persisted) block in the
|
// script in test mode this would be the last accepted (persisted) block in the
|
||||||
// chain, but when running as a part of the new block the time returned is the
|
// chain, but when running as a part of the new block the time returned is the
|
||||||
// time of this (currently being processed) block. This function uses
|
// time of this (currently being processed) block. This function uses
|
||||||
// `Neo.Runtime.GetTime` syscall.
|
// `System.Runtime.GetTime` syscall.
|
||||||
func GetTime() int {
|
func GetTime() int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ func GetTime() int {
|
||||||
// as a part of verification process from running it as a regular application.
|
// as a part of verification process from running it as a regular application.
|
||||||
// Some interop functions (especially ones that change the state in any way) are
|
// Some interop functions (especially ones that change the state in any way) are
|
||||||
// not available when running with verification trigger. This function uses
|
// not available when running with verification trigger. This function uses
|
||||||
// `Neo.Runtime.GetTrigger` syscall.
|
// `System.Runtime.GetTrigger` syscall.
|
||||||
func GetTrigger() byte {
|
func GetTrigger() byte {
|
||||||
return 0x00
|
return 0x00
|
||||||
}
|
}
|
||||||
|
@ -58,13 +58,13 @@ func Verification() byte {
|
||||||
// Serialize serializes any given item into a byte slice. It works for all
|
// Serialize serializes any given item into a byte slice. It works for all
|
||||||
// regular VM types (not ones from interop package) and allows to save them in
|
// regular VM types (not ones from interop package) and allows to save them in
|
||||||
// storage or pass into Notify and then Deserialize them on the next run or in
|
// storage or pass into Notify and then Deserialize them on the next run or in
|
||||||
// the external event receiver. It uses `Neo.Runtime.Serialize` syscall.
|
// the external event receiver. It uses `System.Runtime.Serialize` syscall.
|
||||||
func Serialize(item interface{}) []byte {
|
func Serialize(item interface{}) []byte {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deserialize unpacks previously serialized value from a byte slice, it's the
|
// Deserialize unpacks previously serialized value from a byte slice, it's the
|
||||||
// opposite of Serialize. It uses `Neo.Runtime.Deserialize` syscall.
|
// opposite of Serialize. It uses `System.Runtime.Deserialize` syscall.
|
||||||
func Deserialize(b []byte) interface{} {
|
func Deserialize(b []byte) interface{} {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,38 +17,38 @@ type Context struct{}
|
||||||
// ConvertContextToReadOnly returns new context from the given one, but with
|
// ConvertContextToReadOnly returns new context from the given one, but with
|
||||||
// writing capability turned off, so that you could only invoke Get and Find
|
// writing capability turned off, so that you could only invoke Get and Find
|
||||||
// using this new Context. If Context is already read-only this function is a
|
// using this new Context. If Context is already read-only this function is a
|
||||||
// no-op. It uses `Neo.StorageContext.AsReadOnly` syscall.
|
// no-op. It uses `System.Storage.AsReadOnly` syscall.
|
||||||
func ConvertContextToReadOnly(ctx Context) Context { return Context{} }
|
func ConvertContextToReadOnly(ctx Context) Context { return Context{} }
|
||||||
|
|
||||||
// GetContext returns current contract's (that invokes this function) storage
|
// GetContext returns current contract's (that invokes this function) storage
|
||||||
// context. It uses `Neo.Storage.GetContext` syscall.
|
// context. It uses `System.Storage.GetContext` syscall.
|
||||||
func GetContext() Context { return Context{} }
|
func GetContext() Context { return Context{} }
|
||||||
|
|
||||||
// GetReadOnlyContext returns current contract's (that invokes this function)
|
// GetReadOnlyContext returns current contract's (that invokes this function)
|
||||||
// storage context in read-only mode, you can use this context for Get and Find
|
// storage context in read-only mode, you can use this context for Get and Find
|
||||||
// functions, but using it for Put and Delete will fail. It uses
|
// functions, but using it for Put and Delete will fail. It uses
|
||||||
// `Neo.Storage.GetReadOnlyContext` syscall.
|
// `System.Storage.GetReadOnlyContext` syscall.
|
||||||
func GetReadOnlyContext() Context { return Context{} }
|
func GetReadOnlyContext() Context { return Context{} }
|
||||||
|
|
||||||
// Put saves given value with given key in the storage using given Context.
|
// Put saves given value with given key in the storage using given Context.
|
||||||
// Even though it accepts interface{} for both, you can only pass simple types
|
// Even though it accepts interface{} for both, you can only pass simple types
|
||||||
// there like string, []byte, int or bool (not structures or slices of more
|
// there like string, []byte, int or bool (not structures or slices of more
|
||||||
// complex types). To put more complex types there serialize them first using
|
// complex types). To put more complex types there serialize them first using
|
||||||
// runtime.Serialize. This function uses `Neo.Storage.Put` syscall.
|
// runtime.Serialize. This function uses `System.Storage.Put` syscall.
|
||||||
func Put(ctx Context, key interface{}, value interface{}) {}
|
func Put(ctx Context, key interface{}, value interface{}) {}
|
||||||
|
|
||||||
// Get retrieves value stored for the given key using given Context. See Put
|
// Get retrieves value stored for the given key using given Context. See Put
|
||||||
// documentation on possible key and value types. This function uses
|
// documentation on possible key and value types. This function uses
|
||||||
// `Neo.Storage.Get` syscall.
|
// `System.Storage.Get` syscall.
|
||||||
func Get(ctx Context, key interface{}) interface{} { return 0 }
|
func Get(ctx Context, key interface{}) interface{} { return 0 }
|
||||||
|
|
||||||
// Delete removes key-value pair from storage by the given key using given
|
// Delete removes key-value pair from storage by the given key using given
|
||||||
// Context. See Put documentation on possible key types. This function uses
|
// Context. See Put documentation on possible key types. This function uses
|
||||||
// `Neo.Storage.Delete` syscall.
|
// `System.Storage.Delete` syscall.
|
||||||
func Delete(ctx Context, key interface{}) {}
|
func Delete(ctx Context, key interface{}) {}
|
||||||
|
|
||||||
// Find returns an iterator.Iterator over key-value pairs in the given Context
|
// Find returns an iterator.Iterator over key-value pairs in the given Context
|
||||||
// that match the given key (contain it as a prefix). See Put documentation on
|
// that match the given key (contain it as a prefix). See Put documentation on
|
||||||
// possible key types and iterator package documentation on how to use the
|
// possible key types and iterator package documentation on how to use the
|
||||||
// returned value. This function uses `Neo.Storage.Find` syscall.
|
// returned value. This function uses `System.Storage.Find` syscall.
|
||||||
func Find(ctx Context, key interface{}) iterator.Iterator { return iterator.Iterator{} }
|
func Find(ctx Context, key interface{}) iterator.Iterator { return iterator.Iterator{} }
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
/*
|
|
||||||
Package witness provides functions dealing with transaction's witnesses.
|
|
||||||
*/
|
|
||||||
package witness
|
|
||||||
|
|
||||||
// Witness is an opaque data structure that can only be created by
|
|
||||||
// transaction.GetWitnesses and representing transaction's witness.
|
|
||||||
type Witness struct{}
|
|
||||||
|
|
||||||
// GetVerificationScript returns verification script stored in the given
|
|
||||||
// witness. It uses `Neo.Witness.GetVerificationScript` syscall.
|
|
||||||
func GetVerificationScript(w Witness) []byte {
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -49,18 +49,18 @@ type rpcTestCase struct {
|
||||||
check func(t *testing.T, e *executor, result interface{})
|
check func(t *testing.T, e *executor, result interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
const testContractHash = "1b4357bff5a01bdf2a6581247cf9ed1e24629176"
|
const testContractHash = "279c86355b30d452386c1717e2ffa01c9dac31f3"
|
||||||
|
|
||||||
var rpcTestCases = map[string][]rpcTestCase{
|
var rpcTestCases = map[string][]rpcTestCase{
|
||||||
"getapplicationlog": {
|
"getapplicationlog": {
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
params: `["5878052c7e9843786d64a9aeab16e74fabffd5abad9a0404aaf4f4bf2b6213e9"]`,
|
params: `["328190e78f1b5b8dcf86e71ec1894d6144f4e4cdb25abc20ea02b618851941dd"]`,
|
||||||
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
|
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
|
||||||
check: func(t *testing.T, e *executor, acc interface{}) {
|
check: func(t *testing.T, e *executor, acc interface{}) {
|
||||||
res, ok := acc.(*result.ApplicationLog)
|
res, ok := acc.(*result.ApplicationLog)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
expectedTxHash, err := util.Uint256DecodeStringLE("5878052c7e9843786d64a9aeab16e74fabffd5abad9a0404aaf4f4bf2b6213e9")
|
expectedTxHash, err := util.Uint256DecodeStringLE("328190e78f1b5b8dcf86e71ec1894d6144f4e4cdb25abc20ea02b618851941dd")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, expectedTxHash, res.TxHash)
|
assert.Equal(t, expectedTxHash, res.TxHash)
|
||||||
assert.Equal(t, 1, len(res.Executions))
|
assert.Equal(t, 1, len(res.Executions))
|
||||||
|
@ -484,7 +484,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
"gettransactionheight": {
|
"gettransactionheight": {
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
params: `["5878052c7e9843786d64a9aeab16e74fabffd5abad9a0404aaf4f4bf2b6213e9"]`,
|
params: `["328190e78f1b5b8dcf86e71ec1894d6144f4e4cdb25abc20ea02b618851941dd"]`,
|
||||||
result: func(e *executor) interface{} {
|
result: func(e *executor) interface{} {
|
||||||
h := 0
|
h := 0
|
||||||
return &h
|
return &h
|
||||||
|
|
BIN
pkg/rpc/server/testdata/test_contract.avm
vendored
BIN
pkg/rpc/server/testdata/test_contract.avm
vendored
Binary file not shown.
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
Binary file not shown.
|
@ -189,9 +189,9 @@ func TestEmitString(t *testing.T) {
|
||||||
|
|
||||||
func TestEmitSyscall(t *testing.T) {
|
func TestEmitSyscall(t *testing.T) {
|
||||||
syscalls := []string{
|
syscalls := []string{
|
||||||
"Neo.Runtime.Log",
|
"System.Runtime.Log",
|
||||||
"Neo.Runtime.Notify",
|
"System.Runtime.Notify",
|
||||||
"Neo.Runtime.Whatever",
|
"System.Runtime.Whatever",
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := io.NewBufBinWriter()
|
buf := io.NewBufBinWriter()
|
||||||
|
|
|
@ -29,35 +29,31 @@ type interopIDFuncPrice struct {
|
||||||
type InteropGetterFunc func(uint32) *InteropFuncPrice
|
type InteropGetterFunc func(uint32) *InteropFuncPrice
|
||||||
|
|
||||||
var defaultVMInterops = []interopIDFuncPrice{
|
var defaultVMInterops = []interopIDFuncPrice{
|
||||||
{emit.InteropNameToID([]byte("Neo.Runtime.Log")),
|
{emit.InteropNameToID([]byte("System.Runtime.Log")),
|
||||||
InteropFuncPrice{runtimeLog, 1}},
|
InteropFuncPrice{runtimeLog, 1}},
|
||||||
{emit.InteropNameToID([]byte("Neo.Runtime.Notify")),
|
{emit.InteropNameToID([]byte("System.Runtime.Notify")),
|
||||||
InteropFuncPrice{runtimeNotify, 1}},
|
InteropFuncPrice{runtimeNotify, 1}},
|
||||||
{emit.InteropNameToID([]byte("Neo.Runtime.Serialize")),
|
|
||||||
InteropFuncPrice{RuntimeSerialize, 1}},
|
|
||||||
{emit.InteropNameToID([]byte("System.Runtime.Serialize")),
|
{emit.InteropNameToID([]byte("System.Runtime.Serialize")),
|
||||||
InteropFuncPrice{RuntimeSerialize, 1}},
|
InteropFuncPrice{RuntimeSerialize, 1}},
|
||||||
{emit.InteropNameToID([]byte("Neo.Runtime.Deserialize")),
|
|
||||||
InteropFuncPrice{RuntimeDeserialize, 1}},
|
|
||||||
{emit.InteropNameToID([]byte("System.Runtime.Deserialize")),
|
{emit.InteropNameToID([]byte("System.Runtime.Deserialize")),
|
||||||
InteropFuncPrice{RuntimeDeserialize, 1}},
|
InteropFuncPrice{RuntimeDeserialize, 1}},
|
||||||
{emit.InteropNameToID([]byte("Neo.Enumerator.Create")),
|
{emit.InteropNameToID([]byte("System.Enumerator.Create")),
|
||||||
InteropFuncPrice{EnumeratorCreate, 1}},
|
InteropFuncPrice{EnumeratorCreate, 1}},
|
||||||
{emit.InteropNameToID([]byte("Neo.Enumerator.Next")),
|
{emit.InteropNameToID([]byte("System.Enumerator.Next")),
|
||||||
InteropFuncPrice{EnumeratorNext, 1}},
|
InteropFuncPrice{EnumeratorNext, 1}},
|
||||||
{emit.InteropNameToID([]byte("Neo.Enumerator.Concat")),
|
{emit.InteropNameToID([]byte("System.Enumerator.Concat")),
|
||||||
InteropFuncPrice{EnumeratorConcat, 1}},
|
InteropFuncPrice{EnumeratorConcat, 1}},
|
||||||
{emit.InteropNameToID([]byte("Neo.Enumerator.Value")),
|
{emit.InteropNameToID([]byte("System.Enumerator.Value")),
|
||||||
InteropFuncPrice{EnumeratorValue, 1}},
|
InteropFuncPrice{EnumeratorValue, 1}},
|
||||||
{emit.InteropNameToID([]byte("Neo.Iterator.Create")),
|
{emit.InteropNameToID([]byte("System.Iterator.Create")),
|
||||||
InteropFuncPrice{IteratorCreate, 1}},
|
InteropFuncPrice{IteratorCreate, 1}},
|
||||||
{emit.InteropNameToID([]byte("Neo.Iterator.Concat")),
|
{emit.InteropNameToID([]byte("System.Iterator.Concat")),
|
||||||
InteropFuncPrice{IteratorConcat, 1}},
|
InteropFuncPrice{IteratorConcat, 1}},
|
||||||
{emit.InteropNameToID([]byte("Neo.Iterator.Key")),
|
{emit.InteropNameToID([]byte("System.Iterator.Key")),
|
||||||
InteropFuncPrice{IteratorKey, 1}},
|
InteropFuncPrice{IteratorKey, 1}},
|
||||||
{emit.InteropNameToID([]byte("Neo.Iterator.Keys")),
|
{emit.InteropNameToID([]byte("System.Iterator.Keys")),
|
||||||
InteropFuncPrice{IteratorKeys, 1}},
|
InteropFuncPrice{IteratorKeys, 1}},
|
||||||
{emit.InteropNameToID([]byte("Neo.Iterator.Values")),
|
{emit.InteropNameToID([]byte("System.Iterator.Values")),
|
||||||
InteropFuncPrice{IteratorValues, 1}},
|
InteropFuncPrice{IteratorValues, 1}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,21 +67,21 @@ func getDefaultVMInterop(id uint32) *InteropFuncPrice {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// runtimeLog handles the syscall "Neo.Runtime.Log" for printing and logging stuff.
|
// runtimeLog handles the syscall "System.Runtime.Log" for printing and logging stuff.
|
||||||
func runtimeLog(vm *VM) error {
|
func runtimeLog(vm *VM) error {
|
||||||
item := vm.Estack().Pop()
|
item := vm.Estack().Pop()
|
||||||
fmt.Printf("NEO-GO-VM (log) > %s\n", item.Value())
|
fmt.Printf("NEO-GO-VM (log) > %s\n", item.Value())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// runtimeNotify handles the syscall "Neo.Runtime.Notify" for printing and logging stuff.
|
// runtimeNotify handles the syscall "System.Runtime.Notify" for printing and logging stuff.
|
||||||
func runtimeNotify(vm *VM) error {
|
func runtimeNotify(vm *VM) error {
|
||||||
item := vm.Estack().Pop()
|
item := vm.Estack().Pop()
|
||||||
fmt.Printf("NEO-GO-VM (notify) > %s\n", item.Value())
|
fmt.Printf("NEO-GO-VM (notify) > %s\n", item.Value())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RuntimeSerialize handles syscalls System.Runtime.Serialize and Neo.Runtime.Serialize.
|
// RuntimeSerialize handles syscalls System.Runtime.Serialize and System.Runtime.Serialize.
|
||||||
func RuntimeSerialize(vm *VM) error {
|
func RuntimeSerialize(vm *VM) error {
|
||||||
item := vm.Estack().Pop()
|
item := vm.Estack().Pop()
|
||||||
data, err := stackitem.SerializeItem(item.value)
|
data, err := stackitem.SerializeItem(item.value)
|
||||||
|
@ -100,7 +96,7 @@ func RuntimeSerialize(vm *VM) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RuntimeDeserialize handles syscalls System.Runtime.Deserialize and Neo.Runtime.Deserialize.
|
// RuntimeDeserialize handles syscalls System.Runtime.Deserialize and System.Runtime.Deserialize.
|
||||||
func RuntimeDeserialize(vm *VM) error {
|
func RuntimeDeserialize(vm *VM) error {
|
||||||
data := vm.Estack().Pop().Bytes()
|
data := vm.Estack().Pop().Bytes()
|
||||||
|
|
||||||
|
@ -121,7 +117,7 @@ func init() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnumeratorCreate handles syscall Neo.Enumerator.Create.
|
// EnumeratorCreate handles syscall System.Enumerator.Create.
|
||||||
func EnumeratorCreate(v *VM) error {
|
func EnumeratorCreate(v *VM) error {
|
||||||
data := v.Estack().Pop().Array()
|
data := v.Estack().Pop().Array()
|
||||||
v.Estack().Push(&Element{
|
v.Estack().Push(&Element{
|
||||||
|
@ -134,7 +130,7 @@ func EnumeratorCreate(v *VM) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnumeratorNext handles syscall Neo.Enumerator.Next.
|
// EnumeratorNext handles syscall System.Enumerator.Next.
|
||||||
func EnumeratorNext(v *VM) error {
|
func EnumeratorNext(v *VM) error {
|
||||||
iop := v.Estack().Pop().Interop()
|
iop := v.Estack().Pop().Interop()
|
||||||
arr := iop.Value().(enumerator)
|
arr := iop.Value().(enumerator)
|
||||||
|
@ -143,7 +139,7 @@ func EnumeratorNext(v *VM) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnumeratorValue handles syscall Neo.Enumerator.Value.
|
// EnumeratorValue handles syscall System.Enumerator.Value.
|
||||||
func EnumeratorValue(v *VM) error {
|
func EnumeratorValue(v *VM) error {
|
||||||
iop := v.Estack().Pop().Interop()
|
iop := v.Estack().Pop().Interop()
|
||||||
arr := iop.Value().(enumerator)
|
arr := iop.Value().(enumerator)
|
||||||
|
@ -152,7 +148,7 @@ func EnumeratorValue(v *VM) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnumeratorConcat handles syscall Neo.Enumerator.Concat.
|
// EnumeratorConcat handles syscall System.Enumerator.Concat.
|
||||||
func EnumeratorConcat(v *VM) error {
|
func EnumeratorConcat(v *VM) error {
|
||||||
iop1 := v.Estack().Pop().Interop()
|
iop1 := v.Estack().Pop().Interop()
|
||||||
arr1 := iop1.Value().(enumerator)
|
arr1 := iop1.Value().(enumerator)
|
||||||
|
@ -169,7 +165,7 @@ func EnumeratorConcat(v *VM) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IteratorCreate handles syscall Neo.Iterator.Create.
|
// IteratorCreate handles syscall System.Iterator.Create.
|
||||||
func IteratorCreate(v *VM) error {
|
func IteratorCreate(v *VM) error {
|
||||||
data := v.Estack().Pop()
|
data := v.Estack().Pop()
|
||||||
var item stackitem.Item
|
var item stackitem.Item
|
||||||
|
@ -197,7 +193,7 @@ func NewMapIterator(m *stackitem.Map) *stackitem.Interop {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// IteratorConcat handles syscall Neo.Iterator.Concat.
|
// IteratorConcat handles syscall System.Iterator.Concat.
|
||||||
func IteratorConcat(v *VM) error {
|
func IteratorConcat(v *VM) error {
|
||||||
iop1 := v.Estack().Pop().Interop()
|
iop1 := v.Estack().Pop().Interop()
|
||||||
iter1 := iop1.Value().(iterator)
|
iter1 := iop1.Value().(iterator)
|
||||||
|
@ -214,7 +210,7 @@ func IteratorConcat(v *VM) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IteratorKey handles syscall Neo.Iterator.Key.
|
// IteratorKey handles syscall System.Iterator.Key.
|
||||||
func IteratorKey(v *VM) error {
|
func IteratorKey(v *VM) error {
|
||||||
iop := v.estack.Pop().Interop()
|
iop := v.estack.Pop().Interop()
|
||||||
iter := iop.Value().(iterator)
|
iter := iop.Value().(iterator)
|
||||||
|
@ -223,7 +219,7 @@ func IteratorKey(v *VM) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IteratorKeys handles syscall Neo.Iterator.Keys.
|
// IteratorKeys handles syscall System.Iterator.Keys.
|
||||||
func IteratorKeys(v *VM) error {
|
func IteratorKeys(v *VM) error {
|
||||||
iop := v.estack.Pop().Interop()
|
iop := v.estack.Pop().Interop()
|
||||||
iter := iop.Value().(iterator)
|
iter := iop.Value().(iterator)
|
||||||
|
@ -234,7 +230,7 @@ func IteratorKeys(v *VM) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IteratorValues handles syscall Neo.Iterator.Values.
|
// IteratorValues handles syscall System.Iterator.Values.
|
||||||
func IteratorValues(v *VM) error {
|
func IteratorValues(v *VM) error {
|
||||||
iop := v.estack.Pop().Interop()
|
iop := v.estack.Pop().Interop()
|
||||||
iter := iop.Value().(iterator)
|
iter := iop.Value().(iterator)
|
||||||
|
|
|
@ -488,16 +488,16 @@ func getEnumeratorProg(n int, isIter bool) (prog []byte) {
|
||||||
prog = []byte{byte(opcode.INITSSLOT), 1, byte(opcode.STSFLD0)}
|
prog = []byte{byte(opcode.INITSSLOT), 1, byte(opcode.STSFLD0)}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
prog = append(prog, byte(opcode.LDSFLD0))
|
prog = append(prog, byte(opcode.LDSFLD0))
|
||||||
prog = append(prog, getSyscallProg("Neo.Enumerator.Next")...)
|
prog = append(prog, getSyscallProg("System.Enumerator.Next")...)
|
||||||
prog = append(prog, byte(opcode.LDSFLD0))
|
prog = append(prog, byte(opcode.LDSFLD0))
|
||||||
prog = append(prog, getSyscallProg("Neo.Enumerator.Value")...)
|
prog = append(prog, getSyscallProg("System.Enumerator.Value")...)
|
||||||
if isIter {
|
if isIter {
|
||||||
prog = append(prog, byte(opcode.LDSFLD0))
|
prog = append(prog, byte(opcode.LDSFLD0))
|
||||||
prog = append(prog, getSyscallProg("Neo.Iterator.Key")...)
|
prog = append(prog, getSyscallProg("System.Iterator.Key")...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prog = append(prog, byte(opcode.LDSFLD0))
|
prog = append(prog, byte(opcode.LDSFLD0))
|
||||||
prog = append(prog, getSyscallProg("Neo.Enumerator.Next")...)
|
prog = append(prog, getSyscallProg("System.Enumerator.Next")...)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -512,7 +512,7 @@ func checkEnumeratorStack(t *testing.T, vm *VM, arr []stackitem.Item) {
|
||||||
|
|
||||||
func testIterableCreate(t *testing.T, typ string) {
|
func testIterableCreate(t *testing.T, typ string) {
|
||||||
isIter := typ == "Iterator"
|
isIter := typ == "Iterator"
|
||||||
prog := getSyscallProg("Neo." + typ + ".Create")
|
prog := getSyscallProg("System." + typ + ".Create")
|
||||||
prog = append(prog, getEnumeratorProg(2, isIter)...)
|
prog = append(prog, getEnumeratorProg(2, isIter)...)
|
||||||
|
|
||||||
vm := load(prog)
|
vm := load(prog)
|
||||||
|
@ -546,10 +546,10 @@ func TestIteratorCreate(t *testing.T) {
|
||||||
|
|
||||||
func testIterableConcat(t *testing.T, typ string) {
|
func testIterableConcat(t *testing.T, typ string) {
|
||||||
isIter := typ == "Iterator"
|
isIter := typ == "Iterator"
|
||||||
prog := getSyscallProg("Neo." + typ + ".Create")
|
prog := getSyscallProg("System." + typ + ".Create")
|
||||||
prog = append(prog, byte(opcode.SWAP))
|
prog = append(prog, byte(opcode.SWAP))
|
||||||
prog = append(prog, getSyscallProg("Neo."+typ+".Create")...)
|
prog = append(prog, getSyscallProg("System."+typ+".Create")...)
|
||||||
prog = append(prog, getSyscallProg("Neo."+typ+".Concat")...)
|
prog = append(prog, getSyscallProg("System."+typ+".Concat")...)
|
||||||
prog = append(prog, getEnumeratorProg(3, isIter)...)
|
prog = append(prog, getEnumeratorProg(3, isIter)...)
|
||||||
vm := load(prog)
|
vm := load(prog)
|
||||||
|
|
||||||
|
@ -589,8 +589,8 @@ func TestIteratorConcat(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIteratorKeys(t *testing.T) {
|
func TestIteratorKeys(t *testing.T) {
|
||||||
prog := getSyscallProg("Neo.Iterator.Create")
|
prog := getSyscallProg("System.Iterator.Create")
|
||||||
prog = append(prog, getSyscallProg("Neo.Iterator.Keys")...)
|
prog = append(prog, getSyscallProg("System.Iterator.Keys")...)
|
||||||
prog = append(prog, getEnumeratorProg(2, false)...)
|
prog = append(prog, getEnumeratorProg(2, false)...)
|
||||||
|
|
||||||
v := load(prog)
|
v := load(prog)
|
||||||
|
@ -609,8 +609,8 @@ func TestIteratorKeys(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIteratorValues(t *testing.T) {
|
func TestIteratorValues(t *testing.T) {
|
||||||
prog := getSyscallProg("Neo.Iterator.Create")
|
prog := getSyscallProg("System.Iterator.Create")
|
||||||
prog = append(prog, getSyscallProg("Neo.Iterator.Values")...)
|
prog = append(prog, getSyscallProg("System.Iterator.Values")...)
|
||||||
prog = append(prog, getEnumeratorProg(2, false)...)
|
prog = append(prog, getEnumeratorProg(2, false)...)
|
||||||
|
|
||||||
v := load(prog)
|
v := load(prog)
|
||||||
|
@ -643,8 +643,8 @@ func getSyscallProg(name string) (prog []byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSerializeProg() (prog []byte) {
|
func getSerializeProg() (prog []byte) {
|
||||||
prog = append(prog, getSyscallProg("Neo.Runtime.Serialize")...)
|
prog = append(prog, getSyscallProg("System.Runtime.Serialize")...)
|
||||||
prog = append(prog, getSyscallProg("Neo.Runtime.Deserialize")...)
|
prog = append(prog, getSyscallProg("System.Runtime.Deserialize")...)
|
||||||
prog = append(prog, byte(opcode.RET))
|
prog = append(prog, byte(opcode.RET))
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -749,7 +749,7 @@ func TestSerializeStruct(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeserializeUnknown(t *testing.T) {
|
func TestDeserializeUnknown(t *testing.T) {
|
||||||
prog := append(getSyscallProg("Neo.Runtime.Deserialize"), byte(opcode.RET))
|
prog := append(getSyscallProg("System.Runtime.Deserialize"), byte(opcode.RET))
|
||||||
|
|
||||||
data, err := stackitem.SerializeItem(stackitem.NewBigInteger(big.NewInt(123)))
|
data, err := stackitem.SerializeItem(stackitem.NewBigInteger(big.NewInt(123)))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -785,7 +785,7 @@ func TestSerializeMapCompat(t *testing.T) {
|
||||||
emit.Bytes(buf.BinWriter, []byte("key"))
|
emit.Bytes(buf.BinWriter, []byte("key"))
|
||||||
emit.Bytes(buf.BinWriter, []byte("value"))
|
emit.Bytes(buf.BinWriter, []byte("value"))
|
||||||
emit.Opcode(buf.BinWriter, opcode.SETITEM)
|
emit.Opcode(buf.BinWriter, opcode.SETITEM)
|
||||||
emit.Syscall(buf.BinWriter, "Neo.Runtime.Serialize")
|
emit.Syscall(buf.BinWriter, "System.Runtime.Serialize")
|
||||||
require.NoError(t, buf.Err)
|
require.NoError(t, buf.Err)
|
||||||
|
|
||||||
vm := load(buf.Bytes())
|
vm := load(buf.Bytes())
|
||||||
|
|
Loading…
Reference in a new issue