From 0b33cf3193382bc77acc2942c69fab0868becb69 Mon Sep 17 00:00:00 2001 From: Anthony De Meulemeester Date: Wed, 22 Aug 2018 09:51:35 +0200 Subject: [PATCH] new mapping for interop api (CityOfZion/neo-storm#10) * new mapping for interop api * Fixed interop API mapping + added missing apis * added engine apis Imported from CityOfZion/neo-storm (ec5e6c8e2b587704a1e071e83b633d2d3a235300). --- examples/engine/engine.go | 22 ++++++ interop/contract/contract.go | 38 +++++++++ interop/engine/engine.go | 29 +++++++ pkg/vm/compiler/analysis.go | 17 ++-- pkg/vm/compiler/codegen.go | 13 ++-- pkg/vm/compiler/func_scope.go | 4 + pkg/vm/compiler/syscall.go | 141 ++++++++++++++++++---------------- 7 files changed, 181 insertions(+), 83 deletions(-) create mode 100644 examples/engine/engine.go create mode 100644 interop/engine/engine.go diff --git a/examples/engine/engine.go b/examples/engine/engine.go new file mode 100644 index 000000000..c436dc33f --- /dev/null +++ b/examples/engine/engine.go @@ -0,0 +1,22 @@ +package engine_contract + +import ( + "github.com/CityOfZion/neo-storm/interop/engine" + "github.com/CityOfZion/neo-storm/interop/runtime" +) + +func Main() bool { + tx := engine.GetScriptContainer() + runtime.Notify(tx) + + callingScriptHash := engine.GetCallingScriptHash() + runtime.Notify(callingScriptHash) + + execScriptHash := engine.GetExecutingScriptHash() + runtime.Notify(execScriptHash) + + entryScriptHash := engine.GetEntryScriptHash() + runtime.Notify(entryScriptHash) + + return true +} diff --git a/interop/contract/contract.go b/interop/contract/contract.go index c1fffcdb4..d9f4676e6 100644 --- a/interop/contract/contract.go +++ b/interop/contract/contract.go @@ -1,5 +1,7 @@ package contract +import "github.com/CityOfZion/neo-storm/interop/storage" + // Package contract provides function signatures that can be used inside // smart contracts that are written in the neo-storm framework. @@ -15,3 +17,39 @@ func GetScript(c Contract) []byte { func IsPayable(c Contract) bool { return false } + +// GetStorageContext returns the storage context for the given contract. +func GetStorageContext(c Contract) storage.Context { + return storage.Context{} +} + +// Create creates a new contract. +// @FIXME What is the type of the returnType here? +func Create( + script []byte, + params []interface{}, + returnType byte, + properties interface{}, + name, + version, + author, + email, + description string) { +} + +// Migrate migrates a new contract. +// @FIXME What is the type of the returnType here? +func Migrate( + script []byte, + params []interface{}, + returnType byte, + properties interface{}, + name, + version, + author, + email, + description string) { +} + +// Destroy deletes a contract that is registered on the blockchain. +func Destroy(c Contract) {} diff --git a/interop/engine/engine.go b/interop/engine/engine.go new file mode 100644 index 000000000..2e2835927 --- /dev/null +++ b/interop/engine/engine.go @@ -0,0 +1,29 @@ +package engine + +import "github.com/CityOfZion/neo-storm/interop/transaction" + +// Package engine provides function signatures that can be used inside +// smart contracts that are written in the neo-storm framework. + +// GetScriptContainer returns the transaction that is in the execution context. +func GetScriptContainer() transaction.Transaction { + return transaction.Transaction{} +} + +// GetExecutingScriptHash returns the script hash of the contract that is +// currently being executed. +func GetExecutingScriptHash() []byte { + return nil +} + +// GetCallingScriptHash returns the script hash of the contract that started +// the execution of the current script. +func GetCallingScriptHash() []byte { + return nil +} + +// GetEntryScriptHash returns the script hash of the contract the started the +// execution from the start. +func GetEntryScriptHash() []byte { + return nil +} diff --git a/pkg/vm/compiler/analysis.go b/pkg/vm/compiler/analysis.go index 2c8422aa9..891aadd64 100644 --- a/pkg/vm/compiler/analysis.go +++ b/pkg/vm/compiler/analysis.go @@ -201,19 +201,12 @@ func isByteArray(lit *ast.CompositeLit, tInfo *types.Info) bool { return false } -func isSyscall(name string) bool { - _, ok := syscalls[name] - return ok -} - -// isNoRetSyscall checks if the syscall has a return value. -func isNoRetSyscall(name string) bool { - for _, s := range noRetSyscalls { - if s == name { - return true - } +func isSyscall(fun *funcScope) bool { + if fun.selector == nil { + return false } - return false + _, ok := syscalls[fun.selector.Name][fun.name] + return ok } func isStringType(t types.Type) bool { diff --git a/pkg/vm/compiler/codegen.go b/pkg/vm/compiler/codegen.go index 3756eaac3..1a0233f7a 100644 --- a/pkg/vm/compiler/codegen.go +++ b/pkg/vm/compiler/codegen.go @@ -185,7 +185,7 @@ func (c *codegen) convertFuncDecl(file ast.Node, decl *ast.FuncDecl) { } // Load in all the global variables in to the scope of the function. // This is not necessary for syscalls. - if !isSyscall(f.name) { + if !isSyscall(f) { c.convertGlobals(file) } @@ -394,7 +394,10 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { // Dont forget to add 1 extra argument when its a method. numArgs++ } + f, ok = c.funcs[fun.Sel.Name] + // @FIXME this could cause runtime errors. + f.selector = fun.X.(*ast.Ident) if !ok { log.Fatalf("could not resolve function %s", fun.Sel.Name) } @@ -433,8 +436,8 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { // Use the ident to check, builtins are not in func scopes. // We can be sure builtins are of type *ast.Ident. c.convertBuiltin(n) - case isSyscall(f.name): - c.convertSyscall(f.name) + case isSyscall(f): + c.convertSyscall(f.selector.Name, f.name) default: emitCall(c.prog, vm.CALL, int16(f.label)) } @@ -531,8 +534,8 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { return c } -func (c *codegen) convertSyscall(name string) { - api, ok := syscalls[name] +func (c *codegen) convertSyscall(api, name string) { + api, ok := syscalls[api][name] if !ok { log.Fatalf("unknown VM syscall api: %s", name) } diff --git a/pkg/vm/compiler/func_scope.go b/pkg/vm/compiler/func_scope.go index 7fdc5f843..a71fcda07 100644 --- a/pkg/vm/compiler/func_scope.go +++ b/pkg/vm/compiler/func_scope.go @@ -10,6 +10,10 @@ type funcScope struct { // identifier of the function. name string + // Selector of the function if there is any. Only functions imported + // from other packages should have a selector. + selector *ast.Ident + // The declaration of the function in the AST. Nil if this scope is not a function. decl *ast.FuncDecl diff --git a/pkg/vm/compiler/syscall.go b/pkg/vm/compiler/syscall.go index ec545a51e..0ac9d45a0 100644 --- a/pkg/vm/compiler/syscall.go +++ b/pkg/vm/compiler/syscall.go @@ -1,69 +1,78 @@ package compiler -var syscalls = map[string]string{ - // - // Standard library API - // - - // Storage API - "GetContext": "System.Storage.GetContext", - "Put": "System.Storage.Put", - "Get": "System.Storage.Get", - "Delete": "System.Storage.Delete", - "Find": "System.Storage.Find", - - // Runtime API - "GetTrigger": "System.Runtime.GetTrigger", - "CheckWitness": "System.Runtime.CheckWitness", - "Notify": "System.Runtime.Notify", - "Log": "System.Runtime.Log", - "GetTime": "System.Runtime.GetTime", - "Serialize": "System.Runtime.Serialize", - "Deserialize": "System.Runtime.Deserialize", - - // Blockchain API - "GetHeight": "System.Blockchain.GetHeight", - "GetHeader": "System.Blockchain.GetHeader", - "GetBlock": "System.Blockchain.GetBlock", - "GetTransaction": "System.Blockchain.GetTransaction", - "GetTransactionHeight": "System.Blockchain.GetTransactionHeight", - "GetContract": "System.Blockchain.GetContract", - - // Header API - "GetIndex": "System.Header.GetContract", - "GetHash": "System.Header.GetHash", - "GetPrevHash": "System.Header.GetPrevHash", - "GetTimestamp": "System.Header.GetTimestamp", - - // Block API - "GetTransactionCount": "System.Block.GetTransactionCount", - "GetTransactions": "System.Block.GetTransactions", - // TODO: Find solution for duplicated map entry - "NGetTransaction": "System.Block.GetTransaction", - - // - // NEO specific API - // - - // Blockchain API - "GetAccount": "Neo.Blockchain.GetAccount", - "GetValidators": "Neo.Blockchain.GetValidators", - "GetAsset": "Neo.Blockchain.GetAsset", - - // Header API - "GetVersion": "Neo.Header.GetVersion", - "GetMerkleRoot": "Neo.Header.GetMerkleRoot", - "GetConsensusData": "Neo.Header.GetConsensusData", - "GetNextConsensus": "Neo.Header.GetNextConsensus", - - // Transaction API - "GetType": "Neo.Transaction.GetType", - "GetAttributes": "Neo.Transaction.GetAttributes", - "GetInputs": "Neo.Transaction.GetInputs", - "GetOutputs": "Neo.Transaction.GetOutputs", - "GetReferences": "Neo.Transaction.GetReferences", - "GetUnspentCoins": "Neo.Transaction.GetUnspentCoins", - "GetScript": "Neo.InvocationTransaction.GetScript", - - // TODO: Add the rest of the interop APIS +var syscalls = map[string]map[string]string{ + "storage": { + "GetContext": "System.Storage.GetContext", + "Put": "System.Storage.Put", + "Get": "System.Storage.Get", + "Delete": "System.Storage.Delete", + "Find": "System.Storage.Find", + }, + "runtime": { + "GetTrigger": "System.Runtime.GetTrigger", + "CheckWitness": "System.Runtime.CheckWitness", + "Notify": "System.Runtime.Notify", + "Log": "System.Runtime.Log", + "GetTime": "System.Runtime.GetTime", + "Serialize": "System.Runtime.Serialize", + "Deserialize": "System.Runtime.Deserialize", + }, + "blockchain": { + "GetHeight": "System.Blockchain.GetHeight", + "GetHeader": "System.Blockchain.GetHeader", + "GetBlock": "System.Blockchain.GetBlock", + "GetTransaction": "System.Blockchain.GetTransaction", + "GetContract": "System.Blockchain.GetContract", + "GetAccount": "Neo.Blockchain.GetAccount", + "GetValidators": "Neo.Blockchain.GetValidators", + "GetAsset": "Neo.Blockchain.GetAsset", + }, + "header": { + "GetIndex": "System.Header.GetIndex", + "GetHash": "System.Header.GetHash", + "GetPrevHash": "System.Header.GetPrevHash", + "GetTimestamp": "System.Header.GetTimestamp", + "GetVersion": "Neo.Header.GetVersion", + "GetMerkleRoot": "Neo.Header.GetMerkleRoot", + "GetConsensusData": "Neo.Header.GetConsensusData", + "GetNextConsensus": "Neo.Header.GetNextConsensus", + }, + "block": { + "GetTransactionCount": "System.Block.GetTransactionCount", + "GetTransactions": "System.Block.GetTransactions", + "GetTransaction": "System.Block.GetTransaction", + }, + "transaction": { + "GetType": "Neo.Transaction.GetType", + "GetAttributes": "Neo.Transaction.GetAttributes", + "GetInputs": "Neo.Transaction.GetInputs", + "GetOutputs": "Neo.Transaction.GetOutputs", + "GetReferences": "Neo.Transaction.GetReferences", + "GetUnspentCoins": "Neo.Transaction.GetUnspentCoins", + "GetScript": "Neo.Transaction.GetScript", + }, + "asset": { + "GetAssetID": "Neo.Asset.GetAssetID", + "GetAssetType": "Neo.Asset.GetAssetType", + "GetAmount": "Neo.Asset.GetAmount", + "Create": "Neo.Asset.Create", + "Renew": "Neo.Asset.Renew", + }, + "contract": { + "GetScript": "Neo.Contract.GetScript", + "IsPayable": "Neo.Contract.IsPayable", + "Create": "Neo.Contract.Create", + "Destroy": "Neo.Contract.Destroy", + "Migrate": "Neo.Contract.Migrate", + "GetStorageContext": "Neo.Contract.GetStorageContext", + }, + "input": { + "GetHash": "Neo.Input.GetHash", + "GetIndex": "Neo.Input.GetIndex", + }, + "output": { + "GetAssetID": "Neo.Output.GetAssetID", + "GetValue": "Neo.Output.GetValue", + "GetScriptHash": "Neo.Output.GetScriptHash", + }, }