Merge pull request #2292 from nspcc-dev/compiler-packages

compiler: update x/tools package
This commit is contained in:
Roman Khimov 2022-01-21 18:01:06 +03:00 committed by GitHub
commit 613a23cc3f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
57 changed files with 537 additions and 268 deletions

View file

@ -13,7 +13,8 @@ DC_FILE=.docker/docker-compose.yml
GOOS ?= $(shell go env GOOS) GOOS ?= $(shell go env GOOS)
REPO ?= "$(shell go list -m)" REPO ?= "$(shell go list -m)"
VERSION ?= "$(shell git describe --tags 2>/dev/null | sed 's/^v//')$(shell if [ "$(GOOS)" = "windows" ]; then echo "_unsupported"; fi)" VERSION ?= "$(shell git describe --tags 2>/dev/null | sed 's/^v//')$(shell if [ "$(GOOS)" = "windows" ]; then echo "_unsupported"; fi)"
BUILD_FLAGS = "-X '$(REPO)/pkg/config.Version=$(VERSION)'" MODVERSION ?= "$(shell cat go.mod | cat go.mod | sed -r -n -e 's|.*pkg/interop (.*)|\1|p')"
BUILD_FLAGS = "-X '$(REPO)/pkg/config.Version=$(VERSION)' -X '$(REPO)/cli/smartcontract.ModVersion=$(MODVERSION)'"
IMAGE_REPO=nspccdev/neo-go IMAGE_REPO=nspccdev/neo-go

View file

@ -10,6 +10,7 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/nspcc-dev/neo-go/cli/smartcontract"
"github.com/nspcc-dev/neo-go/internal/random" "github.com/nspcc-dev/neo-go/internal/random"
"github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/core/interop/storage" "github.com/nspcc-dev/neo-go/pkg/core/interop/storage"
@ -82,6 +83,12 @@ func TestCalcHash(t *testing.T) {
} }
func TestContractInitAndCompile(t *testing.T) { func TestContractInitAndCompile(t *testing.T) {
// For proper nef generation.
config.Version = "v0.98.1-test"
// For proper contract init. The actual version as it will be replaced.
smartcontract.ModVersion = "v0.0.0"
tmpDir := t.TempDir() tmpDir := t.TempDir()
e := newExecutor(t, false) e := newExecutor(t, false)
@ -99,9 +106,6 @@ func TestContractInitAndCompile(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "init", "--name", ctrPath) e.RunWithError(t, "neo-go", "contract", "init", "--name", ctrPath)
}) })
// For proper nef generation.
config.Version = "0.90.0-test"
srcPath := filepath.Join(ctrPath, "main.go") srcPath := filepath.Join(ctrPath, "main.go")
cfgPath := filepath.Join(ctrPath, "neo-go.yml") cfgPath := filepath.Join(ctrPath, "neo-go.yml")
nefPath := filepath.Join(tmpDir, "testcontract.nef") nefPath := filepath.Join(tmpDir, "testcontract.nef")
@ -120,6 +124,17 @@ func TestContractInitAndCompile(t *testing.T) {
e.RunWithError(t, append(cmd, "--config", cfgName)...) e.RunWithError(t, append(cmd, "--config", cfgName)...)
}) })
// Replace `pkg/interop` in go.mod to avoid getting an actual module version.
goMod := filepath.Join(ctrPath, "go.mod")
data, err := ioutil.ReadFile(goMod)
require.NoError(t, err)
wd, err := os.Getwd()
require.NoError(t, err)
data = append(data, "\nreplace github.com/nspcc-dev/neo-go/pkg/interop => "...)
data = append(data, filepath.Join(wd, "../pkg/interop")...)
require.NoError(t, ioutil.WriteFile(goMod, data, os.ModePerm))
cmd = append(cmd, "--config", cfgPath) cmd = append(cmd, "--config", cfgPath)
e.Run(t, cmd...) e.Run(t, cmd...)
e.checkEOF(t) e.checkEOF(t)

View file

@ -69,6 +69,10 @@ var (
} }
) )
// ModVersion contains `pkg/interop` module version
// suitable to be used in go.mod.
var ModVersion string
const ( const (
// smartContractTmpl is written to a file when used with `init` command. // smartContractTmpl is written to a file when used with `init` command.
// %s is parsed to be the smartContractName. // %s is parsed to be the smartContractName.
@ -450,6 +454,19 @@ func initSmartContract(ctx *cli.Context) error {
return cli.NewExitError(err, 1) return cli.NewExitError(err, 1)
} }
ver := ModVersion
if ver == "" {
ver = "latest"
}
gm := []byte("module " + contractName + `
require (
github.com/nspcc-dev/neo-go/pkg/interop ` + ver + `
)`)
if err := ioutil.WriteFile(filepath.Join(basePath, "go.mod"), gm, 0644); err != nil {
return cli.NewExitError(err, 1)
}
data := []byte(fmt.Sprintf(smartContractTmpl, contractName)) data := []byte(fmt.Sprintf(smartContractTmpl, contractName))
if err := ioutil.WriteFile(filepath.Join(basePath, fileName), data, 0644); err != nil { if err := ioutil.WriteFile(filepath.Join(basePath, fileName), data, 0644); err != nil {
return cli.NewExitError(err, 1) return cli.NewExitError(err, 1)

View file

@ -33,10 +33,11 @@ func TestInitSmartContract(t *testing.T) {
require.True(t, dirInfo.IsDir()) require.True(t, dirInfo.IsDir())
files, err := ioutil.ReadDir(contractName) files, err := ioutil.ReadDir(contractName)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(files)) require.Equal(t, 3, len(files))
require.Equal(t, "main.go", files[0].Name()) require.Equal(t, "go.mod", files[0].Name())
require.Equal(t, "neo-go.yml", files[1].Name()) require.Equal(t, "main.go", files[1].Name())
main, err := ioutil.ReadFile(contractName + "/" + files[0].Name()) require.Equal(t, "neo-go.yml", files[2].Name())
main, err := ioutil.ReadFile(contractName + "/" + files[1].Name())
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, require.Equal(t,
`package `+contractName+` `package `+contractName+`
@ -55,7 +56,7 @@ func RuntimeNotify(args []interface{}) {
runtime.Notify(notificationName, args) runtime.Notify(notificationName, args)
}`, string(main)) }`, string(main))
manifest, err := ioutil.ReadFile(contractName + "/" + files[1].Name()) manifest, err := ioutil.ReadFile(contractName + "/" + files[2].Name())
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, require.Equal(t,
`name: testContract `name: testContract

View file

@ -54,10 +54,16 @@ this requires you to set proper `GOROOT` environment variable, like
export GOROOT=/usr/lib64/go/1.15 export GOROOT=/usr/lib64/go/1.15
``` ```
You'll also need to initialize go modules for your contract like this (in the The best way to create a new contract is using `contract init` command. This will
create an example source file, config file and `go.mod` with `github.com/nspcc-dev/neo-go/pkg/interop` dependency.
```
$ ./bin/neo-go contract init --name MyAwesomeContract
$ cd MyAwesomeContract
```
You'll also need to download dependency modules for your contract like this (in the
directory containing contract package): directory containing contract package):
``` ```
$ go mod init
$ go mod tidy $ go mod tidy
``` ```

5
examples/engine/go.mod Normal file
View file

@ -0,0 +1,5 @@
module github.com/nspcc-dev/neo-go/examples/engine
go 1.16
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652

2
examples/engine/go.sum Normal file
View file

@ -0,0 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652 h1:Paq5oU7mlXjzFcVDD97RA4sxFljAmFrnLrcsObBGIGY=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652/go.mod h1:/zA6GVDzpSkwq8/HQJxPWDcvfn2BbZnahUO9A1wAevM=

5
examples/events/go.mod Normal file
View file

@ -0,0 +1,5 @@
module github.com/nspcc-dev/neo-go/examples/events
go 1.16
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652

2
examples/events/go.sum Normal file
View file

@ -0,0 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652 h1:Paq5oU7mlXjzFcVDD97RA4sxFljAmFrnLrcsObBGIGY=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652/go.mod h1:/zA6GVDzpSkwq8/HQJxPWDcvfn2BbZnahUO9A1wAevM=

5
examples/iterator/go.mod Normal file
View file

@ -0,0 +1,5 @@
module github.com/nspcc-dev/neo-go/examples/iterator
go 1.16
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652

2
examples/iterator/go.sum Normal file
View file

@ -0,0 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652 h1:Paq5oU7mlXjzFcVDD97RA4sxFljAmFrnLrcsObBGIGY=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652/go.mod h1:/zA6GVDzpSkwq8/HQJxPWDcvfn2BbZnahUO9A1wAevM=

View file

@ -0,0 +1,5 @@
module github.com/nspcc-dev/neo-go/examples/nft-nd-nns
go 1.16
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652 // indirect

View file

@ -0,0 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652 h1:Paq5oU7mlXjzFcVDD97RA4sxFljAmFrnLrcsObBGIGY=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652/go.mod h1:/zA6GVDzpSkwq8/HQJxPWDcvfn2BbZnahUO9A1wAevM=

5
examples/nft-nd/go.mod Normal file
View file

@ -0,0 +1,5 @@
module github.com/nspcc-dev/neo-go/examples/nft-nd
go 1.16
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652

2
examples/nft-nd/go.sum Normal file
View file

@ -0,0 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652 h1:Paq5oU7mlXjzFcVDD97RA4sxFljAmFrnLrcsObBGIGY=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652/go.mod h1:/zA6GVDzpSkwq8/HQJxPWDcvfn2BbZnahUO9A1wAevM=

5
examples/oracle/go.mod Normal file
View file

@ -0,0 +1,5 @@
module github.com/nspcc-dev/neo-go/examples/oracle
go 1.16
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652

2
examples/oracle/go.sum Normal file
View file

@ -0,0 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652 h1:Paq5oU7mlXjzFcVDD97RA4sxFljAmFrnLrcsObBGIGY=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652/go.mod h1:/zA6GVDzpSkwq8/HQJxPWDcvfn2BbZnahUO9A1wAevM=

5
examples/runtime/go.mod Normal file
View file

@ -0,0 +1,5 @@
module github.com/nspcc-dev/neo-go/examples/runtime
go 1.16
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652

2
examples/runtime/go.sum Normal file
View file

@ -0,0 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652 h1:Paq5oU7mlXjzFcVDD97RA4sxFljAmFrnLrcsObBGIGY=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652/go.mod h1:/zA6GVDzpSkwq8/HQJxPWDcvfn2BbZnahUO9A1wAevM=

5
examples/storage/go.mod Normal file
View file

@ -0,0 +1,5 @@
module github.com/nspcc-dev/neo-go/examples/storage
go 1.16
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652

2
examples/storage/go.sum Normal file
View file

@ -0,0 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652 h1:Paq5oU7mlXjzFcVDD97RA4sxFljAmFrnLrcsObBGIGY=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652/go.mod h1:/zA6GVDzpSkwq8/HQJxPWDcvfn2BbZnahUO9A1wAevM=

5
examples/timer/go.mod Normal file
View file

@ -0,0 +1,5 @@
module github.com/nspcc-dev/neo-go/examples/timer
go 1.16
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652

2
examples/timer/go.sum Normal file
View file

@ -0,0 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652 h1:Paq5oU7mlXjzFcVDD97RA4sxFljAmFrnLrcsObBGIGY=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652/go.mod h1:/zA6GVDzpSkwq8/HQJxPWDcvfn2BbZnahUO9A1wAevM=

View file

@ -0,0 +1,5 @@
module github.com/nspcc-dev/neo-go/examples/token-sale
go 1.16
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652

View file

@ -0,0 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652 h1:Paq5oU7mlXjzFcVDD97RA4sxFljAmFrnLrcsObBGIGY=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652/go.mod h1:/zA6GVDzpSkwq8/HQJxPWDcvfn2BbZnahUO9A1wAevM=

5
examples/token/go.mod Normal file
View file

@ -0,0 +1,5 @@
module github.com/nspcc-dev/neo-go/examples/token
go 1.16
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652

2
examples/token/go.sum Normal file
View file

@ -0,0 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652 h1:Paq5oU7mlXjzFcVDD97RA4sxFljAmFrnLrcsObBGIGY=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652/go.mod h1:/zA6GVDzpSkwq8/HQJxPWDcvfn2BbZnahUO9A1wAevM=

6
go.mod
View file

@ -10,6 +10,8 @@ require (
github.com/mr-tron/base58 v1.2.0 github.com/mr-tron/base58 v1.2.0
github.com/nspcc-dev/dbft v0.0.0-20210721160347-1b03241391ac github.com/nspcc-dev/dbft v0.0.0-20210721160347-1b03241391ac
github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22
github.com/nspcc-dev/neo-go/examples/nft-nd-nns v0.0.0-20220121072229-d19c0492d4d7
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220120102126-25583f9aeb13
github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659 github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659
github.com/nspcc-dev/rfc6979 v0.2.0 github.com/nspcc-dev/rfc6979 v0.2.0
github.com/pierrec/lz4 v2.6.1+incompatible github.com/pierrec/lz4 v2.6.1+incompatible
@ -23,8 +25,8 @@ require (
go.uber.org/zap v1.18.1 go.uber.org/zap v1.18.1
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4 golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4
golang.org/x/text v0.3.6 golang.org/x/text v0.3.7
golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9 golang.org/x/tools v0.1.8
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
) )

22
go.sum
View file

@ -186,6 +186,11 @@ github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y=
github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU= github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU=
github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg= github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg=
github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM= github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM=
github.com/nspcc-dev/neo-go/examples/nft-nd-nns v0.0.0-20220121072229-d19c0492d4d7 h1:HJmUeYeJqLw4whSLXD4AINb0vJ+DcGSy6HYMIc3Bjs4=
github.com/nspcc-dev/neo-go/examples/nft-nd-nns v0.0.0-20220121072229-d19c0492d4d7/go.mod h1:yBgKeBQfR+2aKuBMn2owA6de6a2kvZ76odotquBcA4M=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220118080652-4eddfdbbc652/go.mod h1:/zA6GVDzpSkwq8/HQJxPWDcvfn2BbZnahUO9A1wAevM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220120102126-25583f9aeb13 h1:BxsNxxydtTVG8CsD5vc+h5w+ir0YMmoNOjX0MpvmAy8=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220120102126-25583f9aeb13/go.mod h1:/zA6GVDzpSkwq8/HQJxPWDcvfn2BbZnahUO9A1wAevM=
github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs=
github.com/nspcc-dev/neofs-api-go/v2 v2.11.1 h1:SVqc523pZsSaS9vnPS1mm3VV6b6xY0gvdA0uYJ/GWZQ= github.com/nspcc-dev/neofs-api-go/v2 v2.11.1 h1:SVqc523pZsSaS9vnPS1mm3VV6b6xY0gvdA0uYJ/GWZQ=
github.com/nspcc-dev/neofs-api-go/v2 v2.11.1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= github.com/nspcc-dev/neofs-api-go/v2 v2.11.1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs=
@ -274,6 +279,7 @@ github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX
github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 h1:JwtAtbp7r/7QSyGz8mKUbYJBg2+6Cd7OjM8o/GNOcVo= github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 h1:JwtAtbp7r/7QSyGz8mKUbYJBg2+6Cd7OjM8o/GNOcVo=
github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1:RmMWU37GKR2s6pgrIEB4ixgpVCt/cf7dnJv3fuH1J1c= github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1:RmMWU37GKR2s6pgrIEB4ixgpVCt/cf7dnJv3fuH1J1c=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
github.com/yuin/gopher-lua v0.0.0-20191128022950-c6266f4fe8d7/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= github.com/yuin/gopher-lua v0.0.0-20191128022950-c6266f4fe8d7/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@ -308,8 +314,9 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -326,8 +333,9 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -367,17 +375,20 @@ golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4 h1:UPou2i3GzKgi6igR+/0C5XyHKBngHxBp/CL5CQ0p3Zk= golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4 h1:UPou2i3GzKgi6igR+/0C5XyHKBngHxBp/CL5CQ0p3Zk=
golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180318012157-96caea41033d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180318012157-96caea41033d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -386,8 +397,9 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9 h1:sEvmEcJVKBNUvgCUClbUQeHOAa9U0I2Ce1BooMvVCY4=
golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w=
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View file

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
gio "io" gio "io"
"strings"
"github.com/nspcc-dev/neo-go/cli/smartcontract" "github.com/nspcc-dev/neo-go/cli/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/compiler" "github.com/nspcc-dev/neo-go/pkg/compiler"
@ -50,18 +51,14 @@ func NewTransferFromOwner(bc blockchainer.Blockchainer, contractHash, to util.Ui
return tx, SignTx(bc, tx) return tx, SignTx(bc, tx)
} }
// NewDeployTx returns new deployment tx for contract with name with Go code read from r. // NewDeployTx returns new deployment for contract with source from r and name equal to
// filename without '.go' suffix.
func NewDeployTx(bc blockchainer.Blockchainer, name string, sender util.Uint160, r gio.Reader, confFile *string) (*transaction.Transaction, util.Uint160, []byte, error) { func NewDeployTx(bc blockchainer.Blockchainer, name string, sender util.Uint160, r gio.Reader, confFile *string) (*transaction.Transaction, util.Uint160, []byte, error) {
// nef.NewFile() cares about version a lot. // nef.NewFile() cares about version a lot.
config.Version = "0.90.0-test" config.Version = "0.90.0-test"
ne, di, err := compiler.CompileWithDebugInfo(name, r)
if err != nil {
return nil, util.Uint160{}, nil, err
}
o := &compiler.Options{ o := &compiler.Options{
Name: name, Name: strings.TrimSuffix(name, ".go"),
NoStandardCheck: true, NoStandardCheck: true,
NoEventsCheck: true, NoEventsCheck: true,
} }
@ -79,6 +76,12 @@ func NewDeployTx(bc blockchainer.Blockchainer, name string, sender util.Uint160,
} }
o.SafeMethods = conf.SafeMethods o.SafeMethods = conf.SafeMethods
} }
ne, di, err := compiler.CompileWithOptions(name, r, o)
if err != nil {
return nil, util.Uint160{}, nil, err
}
m, err := compiler.CreateManifest(di, o) m, err := compiler.CreateManifest(di, o)
if err != nil { if err != nil {
return nil, util.Uint160{}, nil, fmt.Errorf("failed to create manifest: %w", err) return nil, util.Uint160{}, nil, fmt.Errorf("failed to create manifest: %w", err)
@ -100,7 +103,7 @@ func NewDeployTx(bc blockchainer.Blockchainer, name string, sender util.Uint160,
tx := transaction.New(buf.Bytes(), 100*native.GASFactor) tx := transaction.New(buf.Bytes(), 100*native.GASFactor)
tx.Signers = []transaction.Signer{{Account: sender}} tx.Signers = []transaction.Signer{{Account: sender}}
h := state.CreateContractHash(tx.Sender(), ne.Checksum, name) h := state.CreateContractHash(tx.Sender(), ne.Checksum, m.Name)
return tx, h, ne.Script, nil return tx, h, ne.Script, nil
} }

View file

@ -5,11 +5,12 @@ import (
"go/ast" "go/ast"
"go/token" "go/token"
"go/types" "go/types"
"path/filepath"
"strings" "strings"
"github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"golang.org/x/tools/go/loader" //nolint:staticcheck // SA1019: package golang.org/x/tools/go/loader is deprecated "golang.org/x/tools/go/packages"
) )
var ( var (
@ -75,18 +76,18 @@ func (c *codegen) traverseGlobals() bool {
emit.Instruction(c.prog.BinWriter, opcode.INITSLOT, []byte{0, 0}) emit.Instruction(c.prog.BinWriter, opcode.INITSLOT, []byte{0, 0})
lastCnt, maxCnt := -1, -1 lastCnt, maxCnt := -1, -1
c.ForEachPackage(func(pkg *loader.PackageInfo) { c.ForEachPackage(func(pkg *packages.Package) {
if n+nConst > 0 { if n+nConst > 0 {
for _, f := range pkg.Files { for _, f := range pkg.Syntax {
c.fillImportMap(f, pkg.Pkg) c.fillImportMap(f, pkg)
c.convertGlobals(f, pkg.Pkg) c.convertGlobals(f, pkg.Types)
} }
} }
for _, f := range pkg.Files { for _, f := range pkg.Syntax {
c.fillImportMap(f, pkg.Pkg) c.fillImportMap(f, pkg)
var currMax int var currMax int
lastCnt, currMax = c.convertInitFuncs(f, pkg.Pkg, lastCnt) lastCnt, currMax = c.convertInitFuncs(f, pkg.Types, lastCnt)
if currMax > maxCnt { if currMax > maxCnt {
maxCnt = currMax maxCnt = currMax
} }
@ -214,26 +215,30 @@ func lastStmtIsReturn(body *ast.BlockStmt) (b bool) {
// that there can be no cyclic initialization dependencies. // that there can be no cyclic initialization dependencies.
func (c *codegen) analyzePkgOrder() { func (c *codegen) analyzePkgOrder() {
seen := make(map[string]bool) seen := make(map[string]bool)
info := c.buildInfo.program.Package(c.buildInfo.initialPackage) info := c.buildInfo.program[0]
c.visitPkg(info.Pkg, seen) c.visitPkg(info, seen)
} }
func (c *codegen) visitPkg(pkg *types.Package, seen map[string]bool) { func (c *codegen) visitPkg(pkg *packages.Package, seen map[string]bool) {
pkgPath := pkg.Path() if seen[pkg.PkgPath] {
if seen[pkgPath] {
return return
} }
for _, imp := range pkg.Imports() { for _, imp := range pkg.Types.Imports() {
c.visitPkg(imp, seen) c.visitPkg(pkg.Imports[imp.Path()], seen)
} }
seen[pkgPath] = true seen[pkg.PkgPath] = true
c.packages = append(c.packages, pkgPath) c.packages = append(c.packages, pkg.PkgPath)
c.packageCache[pkg.PkgPath] = pkg
} }
func (c *codegen) fillDocumentInfo() { func (c *codegen) fillDocumentInfo() {
fset := c.buildInfo.program.Fset fset := c.buildInfo.config.Fset
fset.Iterate(func(f *token.File) bool { fset.Iterate(func(f *token.File) bool {
filePath := f.Position(f.Pos(0)).Filename filePath := f.Position(f.Pos(0)).Filename
filePath, err := filepath.Rel(c.buildInfo.config.Dir, filePath)
if err != nil {
panic(err)
}
c.docIndex[filePath] = len(c.documents) c.docIndex[filePath] = len(c.documents)
c.documents = append(c.documents, filePath) c.documents = append(c.documents, filePath)
return true return true
@ -257,7 +262,7 @@ func (c *codegen) analyzeFuncUsage() funcUsage {
diff := funcUsage{} diff := funcUsage{}
c.ForEachFile(func(f *ast.File, pkg *types.Package) { c.ForEachFile(func(f *ast.File, pkg *types.Package) {
var pkgPath string var pkgPath string
isMain := pkg == c.mainPkg.Pkg isMain := pkg == c.mainPkg.Types
if !isMain { if !isMain {
pkgPath = pkg.Path() pkgPath = pkg.Path()
} }
@ -303,10 +308,10 @@ func (c *codegen) analyzeFuncUsage() funcUsage {
pkg := c.mainPkg pkg := c.mainPkg
if fd.path != "" { if fd.path != "" {
pkg = c.buildInfo.program.Package(fd.path) pkg = c.packageCache[fd.path]
} }
c.typeInfo = &pkg.Info c.typeInfo = pkg.TypesInfo
c.currPkg = pkg.Pkg c.currPkg = pkg
c.importMap = fd.importMap c.importMap = fd.importMap
ast.Inspect(fd.decl, func(node ast.Node) bool { ast.Inspect(fd.decl, func(node ast.Node) bool {
switch n := node.(type) { switch n := node.(type) {

View file

@ -1,9 +1,15 @@
package compiler_test package compiler_test
import ( import (
"bytes"
"fmt" "fmt"
"math/big" "math/big"
"strings"
"testing" "testing"
"github.com/nspcc-dev/neo-go/pkg/compiler"
"github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/stretchr/testify/require"
) )
var binaryExprTestCases = []testCase{ var binaryExprTestCases = []testCase{
@ -264,34 +270,55 @@ func TestBinaryExprs(t *testing.T) {
runTestCases(t, binaryExprTestCases) runTestCases(t, binaryExprTestCases)
} }
func getBoolExprTestFunc(val bool, cond string) func(t *testing.T) { func addBoolExprTestFunc(testCases []testCase, b *bytes.Buffer, val bool, cond string) []testCase {
srcTmpl := `package foo n := len(testCases)
var s = "str" b.WriteString(fmt.Sprintf(`
var v = 9 func F%d_expr() int {
var cond = %s var cond%d = %s
func Main() int { if cond%d { return 42 }
if %s {
return 42
} %s
return 17 return 17
%s }
}` func F%d_cond() int {
if %s { return 42 }
return 17
}
func F%d_else() int {
if %s { return 42 } else { return 17 }
}
`, n, n, cond, n, n, cond, n, cond))
res := big.NewInt(42) res := big.NewInt(42)
if !val { if !val {
res.SetInt64(17) res.SetInt64(17)
} }
return func(t *testing.T) {
return append(testCases, testCase{
name: cond,
result: res,
})
}
func runBooleanCases(t *testing.T, testCases []testCase, src string) {
ne, di, err := compiler.CompileWithOptions("file.go", strings.NewReader(src), nil)
require.NoError(t, err)
for i, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Run("AsExpression", func(t *testing.T) { t.Run("AsExpression", func(t *testing.T) {
src := fmt.Sprintf(srcTmpl, cond, "cond", "", "") v := vm.New()
eval(t, src, res) invokeMethod(t, fmt.Sprintf("F%d_expr", i), ne.Script, v, di)
runAndCheck(t, v, tc.result)
}) })
t.Run("InCondition", func(t *testing.T) { t.Run("InCondition", func(t *testing.T) {
src := fmt.Sprintf(srcTmpl, "true", cond, "", "") v := vm.New()
eval(t, src, res) invokeMethod(t, fmt.Sprintf("F%d_cond", i), ne.Script, v, di)
runAndCheck(t, v, tc.result)
}) })
t.Run("InConditionWithElse", func(t *testing.T) { t.Run("InConditionWithElse", func(t *testing.T) {
src := fmt.Sprintf(srcTmpl, "true", cond, " else {", "}") v := vm.New()
eval(t, src, res) invokeMethod(t, fmt.Sprintf("F%d_else", i), ne.Script, v, di)
runAndCheck(t, v, tc.result)
})
}) })
} }
} }
@ -299,22 +326,32 @@ func getBoolExprTestFunc(val bool, cond string) func(t *testing.T) {
// TestBooleanExprs enumerates a lot of possible combinations of boolean expressions // TestBooleanExprs enumerates a lot of possible combinations of boolean expressions
// and tests if the result matches to that of Go. // and tests if the result matches to that of Go.
func TestBooleanExprs(t *testing.T) { func TestBooleanExprs(t *testing.T) {
header := `package foo
var s = "str"
var v = 9
`
srcBuilder := bytes.NewBuffer([]byte(header))
var testCases []testCase
trueExpr := []string{"true", "v < 10", "v <= 9", "v > 8", "v >= 9", "v == 9", "v != 8", `s == "str"`} trueExpr := []string{"true", "v < 10", "v <= 9", "v > 8", "v >= 9", "v == 9", "v != 8", `s == "str"`}
falseExpr := []string{"false", "v > 9", "v >= 10", "v < 9", "v <= 8", "v == 8", "v != 9", `s == "a"`} falseExpr := []string{"false", "v > 9", "v >= 10", "v < 9", "v <= 8", "v == 8", "v != 9", `s == "a"`}
t.Run("Single", func(t *testing.T) { t.Run("Single", func(t *testing.T) {
for _, s := range trueExpr { for _, s := range trueExpr {
t.Run(s, getBoolExprTestFunc(true, s)) testCases = addBoolExprTestFunc(testCases, srcBuilder, true, s)
} }
for _, s := range falseExpr { for _, s := range falseExpr {
t.Run(s, getBoolExprTestFunc(false, s)) testCases = addBoolExprTestFunc(testCases, srcBuilder, false, s)
} }
runBooleanCases(t, testCases, srcBuilder.String())
}) })
type arg struct { type arg struct {
val bool val bool
s string s string
} }
t.Run("Combine", func(t *testing.T) {
var double []arg var double []arg
for _, e := range trueExpr { for _, e := range trueExpr {
double = append(double, arg{true, e + " || false"}) double = append(double, arg{true, e + " || false"})
@ -324,9 +361,16 @@ func TestBooleanExprs(t *testing.T) {
double = append(double, arg{false, e + " && true"}) double = append(double, arg{false, e + " && true"})
double = append(double, arg{false, e + " || false"}) double = append(double, arg{false, e + " || false"})
} }
t.Run("Double", func(t *testing.T) {
testCases = testCases[:0]
srcBuilder.Reset()
srcBuilder.WriteString(header)
for i := range double { for i := range double {
t.Run(double[i].s, getBoolExprTestFunc(double[i].val, double[i].s)) testCases = addBoolExprTestFunc(testCases, srcBuilder, double[i].val, double[i].s)
} }
runBooleanCases(t, testCases, srcBuilder.String())
})
var triple []arg var triple []arg
for _, a1 := range double { for _, a1 := range double {
@ -335,8 +379,17 @@ func TestBooleanExprs(t *testing.T) {
triple = append(triple, arg{a1.val && a2.val, fmt.Sprintf("(%s) && (%s)", a1.s, a2.s)}) triple = append(triple, arg{a1.val && a2.val, fmt.Sprintf("(%s) && (%s)", a1.s, a2.s)})
} }
} }
for i := range triple {
t.Run(triple[i].s, getBoolExprTestFunc(triple[i].val, triple[i].s)) t.Run("Triple", func(t *testing.T) {
const step = 256 // empirically found value to make script less than 65536 in size
for start := 0; start < len(triple); start += step {
testCases = testCases[:0]
srcBuilder.Reset()
srcBuilder.WriteString(header)
for i := start; i < start+step && i < len(triple); i++ {
testCases = addBoolExprTestFunc(testCases, srcBuilder, triple[i].val, triple[i].s)
}
runBooleanCases(t, testCases, srcBuilder.String())
} }
}) })
} }

View file

@ -23,7 +23,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"golang.org/x/tools/go/loader" //nolint:staticcheck // SA1019: package golang.org/x/tools/go/loader is deprecated "golang.org/x/tools/go/packages"
) )
type codegen struct { type codegen struct {
@ -36,7 +36,7 @@ type codegen struct {
// Type information. // Type information.
typeInfo *types.Info typeInfo *types.Info
// pkgInfoInline is stack of type information for packages containing inline functions. // pkgInfoInline is stack of type information for packages containing inline functions.
pkgInfoInline []*loader.PackageInfo pkgInfoInline []*packages.Package
// A mapping of func identifiers with their scope. // A mapping of func identifiers with their scope.
funcs map[string]*funcScope funcs map[string]*funcScope
@ -93,13 +93,14 @@ type codegen struct {
constMap map[string]types.TypeAndValue constMap map[string]types.TypeAndValue
// currPkg is current package being processed. // currPkg is current package being processed.
currPkg *types.Package currPkg *packages.Package
// mainPkg is a main package metadata. // mainPkg is a main package metadata.
mainPkg *loader.PackageInfo mainPkg *packages.Package
// packages contains packages in the order they were loaded. // packages contains packages in the order they were loaded.
packages []string packages []string
packageCache map[string]*packages.Package
// exceptionIndex is the index of static slot where exception is stored. // exceptionIndex is the index of static slot where exception is stored.
exceptionIndex int exceptionIndex int
@ -553,14 +554,15 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
for _, spec := range n.Specs { for _, spec := range n.Specs {
vs := spec.(*ast.ValueSpec) vs := spec.(*ast.ValueSpec)
for i := range vs.Names { for i := range vs.Names {
info := c.buildInfo.program.Package(c.currPkg.Path()) obj := c.currPkg.Types.Scope().Lookup(vs.Names[i].Name)
obj := info.Defs[vs.Names[i]] if obj != nil { // can be nil if unused
c.constMap[c.getIdentName("", vs.Names[i].Name)] = types.TypeAndValue{ c.constMap[c.getIdentName("", vs.Names[i].Name)] = types.TypeAndValue{
Type: obj.Type(), Type: obj.Type(),
Value: obj.(*types.Const).Val(), Value: obj.(*types.Const).Val(),
} }
} }
} }
}
return nil return nil
} }
for _, spec := range n.Specs { for _, spec := range n.Specs {
@ -621,7 +623,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
ast.Walk(c, n.Rhs[i]) ast.Walk(c, n.Rhs[i])
} }
typ := c.typeOf(t.X) typ := c.typeOf(t.X)
if typ == nil { if c.isInvalidType(typ) {
// Store to other package global variable. // Store to other package global variable.
c.emitStoreVar(t.X.(*ast.Ident).Name, t.Sel.Name) c.emitStoreVar(t.X.(*ast.Ident).Name, t.Sel.Name)
return nil return nil
@ -920,11 +922,6 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
} }
} else { } else {
typ := c.typeOf(fun) typ := c.typeOf(fun)
if _, ok := typ.(*types.Signature); ok {
c.prog.Err = fmt.Errorf("could not resolve function %s", fun.Sel.Name)
return nil
}
ast.Walk(c, n.Args[0]) ast.Walk(c, n.Args[0])
c.emitExplicitConvert(c.typeOf(n.Args[0]), typ) c.emitExplicitConvert(c.typeOf(n.Args[0]), typ)
return nil return nil
@ -1024,7 +1021,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
case *ast.SelectorExpr: case *ast.SelectorExpr:
typ := c.typeOf(n.X) typ := c.typeOf(n.X)
if typ == nil { if c.isInvalidType(typ) {
// This is a global variable from a package. // This is a global variable from a package.
pkgAlias := n.X.(*ast.Ident).Name pkgAlias := n.X.(*ast.Ident).Name
name := c.getIdentName(pkgAlias, n.Sel.Name) name := c.getIdentName(pkgAlias, n.Sel.Name)
@ -1380,6 +1377,11 @@ func (c *codegen) emitExplicitConvert(from, to types.Type) {
} }
} }
func (c *codegen) isInvalidType(typ types.Type) bool {
tb, ok := typ.(*types.Basic)
return typ == nil || ok && tb.Kind() == types.Invalid
}
func (c *codegen) rangeLoadKey() { func (c *codegen) rangeLoadKey() {
emit.Int(c.prog.BinWriter, 2) emit.Int(c.prog.BinWriter, 2)
emit.Opcodes(c.prog.BinWriter, emit.Opcodes(c.prog.BinWriter,
@ -2028,7 +2030,7 @@ func (c *codegen) newFunc(decl *ast.FuncDecl) *funcScope {
func (c *codegen) getFuncFromIdent(fun *ast.Ident) (*funcScope, bool) { func (c *codegen) getFuncFromIdent(fun *ast.Ident) (*funcScope, bool) {
var pkgName string var pkgName string
if len(c.pkgInfoInline) != 0 { if len(c.pkgInfoInline) != 0 {
pkgName = c.pkgInfoInline[len(c.pkgInfoInline)-1].Pkg.Path() pkgName = c.pkgInfoInline[len(c.pkgInfoInline)-1].PkgPath
} }
f, ok := c.funcs[c.getIdentName(pkgName, fun.Name)] f, ok := c.funcs[c.getIdentName(pkgName, fun.Name)]
@ -2056,7 +2058,7 @@ func (c *codegen) newLambda(u uint16, lit *ast.FuncLit) {
c.lambda[c.getFuncNameFromDecl("", f.decl)] = f c.lambda[c.getFuncNameFromDecl("", f.decl)] = f
} }
func (c *codegen) compile(info *buildInfo, pkg *loader.PackageInfo) error { func (c *codegen) compile(info *buildInfo, pkg *packages.Package) error {
c.mainPkg = pkg c.mainPkg = pkg
c.analyzePkgOrder() c.analyzePkgOrder()
c.fillDocumentInfo() c.fillDocumentInfo()
@ -2080,9 +2082,9 @@ func (c *codegen) compile(info *buildInfo, pkg *loader.PackageInfo) error {
} }
// sort map keys to generate code deterministically. // sort map keys to generate code deterministically.
keys := make([]*types.Package, 0, len(info.program.AllPackages)) keys := make([]*types.Package, 0, len(info.program))
for p := range info.program.AllPackages { for _, p := range info.program {
keys = append(keys, p) keys = append(keys, p.Types)
} }
sort.Slice(keys, func(i, j int) bool { return keys[i].Path() < keys[j].Path() }) sort.Slice(keys, func(i, j int) bool { return keys[i].Path() < keys[j].Path() })
@ -2094,7 +2096,7 @@ func (c *codegen) compile(info *buildInfo, pkg *loader.PackageInfo) error {
// Don't convert the function if it's not used. This will save a lot // Don't convert the function if it's not used. This will save a lot
// of bytecode space. // of bytecode space.
pkgPath := "" pkgPath := ""
if pkg != c.mainPkg.Pkg { // not a main package if pkg != c.mainPkg.Types { // not a main package
pkgPath = pkg.Path() pkgPath = pkg.Path()
} }
name := c.getFuncNameFromDecl(pkgPath, n) name := c.getFuncNameFromDecl(pkgPath, n)
@ -2109,7 +2111,7 @@ func (c *codegen) compile(info *buildInfo, pkg *loader.PackageInfo) error {
return c.prog.Err return c.prog.Err
} }
func newCodegen(info *buildInfo, pkg *loader.PackageInfo) *codegen { func newCodegen(info *buildInfo, pkg *packages.Package) *codegen {
return &codegen{ return &codegen{
buildInfo: info, buildInfo: info,
prog: io.NewBufBinWriter(), prog: io.NewBufBinWriter(),
@ -2119,9 +2121,10 @@ func newCodegen(info *buildInfo, pkg *loader.PackageInfo) *codegen {
reverseOffsetMap: map[int]nameWithLocals{}, reverseOffsetMap: map[int]nameWithLocals{},
globals: map[string]int{}, globals: map[string]int{},
labels: map[labelWithType]uint16{}, labels: map[labelWithType]uint16{},
typeInfo: &pkg.Info, typeInfo: pkg.TypesInfo,
constMap: map[string]types.TypeAndValue{}, constMap: map[string]types.TypeAndValue{},
docIndex: map[string]int{}, docIndex: map[string]int{},
packageCache: map[string]*packages.Package{},
initEndOffset: -1, initEndOffset: -1,
deployEndOffset: -1, deployEndOffset: -1,
@ -2134,7 +2137,7 @@ func newCodegen(info *buildInfo, pkg *loader.PackageInfo) *codegen {
// codeGen compiles the program to bytecode. // codeGen compiles the program to bytecode.
func codeGen(info *buildInfo) (*nef.File, *DebugInfo, error) { func codeGen(info *buildInfo) (*nef.File, *DebugInfo, error) {
pkg := info.program.Package(info.initialPackage) pkg := info.program[0]
c := newCodegen(info, pkg) c := newCodegen(info, pkg)
if err := c.compile(info, pkg); err != nil { if err := c.compile(info, pkg); err != nil {

View file

@ -6,18 +6,20 @@ import (
"fmt" "fmt"
"go/ast" "go/ast"
"go/parser" "go/parser"
"go/token"
"go/types" "go/types"
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"runtime"
"strings" "strings"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest/standard" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest/standard"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"golang.org/x/tools/go/loader" //nolint:staticcheck // SA1019: package golang.org/x/tools/go/loader is deprecated "golang.org/x/tools/go/packages"
) )
const fileExt = "nef" const fileExt = "nef"
@ -73,85 +75,130 @@ type Options struct {
} }
type buildInfo struct { type buildInfo struct {
initialPackage string config *packages.Config
program *loader.Program program []*packages.Package
options *Options options *Options
} }
// ForEachPackage executes fn on each package used in the current program // ForEachPackage executes fn on each package used in the current program
// in the order they should be initialized. // in the order they should be initialized.
func (c *codegen) ForEachPackage(fn func(*loader.PackageInfo)) { func (c *codegen) ForEachPackage(fn func(*packages.Package)) {
for i := range c.packages { for _, pkgPath := range c.packages {
pkg := c.buildInfo.program.Package(c.packages[i]) p := c.packageCache[pkgPath]
c.typeInfo = &pkg.Info c.typeInfo = p.TypesInfo
c.currPkg = pkg.Pkg c.currPkg = p
fn(pkg) fn(p)
} }
} }
// ForEachFile executes fn on each file used in current program. // ForEachFile executes fn on each file used in current program.
func (c *codegen) ForEachFile(fn func(*ast.File, *types.Package)) { func (c *codegen) ForEachFile(fn func(*ast.File, *types.Package)) {
c.ForEachPackage(func(pkg *loader.PackageInfo) { c.ForEachPackage(func(pkg *packages.Package) {
for _, f := range pkg.Files { for _, f := range pkg.Syntax {
c.fillImportMap(f, pkg.Pkg) c.fillImportMap(f, pkg)
fn(f, pkg.Pkg) fn(f, pkg.Types)
} }
}) })
} }
// fillImportMap fills import map for f. // fillImportMap fills import map for f.
func (c *codegen) fillImportMap(f *ast.File, pkg *types.Package) { func (c *codegen) fillImportMap(f *ast.File, pkg *packages.Package) {
c.importMap = map[string]string{"": pkg.Path()} c.importMap = map[string]string{"": pkg.PkgPath}
for _, imp := range f.Imports { for _, imp := range f.Imports {
// We need to load find package metadata because // We need to load find package metadata because
// name specified in `package ...` decl, can be in // name specified in `package ...` decl, can be in
// conflict with package path. // conflict with package path.
pkgPath := strings.Trim(imp.Path.Value, `"`) pkgPath := strings.Trim(imp.Path.Value, `"`)
realPkg := c.buildInfo.program.Package(pkgPath) realPkg := pkg.Imports[pkgPath]
name := realPkg.Pkg.Name() name := realPkg.Name
if imp.Name != nil { if imp.Name != nil {
name = imp.Name.Name name = imp.Name.Name
} }
c.importMap[name] = realPkg.Pkg.Path() c.importMap[name] = realPkg.PkgPath
} }
} }
func getBuildInfo(name string, src interface{}) (*buildInfo, error) { func getBuildInfo(name string, src interface{}) (*buildInfo, error) {
conf := loader.Config{ParserMode: parser.ParseComments} dir, err := filepath.Abs(name)
if src != nil {
f, err := conf.ParseFile(name, src)
if err != nil { if err != nil {
return nil, err return nil, err
} }
conf.CreateFromFiles("", f) absName := dir
} else {
singleFile := strings.HasSuffix(absName, ".go")
if singleFile {
dir = filepath.Dir(dir)
}
conf := &packages.Config{
Mode: packages.NeedName |
packages.NeedImports |
packages.NeedDeps |
packages.NeedTypes |
packages.NeedSyntax |
packages.NeedTypesInfo,
Fset: token.NewFileSet(),
Dir: dir,
Overlay: make(map[string][]byte),
}
var names []string var names []string
if strings.HasSuffix(name, ".go") { if src != nil {
names = append(names, name) var buf []byte
} else { var err error
ds, err := ioutil.ReadDir(name)
if err != nil {
return nil, fmt.Errorf("'%s' is neither Go source nor a directory", name)
}
for i := range ds {
if !ds[i].IsDir() && strings.HasSuffix(ds[i].Name(), ".go") {
names = append(names, filepath.Join(name, ds[i].Name()))
}
}
}
if len(names) == 0 {
return nil, errors.New("no files provided")
}
conf.CreateFromFilenames("", names...)
}
prog, err := conf.Load() switch s := src.(type) {
case string:
buf = []byte(s)
case io.Reader:
buf, err = ioutil.ReadAll(s)
if err != nil { if err != nil {
return nil, err return nil, err
} }
default:
panic(fmt.Sprintf("unsupported src type: %T", s))
}
if strings.HasPrefix(runtime.Version(), "go1.15") {
dir, err = ioutil.TempDir("", "*")
if err != nil {
return nil, err
}
name = filepath.Join(dir, filepath.Base(name))
absName = name
names = append(names, "file="+name)
} else {
names = append(names, name)
}
conf.Overlay[absName] = buf
} else {
if strings.HasSuffix(name, ".go") {
names = append(names, "file="+absName)
} else {
names = append(names, "pattern="+absName)
}
}
conf.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
// When compiling a single file we can or can not load other files from the same package.
// Here we chose the latter which is consistent with `go run` behaviour.
// Other dependencies should still be processed.
if singleFile && filepath.Dir(filename) == filepath.Dir(absName) && filename != absName {
return nil, nil
}
const mode = parser.AllErrors
return parser.ParseFile(fset, filename, src, mode)
}
prog, err := packages.Load(conf, names...)
if err != nil {
return nil, err
}
for _, p := range prog {
if len(p.Errors) != 0 {
return nil, p.Errors[0]
}
}
return &buildInfo{ return &buildInfo{
initialPackage: prog.InitialPackages()[0].Pkg.Name(), config: conf,
program: prog, program: prog,
}, nil }, nil
} }
@ -160,7 +207,7 @@ func getBuildInfo(name string, src interface{}) (*buildInfo, error) {
// If `r != nil`, `name` is interpreted as a filename, and `r` as file contents. // If `r != nil`, `name` is interpreted as a filename, and `r` as file contents.
// Otherwise `name` is either file name or name of the directory containing source files. // Otherwise `name` is either file name or name of the directory containing source files.
func Compile(name string, r io.Reader) ([]byte, error) { func Compile(name string, r io.Reader) ([]byte, error) {
f, _, err := CompileWithDebugInfo(name, r) f, _, err := CompileWithOptions(name, r, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -168,13 +215,6 @@ func Compile(name string, r io.Reader) ([]byte, error) {
return f.Script, nil return f.Script, nil
} }
// CompileWithDebugInfo compiles a Go program into bytecode and emits debug info.
func CompileWithDebugInfo(name string, r io.Reader) (*nef.File, *DebugInfo, error) {
return CompileWithOptions(name, r, &Options{
NoEventsCheck: true,
})
}
// CompileWithOptions compiles a Go program into bytecode with provided compiler options. // CompileWithOptions compiles a Go program into bytecode with provided compiler options.
func CompileWithOptions(name string, r io.Reader, o *Options) (*nef.File, *DebugInfo, error) { func CompileWithOptions(name string, r io.Reader, o *Options) (*nef.File, *DebugInfo, error) {
ctx, err := getBuildInfo(name, r) ctx, err := getBuildInfo(name, r)

View file

@ -36,7 +36,7 @@ func TestCompiler(t *testing.T) {
name: "TestCompileDirectory", name: "TestCompileDirectory",
function: func(t *testing.T) { function: func(t *testing.T) {
const multiMainDir = "testdata/multi" const multiMainDir = "testdata/multi"
_, di, err := compiler.CompileWithDebugInfo(multiMainDir, nil) _, di, err := compiler.CompileWithOptions(multiMainDir, nil, nil)
require.NoError(t, err) require.NoError(t, err)
m := map[string]bool{} m := map[string]bool{}
for i := range di.Methods { for i := range di.Methods {
@ -59,7 +59,7 @@ func TestCompiler(t *testing.T) {
} }
targetPath := filepath.Join(examplePath, info.Name()) targetPath := filepath.Join(examplePath, info.Name())
require.NoError(t, compileFile(targetPath)) require.NoError(t, compileFile(targetPath), info.Name())
} }
}, },
}, },
@ -93,7 +93,7 @@ func compileFile(src string) error {
func TestOnPayableChecks(t *testing.T) { func TestOnPayableChecks(t *testing.T) {
compileAndCheck := func(t *testing.T, src string) error { compileAndCheck := func(t *testing.T, src string) error {
_, di, err := compiler.CompileWithDebugInfo("payable", strings.NewReader(src)) _, di, err := compiler.CompileWithOptions("payable.go", strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
_, err = compiler.CreateManifest(di, &compiler.Options{}) _, err = compiler.CreateManifest(di, &compiler.Options{})
return err return err
@ -129,7 +129,8 @@ func TestSafeMethodWarnings(t *testing.T) {
src := `package payable src := `package payable
func Main() int { return 1 }` func Main() int { return 1 }`
_, di, err := compiler.CompileWithDebugInfo("eventTest", strings.NewReader(src)) _, di, err := compiler.CompileWithOptions("eventTest.go", strings.NewReader(src),
&compiler.Options{Name: "eventTest"})
require.NoError(t, err) require.NoError(t, err)
_, err = compiler.CreateManifest(di, &compiler.Options{SafeMethods: []string{"main"}}) _, err = compiler.CreateManifest(di, &compiler.Options{SafeMethods: []string{"main"}})
@ -144,7 +145,7 @@ func TestEventWarnings(t *testing.T) {
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime" import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
func Main() { runtime.Notify("Event", 1) }` func Main() { runtime.Notify("Event", 1) }`
_, di, err := compiler.CompileWithDebugInfo("eventTest", strings.NewReader(src)) _, di, err := compiler.CompileWithOptions("eventTest.go", strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
t.Run("event it missing from config", func(t *testing.T) { t.Run("event it missing from config", func(t *testing.T) {
@ -188,7 +189,7 @@ func TestEventWarnings(t *testing.T) {
return notify.Value return notify.Value
}` }`
_, di, err := compiler.CompileWithDebugInfo("eventTest", strings.NewReader(src)) _, di, err := compiler.CompileWithOptions("eventTest.go", strings.NewReader(src), &compiler.Options{Name: "eventTest"})
require.NoError(t, err) require.NoError(t, err)
_, err = compiler.CreateManifest(di, &compiler.Options{NoEventsCheck: true}) _, err = compiler.CreateManifest(di, &compiler.Options{NoEventsCheck: true})
@ -202,7 +203,8 @@ func TestEventWarnings(t *testing.T) {
return 42 return 42
}` }`
_, di, err := compiler.CompileWithDebugInfo("eventTest", strings.NewReader(src)) _, di, err := compiler.CompileWithOptions("eventTest.go",
strings.NewReader(src), &compiler.Options{Name: "eventTest"})
require.NoError(t, err) require.NoError(t, err)
_, err = compiler.CreateManifest(di, &compiler.Options{}) _, err = compiler.CreateManifest(di, &compiler.Options{})
@ -224,12 +226,12 @@ func TestNotifyInVerify(t *testing.T) {
for _, name := range []string{"Notify", "Log"} { for _, name := range []string{"Notify", "Log"} {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
src := fmt.Sprintf(srcTmpl, name) src := fmt.Sprintf(srcTmpl, name)
_, _, err := compiler.CompileWithOptions("eventTest", strings.NewReader(src), _, _, err := compiler.CompileWithOptions("eventTest.go", strings.NewReader(src),
&compiler.Options{ContractEvents: []manifest.Event{{Name: "Event"}}}) &compiler.Options{ContractEvents: []manifest.Event{{Name: "Event"}}})
require.Error(t, err) require.Error(t, err)
t.Run("suppress", func(t *testing.T) { t.Run("suppress", func(t *testing.T) {
_, _, err := compiler.CompileWithOptions("eventTest", strings.NewReader(src), _, _, err := compiler.CompileWithOptions("eventTest.go", strings.NewReader(src),
&compiler.Options{NoEventsCheck: true}) &compiler.Options{NoEventsCheck: true})
require.NoError(t, err) require.NoError(t, err)
}) })
@ -258,7 +260,7 @@ func TestInvokedContractsPermissons(t *testing.T) {
return 0 return 0
}` }`
_, di, err := compiler.CompileWithOptions("permissionTest", strings.NewReader(src), &compiler.Options{}) _, di, err := compiler.CompileWithOptions("permissionTest.go", strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
var nh util.Uint160 var nh util.Uint160
@ -302,7 +304,7 @@ func TestInvokedContractsPermissons(t *testing.T) {
contract.Call(runh.RuntimeHash(), "method4", contract.All) contract.Call(runh.RuntimeHash(), "method4", contract.All)
}`, hashStr) }`, hashStr)
_, di, err := compiler.CompileWithOptions("permissionTest", strings.NewReader(src), &compiler.Options{}) _, di, err := compiler.CompileWithOptions("permissionTest.go", strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
var h util.Uint160 var h util.Uint160

View file

@ -105,7 +105,7 @@ func (c *codegen) saveSequencePoint(n ast.Node) {
name = c.scope.name name = c.scope.name
} }
fset := c.buildInfo.program.Fset fset := c.buildInfo.config.Fset
start := fset.Position(n.Pos()) start := fset.Position(n.Pos())
end := fset.Position(n.End()) end := fset.Position(n.End())
c.sequencePoints[name] = append(c.sequencePoints[name], DebugSeqPoint{ c.sequencePoints[name] = append(c.sequencePoints[name], DebugSeqPoint{
@ -120,7 +120,7 @@ func (c *codegen) saveSequencePoint(n ast.Node) {
func (c *codegen) emitDebugInfo(contract []byte) *DebugInfo { func (c *codegen) emitDebugInfo(contract []byte) *DebugInfo {
d := &DebugInfo{ d := &DebugInfo{
MainPkg: c.mainPkg.Pkg.Name(), MainPkg: c.mainPkg.Name,
Events: []EventDebugInfo{}, Events: []EventDebugInfo{},
Documents: c.documents, Documents: c.documents,
StaticVariables: c.staticVariables, StaticVariables: c.staticVariables,
@ -130,7 +130,7 @@ func (c *codegen) emitDebugInfo(contract []byte) *DebugInfo {
ID: manifest.MethodInit, ID: manifest.MethodInit,
Name: DebugMethodName{ Name: DebugMethodName{
Name: manifest.MethodInit, Name: manifest.MethodInit,
Namespace: c.mainPkg.Pkg.Name(), Namespace: c.mainPkg.Name,
}, },
IsExported: true, IsExported: true,
IsFunction: true, IsFunction: true,
@ -149,7 +149,7 @@ func (c *codegen) emitDebugInfo(contract []byte) *DebugInfo {
ID: manifest.MethodDeploy, ID: manifest.MethodDeploy,
Name: DebugMethodName{ Name: DebugMethodName{
Name: manifest.MethodDeploy, Name: manifest.MethodDeploy,
Namespace: c.mainPkg.Pkg.Name(), Namespace: c.mainPkg.Name,
}, },
IsExported: true, IsExported: true,
IsFunction: true, IsFunction: true,

View file

@ -67,17 +67,8 @@ func (ms *MyStruct) MethodOnPointerToStruct() { }
func _deploy(data interface{}, isUpdate bool) { x := 1; _ = x } func _deploy(data interface{}, isUpdate bool) { x := 1; _ = x }
` `
info, err := getBuildInfo("foo.go", src) ne, d, err := CompileWithOptions("foo.go", strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
pkg := info.program.Package(info.initialPackage)
c := newCodegen(info, pkg)
require.NoError(t, c.compile(info, pkg))
buf, err := c.writeJumps(c.prog.Bytes())
require.NoError(t, err)
d := c.emitDebugInfo(buf)
require.NotNil(t, d) require.NotNil(t, d)
t.Run("return types", func(t *testing.T) { t.Run("return types", func(t *testing.T) {
@ -171,8 +162,8 @@ func _deploy(data interface{}, isUpdate bool) { x := 1; _ = x }
// basic check that last instruction of every method is indeed RET // basic check that last instruction of every method is indeed RET
for i := range d.Methods { for i := range d.Methods {
index := d.Methods[i].Range.End index := d.Methods[i].Range.End
require.True(t, int(index) < len(buf)) require.True(t, int(index) < len(ne.Script))
require.EqualValues(t, opcode.RET, buf[index]) require.EqualValues(t, opcode.RET, ne.Script[index])
} }
t.Run("convert to Manifest", func(t *testing.T) { t.Run("convert to Manifest", func(t *testing.T) {
@ -308,18 +299,12 @@ func TestSequencePoints(t *testing.T) {
return false return false
}` }`
info, err := getBuildInfo("foo.go", src) _, d, err := CompileWithOptions("foo.go", strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
pkg := info.program.Package(info.initialPackage)
c := newCodegen(info, pkg)
require.NoError(t, c.compile(info, pkg))
buf := c.prog.Bytes()
d := c.emitDebugInfo(buf)
require.NotNil(t, d) require.NotNil(t, d)
require.Equal(t, d.Documents, []string{"foo.go"}) require.Equal(t, 1, len(d.Documents))
require.True(t, strings.HasSuffix(d.Documents[0], "foo.go"))
// Main func has 2 return on 4-th and 6-th lines. // Main func has 2 return on 4-th and 6-th lines.
ps := d.Methods[0].SeqPoints ps := d.Methods[0].SeqPoints
@ -381,7 +366,7 @@ func TestManifestOverload(t *testing.T) {
return 4 return 4
}` }`
_, di, err := CompileWithDebugInfo("foo", strings.NewReader(src)) _, di, err := CompileWithOptions("foo.go", strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
m, err := di.ConvertToManifest(&Options{Overloads: map[string]string{"add3Aux": "add3"}}) m, err := di.ConvertToManifest(&Options{Overloads: map[string]string{"add3Aux": "add3"}})

View file

@ -69,7 +69,7 @@ func (c *codegen) newFuncScope(decl *ast.FuncDecl, label uint16) *funcScope {
name: name, name: name,
decl: decl, decl: decl,
label: label, label: label,
pkg: c.currPkg, pkg: c.currPkg.Types,
vars: newVarScope(), vars: newVarScope(),
voidCalls: map[*ast.CallExpr]bool{}, voidCalls: map[*ast.CallExpr]bool{},
variables: []string{}, variables: []string{},

View file

@ -302,7 +302,7 @@ func TestJumpOptimize(t *testing.T) {
func Main() int { func Main() int {
return Get3() return Get3()
}` }`
b, di, err := compiler.CompileWithDebugInfo("", strings.NewReader(src)) b, di, err := compiler.CompileWithOptions("file.go", strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 6, len(di.Methods)) require.Equal(t, 6, len(di.Methods))
for _, mi := range di.Methods { for _, mi := range di.Methods {
@ -333,7 +333,7 @@ func TestUnusedFunctions(t *testing.T) {
return nestedcall.X return nestedcall.X
}` }`
b, err := compiler.Compile("foo", strings.NewReader(src)) b, err := compiler.Compile("foo.go", strings.NewReader(src))
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 3, len(b)) // PUSHINT8 (42) + RET require.Equal(t, 3, len(b)) // PUSHINT8 (42) + RET
eval(t, src, big.NewInt(42)) eval(t, src, big.NewInt(42))
@ -346,7 +346,7 @@ func TestUnusedFunctions(t *testing.T) {
return inner.N() return inner.N()
}` }`
_, err := compiler.Compile("foo", strings.NewReader(src)) _, err := compiler.Compile("foo.go", strings.NewReader(src))
require.NoError(t, err) require.NoError(t, err)
eval(t, src, big.NewInt(65)) eval(t, src, big.NewInt(65))
}) })
@ -359,7 +359,7 @@ func TestUnusedFunctions(t *testing.T) {
return t.Method() return t.Method()
}` }`
_, err := compiler.Compile("foo", strings.NewReader(src)) _, err := compiler.Compile("foo.go", strings.NewReader(src))
require.NoError(t, err) require.NoError(t, err)
eval(t, src, big.NewInt(2231)) eval(t, src, big.NewInt(2231))
}) })

View file

@ -12,6 +12,18 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestUnusedGlobal(t *testing.T) {
src := `package foo
const (
_ int = iota
a
)
func Main() int {
return 1
}`
eval(t, src, big.NewInt(1))
}
func TestChangeGlobal(t *testing.T) { func TestChangeGlobal(t *testing.T) {
src := `package foo src := `package foo
var a int var a int
@ -131,7 +143,7 @@ func TestContractWithNoMain(t *testing.T) {
someLocal := 2 someLocal := 2
return someGlobal + someLocal + a return someGlobal + someLocal + a
}` }`
b, di, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(src)) b, di, err := compiler.CompileWithOptions("foo.go", strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
v := vm.New() v := vm.New()
invokeMethod(t, "Add3", b.Script, v, di) invokeMethod(t, "Add3", b.Script, v, di)

View file

@ -29,7 +29,7 @@ func (c *codegen) inlineCall(f *funcScope, n *ast.CallExpr) {
c.labelList = c.labelList[:labelSz] c.labelList = c.labelList[:labelSz]
}() }()
pkg := c.buildInfo.program.Package(f.pkg.Path()) pkg := c.packageCache[f.pkg.Path()]
sig := c.typeOf(n.Fun).(*types.Signature) sig := c.typeOf(n.Fun).(*types.Signature)
c.processStdlibCall(f, n.Args) c.processStdlibCall(f, n.Args)
@ -101,7 +101,7 @@ func (c *codegen) inlineCall(f *funcScope, n *ast.CallExpr) {
oldMap := c.importMap oldMap := c.importMap
oldDefers := c.scope.deferStack oldDefers := c.scope.deferStack
c.scope.deferStack = nil c.scope.deferStack = nil
c.fillImportMap(f.file, pkg.Pkg) c.fillImportMap(f.file, pkg)
ast.Inspect(f.decl, c.scope.analyzeVoidCalls) ast.Inspect(f.decl, c.scope.analyzeVoidCalls)
ast.Walk(c, f.decl.Body) ast.Walk(c, f.decl.Body)
if c.scope.voidCalls[n] { if c.scope.voidCalls[n] {
@ -131,7 +131,7 @@ func (c *codegen) processStdlibCall(f *funcScope, args []ast.Expr) {
func (c *codegen) processNotify(f *funcScope, args []ast.Expr) { func (c *codegen) processNotify(f *funcScope, args []ast.Expr) {
if c.scope != nil && c.isVerifyFunc(c.scope.decl) && if c.scope != nil && c.isVerifyFunc(c.scope.decl) &&
c.scope.pkg == c.mainPkg.Pkg && !c.buildInfo.options.NoEventsCheck { c.scope.pkg == c.mainPkg.Types && !c.buildInfo.options.NoEventsCheck {
c.prog.Err = fmt.Errorf("runtime.%s is not allowed in `Verify`", f.name) c.prog.Err = fmt.Errorf("runtime.%s is not allowed in `Verify`", f.name)
return return
} }

View file

@ -128,7 +128,7 @@ func TestAbort(t *testing.T) {
} }
func spawnVM(t *testing.T, ic *interop.Context, src string) *vm.VM { func spawnVM(t *testing.T, ic *interop.Context, src string) *vm.VM {
b, di, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(src)) b, di, err := compiler.CompileWithOptions("foo.go", strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
v := core.SpawnVM(ic) v := core.SpawnVM(ic)
invokeMethod(t, testMainIdent, b.Script, v, di) invokeMethod(t, testMainIdent, b.Script, v, di)
@ -141,7 +141,7 @@ func TestAppCall(t *testing.T) {
func Get42() int { func Get42() int {
return 42 return 42
}` }`
barCtr, di, err := compiler.CompileWithDebugInfo("bar.go", strings.NewReader(srcDeep)) barCtr, di, err := compiler.CompileWithOptions("bar.go", strings.NewReader(srcDeep), nil)
require.NoError(t, err) require.NoError(t, err)
mBar, err := di.ConvertToManifest(&compiler.Options{Name: "Bar"}) mBar, err := di.ConvertToManifest(&compiler.Options{Name: "Bar"})
require.NoError(t, err) require.NoError(t, err)
@ -167,7 +167,7 @@ func TestAppCall(t *testing.T) {
srcInner = fmt.Sprintf(srcInner, srcInner = fmt.Sprintf(srcInner,
fmt.Sprintf("%#v", cinterop.Hash160(barH.BytesBE()))) fmt.Sprintf("%#v", cinterop.Hash160(barH.BytesBE())))
inner, di, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(srcInner)) inner, di, err := compiler.CompileWithOptions("foo.go", strings.NewReader(srcInner), nil)
require.NoError(t, err) require.NoError(t, err)
m, err := di.ConvertToManifest(&compiler.Options{ m, err := di.ConvertToManifest(&compiler.Options{
Name: "Foo", Name: "Foo",

View file

@ -251,7 +251,7 @@ func runNativeTestCase(t *testing.T, ctr interop.ContractMD, name, method string
v := vm.New() v := vm.New()
v.GasLimit = -1 v.GasLimit = -1
b, di, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(src)) b, di, err := compiler.CompileWithOptions("foo.go", strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
result := getTestStackItem(md.MD.ReturnType) result := getTestStackItem(md.MD.ReturnType)

View file

@ -139,7 +139,7 @@ func runSyscallTestCase(t *testing.T, ic *interop.Context, goName string, tc sys
} }
ss := strings.Split(goName, ".") ss := strings.Split(goName, ".")
src := fmt.Sprintf(srcTmpl, ss[0], goName, strings.Join(tc.params, ", ")) src := fmt.Sprintf(srcTmpl, ss[0], goName, strings.Join(tc.params, ", "))
b, _, err := compiler.CompileWithDebugInfo("foo", strings.NewReader(src)) b, _, err := compiler.CompileWithOptions("foo.go", strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
v := ic.SpawnVM() v := ic.SpawnVM()
@ -198,7 +198,7 @@ func TestNotify(t *testing.T) {
runtime.Notify("long event12345678901234567890123") runtime.Notify("long event12345678901234567890123")
}` }`
_, _, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(src)) _, _, err := compiler.CompileWithOptions("foo.go", strings.NewReader(src), nil)
require.Error(t, err) require.Error(t, err)
}) })
} }

View file

@ -9,15 +9,37 @@ import (
func (c *codegen) typeAndValueOf(e ast.Expr) types.TypeAndValue { func (c *codegen) typeAndValueOf(e ast.Expr) types.TypeAndValue {
for i := len(c.pkgInfoInline) - 1; i >= 0; i-- { for i := len(c.pkgInfoInline) - 1; i >= 0; i-- {
if tv, ok := c.pkgInfoInline[i].Types[e]; ok { if tv, ok := c.pkgInfoInline[i].TypesInfo.Types[e]; ok {
return tv return tv
} }
} }
return c.typeInfo.Types[e]
if tv, ok := c.typeInfo.Types[e]; ok {
return tv
}
se, ok := e.(*ast.SelectorExpr)
if ok {
if tv, ok := c.typeInfo.Selections[se]; ok {
return types.TypeAndValue{Type: tv.Type()}
}
}
return types.TypeAndValue{}
} }
func (c *codegen) typeOf(e ast.Expr) types.Type { func (c *codegen) typeOf(e ast.Expr) types.Type {
return c.typeAndValueOf(e).Type for i := len(c.pkgInfoInline) - 1; i >= 0; i-- {
if typ := c.pkgInfoInline[i].TypesInfo.TypeOf(e); typ != nil {
return typ
}
}
for _, p := range c.packageCache {
typ := p.TypesInfo.TypeOf(e)
if typ != nil {
return typ
}
}
return nil
} }
func isBasicTypeOfKind(typ types.Type, ks ...types.BasicKind) bool { func isBasicTypeOfKind(typ types.Type, ks ...types.BasicKind) bool {

View file

@ -33,11 +33,15 @@ func runTestCases(t *testing.T, tcases []testCase) {
} }
func eval(t *testing.T, src string, result interface{}) { func eval(t *testing.T, src string, result interface{}) {
vm := vmAndCompile(t, src) vm, _ := vmAndCompileInterop(t, src)
err := vm.Run() runAndCheck(t, vm, result)
}
func runAndCheck(t *testing.T, v *vm.VM, result interface{}) {
err := v.Run()
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 1, vm.Estack().Len(), "stack contains unexpected items") assert.Equal(t, 1, v.Estack().Len(), "stack contains unexpected items")
assertResult(t, vm, result) assertResult(t, v, result)
} }
func evalWithArgs(t *testing.T, src string, op []byte, args []stackitem.Item, result interface{}) { func evalWithArgs(t *testing.T, src string, op []byte, args []stackitem.Item, result interface{}) {
@ -48,10 +52,7 @@ func evalWithArgs(t *testing.T, src string, op []byte, args []stackitem.Item, re
if op != nil { if op != nil {
vm.Estack().PushVal(op) vm.Estack().PushVal(op)
} }
err := vm.Run() runAndCheck(t, vm, result)
require.NoError(t, err)
assert.Equal(t, 1, vm.Estack().Len(), "stack contains unexpected items")
assertResult(t, vm, result)
} }
func assertResult(t *testing.T, vm *vm.VM, result interface{}) { func assertResult(t *testing.T, vm *vm.VM, result interface{}) {
@ -71,7 +72,7 @@ func vmAndCompileInterop(t *testing.T, src string) (*vm.VM, *storagePlugin) {
vm.GasLimit = -1 vm.GasLimit = -1
vm.SyscallHandler = storePlugin.syscallHandler vm.SyscallHandler = storePlugin.syscallHandler
b, di, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(src)) b, di, err := compiler.CompileWithOptions("foo.go", strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
storePlugin.info = di storePlugin.info = di

View file

@ -1257,7 +1257,7 @@ func TestIsTxStillRelevant(t *testing.T) {
currentHeight := contract.Call(addr, "currentIndex", contract.ReadStates) currentHeight := contract.Call(addr, "currentIndex", contract.ReadStates)
return currentHeight.(int) < %d return currentHeight.(int) < %d
}`, bc.BlockHeight()+2) // deploy + next block }`, bc.BlockHeight()+2) // deploy + next block
txDeploy, h, _, err := testchain.NewDeployTx(bc, "TestVerify", neoOwner, strings.NewReader(src), nil) txDeploy, h, _, err := testchain.NewDeployTx(bc, "TestVerify.go", neoOwner, strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
txDeploy.ValidUntilBlock = bc.BlockHeight() + 1 txDeploy.ValidUntilBlock = bc.BlockHeight() + 1
addSigners(neoOwner, txDeploy) addSigners(neoOwner, txDeploy)

View file

@ -1,12 +1,10 @@
package core package core
import ( import (
"bytes"
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil"
"math/big" "math/big"
"os" "os"
"path" "path"
@ -187,7 +185,7 @@ func TestBug1728(t *testing.T) {
func _deploy(_ interface{}, isUpdate bool) { func _deploy(_ interface{}, isUpdate bool) {
runtime.Log("Deploy") runtime.Log("Deploy")
}` }`
nf, di, err := compiler.CompileWithDebugInfo("foo", strings.NewReader(src)) nf, di, err := compiler.CompileWithOptions("foo.go", strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
m, err := di.ConvertToManifest(&compiler.Options{Name: "TestContract"}) m, err := di.ConvertToManifest(&compiler.Options{Name: "TestContract"})
require.NoError(t, err) require.NoError(t, err)
@ -422,7 +420,8 @@ func initBasicChain(t *testing.T, bc *Blockchain) {
t.Logf("sendRublesTx: %v", transferTx.Hash().StringLE()) t.Logf("sendRublesTx: %v", transferTx.Hash().StringLE())
// Push verification contract into the chain. // Push verification contract into the chain.
txDeploy2, _ := newDeployTx(t, bc, priv0ScriptHash, prefix+"verification_contract.go", "Verify", nil) verifyPath := filepath.Join(prefix, "verify", "verification_contract.go")
txDeploy2, _ := newDeployTx(t, bc, priv0ScriptHash, verifyPath, "Verify", nil)
txDeploy2.Nonce = getNextNonce() txDeploy2.Nonce = getNextNonce()
txDeploy2.ValidUntilBlock = validUntilBlock txDeploy2.ValidUntilBlock = validUntilBlock
require.NoError(t, addNetworkFee(bc, txDeploy2, acc0)) require.NoError(t, addNetworkFee(bc, txDeploy2, acc0))
@ -458,7 +457,8 @@ func initBasicChain(t *testing.T, bc *Blockchain) {
t.Logf("Designated Notary node: %s", hex.EncodeToString(ntr.Accounts[0].PrivateKey().PublicKey().Bytes())) t.Logf("Designated Notary node: %s", hex.EncodeToString(ntr.Accounts[0].PrivateKey().PublicKey().Bytes()))
// Push verification contract with arguments into the chain. // Push verification contract with arguments into the chain.
txDeploy3, _ := newDeployTx(t, bc, priv0ScriptHash, prefix+"verification_with_args_contract.go", "VerifyWithArgs", nil) verifyPath = filepath.Join(prefix, "verify_args", "verification_with_args_contract.go")
txDeploy3, _ := newDeployTx(t, bc, priv0ScriptHash, verifyPath, "VerifyWithArgs", nil)
txDeploy3.Nonce = getNextNonce() txDeploy3.Nonce = getNextNonce()
txDeploy3.ValidUntilBlock = validUntilBlock txDeploy3.ValidUntilBlock = validUntilBlock
require.NoError(t, addNetworkFee(bc, txDeploy3, acc0)) require.NoError(t, addNetworkFee(bc, txDeploy3, acc0))
@ -516,7 +516,9 @@ func initBasicChain(t *testing.T, bc *Blockchain) {
checkTxHalt(t, bc, txInv.Hash()) checkTxHalt(t, bc, txInv.Hash())
// Compile contract to test `invokescript` RPC call // Compile contract to test `invokescript` RPC call
_, _ = newDeployTx(t, bc, priv0ScriptHash, prefix+"invokescript_contract.go", "ContractForInvokescriptTest", nil) invokePath := filepath.Join(prefix, "invoke", "invokescript_contract.go")
invokeCfg := filepath.Join(prefix, "invoke", "invoke.yml")
_, _ = newDeployTx(t, bc, priv0ScriptHash, invokePath, "ContractForInvokescriptTest", &invokeCfg)
} }
func newNEP17Transfer(sc, from, to util.Uint160, amount int64, additionalArgs ...interface{}) *transaction.Transaction { func newNEP17Transfer(sc, from, to util.Uint160, amount int64, additionalArgs ...interface{}) *transaction.Transaction {
@ -538,17 +540,7 @@ func newNEP17TransferWithAssert(sc, from, to util.Uint160, amount int64, needAss
} }
func newDeployTx(t *testing.T, bc *Blockchain, sender util.Uint160, name, ctrName string, cfgName *string) (*transaction.Transaction, util.Uint160) { func newDeployTx(t *testing.T, bc *Blockchain, sender util.Uint160, name, ctrName string, cfgName *string) (*transaction.Transaction, util.Uint160) {
c, err := ioutil.ReadFile(name) tx, h, avm, err := testchain.NewDeployTx(bc, name, sender, nil, cfgName)
var (
tx *transaction.Transaction
h util.Uint160
avm []byte
)
if err == nil {
tx, h, avm, err = testchain.NewDeployTx(bc, ctrName, sender, bytes.NewReader(c), cfgName)
} else {
tx, h, avm, err = testchain.NewDeployTx(bc, ctrName, sender, nil, cfgName)
}
require.NoError(t, err) require.NoError(t, err)
t.Logf("contract (%s): \n\tHash: %s\n\tAVM: %s", name, h.StringLE(), base64.StdEncoding.EncodeToString(avm)) t.Logf("contract (%s): \n\tHash: %s\n\tAVM: %s", name, h.StringLE(), base64.StdEncoding.EncodeToString(avm))
return tx, h return tx, h

3
pkg/interop/go.mod Normal file
View file

@ -0,0 +1,3 @@
module github.com/nspcc-dev/neo-go/pkg/interop
go 1.16

View file

@ -29,7 +29,7 @@ func CompileSource(t *testing.T, sender util.Uint160, src io.Reader, opts *compi
// nef.NewFile() cares about version a lot. // nef.NewFile() cares about version a lot.
config.Version = "neotest" config.Version = "neotest"
ne, di, err := compiler.CompileWithDebugInfo(opts.Name, src) ne, di, err := compiler.CompileWithOptions("contract.go", src, opts)
require.NoError(t, err) require.NoError(t, err)
m, err := compiler.CreateManifest(di, opts) m, err := compiler.CreateManifest(di, opts)
@ -51,7 +51,7 @@ func CompileFile(t *testing.T, sender util.Uint160, srcPath string, configPath s
// nef.NewFile() cares about version a lot. // nef.NewFile() cares about version a lot.
config.Version = "neotest" config.Version = "neotest"
ne, di, err := compiler.CompileWithDebugInfo(srcPath, nil) ne, di, err := compiler.CompileWithOptions(srcPath, nil, nil)
require.NoError(t, err) require.NoError(t, err)
conf, err := smartcontract.ParseContractConfig(configPath) conf, err := smartcontract.ParseContractConfig(configPath)

View file

@ -0,0 +1,3 @@
name: ContractForInvokescriptTest
permissions:
- methods: ['transfer']

View file

@ -1,4 +1,4 @@
package testdata package invoke
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime" import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"

View file

@ -1,4 +1,4 @@
package testdata package verify
import ( import (
"github.com/nspcc-dev/neo-go/pkg/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/interop/runtime"

View file

@ -1,4 +1,4 @@
package testdata package verify_args
// Verify is a verification contract method which takes several arguments. // Verify is a verification contract method which takes several arguments.
func Verify(argString string, argInt int, argBool bool) bool { func Verify(argString string, argInt int, argBool bool) bool {

View file

@ -394,7 +394,9 @@ func handleLoadGo(c *ishell.Context) {
c.Err(fmt.Errorf("%w: <file>", ErrMissingParameter)) c.Err(fmt.Errorf("%w: <file>", ErrMissingParameter))
return return
} }
b, di, err := compiler.CompileWithDebugInfo(c.Args[0], nil)
name := strings.TrimSuffix(c.Args[0], ".go")
b, di, err := compiler.CompileWithOptions(c.Args[0], nil, &compiler.Options{Name: name})
if err != nil { if err != nil {
c.Err(err) c.Err(err)
return return

View file

@ -208,6 +208,9 @@ func TestLoad(t *testing.T) {
filenameErr := filepath.Join(tmpDir, "vmtestcontract_err.go") filenameErr := filepath.Join(tmpDir, "vmtestcontract_err.go")
require.NoError(t, ioutil.WriteFile(filenameErr, []byte(src+"invalid_token"), os.ModePerm)) require.NoError(t, ioutil.WriteFile(filenameErr, []byte(src+"invalid_token"), os.ModePerm))
filenameErr = "'" + filenameErr + "'" filenameErr = "'" + filenameErr + "'"
goMod := []byte(`module test.example/vmcli
go 1.16`)
require.NoError(t, ioutil.WriteFile(filepath.Join(tmpDir, "go.mod"), goMod, os.ModePerm))
e := newTestVMCLI(t) e := newTestVMCLI(t)
e.runProg(t, e.runProg(t,
@ -232,6 +235,15 @@ func TestLoad(t *testing.T) {
filename := filepath.Join(tmpDir, "vmtestcontract.go") filename := filepath.Join(tmpDir, "vmtestcontract.go")
require.NoError(t, ioutil.WriteFile(filename, []byte(srcAllowNotify), os.ModePerm)) require.NoError(t, ioutil.WriteFile(filename, []byte(srcAllowNotify), os.ModePerm))
filename = "'" + filename + "'" filename = "'" + filename + "'"
wd, err := os.Getwd()
require.NoError(t, err)
goMod := []byte(`module test.example/kek
require (
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0
)
replace github.com/nspcc-dev/neo-go/pkg/interop => ` + filepath.Join(wd, "../../interop") + `
go 1.16`)
require.NoError(t, ioutil.WriteFile(filepath.Join(tmpDir, "go.mod"), goMod, os.ModePerm))
e := newTestVMCLI(t) e := newTestVMCLI(t)
e.runProg(t, e.runProg(t,
@ -243,7 +255,7 @@ func TestLoad(t *testing.T) {
t.Run("loadnef", func(t *testing.T) { t.Run("loadnef", func(t *testing.T) {
config.Version = "0.92.0-test" config.Version = "0.92.0-test"
nefFile, di, err := compiler.CompileWithDebugInfo("test", strings.NewReader(src)) nefFile, di, err := compiler.CompileWithOptions("test.go", strings.NewReader(src), nil)
require.NoError(t, err) require.NoError(t, err)
filename := filepath.Join(tmpDir, "vmtestcontract.nef") filename := filepath.Join(tmpDir, "vmtestcontract.nef")
rawNef, err := nefFile.Bytes() rawNef, err := nefFile.Bytes()

View file

@ -75,7 +75,7 @@ func main() {
handleError("can't tranfser GAS", err) handleError("can't tranfser GAS", err)
lastBlock = addBlock(bc, lastBlock, valScript, txMoveNeo, txMoveGas) lastBlock = addBlock(bc, lastBlock, valScript, txMoveNeo, txMoveGas)
tx, contractHash, _, err := testchain.NewDeployTx(bc, "DumpContract", h, strings.NewReader(contract), nil) tx, contractHash, _, err := testchain.NewDeployTx(bc, "DumpContract.go", h, strings.NewReader(contract), nil)
handleError("can't create deploy tx", err) handleError("can't create deploy tx", err)
tx.NetworkFee = 10_000_000 tx.NetworkFee = 10_000_000
tx.ValidUntilBlock = bc.BlockHeight() + 1 tx.ValidUntilBlock = bc.BlockHeight() + 1