compiler: refactor syscall handling

Close #941.
This commit is contained in:
Evgeniy Stratonikov 2021-02-05 19:02:09 +03:00
parent f7b9861c11
commit df5314f286
12 changed files with 157 additions and 128 deletions

View file

@ -277,8 +277,7 @@ func isSyscall(fun *funcScope) bool {
if fun.selector == nil || fun.pkg == nil || !isInteropPath(fun.pkg.Path()) { if fun.selector == nil || fun.pkg == nil || !isInteropPath(fun.pkg.Path()) {
return false return false
} }
_, ok := syscalls[fun.pkg.Name()][fun.name] return fun.pkg.Name() == "neogointernal" && strings.HasPrefix(fun.name, "Syscall")
return ok
} }
const interopPrefix = "github.com/nspcc-dev/neo-go/pkg/interop" const interopPrefix = "github.com/nspcc-dev/neo-go/pkg/interop"
@ -309,6 +308,13 @@ func canConvert(s string) bool {
// Currently there is a static list of function which are inlined, // Currently there is a static list of function which are inlined,
// this may change in future. // this may change in future.
func canInline(s string) bool { func canInline(s string) bool {
return isNativeHelpersPath(s) || if strings.HasPrefix(s, "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/inline") {
strings.HasPrefix(s, "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/inline") return true
}
if !isInteropPath(s) {
return false
}
return !strings.HasPrefix(s[len(interopPrefix):], "/neogointernal") &&
!strings.HasPrefix(s[len(interopPrefix):], "/util") &&
!strings.HasPrefix(s[len(interopPrefix):], "/convert")
} }

View file

@ -872,7 +872,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
c.saveSequencePoint(n) c.saveSequencePoint(n)
args := transformArgs(n.Fun, n.Args) args := transformArgs(f, n.Fun, n.Args)
// Handle the arguments // Handle the arguments
for _, arg := range args { for _, arg := range args {
@ -888,7 +888,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
} }
} }
// Do not swap for builtin functions. // Do not swap for builtin functions.
if !isBuiltin { if !isBuiltin && (f != nil && !isSyscall(f)) {
typ, ok := c.typeOf(n.Fun).(*types.Signature) typ, ok := c.typeOf(n.Fun).(*types.Signature)
if ok && typ.Variadic() && !n.Ellipsis.IsValid() { if ok && typ.Variadic() && !n.Ellipsis.IsValid() {
// pack variadic args into an array only if last argument is not of form `...` // pack variadic args into an array only if last argument is not of form `...`
@ -932,7 +932,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
c.emittedEvents[name] = append(c.emittedEvents[name], params) c.emittedEvents[name] = append(c.emittedEvents[name], params)
} }
} }
c.convertSyscall(n, f.pkg.Name(), f.name) c.convertSyscall(n)
default: default:
emit.Call(c.prog.BinWriter, opcode.CALLL, f.label) emit.Call(c.prog.BinWriter, opcode.CALLL, f.label)
} }
@ -1523,12 +1523,13 @@ func (c *codegen) getByteArray(expr ast.Expr) []byte {
} }
} }
func (c *codegen) convertSyscall(expr *ast.CallExpr, api, name string) { func (c *codegen) convertSyscall(expr *ast.CallExpr) {
syscall, ok := syscalls[api][name] for _, arg := range expr.Args[1:] {
if !ok { ast.Walk(c, arg)
c.prog.Err = fmt.Errorf("unknown VM syscall api: %s.%s", api, name)
return
} }
c.emitReverse(len(expr.Args) - 1)
tv := c.typeAndValueOf(expr.Args[0])
syscall := constant.StringVal(tv.Value)
emit.Syscall(c.prog.BinWriter, syscall) emit.Syscall(c.prog.BinWriter, syscall)
// This NOP instruction is basically not needed, but if we do, we have a // This NOP instruction is basically not needed, but if we do, we have a
@ -1714,12 +1715,15 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
// so there is no need to push parameters on stack and perform an actual call // so there is no need to push parameters on stack and perform an actual call
// 2. With panic, generated code depends on if argument was nil or a string so // 2. With panic, generated code depends on if argument was nil or a string so
// it should be handled accordingly. // it should be handled accordingly.
func transformArgs(fun ast.Expr, args []ast.Expr) []ast.Expr { func transformArgs(fs *funcScope, fun ast.Expr, args []ast.Expr) []ast.Expr {
switch f := fun.(type) { switch f := fun.(type) {
case *ast.SelectorExpr: case *ast.SelectorExpr:
if f.Sel.Name == "FromAddress" { if f.Sel.Name == "FromAddress" {
return args[1:] return args[1:]
} }
if fs != nil && isSyscall(fs) {
return nil
}
case *ast.Ident: case *ast.Ident:
switch f.Name { switch f.Name {
case "make", "copy", "append": case "make", "copy", "append":

View file

@ -1,66 +0,0 @@
package compiler
import "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
// All lists are sorted, keep 'em this way, please.
var syscalls = map[string]map[string]string{
"binary": {
"Atoi": interopnames.SystemBinaryAtoi,
"Base58Decode": interopnames.SystemBinaryBase58Decode,
"Base58Encode": interopnames.SystemBinaryBase58Encode,
"Base64Decode": interopnames.SystemBinaryBase64Decode,
"Base64Encode": interopnames.SystemBinaryBase64Encode,
"Deserialize": interopnames.SystemBinaryDeserialize,
"Itoa": interopnames.SystemBinaryItoa,
"Serialize": interopnames.SystemBinarySerialize,
},
"contract": {
"Call": interopnames.SystemContractCall,
"CreateMultisigAccount": interopnames.SystemContractCreateMultisigAccount,
"CreateStandardAccount": interopnames.SystemContractCreateStandardAccount,
"IsStandard": interopnames.SystemContractIsStandard,
"GetCallFlags": interopnames.SystemContractGetCallFlags,
},
"crypto": {
"ECDsaSecp256k1Verify": interopnames.NeoCryptoVerifyWithECDsaSecp256k1,
"ECDSASecp256k1CheckMultisig": interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1,
"ECDsaSecp256r1Verify": interopnames.NeoCryptoVerifyWithECDsaSecp256r1,
"ECDSASecp256r1CheckMultisig": interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1,
"RIPEMD160": interopnames.NeoCryptoRIPEMD160,
"SHA256": interopnames.NeoCryptoSHA256,
},
"iterator": {
"Create": interopnames.SystemIteratorCreate,
"Next": interopnames.SystemIteratorNext,
"Value": interopnames.SystemIteratorValue,
},
"json": {
"Deserialize": interopnames.SystemJSONDeserialize,
"Serialize": interopnames.SystemJSONSerialize,
},
"runtime": {
"GasLeft": interopnames.SystemRuntimeGasLeft,
"GetInvocationCounter": interopnames.SystemRuntimeGetInvocationCounter,
"GetCallingScriptHash": interopnames.SystemRuntimeGetCallingScriptHash,
"GetEntryScriptHash": interopnames.SystemRuntimeGetEntryScriptHash,
"GetExecutingScriptHash": interopnames.SystemRuntimeGetExecutingScriptHash,
"GetNotifications": interopnames.SystemRuntimeGetNotifications,
"GetScriptContainer": interopnames.SystemRuntimeGetScriptContainer,
"GetTime": interopnames.SystemRuntimeGetTime,
"GetTrigger": interopnames.SystemRuntimeGetTrigger,
"CheckWitness": interopnames.SystemRuntimeCheckWitness,
"Log": interopnames.SystemRuntimeLog,
"Notify": interopnames.SystemRuntimeNotify,
"Platform": interopnames.SystemRuntimePlatform,
},
"storage": {
"ConvertContextToReadOnly": interopnames.SystemStorageAsReadOnly,
"Delete": interopnames.SystemStorageDelete,
"Find": interopnames.SystemStorageFind,
"Get": interopnames.SystemStorageGet,
"GetContext": interopnames.SystemStorageGetContext,
"GetReadOnlyContext": interopnames.SystemStorageGetReadOnlyContext,
"Put": interopnames.SystemStoragePut,
"PutEx": interopnames.SystemStoragePutEx,
},
}

View file

@ -3,52 +3,56 @@ Package binary provides binary serialization routines.
*/ */
package binary package binary
import (
"github.com/nspcc-dev/neo-go/pkg/interop/neogointernal"
)
// 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 `System.Binary.Serialize` syscall. // the external event receiver. It uses `System.Binary.Serialize` syscall.
func Serialize(item interface{}) []byte { func Serialize(item interface{}) []byte {
return nil return neogointernal.Syscall1("System.Binary.Serialize", item).([]byte)
} }
// 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 `System.Binary.Deserialize` syscall. // opposite of Serialize. It uses `System.Binary.Deserialize` syscall.
func Deserialize(b []byte) interface{} { func Deserialize(b []byte) interface{} {
return nil return neogointernal.Syscall1("System.Binary.Deserialize", b)
} }
// Base64Encode encodes given byte slice into a base64 string and returns byte // Base64Encode encodes given byte slice into a base64 string and returns byte
// representation of this string. It uses `System.Binary.Base64Encode` interop. // representation of this string. It uses `System.Binary.Base64Encode` interop.
func Base64Encode(b []byte) string { func Base64Encode(b []byte) string {
return "" return neogointernal.Syscall1("System.Binary.Base64Encode", b).(string)
} }
// Base64Decode decodes given base64 string represented as a byte slice into // Base64Decode decodes given base64 string represented as a byte slice into
// byte slice. It uses `System.Binary.Base64Decode` interop. // byte slice. It uses `System.Binary.Base64Decode` interop.
func Base64Decode(b []byte) []byte { func Base64Decode(b []byte) []byte {
return nil return neogointernal.Syscall1("System.Binary.Base64Decode", b).([]byte)
} }
// Base58Encode encodes given byte slice into a base58 string and returns byte // Base58Encode encodes given byte slice into a base58 string and returns byte
// representation of this string. It uses `System.Binary.Base58Encode` syscall. // representation of this string. It uses `System.Binary.Base58Encode` syscall.
func Base58Encode(b []byte) string { func Base58Encode(b []byte) string {
return "" return neogointernal.Syscall1("System.Binary.Base58Encode", b).(string)
} }
// Base58Decode decodes given base58 string represented as a byte slice into // Base58Decode decodes given base58 string represented as a byte slice into
// a new byte slice. It uses `System.Binary.Base58Decode` syscall. // a new byte slice. It uses `System.Binary.Base58Decode` syscall.
func Base58Decode(b []byte) []byte { func Base58Decode(b []byte) []byte {
return nil return neogointernal.Syscall1("System.Binary.Base64Decode", b).([]byte)
} }
// Itoa converts num in a given base to string. Base should be either 10 or 16. // Itoa converts num in a given base to string. Base should be either 10 or 16.
// It uses `System.Binary.Itoa` syscall. // It uses `System.Binary.Itoa` syscall.
func Itoa(num int, base int) string { func Itoa(num int, base int) string {
return "" return neogointernal.Syscall2("System.Binary.Itoa", num, base).(string)
} }
// Atoi converts string to a number in a given base. Base should be either 10 or 16. // Atoi converts string to a number in a given base. Base should be either 10 or 16.
// It uses `System.Binary.Atoi` syscall. // It uses `System.Binary.Atoi` syscall.
func Atoi(s string, base int) int { func Atoi(s string, base int) int {
return 0 return neogointernal.Syscall2("System.Binary.Atoi", s, base).(int)
} }

View file

@ -3,7 +3,10 @@ Package contract provides functions to work with contracts.
*/ */
package contract package contract
import "github.com/nspcc-dev/neo-go/pkg/interop" import (
"github.com/nspcc-dev/neo-go/pkg/interop"
"github.com/nspcc-dev/neo-go/pkg/interop/neogointernal"
)
// CallFlag specifies valid call flags. // CallFlag specifies valid call flags.
type CallFlag byte type CallFlag byte
@ -24,26 +27,26 @@ const (
// IsStandard checks if contract with provided hash is a standard signature/multisig contract. // IsStandard checks if contract with provided hash is a standard signature/multisig contract.
// This function uses `System.Contract.IsStandard` syscall. // This function uses `System.Contract.IsStandard` syscall.
func IsStandard(h interop.Hash160) bool { func IsStandard(h interop.Hash160) bool {
return false return neogointernal.Syscall1("System.Contract.IsStandard", h).(bool)
} }
// CreateMultisigAccount calculates script hash of an m out of n multisignature // CreateMultisigAccount calculates script hash of an m out of n multisignature
// script using given m and a set of public keys bytes. This function uses // script using given m and a set of public keys bytes. This function uses
// `System.Contract.CreateMultisigAccount` syscall. // `System.Contract.CreateMultisigAccount` syscall.
func CreateMultisigAccount(m int, pubs []interop.PublicKey) []byte { func CreateMultisigAccount(m int, pubs []interop.PublicKey) []byte {
return nil return neogointernal.Syscall1("System.Contract.CreateMultisigAccount", pubs).([]byte)
} }
// CreateStandardAccount calculates script hash of a given public key. // CreateStandardAccount calculates script hash of a given public key.
// This function uses `System.Contract.CreateStandardAccount` syscall. // This function uses `System.Contract.CreateStandardAccount` syscall.
func CreateStandardAccount(pub interop.PublicKey) []byte { func CreateStandardAccount(pub interop.PublicKey) []byte {
return nil return neogointernal.Syscall1("System.Contract.CreateStandardAccount", pub).([]byte)
} }
// GetCallFlags returns calling flags which execution context was created with. // GetCallFlags returns calling flags which execution context was created with.
// This function uses `System.Contract.GetCallFlags` syscall. // This function uses `System.Contract.GetCallFlags` syscall.
func GetCallFlags() int64 { func GetCallFlags() int64 {
return 0 return neogointernal.Syscall0("System.Contract.GetFlags").(int64)
} }
// Call executes previously deployed blockchain contract with specified hash // Call executes previously deployed blockchain contract with specified hash
@ -51,5 +54,5 @@ func GetCallFlags() int64 {
// It returns whatever this contract returns. This function uses // It returns whatever this contract returns. This function uses
// `System.Contract.Call` syscall. // `System.Contract.Call` syscall.
func Call(scriptHash interop.Hash160, method string, f CallFlag, args ...interface{}) interface{} { func Call(scriptHash interop.Hash160, method string, f CallFlag, args ...interface{}) interface{} {
return nil return neogointernal.Syscall4("System.Contract.Call", scriptHash, method, f, args)
} }

View file

@ -3,38 +3,41 @@ Package crypto provides an interface to cryptographic syscalls.
*/ */
package crypto package crypto
import "github.com/nspcc-dev/neo-go/pkg/interop" import (
"github.com/nspcc-dev/neo-go/pkg/interop"
"github.com/nspcc-dev/neo-go/pkg/interop/neogointernal"
)
// SHA256 computes SHA256 hash of b. It uses `Neo.Crypto.SHA256` syscall. // SHA256 computes SHA256 hash of b. It uses `Neo.Crypto.SHA256` syscall.
func SHA256(b []byte) interop.Hash256 { func SHA256(b []byte) interop.Hash256 {
return nil return neogointernal.Syscall1("Neo.Crypto.SHA256", b).(interop.Hash256)
} }
// RIPEMD160 computes RIPEMD160 hash of b. It uses `Neo.Crypto.RIPEMD160` syscall. // RIPEMD160 computes RIPEMD160 hash of b. It uses `Neo.Crypto.RIPEMD160` syscall.
func RIPEMD160(b []byte) interop.Hash160 { func RIPEMD160(b []byte) interop.Hash160 {
return nil return neogointernal.Syscall1("Neo.Crypto.RIPEMD160", b).(interop.Hash160)
} }
// ECDsaSecp256r1Verify checks that sig is correct msg's signature for a given pub // ECDsaSecp256r1Verify checks that sig is correct msg's signature for a given pub
// (serialized public key). It uses `Neo.Crypto.VerifyWithECDsaSecp256r1` syscall. // (serialized public key). It uses `Neo.Crypto.VerifyWithECDsaSecp256r1` syscall.
func ECDsaSecp256r1Verify(msg []byte, pub interop.PublicKey, sig interop.Signature) bool { func ECDsaSecp256r1Verify(msg []byte, pub interop.PublicKey, sig interop.Signature) bool {
return false return neogointernal.Syscall3("Neo.Crypto.VerifyWithECDsaSecp256r1", msg, pub, sig).(bool)
} }
// ECDsaSecp256k1Verify checks that sig is correct msg's signature for a given pub // ECDsaSecp256k1Verify checks that sig is correct msg's signature for a given pub
// (serialized public key). It uses `Neo.Crypto.VerifyWithECDsaSecp256k1` syscall. // (serialized public key). It uses `Neo.Crypto.VerifyWithECDsaSecp256k1` syscall.
func ECDsaSecp256k1Verify(msg []byte, pub interop.PublicKey, sig interop.Signature) bool { func ECDsaSecp256k1Verify(msg []byte, pub interop.PublicKey, sig interop.Signature) bool {
return false return neogointernal.Syscall3("Neo.Crypto.VerifyWithECDsaSecp256k1", msg, pub, sig).(bool)
} }
// ECDSASecp256r1CheckMultisig checks multiple ECDSA signatures at once. It uses // ECDSASecp256r1CheckMultisig checks multiple ECDSA signatures at once. It uses
// `Neo.Crypto.CheckMultisigWithECDsaSecp256r1` syscall. // `Neo.Crypto.CheckMultisigWithECDsaSecp256r1` syscall.
func ECDSASecp256r1CheckMultisig(msg []byte, pubs []interop.PublicKey, sigs []interop.Signature) bool { func ECDSASecp256r1CheckMultisig(msg []byte, pubs []interop.PublicKey, sigs []interop.Signature) bool {
return false return neogointernal.Syscall3("Neo.Crypto.CheckMultisigWithECDsaSecp256r1", msg, pubs, sigs).(bool)
} }
// ECDSASecp256k1CheckMultisig checks multiple ECDSA signatures at once. It uses // ECDSASecp256k1CheckMultisig checks multiple ECDSA signatures at once. It uses
// `Neo.Crypto.CheckMultisigWithECDsaSecp256k1` syscall. // `Neo.Crypto.CheckMultisigWithECDsaSecp256k1` syscall.
func ECDSASecp256k1CheckMultisig(msg []byte, pubs []interop.PublicKey, sigs []interop.Signature) bool { func ECDSASecp256k1CheckMultisig(msg []byte, pubs []interop.PublicKey, sigs []interop.Signature) bool {
return false return neogointernal.Syscall3("Neo.Crypto.CheckMultisigWithECDsaSecp256k1", msg, pubs, sigs).(bool)
} }

View file

@ -3,6 +3,8 @@ Package iterator provides functions to work with Neo iterators.
*/ */
package iterator package iterator
import "github.com/nspcc-dev/neo-go/pkg/interop/neogointernal"
// Iterator represents a Neo iterator, it's an opaque data structure that can // Iterator represents a Neo iterator, it's an opaque data structure that can
// be properly created by Create or storage.Find. Unlike enumerators, iterators // be properly created by Create or storage.Find. Unlike enumerators, iterators
// range over key-value pairs, so it's convenient to use them for maps. This // range over key-value pairs, so it's convenient to use them for maps. This
@ -14,14 +16,14 @@ type Iterator struct{}
// to point at element -1, so to access its first element you need to call Next // to point at element -1, so to access its first element you need to call Next
// first. This function uses `System.Iterator.Create` syscall. // first. This function uses `System.Iterator.Create` syscall.
func Create(items interface{}) Iterator { func Create(items interface{}) Iterator {
return Iterator{} return neogointernal.Syscall1("System.Iterator.Create", items).(Iterator)
} }
// 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 `System.Iterator.Next` syscall. // this Iterator). This function uses `System.Iterator.Next` syscall.
func Next(it Iterator) bool { func Next(it Iterator) bool {
return true return neogointernal.Syscall1("System.Iterator.Next", it).(bool)
} }
// 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
@ -30,5 +32,5 @@ func Next(it Iterator) bool {
// For maps the result can be casted to a slice of 2 elements: key and value. // For maps the result can be casted to a slice of 2 elements: key and value.
// For storage iterators refer to `storage.FindFlags` documentation. // For storage iterators refer to `storage.FindFlags` documentation.
func Value(it Iterator) interface{} { func Value(it Iterator) interface{} {
return nil return neogointernal.Syscall1("System.Iterator.Value", it)
} }

View file

@ -3,6 +3,8 @@ Package json provides various JSON serialization/deserialization routines.
*/ */
package json package json
import "github.com/nspcc-dev/neo-go/pkg/interop/neogointernal"
// ToJSON serializes value to json. It uses `System.Json.Serialize` syscall. // ToJSON serializes value to json. It uses `System.Json.Serialize` syscall.
// Serialization format is the following: // Serialization format is the following:
// []byte -> base64 string // []byte -> base64 string
@ -13,7 +15,7 @@ package json
// []interface{} -> json array // []interface{} -> json array
// map[type1]type2 -> json object with string keys marshaled as strings (not base64). // map[type1]type2 -> json object with string keys marshaled as strings (not base64).
func ToJSON(item interface{}) []byte { func ToJSON(item interface{}) []byte {
return nil return neogointernal.Syscall1("System.Json.Serialize", item).([]byte)
} }
// FromJSON deserializes value from json. It uses `System.Json.Deserialize` syscall. // FromJSON deserializes value from json. It uses `System.Json.Deserialize` syscall.
@ -24,5 +26,5 @@ func ToJSON(item interface{}) []byte {
// arrays -> []interface{} // arrays -> []interface{}
// maps -> map[string]interface{} // maps -> map[string]interface{}
func FromJSON(data []byte) interface{} { func FromJSON(data []byte) interface{} {
return nil return neogointernal.Syscall1("System.Json.Deserialize", data).(interface{})
} }

View file

@ -0,0 +1,46 @@
package neogointernal
// Syscall0 performs syscall with 0 arguments.
func Syscall0(name string) interface{} {
return nil
}
// Syscall0NoReturn performs syscall with 0 arguments.
func Syscall0NoReturn(name string) {
}
// Syscall1 performs syscall with 1 arguments.
func Syscall1(name string, arg interface{}) interface{} {
return nil
}
// Syscall1NoReturn performs syscall with 1 arguments.
func Syscall1NoReturn(name string, arg interface{}) {
}
// Syscall2 performs syscall with 2 arguments.
func Syscall2(name string, arg1, arg2 interface{}) interface{} {
return nil
}
// Syscall2NoReturn performs syscall with 2 arguments.
func Syscall2NoReturn(name string, arg1, arg2 interface{}) {
}
// Syscall3 performs syscall with 3 arguments.
func Syscall3(name string, arg1, arg2, arg3 interface{}) interface{} {
return nil
}
// Syscall3NoReturn performs syscall with 3 arguments.
func Syscall3NoReturn(name string, arg1, arg2, arg3 interface{}) {
}
// Syscall4 performs syscall with 4 arguments.
func Syscall4(name string, arg1, arg2, arg3, arg4 interface{}) interface{} {
return nil
}
// Syscall4NoReturn performs syscall with 4 arguments.
func Syscall4NoReturn(name string, arg1, arg2, arg3, arg4 interface{}) {
}

View file

@ -3,6 +3,7 @@ package runtime
import ( import (
"github.com/nspcc-dev/neo-go/pkg/interop" "github.com/nspcc-dev/neo-go/pkg/interop"
"github.com/nspcc-dev/neo-go/pkg/interop/native/ledger" "github.com/nspcc-dev/neo-go/pkg/interop/native/ledger"
"github.com/nspcc-dev/neo-go/pkg/interop/neogointernal"
) )
// GetScriptContainer returns the transaction that initially triggered current // GetScriptContainer returns the transaction that initially triggered current
@ -10,7 +11,7 @@ import (
// this execution goes. This function uses // this execution goes. This function uses
// `System.Runtime.GetScriptContainer` syscall. // `System.Runtime.GetScriptContainer` syscall.
func GetScriptContainer() *ledger.Transaction { func GetScriptContainer() *ledger.Transaction {
return &ledger.Transaction{} return neogointernal.Syscall0("System.Runtime.GetScriptContainer").(*ledger.Transaction)
} }
// GetExecutingScriptHash returns script hash (160 bit in BE form represented // GetExecutingScriptHash returns script hash (160 bit in BE form represented
@ -19,7 +20,7 @@ func GetScriptContainer() *ledger.Transaction {
// different contract. This function uses // different contract. This function uses
// `System.Runtime.GetExecutingScriptHash` syscall. // `System.Runtime.GetExecutingScriptHash` syscall.
func GetExecutingScriptHash() interop.Hash160 { func GetExecutingScriptHash() interop.Hash160 {
return nil return neogointernal.Syscall0("System.Runtime.GetExecutingScriptHash").(interop.Hash160)
} }
// GetCallingScriptHash returns script hash (160 bit in BE form represented // GetCallingScriptHash returns script hash (160 bit in BE form represented
@ -28,7 +29,7 @@ func GetExecutingScriptHash() interop.Hash160 {
// above the GetExecutingScriptHash in the call stack. It uses // above the GetExecutingScriptHash in the call stack. It uses
// `System.Runtime.GetCallingScriptHash` syscall. // `System.Runtime.GetCallingScriptHash` syscall.
func GetCallingScriptHash() interop.Hash160 { func GetCallingScriptHash() interop.Hash160 {
return nil return neogointernal.Syscall0("System.Runtime.GetCallingScriptHash").(interop.Hash160)
} }
// GetEntryScriptHash returns script hash (160 bit in BE form represented // GetEntryScriptHash returns script hash (160 bit in BE form represented
@ -37,5 +38,5 @@ func GetCallingScriptHash() interop.Hash160 {
// GetScriptContainer) execution from the start. This function uses // GetScriptContainer) execution from the start. This function uses
// `System.Runtime.GetEntryScriptHash` syscall. // `System.Runtime.GetEntryScriptHash` syscall.
func GetEntryScriptHash() interop.Hash160 { func GetEntryScriptHash() interop.Hash160 {
return nil return neogointernal.Syscall0("System.Runtime.GetEntryScriptHash").(interop.Hash160)
} }

View file

@ -4,7 +4,10 @@ It has similar function to Runtime class in .net framwork for Neo.
*/ */
package runtime package runtime
import "github.com/nspcc-dev/neo-go/pkg/interop" import (
"github.com/nspcc-dev/neo-go/pkg/interop"
"github.com/nspcc-dev/neo-go/pkg/interop/neogointernal"
)
// Trigger values to compare with GetTrigger result. // Trigger values to compare with GetTrigger result.
const ( const (
@ -18,13 +21,15 @@ const (
// 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.
func CheckWitness(hashOrKey []byte) bool { func CheckWitness(hashOrKey []byte) bool {
return true return neogointernal.Syscall1("System.Runtime.CheckWitness", hashOrKey).(bool)
} }
// 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 `System.Runtime.Log` syscall. // only visible in the VM logs. This function uses `System.Runtime.Log` syscall.
func Log(message string) {} func Log(message string) {
neogointernal.Syscall1NoReturn("System.Runtime.Log", message)
}
// Notify sends a notification (collecting all arguments in an array) to the // Notify sends a notification (collecting all arguments in an array) to the
// executing environment. Unlike Log it can accept any data along with the event name // executing environment. Unlike Log it can accept any data along with the event name
@ -32,7 +37,9 @@ func Log(message string) {}
// 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
// `System.Runtime.Notify` syscall. // `System.Runtime.Notify` syscall.
func Notify(name string, arg ...interface{}) {} func Notify(name string, args ...interface{}) {
neogointernal.Syscall2NoReturn("System.Runtime.Notify", name, args)
}
// 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
@ -40,7 +47,7 @@ func Notify(name string, arg ...interface{}) {}
// time of this (currently being processed) block. This function uses // time of this (currently being processed) block. This function uses
// `System.Runtime.GetTime` syscall. // `System.Runtime.GetTime` syscall.
func GetTime() int { func GetTime() int {
return 0 return neogointernal.Syscall0("System.Runtime.GetTime").(int)
} }
// GetTrigger returns the smart contract invocation trigger which can be either // GetTrigger returns the smart contract invocation trigger which can be either
@ -50,13 +57,13 @@ func GetTime() int {
// not available when running with verification trigger. This function uses // not available when running with verification trigger. This function uses
// `System.Runtime.GetTrigger` syscall. // `System.Runtime.GetTrigger` syscall.
func GetTrigger() byte { func GetTrigger() byte {
return 0x00 return neogointernal.Syscall0("System.Runtime.GetTrigger").(byte)
} }
// GasLeft returns the amount of gas available for the current execution. // GasLeft returns the amount of gas available for the current execution.
// This function uses `System.Runtime.GasLeft` syscall. // This function uses `System.Runtime.GasLeft` syscall.
func GasLeft() int64 { func GasLeft() int64 {
return 0 return neogointernal.Syscall0("System.Runtime.GasLeft").(int64)
} }
// GetNotifications returns notifications emitted by contract h. // GetNotifications returns notifications emitted by contract h.
@ -64,17 +71,17 @@ func GasLeft() int64 {
// [ scripthash of notification's contract , emitted item ]. // [ scripthash of notification's contract , emitted item ].
// This function uses `System.Runtime.GetNotifications` syscall. // This function uses `System.Runtime.GetNotifications` syscall.
func GetNotifications(h interop.Hash160) [][]interface{} { func GetNotifications(h interop.Hash160) [][]interface{} {
return nil return neogointernal.Syscall1("System.Runtime.GetNotifications", h).([][]interface{})
} }
// GetInvocationCounter returns how many times current contract was invoked during current tx execution. // GetInvocationCounter returns how many times current contract was invoked during current tx execution.
// This function uses `System.Runtime.GetInvocationCounter` syscall. // This function uses `System.Runtime.GetInvocationCounter` syscall.
func GetInvocationCounter() int { func GetInvocationCounter() int {
return 0 return neogointernal.Syscall0("System.Runtime.GetInvocationCounter").(int)
} }
// Platform returns the platform name, which is set to be `NEO`. This function uses // Platform returns the platform name, which is set to be `NEO`. This function uses
// `System.Runtime.Platform` syscall. // `System.Runtime.Platform` syscall.
func Platform() []byte { func Platform() []byte {
return nil return neogointernal.Syscall0("System.Runtime.Platform").([]byte)
} }

View file

@ -6,7 +6,10 @@ contract.
*/ */
package storage package storage
import "github.com/nspcc-dev/neo-go/pkg/interop/iterator" import (
"github.com/nspcc-dev/neo-go/pkg/interop/iterator"
"github.com/nspcc-dev/neo-go/pkg/interop/neogointernal"
)
// Context represents storage context that is mandatory for Put/Get/Delete // Context represents storage context that is mandatory for Put/Get/Delete
// operations. It's an opaque type that can only be created properly by // operations. It's an opaque type that can only be created properly by
@ -39,46 +42,60 @@ const (
// 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 `System.Storage.AsReadOnly` syscall. // no-op. It uses `System.Storage.AsReadOnly` syscall.
func ConvertContextToReadOnly(ctx Context) Context { return Context{} } func ConvertContextToReadOnly(ctx Context) Context {
return neogointernal.Syscall0("System.Storage.AsReadOnly").(Context)
}
// GetContext returns current contract's (that invokes this function) storage // GetContext returns current contract's (that invokes this function) storage
// context. It uses `System.Storage.GetContext` syscall. // context. It uses `System.Storage.GetContext` syscall.
func GetContext() Context { return Context{} } func GetContext() Context {
return neogointernal.Syscall0("System.Storage.GetContext").(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
// `System.Storage.GetReadOnlyContext` syscall. // `System.Storage.GetReadOnlyContext` syscall.
func GetReadOnlyContext() Context { return Context{} } func GetReadOnlyContext() Context {
return neogointernal.Syscall0("System.Storage.GetReadOnlyContext").(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 `System.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{}) {
neogointernal.Syscall3NoReturn("System.Storage.Put", ctx, key, value)
}
// PutEx is an advanced version of Put which saves given value with given key // PutEx is an advanced version of Put which saves given value with given key
// and given ReadOnly flag in the storage using given Context. `flag` argument // and given ReadOnly flag in the storage using given Context. `flag` argument
// can either be odd for constant storage items or even for variable storage items. // can either be odd for constant storage items or even for variable storage items.
// Refer to Put function description for details on how to pass the remaining // Refer to Put function description for details on how to pass the remaining
// arguments. This function uses `System.Storage.PutEx` syscall. // arguments. This function uses `System.Storage.PutEx` syscall.
func PutEx(ctx Context, key interface{}, value interface{}, flag int64) {} func PutEx(ctx Context, key interface{}, value interface{}, flag int64) {
neogointernal.Syscall4NoReturn("System.Storage.PutEx", ctx, key, value, flag)
}
// 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. If the value is not present in // documentation on possible key and value types. If the value is not present in
// the database it returns nil. This function uses `System.Storage.Get` syscall. // the database it returns nil. This function uses `System.Storage.Get` syscall.
func Get(ctx Context, key interface{}) interface{} { return nil } func Get(ctx Context, key interface{}) interface{} {
return neogointernal.Syscall2("System.Storage.Get", ctx, key)
}
// 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
// `System.Storage.Delete` syscall. // `System.Storage.Delete` syscall.
func Delete(ctx Context, key interface{}) {} func Delete(ctx Context, key interface{}) {
neogointernal.Syscall2NoReturn("System.Storage.Delete", ctx, key)
}
// 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 `System.Storage.Find` syscall. // returned value. This function uses `System.Storage.Find` syscall.
func Find(ctx Context, key interface{}, options FindFlags) iterator.Iterator { func Find(ctx Context, key interface{}, options FindFlags) iterator.Iterator {
return iterator.Iterator{} return neogointernal.Syscall3("System.Storage.Find", ctx, key, options).(iterator.Iterator)
} }