diff --git a/pkg/compiler/analysis.go b/pkg/compiler/analysis.go index d6553bfe4..1ffd979c7 100644 --- a/pkg/compiler/analysis.go +++ b/pkg/compiler/analysis.go @@ -277,8 +277,7 @@ func isSyscall(fun *funcScope) bool { if fun.selector == nil || fun.pkg == nil || !isInteropPath(fun.pkg.Path()) { return false } - _, ok := syscalls[fun.pkg.Name()][fun.name] - return ok + return fun.pkg.Name() == "neogointernal" && strings.HasPrefix(fun.name, "Syscall") } 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, // this may change in future. func canInline(s string) bool { - return isNativeHelpersPath(s) || - strings.HasPrefix(s, "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/inline") + if 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") } diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 0d4f59a17..85b0b16f4 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -872,7 +872,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { c.saveSequencePoint(n) - args := transformArgs(n.Fun, n.Args) + args := transformArgs(f, n.Fun, n.Args) // Handle the arguments for _, arg := range args { @@ -888,7 +888,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { } } // Do not swap for builtin functions. - if !isBuiltin { + if !isBuiltin && (f != nil && !isSyscall(f)) { typ, ok := c.typeOf(n.Fun).(*types.Signature) if ok && typ.Variadic() && !n.Ellipsis.IsValid() { // 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.convertSyscall(n, f.pkg.Name(), f.name) + c.convertSyscall(n) default: 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) { - syscall, ok := syscalls[api][name] - if !ok { - c.prog.Err = fmt.Errorf("unknown VM syscall api: %s.%s", api, name) - return +func (c *codegen) convertSyscall(expr *ast.CallExpr) { + for _, arg := range expr.Args[1:] { + ast.Walk(c, arg) } + c.emitReverse(len(expr.Args) - 1) + tv := c.typeAndValueOf(expr.Args[0]) + syscall := constant.StringVal(tv.Value) emit.Syscall(c.prog.BinWriter, syscall) // 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 // 2. With panic, generated code depends on if argument was nil or a string so // 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) { case *ast.SelectorExpr: if f.Sel.Name == "FromAddress" { return args[1:] } + if fs != nil && isSyscall(fs) { + return nil + } case *ast.Ident: switch f.Name { case "make", "copy", "append": diff --git a/pkg/compiler/func_scope.go b/pkg/compiler/func_scope.go index 3f5891b8c..eabc09c79 100644 --- a/pkg/compiler/func_scope.go +++ b/pkg/compiler/func_scope.go @@ -131,6 +131,11 @@ func (c *codegen) countLocalsInline(decl *ast.FuncDecl, pkg *types.Package, f *f return false } if inner, ok := c.funcs[name]; ok && canInline(name) { + sig, ok := c.typeOf(n.Fun).(*types.Signature) + if !ok { + info := c.buildInfo.program.Package(pkg.Path()) + sig = info.Types[n.Fun].Type.(*types.Signature) + } for i := range n.Args { switch n.Args[i].(type) { case *ast.Ident: @@ -139,6 +144,10 @@ func (c *codegen) countLocalsInline(decl *ast.FuncDecl, pkg *types.Package, f *f size++ } } + // Variadic with direct var args. + if sig.Variadic() && !n.Ellipsis.IsValid() { + size++ + } innerSz, _ := c.countLocalsInline(inner.decl, inner.pkg, inner) size += innerSz } diff --git a/pkg/compiler/syscall.go b/pkg/compiler/syscall.go deleted file mode 100644 index 24d16787d..000000000 --- a/pkg/compiler/syscall.go +++ /dev/null @@ -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, - }, -} diff --git a/pkg/interop/binary/binary.go b/pkg/interop/binary/binary.go index a53f51ac4..93e8207b6 100644 --- a/pkg/interop/binary/binary.go +++ b/pkg/interop/binary/binary.go @@ -3,52 +3,56 @@ Package binary provides binary serialization routines. */ 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 // 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 // the external event receiver. It uses `System.Binary.Serialize` syscall. 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 // opposite of Serialize. It uses `System.Binary.Deserialize` syscall. 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 // representation of this string. It uses `System.Binary.Base64Encode` interop. 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 // byte slice. It uses `System.Binary.Base64Decode` interop. 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 // representation of this string. It uses `System.Binary.Base58Encode` syscall. 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 // a new byte slice. It uses `System.Binary.Base58Decode` syscall. 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. // It uses `System.Binary.Itoa` syscall. 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. // It uses `System.Binary.Atoi` syscall. func Atoi(s string, base int) int { - return 0 + return neogointernal.Syscall2("System.Binary.Atoi", s, base).(int) } diff --git a/pkg/interop/contract/contract.go b/pkg/interop/contract/contract.go index 7d5849c41..594431d5b 100644 --- a/pkg/interop/contract/contract.go +++ b/pkg/interop/contract/contract.go @@ -3,7 +3,10 @@ Package contract provides functions to work with contracts. */ 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. type CallFlag byte @@ -24,26 +27,26 @@ const ( // IsStandard checks if contract with provided hash is a standard signature/multisig contract. // This function uses `System.Contract.IsStandard` syscall. 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 // script using given m and a set of public keys bytes. This function uses // `System.Contract.CreateMultisigAccount` syscall. 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. // This function uses `System.Contract.CreateStandardAccount` syscall. 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. // This function uses `System.Contract.GetCallFlags` syscall. func GetCallFlags() int64 { - return 0 + return neogointernal.Syscall0("System.Contract.GetFlags").(int64) } // 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 // `System.Contract.Call` syscall. func Call(scriptHash interop.Hash160, method string, f CallFlag, args ...interface{}) interface{} { - return nil + return neogointernal.Syscall4("System.Contract.Call", scriptHash, method, f, args) } diff --git a/pkg/interop/crypto/crypto.go b/pkg/interop/crypto/crypto.go index 84d1b2a99..28702d7e9 100644 --- a/pkg/interop/crypto/crypto.go +++ b/pkg/interop/crypto/crypto.go @@ -3,38 +3,41 @@ Package crypto provides an interface to cryptographic syscalls. */ 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. 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. 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 // (serialized public key). It uses `Neo.Crypto.VerifyWithECDsaSecp256r1` syscall. 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 // (serialized public key). It uses `Neo.Crypto.VerifyWithECDsaSecp256k1` syscall. 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 // `Neo.Crypto.CheckMultisigWithECDsaSecp256r1` syscall. 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 // `Neo.Crypto.CheckMultisigWithECDsaSecp256k1` syscall. func ECDSASecp256k1CheckMultisig(msg []byte, pubs []interop.PublicKey, sigs []interop.Signature) bool { - return false + return neogointernal.Syscall3("Neo.Crypto.CheckMultisigWithECDsaSecp256k1", msg, pubs, sigs).(bool) } diff --git a/pkg/interop/iterator/iterator.go b/pkg/interop/iterator/iterator.go index 396a42dba..4169bc0ca 100644 --- a/pkg/interop/iterator/iterator.go +++ b/pkg/interop/iterator/iterator.go @@ -3,6 +3,8 @@ Package iterator provides functions to work with Neo iterators. */ 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 // 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 @@ -14,14 +16,14 @@ type Iterator struct{} // to point at element -1, so to access its first element you need to call Next // first. This function uses `System.Iterator.Create` syscall. 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 // can use Key or Value) and false otherwise (and there are no more elements in // this Iterator). This function uses `System.Iterator.Next` syscall. 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 @@ -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 storage iterators refer to `storage.FindFlags` documentation. func Value(it Iterator) interface{} { - return nil + return neogointernal.Syscall1("System.Iterator.Value", it) } diff --git a/pkg/interop/json/json.go b/pkg/interop/json/json.go index ac9183ca8..05eede334 100644 --- a/pkg/interop/json/json.go +++ b/pkg/interop/json/json.go @@ -3,6 +3,8 @@ Package json provides various JSON serialization/deserialization routines. */ package json +import "github.com/nspcc-dev/neo-go/pkg/interop/neogointernal" + // ToJSON serializes value to json. It uses `System.Json.Serialize` syscall. // Serialization format is the following: // []byte -> base64 string @@ -13,7 +15,7 @@ package json // []interface{} -> json array // map[type1]type2 -> json object with string keys marshaled as strings (not base64). 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. @@ -24,5 +26,5 @@ func ToJSON(item interface{}) []byte { // arrays -> []interface{} // maps -> map[string]interface{} func FromJSON(data []byte) interface{} { - return nil + return neogointernal.Syscall1("System.Json.Deserialize", data).(interface{}) } diff --git a/pkg/interop/neogointernal/syscall.go b/pkg/interop/neogointernal/syscall.go new file mode 100644 index 000000000..f42ed2735 --- /dev/null +++ b/pkg/interop/neogointernal/syscall.go @@ -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{}) { +} diff --git a/pkg/interop/runtime/engine.go b/pkg/interop/runtime/engine.go index 9975b4e90..d99418eb7 100644 --- a/pkg/interop/runtime/engine.go +++ b/pkg/interop/runtime/engine.go @@ -3,6 +3,7 @@ package runtime import ( "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/neogointernal" ) // GetScriptContainer returns the transaction that initially triggered current @@ -10,7 +11,7 @@ import ( // this execution goes. This function uses // `System.Runtime.GetScriptContainer` syscall. 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 @@ -19,7 +20,7 @@ func GetScriptContainer() *ledger.Transaction { // different contract. This function uses // `System.Runtime.GetExecutingScriptHash` syscall. func GetExecutingScriptHash() interop.Hash160 { - return nil + return neogointernal.Syscall0("System.Runtime.GetExecutingScriptHash").(interop.Hash160) } // 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 // `System.Runtime.GetCallingScriptHash` syscall. func GetCallingScriptHash() interop.Hash160 { - return nil + return neogointernal.Syscall0("System.Runtime.GetCallingScriptHash").(interop.Hash160) } // 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 // `System.Runtime.GetEntryScriptHash` syscall. func GetEntryScriptHash() interop.Hash160 { - return nil + return neogointernal.Syscall0("System.Runtime.GetEntryScriptHash").(interop.Hash160) } diff --git a/pkg/interop/runtime/runtime.go b/pkg/interop/runtime/runtime.go index d62ef8e75..a8595317c 100644 --- a/pkg/interop/runtime/runtime.go +++ b/pkg/interop/runtime/runtime.go @@ -4,7 +4,10 @@ It has similar function to Runtime class in .net framwork for Neo. */ 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. const ( @@ -18,13 +21,15 @@ const ( // slice) or key (compressed serialized 33-byte form) is one of the signers of // this invocation. It uses `System.Runtime.CheckWitness` syscall. 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 // 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. -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 // 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 // from outside and act upon accordingly. This function uses // `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 // 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 // `System.Runtime.GetTime` syscall. func GetTime() int { - return 0 + return neogointernal.Syscall0("System.Runtime.GetTime").(int) } // 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 // `System.Runtime.GetTrigger` syscall. func GetTrigger() byte { - return 0x00 + return neogointernal.Syscall0("System.Runtime.GetTrigger").(byte) } // GasLeft returns the amount of gas available for the current execution. // This function uses `System.Runtime.GasLeft` syscall. func GasLeft() int64 { - return 0 + return neogointernal.Syscall0("System.Runtime.GasLeft").(int64) } // GetNotifications returns notifications emitted by contract h. @@ -64,17 +71,17 @@ func GasLeft() int64 { // [ scripthash of notification's contract , emitted item ]. // This function uses `System.Runtime.GetNotifications` syscall. 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. // This function uses `System.Runtime.GetInvocationCounter` syscall. 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 // `System.Runtime.Platform` syscall. func Platform() []byte { - return nil + return neogointernal.Syscall0("System.Runtime.Platform").([]byte) } diff --git a/pkg/interop/storage/storage.go b/pkg/interop/storage/storage.go index 521c9888a..87a9f899b 100644 --- a/pkg/interop/storage/storage.go +++ b/pkg/interop/storage/storage.go @@ -6,7 +6,10 @@ contract. */ 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 // 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 // using this new Context. If Context is already read-only this function is a // 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 // 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) // 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 // `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. // 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 // complex types). To put more complex types there serialize them first using // 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 // 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. // Refer to Put function description for details on how to pass the remaining // 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 // 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. -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 // Context. See Put documentation on possible key types. This function uses // `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 // 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 // returned value. This function uses `System.Storage.Find` syscall. func Find(ctx Context, key interface{}, options FindFlags) iterator.Iterator { - return iterator.Iterator{} + return neogointernal.Syscall3("System.Storage.Find", ctx, key, options).(iterator.Iterator) }