Merge pull request #1375 from nspcc-dev/compiler/types

Smartcontract types definition in interops
This commit is contained in:
Roman Khimov 2020-09-16 14:43:50 +03:00 committed by GitHub
commit 5f22bdfecf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 189 additions and 111 deletions

View file

@ -2,6 +2,7 @@ package tokencontract
import ( import (
"github.com/nspcc-dev/neo-go/examples/token/nep5" "github.com/nspcc-dev/neo-go/examples/token/nep5"
"github.com/nspcc-dev/neo-go/pkg/interop"
"github.com/nspcc-dev/neo-go/pkg/interop/storage" "github.com/nspcc-dev/neo-go/pkg/interop/storage"
"github.com/nspcc-dev/neo-go/pkg/interop/util" "github.com/nspcc-dev/neo-go/pkg/interop/util"
) )
@ -52,12 +53,12 @@ func TotalSupply() int {
} }
// BalanceOf returns the amount of token on the specified address // BalanceOf returns the amount of token on the specified address
func BalanceOf(holder []byte) interface{} { func BalanceOf(holder interop.Hash160) interface{} {
return token.BalanceOf(ctx, holder) return token.BalanceOf(ctx, holder)
} }
// Transfer token from one user to another // Transfer token from one user to another
func Transfer(from []byte, to []byte, amount int) bool { func Transfer(from interop.Hash160, to interop.Hash160, amount int) bool {
return token.Transfer(ctx, from, to, amount) return token.Transfer(ctx, from, to, amount)
} }

View file

@ -1396,10 +1396,7 @@ func (c *codegen) convertSyscall(expr *ast.CallExpr, api, name string) {
c.prog.Err = fmt.Errorf("unknown VM syscall api: %s.%s", api, name) c.prog.Err = fmt.Errorf("unknown VM syscall api: %s.%s", api, name)
return return
} }
emit.Syscall(c.prog.BinWriter, syscall.API) emit.Syscall(c.prog.BinWriter, syscall)
if syscall.ConvertResultToStruct {
c.emitConvert(stackitem.StructT)
}
// 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
// one to one matching avm file with neo-python which is very nice for debugging. // one to one matching avm file with neo-python which is very nice for debugging.

View file

@ -201,6 +201,21 @@ func (c *codegen) scTypeFromExpr(typ ast.Expr) string {
if c.typeOf(typ) == nil { if c.typeOf(typ) == nil {
return "Any" return "Any"
} }
if named, ok := t.(*types.Named); ok {
if isInteropPath(named.String()) {
name := named.Obj().Name()
pkg := named.Obj().Pkg().Name()
switch pkg {
case "blockchain", "contract":
return "Array" // Block, Transaction, Contract
case "interop":
if name != "Interface" {
return name
}
}
return "InteropInterface"
}
}
switch t := t.Underlying().(type) { switch t := t.Underlying().(type) {
case *types.Basic: case *types.Basic:
info := t.Info() info := t.Info()

View file

@ -15,6 +15,10 @@ import (
func TestCodeGen_DebugInfo(t *testing.T) { func TestCodeGen_DebugInfo(t *testing.T) {
src := `package foo src := `package foo
import "github.com/nspcc-dev/neo-go/pkg/interop"
import "github.com/nspcc-dev/neo-go/pkg/interop/storage"
import "github.com/nspcc-dev/neo-go/pkg/interop/blockchain"
import "github.com/nspcc-dev/neo-go/pkg/interop/contract"
func Main(op string) bool { func Main(op string) bool {
var s string var s string
_ = s _ = s
@ -42,6 +46,12 @@ func MethodByteArray() []byte { return nil }
func MethodArray() []bool { return nil } func MethodArray() []bool { return nil }
func MethodStruct() struct{} { return struct{}{} } func MethodStruct() struct{} { return struct{}{} }
func unexportedMethod() int { return 1 } func unexportedMethod() int { return 1 }
func MethodParams(addr interop.Hash160, h interop.Hash256,
sig interop.Signature, pub interop.PublicKey,
inter interop.Interface, ctr contract.Contract,
ctx storage.Context, tx blockchain.Transaction) bool {
return true
}
type MyStruct struct {} type MyStruct struct {}
func (ms MyStruct) MethodOnStruct() { } func (ms MyStruct) MethodOnStruct() { }
func (ms *MyStruct) MethodOnPointerToStruct() { } func (ms *MyStruct) MethodOnPointerToStruct() { }
@ -72,6 +82,7 @@ func (ms *MyStruct) MethodOnPointerToStruct() { }
"unexportedMethod": "Integer", "unexportedMethod": "Integer",
"MethodOnStruct": "Void", "MethodOnStruct": "Void",
"MethodOnPointerToStruct": "Void", "MethodOnPointerToStruct": "Void",
"MethodParams": "Boolean",
} }
for i := range d.Methods { for i := range d.Methods {
name := d.Methods[i].ID name := d.Methods[i].ID
@ -201,6 +212,21 @@ func (ms *MyStruct) MethodOnPointerToStruct() { }
}, },
ReturnType: smartcontract.StringType, ReturnType: smartcontract.StringType,
}, },
{
Name: "methodParams",
Offset: 125,
Parameters: []manifest.Parameter{
manifest.NewParameter("addr", smartcontract.Hash160Type),
manifest.NewParameter("h", smartcontract.Hash256Type),
manifest.NewParameter("sig", smartcontract.SignatureType),
manifest.NewParameter("pub", smartcontract.PublicKeyType),
manifest.NewParameter("inter", smartcontract.InteropInterfaceType),
manifest.NewParameter("ctr", smartcontract.ArrayType),
manifest.NewParameter("ctx", smartcontract.InteropInterfaceType),
manifest.NewParameter("tx", smartcontract.ArrayType),
},
ReturnType: smartcontract.BoolType,
},
}, },
Events: []manifest.Event{}, Events: []manifest.Event{},
}, },

View file

@ -2,91 +2,85 @@ package compiler
import "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" import "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
// Syscall represents NEO or System syscall API with flag for proper AVM generation
type Syscall struct {
API string
ConvertResultToStruct bool
}
// All lists are sorted, keep 'em this way, please. // All lists are sorted, keep 'em this way, please.
var syscalls = map[string]map[string]Syscall{ var syscalls = map[string]map[string]string{
"binary": { "binary": {
"Base58Decode": {interopnames.SystemBinaryBase58Decode, false}, "Base58Decode": interopnames.SystemBinaryBase58Decode,
"Base58Encode": {interopnames.SystemBinaryBase58Encode, false}, "Base58Encode": interopnames.SystemBinaryBase58Encode,
"Base64Decode": {interopnames.SystemBinaryBase64Decode, false}, "Base64Decode": interopnames.SystemBinaryBase64Decode,
"Base64Encode": {interopnames.SystemBinaryBase64Encode, false}, "Base64Encode": interopnames.SystemBinaryBase64Encode,
"Deserialize": {interopnames.SystemBinaryDeserialize, false}, "Deserialize": interopnames.SystemBinaryDeserialize,
"Serialize": {interopnames.SystemBinarySerialize, false}, "Serialize": interopnames.SystemBinarySerialize,
}, },
"blockchain": { "blockchain": {
"GetBlock": {interopnames.SystemBlockchainGetBlock, true}, "GetBlock": interopnames.SystemBlockchainGetBlock,
"GetContract": {interopnames.SystemBlockchainGetContract, true}, "GetContract": interopnames.SystemBlockchainGetContract,
"GetHeight": {interopnames.SystemBlockchainGetHeight, false}, "GetHeight": interopnames.SystemBlockchainGetHeight,
"GetTransaction": {interopnames.SystemBlockchainGetTransaction, true}, "GetTransaction": interopnames.SystemBlockchainGetTransaction,
"GetTransactionFromBlock": {interopnames.SystemBlockchainGetTransactionFromBlock, false}, "GetTransactionFromBlock": interopnames.SystemBlockchainGetTransactionFromBlock,
"GetTransactionHeight": {interopnames.SystemBlockchainGetTransactionHeight, false}, "GetTransactionHeight": interopnames.SystemBlockchainGetTransactionHeight,
}, },
"contract": { "contract": {
"Create": {interopnames.SystemContractCreate, true}, "Create": interopnames.SystemContractCreate,
"CreateStandardAccount": {interopnames.SystemContractCreateStandardAccount, false}, "CreateStandardAccount": interopnames.SystemContractCreateStandardAccount,
"Destroy": {interopnames.SystemContractDestroy, false}, "Destroy": interopnames.SystemContractDestroy,
"IsStandard": {interopnames.SystemContractIsStandard, false}, "IsStandard": interopnames.SystemContractIsStandard,
"GetCallFlags": {interopnames.SystemContractGetCallFlags, false}, "GetCallFlags": interopnames.SystemContractGetCallFlags,
"Update": {interopnames.SystemContractUpdate, false}, "Update": interopnames.SystemContractUpdate,
}, },
"crypto": { "crypto": {
"ECDsaSecp256k1Verify": {interopnames.NeoCryptoVerifyWithECDsaSecp256k1, false}, "ECDsaSecp256k1Verify": interopnames.NeoCryptoVerifyWithECDsaSecp256k1,
"ECDSASecp256k1CheckMultisig": {interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1, false}, "ECDSASecp256k1CheckMultisig": interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1,
"ECDsaSecp256r1Verify": {interopnames.NeoCryptoVerifyWithECDsaSecp256r1, false}, "ECDsaSecp256r1Verify": interopnames.NeoCryptoVerifyWithECDsaSecp256r1,
"ECDSASecp256r1CheckMultisig": {interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1, false}, "ECDSASecp256r1CheckMultisig": interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1,
"RIPEMD160": {interopnames.NeoCryptoRIPEMD160, false}, "RIPEMD160": interopnames.NeoCryptoRIPEMD160,
"SHA256": {interopnames.NeoCryptoSHA256, false}, "SHA256": interopnames.NeoCryptoSHA256,
}, },
"enumerator": { "enumerator": {
"Concat": {interopnames.SystemEnumeratorConcat, false}, "Concat": interopnames.SystemEnumeratorConcat,
"Create": {interopnames.SystemEnumeratorCreate, false}, "Create": interopnames.SystemEnumeratorCreate,
"Next": {interopnames.SystemEnumeratorNext, false}, "Next": interopnames.SystemEnumeratorNext,
"Value": {interopnames.SystemEnumeratorValue, false}, "Value": interopnames.SystemEnumeratorValue,
}, },
"engine": { "engine": {
"AppCall": {interopnames.SystemContractCall, false}, "AppCall": interopnames.SystemContractCall,
}, },
"iterator": { "iterator": {
"Concat": {interopnames.SystemIteratorConcat, false}, "Concat": interopnames.SystemIteratorConcat,
"Create": {interopnames.SystemIteratorCreate, false}, "Create": interopnames.SystemIteratorCreate,
"Key": {interopnames.SystemIteratorKey, false}, "Key": interopnames.SystemIteratorKey,
"Keys": {interopnames.SystemIteratorKeys, false}, "Keys": interopnames.SystemIteratorKeys,
"Next": {interopnames.SystemEnumeratorNext, false}, "Next": interopnames.SystemEnumeratorNext,
"Value": {interopnames.SystemEnumeratorValue, false}, "Value": interopnames.SystemEnumeratorValue,
"Values": {interopnames.SystemIteratorValues, false}, "Values": interopnames.SystemIteratorValues,
}, },
"json": { "json": {
"Deserialize": {interopnames.SystemJSONDeserialize, false}, "Deserialize": interopnames.SystemJSONDeserialize,
"Serialize": {interopnames.SystemJSONSerialize, false}, "Serialize": interopnames.SystemJSONSerialize,
}, },
"runtime": { "runtime": {
"GasLeft": {interopnames.SystemRuntimeGasLeft, false}, "GasLeft": interopnames.SystemRuntimeGasLeft,
"GetInvocationCounter": {interopnames.SystemRuntimeGetInvocationCounter, false}, "GetInvocationCounter": interopnames.SystemRuntimeGetInvocationCounter,
"GetCallingScriptHash": {interopnames.SystemRuntimeGetCallingScriptHash, false}, "GetCallingScriptHash": interopnames.SystemRuntimeGetCallingScriptHash,
"GetEntryScriptHash": {interopnames.SystemRuntimeGetEntryScriptHash, false}, "GetEntryScriptHash": interopnames.SystemRuntimeGetEntryScriptHash,
"GetExecutingScriptHash": {interopnames.SystemRuntimeGetExecutingScriptHash, false}, "GetExecutingScriptHash": interopnames.SystemRuntimeGetExecutingScriptHash,
"GetNotifications": {interopnames.SystemRuntimeGetNotifications, false}, "GetNotifications": interopnames.SystemRuntimeGetNotifications,
"GetScriptContainer": {interopnames.SystemRuntimeGetScriptContainer, true}, "GetScriptContainer": interopnames.SystemRuntimeGetScriptContainer,
"GetTime": {interopnames.SystemRuntimeGetTime, false}, "GetTime": interopnames.SystemRuntimeGetTime,
"GetTrigger": {interopnames.SystemRuntimeGetTrigger, false}, "GetTrigger": interopnames.SystemRuntimeGetTrigger,
"CheckWitness": {interopnames.SystemRuntimeCheckWitness, false}, "CheckWitness": interopnames.SystemRuntimeCheckWitness,
"Log": {interopnames.SystemRuntimeLog, false}, "Log": interopnames.SystemRuntimeLog,
"Notify": {interopnames.SystemRuntimeNotify, false}, "Notify": interopnames.SystemRuntimeNotify,
"Platform": {interopnames.SystemRuntimePlatform, false}, "Platform": interopnames.SystemRuntimePlatform,
}, },
"storage": { "storage": {
"ConvertContextToReadOnly": {interopnames.SystemStorageAsReadOnly, false}, "ConvertContextToReadOnly": interopnames.SystemStorageAsReadOnly,
"Delete": {interopnames.SystemStorageDelete, false}, "Delete": interopnames.SystemStorageDelete,
"Find": {interopnames.SystemStorageFind, false}, "Find": interopnames.SystemStorageFind,
"Get": {interopnames.SystemStorageGet, false}, "Get": interopnames.SystemStorageGet,
"GetContext": {interopnames.SystemStorageGetContext, false}, "GetContext": interopnames.SystemStorageGetContext,
"GetReadOnlyContext": {interopnames.SystemStorageGetReadOnlyContext, false}, "GetReadOnlyContext": interopnames.SystemStorageGetReadOnlyContext,
"Put": {interopnames.SystemStoragePut, false}, "Put": interopnames.SystemStoragePut,
"PutEx": {interopnames.SystemStoragePutEx, false}, "PutEx": interopnames.SystemStoragePutEx,
}, },
} }

View file

@ -19,8 +19,8 @@ func Deserialize(b []byte) interface{} {
// 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) []byte { func Base64Encode(b []byte) string {
return nil return ""
} }
// Base64Decode decodes given base64 string represented as a byte slice into // Base64Decode decodes given base64 string represented as a byte slice into
@ -31,8 +31,8 @@ func Base64Decode(b []byte) []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) []byte { func Base58Encode(b []byte) string {
return nil return ""
} }
// Base58Decode decodes given base58 string represented as a byte slice into // Base58Decode decodes given base58 string represented as a byte slice into

View file

@ -3,21 +3,24 @@ Package blockchain provides functions to access various blockchain data.
*/ */
package blockchain package blockchain
import "github.com/nspcc-dev/neo-go/pkg/interop/contract" import (
"github.com/nspcc-dev/neo-go/pkg/interop"
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
)
// Transaction represents a NEO transaction. It's similar to Transaction class // Transaction represents a NEO transaction. It's similar to Transaction class
// in Neo .net framework. // in Neo .net framework.
type Transaction struct { type Transaction struct {
// Hash represents the hash (256 bit BE value in a 32 byte slice) of the // Hash represents the hash (256 bit BE value in a 32 byte slice) of the
// given transaction (which also is its ID). // given transaction (which also is its ID).
Hash []byte Hash interop.Hash256
// Version represents the transaction version. // Version represents the transaction version.
Version int Version int
// Nonce is a random number to avoid hash collision. // Nonce is a random number to avoid hash collision.
Nonce int Nonce int
// Sender represents the sender (160 bit BE value in a 20 byte slice) of the // Sender represents the sender (160 bit BE value in a 20 byte slice) of the
// given Transaction. // given Transaction.
Sender []byte Sender interop.Hash160
// SysFee represents fee to be burned. // SysFee represents fee to be burned.
SysFee int SysFee int
// NetFee represents fee to be distributed to consensus nodes. // NetFee represents fee to be distributed to consensus nodes.
@ -35,22 +38,22 @@ type Transaction struct {
type Block struct { type Block struct {
// Hash represents the hash (256 bit BE value in a 32 byte slice) of the // Hash represents the hash (256 bit BE value in a 32 byte slice) of the
// given block. // given block.
Hash []byte Hash interop.Hash256
// Version of the block. // Version of the block.
Version int Version int
// PrevHash represents the hash (256 bit BE value in a 32 byte slice) of the // PrevHash represents the hash (256 bit BE value in a 32 byte slice) of the
// previous block. // previous block.
PrevHash []byte PrevHash interop.Hash256
// MerkleRoot represents the root hash (256 bit BE value in a 32 byte slice) // MerkleRoot represents the root hash (256 bit BE value in a 32 byte slice)
// of a transaction list. // of a transaction list.
MerkleRoot []byte MerkleRoot interop.Hash256
// Timestamp represents millisecond-precision block timestamp. // Timestamp represents millisecond-precision block timestamp.
Timestamp int Timestamp int
// Index represents the height of the block. // Index represents the height of the block.
Index int Index int
// NextConsensus represents contract address of the next miner (160 bit BE // NextConsensus represents contract address of the next miner (160 bit BE
// value in a 20 byte slice). // value in a 20 byte slice).
NextConsensus []byte NextConsensus interop.Hash160
// TransactionsLength represents the length of block's transactions array. // TransactionsLength represents the length of block's transactions array.
TransactionsLength int TransactionsLength int
} }
@ -67,29 +70,29 @@ func GetHeight() int {
// 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.
func GetBlock(heightOrHash interface{}) Block { func GetBlock(heightOrHash interface{}) *Block {
return Block{} return &Block{}
} }
// GetTransaction returns transaction found by the given hash (256 bit in BE // GetTransaction returns transaction found by the given hash (256 bit in BE
// format represented as a slice of 32 bytes). This function uses // format represented as a slice of 32 bytes). This function uses
// `System.Blockchain.GetTransaction` syscall. // `System.Blockchain.GetTransaction` syscall.
func GetTransaction(hash []byte) Transaction { func GetTransaction(hash interop.Hash256) *Transaction {
return Transaction{} return &Transaction{}
} }
// GetTransactionFromBlock returns transaction hash (256 bit in BE format // GetTransactionFromBlock returns transaction hash (256 bit in BE format
// represented as a slice of 32 bytes) from the block found by the given hash or // represented as a slice of 32 bytes) from the block found by the given hash or
// index (with the same encoding as for GetHeader) by its index. This // index (with the same encoding as for GetHeader) by its index. This
// function uses `System.Blockchain.GetTransactionFromBlock` syscall. // function uses `System.Blockchain.GetTransactionFromBlock` syscall.
func GetTransactionFromBlock(heightOrHash interface{}, index int) []byte { func GetTransactionFromBlock(heightOrHash interface{}, index int) interop.Hash256 {
return nil return nil
} }
// GetTransactionHeight returns transaction's height (index of the block that // GetTransactionHeight returns transaction's height (index of the block that
// includes it) by the given ID (256 bit in BE format represented as a slice of // includes it) by the given ID (256 bit in BE format represented as a slice of
// 32 bytes). This function uses `System.Blockchain.GetTransactionHeight` syscall. // 32 bytes). This function uses `System.Blockchain.GetTransactionHeight` syscall.
func GetTransactionHeight(hash []byte) int { func GetTransactionHeight(hash interop.Hash256) int {
return 0 return 0
} }
@ -97,6 +100,6 @@ func GetTransactionHeight(hash []byte) int {
// 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
// `System.Blockchain.GetContract` syscall. // `System.Blockchain.GetContract` syscall.
func GetContract(scriptHash []byte) contract.Contract { func GetContract(scriptHash interop.Hash160) *contract.Contract {
return contract.Contract{} return &contract.Contract{}
} }

View file

@ -3,6 +3,8 @@ Package contract provides functions to work with contracts.
*/ */
package contract package contract
import "github.com/nspcc-dev/neo-go/pkg/interop"
// Contract represents a Neo contract and is used in interop functions. It's // Contract represents a Neo contract and is used in interop functions. It's
// a data structure that you can manipulate with using functions from // a data structure that you can manipulate with using functions from
// this package. It's similar in function to the Contract class in the Neo .net // this package. It's similar in function to the Contract class in the Neo .net
@ -19,8 +21,8 @@ type Contract struct {
// manifest contract's manifest (limited in length by 2 KiB) // manifest contract's manifest (limited in length by 2 KiB)
// It returns this new created Contract when successful (and fails transaction // It returns this new created Contract when successful (and fails transaction
// if not). It uses `System.Contract.Create` syscall. // if not). It uses `System.Contract.Create` syscall.
func Create(script []byte, manifest []byte) Contract { func Create(script []byte, manifest []byte) *Contract {
return Contract{} return &Contract{}
} }
// Update updates script and manifest of the calling contract (that is the one that calls Update) // Update updates script and manifest of the calling contract (that is the one that calls Update)
@ -40,13 +42,13 @@ func Destroy() {}
// 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 []byte) bool { func IsStandard(h interop.Hash160) bool {
return false return false
} }
// 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 []byte) []byte { func CreateStandardAccount(pub interop.PublicKey) []byte {
return nil return nil
} }

View file

@ -3,36 +3,38 @@ Package crypto provides an interface to cryptographic syscalls.
*/ */
package crypto package crypto
import "github.com/nspcc-dev/neo-go/pkg/interop"
// 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) []byte { func SHA256(b []byte) interop.Hash256 {
return nil return nil
} }
// 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) []byte { func RIPEMD160(b []byte) interop.Hash160 {
return nil return nil
} }
// 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 []byte, sig []byte) bool { func ECDsaSecp256r1Verify(msg []byte, pub interop.PublicKey, sig interop.Signature) bool {
return false return false
} }
// 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 []byte, sig []byte) bool { func ECDsaSecp256k1Verify(msg []byte, pub interop.PublicKey, sig interop.Signature) bool {
return false return false
} }
// 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 [][]byte, sigs [][]byte) bool { func ECDSASecp256r1CheckMultisig(msg []byte, pubs []interop.PublicKey, sigs []interop.Signature) bool {
return false return false
} }
// 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 [][]byte, sigs [][]byte) bool { func ECDSASecp256k1CheckMultisig(msg []byte, pubs []interop.PublicKey, sigs []interop.Signature) bool {
return false return false
} }

View file

@ -1,11 +1,23 @@
/* /*
Package interop contains smart contract API functions. Package interop contains smart contract API functions and type synonyms.
Its subpackages can be imported into smart contracts written in Go to provide Its subpackages can be imported into smart contracts written in Go to provide
various functionality. Upon compilation, functions from these packages will various functionality. Upon compilation, functions from these packages will
be substituted with appropriate NeoVM system calls implemented by Neo. Usually be substituted with appropriate NeoVM system calls implemented by Neo. Usually
these system calls have additional price in NeoVM, so they're explicitly written these system calls have additional price in NeoVM, so they're explicitly written
in the documentation of respective functions. in the documentation of respective functions.
Types defined here are used for proper manifest generation. Here is how Go types
correspond to smartcontract and VM types:
int-like - Integer
bool - Boolean
[]byte - ByteArray (Buffer in VM)
string - String (ByteString in VM)
(interface{})(nil) - Any
non-byte slice - Array
map[K]V - map
Other types are defined explicitly in this pkg:
Hash160, Hash256, InteropInterface, PublicKey, Signature
Note that unless written otherwise structures defined in this packages can't be Note that unless written otherwise structures defined in this packages can't be
correctly created by new() or composite literals, they should be received from correctly created by new() or composite literals, they should be received from
some interop functions (and then used as parameters for some other interop some interop functions (and then used as parameters for some other interop

View file

@ -5,10 +5,12 @@ framework.
*/ */
package engine package engine
import "github.com/nspcc-dev/neo-go/pkg/interop"
// AppCall executes previously deployed blockchain contract with specified hash // AppCall executes previously deployed blockchain contract with specified hash
// (160 bit in BE form represented as 20-byte slice) using provided arguments. // (160 bit in BE form represented as 20-byte slice) using provided arguments.
// 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 AppCall(scriptHash []byte, method string, args ...interface{}) interface{} { func AppCall(scriptHash interop.Hash160, method string, args ...interface{}) interface{} {
return nil return nil
} }

View file

@ -1,13 +1,16 @@
package runtime package runtime
import "github.com/nspcc-dev/neo-go/pkg/interop/blockchain" import (
"github.com/nspcc-dev/neo-go/pkg/interop"
"github.com/nspcc-dev/neo-go/pkg/interop/blockchain"
)
// GetScriptContainer returns the transaction that initially triggered current // GetScriptContainer returns the transaction that initially triggered current
// execution context. It never changes in a single execution, no matter how deep // execution context. It never changes in a single execution, no matter how deep
// this execution goes. This function uses // this execution goes. This function uses
// `System.Runtime.GetScriptContainer` syscall. // `System.Runtime.GetScriptContainer` syscall.
func GetScriptContainer() blockchain.Transaction { func GetScriptContainer() *blockchain.Transaction {
return blockchain.Transaction{} return &blockchain.Transaction{}
} }
// GetExecutingScriptHash returns script hash (160 bit in BE form represented // GetExecutingScriptHash returns script hash (160 bit in BE form represented
@ -15,7 +18,7 @@ func GetScriptContainer() blockchain.Transaction {
// AppCall can change the value returned by this function if it calls a // AppCall can change the value returned by this function if it calls a
// different contract. This function uses // different contract. This function uses
// `System.Runtime.GetExecutingScriptHash` syscall. // `System.Runtime.GetExecutingScriptHash` syscall.
func GetExecutingScriptHash() []byte { func GetExecutingScriptHash() interop.Hash160 {
return nil return nil
} }
@ -24,7 +27,7 @@ func GetExecutingScriptHash() []byte {
// running context (caller of current contract or function), so it's one level // running context (caller of current contract or function), so it's one level
// 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() []byte { func GetCallingScriptHash() interop.Hash160 {
return nil return nil
} }
@ -33,6 +36,6 @@ func GetCallingScriptHash() []byte {
// (this is a script that is contained in a transaction returned by // (this is a script that is contained in a transaction returned by
// 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() []byte { func GetEntryScriptHash() interop.Hash160 {
return nil return nil
} }

View file

@ -4,6 +4,8 @@ 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"
// Trigger values to compare with GetTrigger result. // Trigger values to compare with GetTrigger result.
const ( const (
System byte = 0x01 System byte = 0x01
@ -60,7 +62,7 @@ func GasLeft() int64 {
// 'nil' literal means no filtering. It returns slice consisting of following elements: // 'nil' literal means no filtering. It returns slice consisting of following elements:
// [ 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 []byte) [][]interface{} { func GetNotifications(h interop.Hash160) [][]interface{} {
return nil return nil
} }

17
pkg/interop/types.go Normal file
View file

@ -0,0 +1,17 @@
package interop
// Signature represents 64-byte signature.
type Signature []byte
// Hash160 represents 20-byte hash.
type Hash160 []byte
// Hash256 represents 32-byte hash.
type Hash256 []byte
// PublicKey represents marshalled ecdsa public key.
type PublicKey []byte
// Interface represents interop interface type which is needed for
// transparent handling of VM-internal types (e.g. storage.Context)
type Interface interface{}

View file

@ -3,11 +3,13 @@ Package util contains some special useful functions that are provided by compile
*/ */
package util package util
import "github.com/nspcc-dev/neo-go/pkg/interop"
// FromAddress is an utility function that converts a Neo address to its hash // FromAddress is an utility function that converts a Neo address to its hash
// (160 bit BE value in a 20 byte slice). It can only be used for strings known // (160 bit BE value in a 20 byte slice). It can only be used for strings known
// at compilation time, because the conversion is actually being done by the // at compilation time, because the conversion is actually being done by the
// compiler. // compiler.
func FromAddress(address string) []byte { func FromAddress(address string) interop.Hash160 {
return nil return nil
} }