Merge pull request #3013 from nspcc-dev/loadnef-enh

cli: autocomplete contract-related filenames for `compile` and `loadnef` commands
This commit is contained in:
Roman Khimov 2023-05-17 15:05:00 +03:00 committed by GitHub
commit d463bad96f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 205 additions and 48 deletions

View file

@ -237,7 +237,8 @@ func TestContractInitAndCompile(t *testing.T) {
e.RunWithError(t, "neo-go", "contract", "init", "--name", ctrPath) e.RunWithError(t, "neo-go", "contract", "init", "--name", ctrPath)
}) })
srcPath := filepath.Join(ctrPath, "main.go") ctrRootPath := filepath.Join(ctrPath, "main")
srcPath := ctrRootPath + ".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")
manifestPath := filepath.Join(tmpDir, "testcontract.manifest.json") manifestPath := filepath.Join(tmpDir, "testcontract.manifest.json")
@ -288,6 +289,19 @@ func TestContractInitAndCompile(t *testing.T) {
e.Run(t, append(cmd, "--verbose")...) e.Run(t, append(cmd, "--verbose")...)
e.CheckNextLine(t, "^[0-9a-hA-H]+$") e.CheckNextLine(t, "^[0-9a-hA-H]+$")
}) })
t.Run("autocomplete outputs", func(t *testing.T) {
cfg, err := os.ReadFile(cfgPath)
require.NoError(t, err)
require.NoError(t, os.WriteFile(filepath.Join(ctrPath, "main.yml"), cfg, os.ModePerm))
e.Run(t, "neo-go", "contract", "compile", "--in", srcPath)
defaultNefPath := ctrRootPath + ".nef"
defaultManifestPath := ctrRootPath + ".manifest.json"
defaultBindingsPath := ctrRootPath + ".bindings.yml"
require.FileExists(t, defaultNefPath)
require.FileExists(t, defaultManifestPath)
require.FileExists(t, defaultBindingsPath)
})
} }
// Checks that error is returned if GAS available for test-invoke exceeds // Checks that error is returned if GAS available for test-invoke exceeds

View file

@ -126,11 +126,18 @@ func NewCommands() []cli.Command {
Name: "compile", Name: "compile",
Usage: "compile a smart contract to a .nef file", Usage: "compile a smart contract to a .nef file",
UsageText: "neo-go contract compile -i path [-o nef] [-v] [-d] [-m manifest] [-c yaml] [--bindings file] [--no-standards] [--no-events] [--no-permissions]", UsageText: "neo-go contract compile -i path [-o nef] [-v] [-d] [-m manifest] [-c yaml] [--bindings file] [--no-standards] [--no-events] [--no-permissions]",
Description: `Compiles given smart contract to a .nef file and emits other associated
information (manifest, bindings configuration, debug information files) if
asked to. If none of --out, --manifest, --config, --bindings flags are specified,
then the output filenames for these flags will be guessed using the contract
name or path provided via --in option by trimming/adding corresponding suffixes
to the common part of the path. In the latter case the configuration filepath
will be guessed from the --in option using the same rule."`,
Action: contractCompile, Action: contractCompile,
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ cli.StringFlag{
Name: "in, i", Name: "in, i",
Usage: "Input file for the smart contract to be compiled", Usage: "Input file for the smart contract to be compiled (*.go file or directory)",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "out, o", Name: "out, o",
@ -400,16 +407,42 @@ func contractCompile(ctx *cli.Context) error {
manifestFile := ctx.String("manifest") manifestFile := ctx.String("manifest")
confFile := ctx.String("config") confFile := ctx.String("config")
debugFile := ctx.String("debug") debugFile := ctx.String("debug")
if len(confFile) == 0 && (len(manifestFile) != 0 || len(debugFile) != 0) { out := ctx.String("out")
bindings := ctx.String("bindings")
if len(confFile) == 0 && (len(manifestFile) != 0 || len(debugFile) != 0 || len(bindings) != 0) {
return cli.NewExitError(errNoConfFile, 1) return cli.NewExitError(errNoConfFile, 1)
} }
autocomplete := len(manifestFile) == 0 &&
len(confFile) == 0 &&
len(out) == 0 &&
len(bindings) == 0
if autocomplete {
var root string
fileInfo, err := os.Stat(src)
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to stat source file or directory: %w", err), 1)
}
if fileInfo.IsDir() {
base := filepath.Base(fileInfo.Name())
if base == string(filepath.Separator) {
base = "contract"
}
root = filepath.Join(src, base)
} else {
root = strings.TrimSuffix(src, ".go")
}
manifestFile = root + ".manifest.json"
confFile = root + ".yml"
out = root + ".nef"
bindings = root + ".bindings.yml"
}
o := &compiler.Options{ o := &compiler.Options{
Outfile: ctx.String("out"), Outfile: out,
DebugInfo: debugFile, DebugInfo: debugFile,
ManifestFile: manifestFile, ManifestFile: manifestFile,
BindingsFile: ctx.String("bindings"), BindingsFile: bindings,
NoStandardCheck: ctx.Bool("no-standards"), NoStandardCheck: ctx.Bool("no-standards"),
NoEventsCheck: ctx.Bool("no-events"), NoEventsCheck: ctx.Bool("no-events"),

View file

@ -151,9 +151,11 @@ Example:
{ {
Name: "loadnef", Name: "loadnef",
Usage: "Load a NEF-consistent script into the VM optionally attaching to it provided signers with scopes", Usage: "Load a NEF-consistent script into the VM optionally attaching to it provided signers with scopes",
UsageText: `loadnef [--historic <height>] [--gas <int>] <file> <manifest> [<signer-with-scope>, ...]`, UsageText: `loadnef [--historic <height>] [--gas <int>] <file> [<manifest>] [-- <signer-with-scope>, ...]`,
Flags: []cli.Flag{historicFlag, gasFlag}, Flags: []cli.Flag{historicFlag, gasFlag},
Description: `<file> and <manifest> parameters are mandatory. Description: `<file> parameter is mandatory, <manifest> parameter (if omitted) will
be guessed from the <file> parameter by replacing '.nef' suffix with '.manifest.json'
suffix.
` + cmdargs.SignersParsingDoc + ` ` + cmdargs.SignersParsingDoc + `
@ -164,7 +166,7 @@ Example:
{ {
Name: "loadbase64", Name: "loadbase64",
Usage: "Load a base64-encoded script string into the VM optionally attaching to it provided signers with scopes", Usage: "Load a base64-encoded script string into the VM optionally attaching to it provided signers with scopes",
UsageText: `loadbase64 [--historic <height>] [--gas <int>] <string> [<signer-with-scope>, ...]`, UsageText: `loadbase64 [--historic <height>] [--gas <int>] <string> [-- <signer-with-scope>, ...]`,
Flags: []cli.Flag{historicFlag, gasFlag}, Flags: []cli.Flag{historicFlag, gasFlag},
Description: `<string> is mandatory parameter. Description: `<string> is mandatory parameter.
@ -177,7 +179,7 @@ Example:
{ {
Name: "loadhex", Name: "loadhex",
Usage: "Load a hex-encoded script string into the VM optionally attaching to it provided signers with scopes", Usage: "Load a hex-encoded script string into the VM optionally attaching to it provided signers with scopes",
UsageText: `loadhex [--historic <height>] [--gas <int>] <string> [<signer-with-scope>, ...]`, UsageText: `loadhex [--historic <height>] [--gas <int>] <string> [-- <signer-with-scope>, ...]`,
Flags: []cli.Flag{historicFlag, gasFlag}, Flags: []cli.Flag{historicFlag, gasFlag},
Description: `<string> is mandatory parameter. Description: `<string> is mandatory parameter.
@ -190,7 +192,7 @@ Example:
{ {
Name: "loadgo", Name: "loadgo",
Usage: "Compile and load a Go file with the manifest into the VM optionally attaching to it provided signers with scopes", Usage: "Compile and load a Go file with the manifest into the VM optionally attaching to it provided signers with scopes",
UsageText: `loadgo [--historic <height>] [--gas <int>] <file> [<signer-with-scope>, ...]`, UsageText: `loadgo [--historic <height>] [--gas <int>] <file> [-- <signer-with-scope>, ...]`,
Flags: []cli.Flag{historicFlag, gasFlag}, Flags: []cli.Flag{historicFlag, gasFlag},
Description: `<file> is mandatory parameter. Description: `<file> is mandatory parameter.
@ -220,7 +222,7 @@ Example:
{ {
Name: "loaddeployed", Name: "loaddeployed",
Usage: "Load deployed contract into the VM from chain optionally attaching to it provided signers with scopes", Usage: "Load deployed contract into the VM from chain optionally attaching to it provided signers with scopes",
UsageText: `loaddeployed [--historic <height>] [--gas <int>] <hash-or-address-or-id> [<signer-with-scope>, ...]`, UsageText: `loaddeployed [--historic <height>] [--gas <int>] <hash-or-address-or-id> [-- <signer-with-scope>, ...]`,
Flags: []cli.Flag{historicFlag, gasFlag}, Flags: []cli.Flag{historicFlag, gasFlag},
Description: `Load deployed contract into the VM from chain optionally attaching to it provided signers with scopes. Description: `Load deployed contract into the VM from chain optionally attaching to it provided signers with scopes.
If '--historic' flag specified, then the historic contract state (historic script and manifest) will be loaded. If '--historic' flag specified, then the historic contract state (historic script and manifest) will be loaded.
@ -671,10 +673,36 @@ func prepareVM(c *cli.Context, tx *transaction.Transaction) error {
func handleLoadNEF(c *cli.Context) error { func handleLoadNEF(c *cli.Context) error {
args := c.Args() args := c.Args()
if len(args) < 2 { if len(args) < 1 {
return fmt.Errorf("%w: <file> <manifest>", ErrMissingParameter) return fmt.Errorf("%w: <nef> is required", ErrMissingParameter)
} }
b, err := os.ReadFile(args[0]) nefFile := args[0]
var (
manifestFile string
signersStartOffset int
)
if len(args) == 2 {
manifestFile = args[1]
} else if len(args) == 3 {
if args[1] != cmdargs.CosignersSeparator {
return fmt.Errorf("%w: `%s` was expected as the second parameter, got %s", ErrInvalidParameter, cmdargs.CosignersSeparator, args[1])
}
signersStartOffset = 2
} else if len(args) > 3 {
if args[1] == cmdargs.CosignersSeparator {
signersStartOffset = 2
} else {
manifestFile = args[1]
if args[2] != cmdargs.CosignersSeparator {
return fmt.Errorf("%w: `%s` was expected as the third parameter, got %s", ErrInvalidParameter, cmdargs.CosignersSeparator, args[2])
}
signersStartOffset = 3
}
}
if len(manifestFile) == 0 {
manifestFile = strings.TrimSuffix(nefFile, ".nef") + ".manifest.json"
}
b, err := os.ReadFile(nefFile)
if err != nil { if err != nil {
return err return err
} }
@ -682,15 +710,15 @@ func handleLoadNEF(c *cli.Context) error {
if err != nil { if err != nil {
return fmt.Errorf("failed to decode NEF file: %w", err) return fmt.Errorf("failed to decode NEF file: %w", err)
} }
m, err := getManifestFromFile(args[1]) m, err := getManifestFromFile(manifestFile)
if err != nil { if err != nil {
return fmt.Errorf("failed to read manifest: %w", err) return fmt.Errorf("failed to read manifest: %w", err)
} }
var signers []transaction.Signer var signers []transaction.Signer
if len(args) > 2 { if signersStartOffset != 0 && len(args) > signersStartOffset {
signers, err = cmdargs.ParseSigners(c.Args()[2:]) signers, err = cmdargs.ParseSigners(c.Args()[signersStartOffset:])
if err != nil { if err != nil {
return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors return fmt.Errorf("%w: failed to parse signers: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
} }
} }
err = prepareVM(c, createFakeTransaction(nef.Script, signers)) err = prepareVM(c, createFakeTransaction(nef.Script, signers))
@ -715,7 +743,13 @@ func handleLoadBase64(c *cli.Context) error {
} }
var signers []transaction.Signer var signers []transaction.Signer
if len(args) > 1 { if len(args) > 1 {
signers, err = cmdargs.ParseSigners(args[1:]) if args[1] != cmdargs.CosignersSeparator {
return fmt.Errorf("%w: `%s` was expected as the second parameter, got %s", ErrInvalidParameter, cmdargs.CosignersSeparator, args[1])
}
if len(args) < 3 {
return fmt.Errorf("%w: signers expected after `%s`, got none", ErrInvalidParameter, cmdargs.CosignersSeparator)
}
signers, err = cmdargs.ParseSigners(args[2:])
if err != nil { if err != nil {
return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
} }
@ -749,7 +783,13 @@ func handleLoadHex(c *cli.Context) error {
} }
var signers []transaction.Signer var signers []transaction.Signer
if len(args) > 1 { if len(args) > 1 {
signers, err = cmdargs.ParseSigners(args[1:]) if args[1] != cmdargs.CosignersSeparator {
return fmt.Errorf("%w: `%s` was expected as the second parameter, got %s", ErrInvalidParameter, cmdargs.CosignersSeparator, args[1])
}
if len(args) < 3 {
return fmt.Errorf("%w: signers expected after `%s`, got none", ErrInvalidParameter, cmdargs.CosignersSeparator)
}
signers, err = cmdargs.ParseSigners(args[2:])
if err != nil { if err != nil {
return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
} }
@ -783,7 +823,13 @@ func handleLoadGo(c *cli.Context) error {
} }
var signers []transaction.Signer var signers []transaction.Signer
if len(args) > 1 { if len(args) > 1 {
signers, err = cmdargs.ParseSigners(args[1:]) if args[1] != cmdargs.CosignersSeparator {
return fmt.Errorf("%w: `%s` was expected as the second parameter, got %s", ErrInvalidParameter, cmdargs.CosignersSeparator, args[1])
}
if len(args) < 3 {
return fmt.Errorf("%w: signers expected after `%s`, got none", ErrInvalidParameter, cmdargs.CosignersSeparator)
}
signers, err = cmdargs.ParseSigners(args[2:])
if err != nil { if err != nil {
return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
} }
@ -849,7 +895,8 @@ func handleLoadDeployed(c *cli.Context) error {
if !c.Args().Present() { if !c.Args().Present() {
return errors.New("contract hash, address or ID is mandatory argument") return errors.New("contract hash, address or ID is mandatory argument")
} }
hashOrID := c.Args().Get(0) args := c.Args()
hashOrID := args[0]
ic := getInteropContextFromContext(c.App) ic := getInteropContextFromContext(c.App)
h, err := flags.ParseAddress(hashOrID) h, err := flags.ParseAddress(hashOrID)
if err != nil { if err != nil {
@ -868,8 +915,14 @@ func handleLoadDeployed(c *cli.Context) error {
} }
var signers []transaction.Signer var signers []transaction.Signer
if len(c.Args()) > 1 { if len(args) > 1 {
signers, err = cmdargs.ParseSigners(c.Args()[1:]) if args[1] != cmdargs.CosignersSeparator {
return fmt.Errorf("%w: %s was expected as the second parameter, got %s", ErrInvalidParameter, cmdargs.CosignersSeparator, args[1])
}
if len(args) < 3 {
return fmt.Errorf("%w: signers expected after `%s`, got none", ErrInvalidParameter, cmdargs.CosignersSeparator)
}
signers, err = cmdargs.ParseSigners(args[2:])
if err != nil { if err != nil {
return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
} }

View file

@ -18,6 +18,7 @@ import (
"time" "time"
"github.com/chzyer/readline" "github.com/chzyer/readline"
"github.com/nspcc-dev/neo-go/cli/cmdargs"
"github.com/nspcc-dev/neo-go/cli/paramcontext" "github.com/nspcc-dev/neo-go/cli/paramcontext"
"github.com/nspcc-dev/neo-go/internal/basicchain" "github.com/nspcc-dev/neo-go/internal/basicchain"
"github.com/nspcc-dev/neo-go/internal/random" "github.com/nspcc-dev/neo-go/internal/random"
@ -298,21 +299,27 @@ func TestLoad(t *testing.T) {
"loadhex", "loadhex",
"loadhex notahex", "loadhex notahex",
"loadhex "+hex.EncodeToString(script), "loadhex "+hex.EncodeToString(script),
"loadhex "+hex.EncodeToString(checkWitnessScript)+" "+ownerAddress, // owner:DefaultScope => true "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator,
"loadhex "+hex.EncodeToString(checkWitnessScript)+" "+"not-a-separator",
"loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+"not-a-signer",
"loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAddress, // owner:DefaultScope => true
"run", "run",
"loadhex "+hex.EncodeToString(checkWitnessScript)+" "+ownerAddress+":None", // owner:None => false "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAddress+":None", // owner:None => false
"run", "run",
"loadhex "+hex.EncodeToString(checkWitnessScript)+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true
"run", "run",
"loadhex "+hex.EncodeToString(checkWitnessScript)+" 0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+"0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true
"run", "run",
"loadhex "+hex.EncodeToString(checkWitnessScript)+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false
"run", "run",
) )
e.checkError(t, ErrMissingParameter) e.checkError(t, ErrMissingParameter)
e.checkError(t, ErrInvalidParameter) e.checkError(t, ErrInvalidParameter)
e.checkNextLine(t, "READY: loaded 3 instructions") e.checkNextLine(t, "READY: loaded 3 instructions")
e.checkError(t, ErrInvalidParameter)
e.checkError(t, ErrInvalidParameter)
e.checkError(t, ErrInvalidParameter)
e.checkNextLine(t, "READY: loaded \\d+ instructions") e.checkNextLine(t, "READY: loaded \\d+ instructions")
e.checkStack(t, true) e.checkStack(t, true)
e.checkNextLine(t, "READY: loaded \\d+ instructions") e.checkNextLine(t, "READY: loaded \\d+ instructions")
@ -330,21 +337,27 @@ func TestLoad(t *testing.T) {
"loadbase64", "loadbase64",
"loadbase64 not_a_base64", "loadbase64 not_a_base64",
"loadbase64 "+base64.StdEncoding.EncodeToString(script), "loadbase64 "+base64.StdEncoding.EncodeToString(script),
"loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+ownerAddress, // owner:DefaultScope => true "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator,
"loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+"not-a-separator",
"loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" not-a-signer",
"loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAddress, // owner:DefaultScope => true
"run", "run",
"loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+ownerAddress+":None", // owner:None => false "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAddress+":None", // owner:None => false
"run", "run",
"loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true
"run", "run",
"loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" 0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+"0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true
"run", "run",
"loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false
"run", "run",
) )
e.checkError(t, ErrMissingParameter) e.checkError(t, ErrMissingParameter)
e.checkError(t, ErrInvalidParameter) e.checkError(t, ErrInvalidParameter)
e.checkNextLine(t, "READY: loaded 3 instructions") e.checkNextLine(t, "READY: loaded 3 instructions")
e.checkError(t, ErrInvalidParameter)
e.checkError(t, ErrInvalidParameter)
e.checkError(t, ErrInvalidParameter)
e.checkNextLine(t, "READY: loaded \\d+ instructions") e.checkNextLine(t, "READY: loaded \\d+ instructions")
e.checkStack(t, true) e.checkStack(t, true)
e.checkNextLine(t, "READY: loaded \\d+ instructions") e.checkNextLine(t, "READY: loaded \\d+ instructions")
@ -440,12 +453,23 @@ go 1.18`)
} }
` `
filename := prepareLoadgoSrc(t, srcCheckWitness) filename := prepareLoadgoSrc(t, srcCheckWitness)
t.Run("invalid", func(t *testing.T) {
e := newTestVMCLI(t)
e.runProg(t,
"loadgo "+filename+" "+cmdargs.CosignersSeparator,
"loadgo "+filename+" "+"not-a-separator",
"loadgo "+filename+" "+cmdargs.CosignersSeparator+" not-a-signer",
)
e.checkError(t, ErrInvalidParameter)
e.checkError(t, ErrInvalidParameter)
e.checkError(t, ErrInvalidParameter)
})
t.Run("address", func(t *testing.T) { t.Run("address", func(t *testing.T) {
e := newTestVMCLI(t) e := newTestVMCLI(t)
e.runProg(t, e.runProg(t,
"loadgo "+filename+" "+ownerAddress, // owner:DefaultScope => true "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+ownerAddress, // owner:DefaultScope => true
"run main", "run main",
"loadgo "+filename+" "+ownerAddress+":None", // owner:None => false "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+ownerAddress+":None", // owner:None => false
"run main") "run main")
e.checkNextLine(t, "READY: loaded \\d+ instructions") e.checkNextLine(t, "READY: loaded \\d+ instructions")
e.checkStack(t, true) e.checkStack(t, true)
@ -455,9 +479,9 @@ go 1.18`)
t.Run("string LE", func(t *testing.T) { t.Run("string LE", func(t *testing.T) {
e := newTestVMCLI(t) e := newTestVMCLI(t)
e.runProg(t, e.runProg(t,
"loadgo "+filename+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true
"run main", "run main",
"loadgo "+filename+" 0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+"0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true
"run main") "run main")
e.checkNextLine(t, "READY: loaded \\d+ instructions") e.checkNextLine(t, "READY: loaded \\d+ instructions")
e.checkStack(t, true) e.checkStack(t, true)
@ -467,7 +491,7 @@ go 1.18`)
t.Run("nonwitnessed signer", func(t *testing.T) { t.Run("nonwitnessed signer", func(t *testing.T) {
e := newTestVMCLI(t) e := newTestVMCLI(t)
e.runProg(t, e.runProg(t,
"loadgo "+filename+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false
"run main") "run main")
e.checkNextLine(t, "READY: loaded \\d+ instructions") e.checkNextLine(t, "READY: loaded \\d+ instructions")
e.checkStack(t, false) e.checkStack(t, false)
@ -503,7 +527,17 @@ go 1.18`)
"loadnef "+filename+" "+notExists, "loadnef "+filename+" "+notExists,
"loadnef "+filename+" "+filename, "loadnef "+filename+" "+filename,
"loadnef "+filename+" "+manifestFile, "loadnef "+filename+" "+manifestFile,
"run main add 3 5") "run main add 3 5",
"loadnef "+filename,
"run main add 3 5",
"loadnef "+filename+" "+cmdargs.CosignersSeparator,
"loadnef "+filename+" "+manifestFile+" "+cmdargs.CosignersSeparator,
"loadnef "+filename+" "+manifestFile+" "+"not-a-separator",
"loadnef "+filename+" "+cmdargs.CosignersSeparator+" "+util.Uint160{1, 2, 3}.StringLE(),
"run main add 3 5",
"loadnef "+filename+" "+manifestFile+" "+cmdargs.CosignersSeparator+" "+util.Uint160{1, 2, 3}.StringLE(),
"run main add 3 5",
)
e.checkError(t, ErrMissingParameter) e.checkError(t, ErrMissingParameter)
e.checkNextLine(t, "Error:") e.checkNextLine(t, "Error:")
@ -511,6 +545,15 @@ go 1.18`)
e.checkNextLine(t, "Error:") e.checkNextLine(t, "Error:")
e.checkNextLine(t, "READY: loaded \\d* instructions") e.checkNextLine(t, "READY: loaded \\d* instructions")
e.checkStack(t, 8) e.checkStack(t, 8)
e.checkNextLine(t, "READY: loaded \\d* instructions")
e.checkStack(t, 8)
e.checkNextLine(t, "Error:") // manifest missing, missing signer after --
e.checkNextLine(t, "Error:") // manifest present, missing signer after --
e.checkNextLine(t, "Error:") // manifest present, invalid separator
e.checkNextLine(t, "READY: loaded \\d* instructions") // manifest missing, signer present, OK
e.checkStack(t, 8)
e.checkNextLine(t, "READY: loaded \\d* instructions") // manifest present, signer present, OK
e.checkStack(t, 8)
}) })
} }
@ -1153,24 +1196,27 @@ func TestLoaddeployed(t *testing.T) {
"run get 1", "run get 1",
"loaddeployed --gas 420000 "+h.StringLE(), // gas-limited "loaddeployed --gas 420000 "+h.StringLE(), // gas-limited
"run get 1", "run get 1",
"loaddeployed 0x"+h.StringLE(), // hash LE with 0x prefix "loaddeployed "+"0x"+h.StringLE(), // hash LE with 0x prefix
"run get 1", "run get 1",
"loaddeployed 1", // contract ID "loaddeployed 1", // contract ID
"run get 1", "run get 1",
"loaddeployed --historic 2 1", // historic state, check that hash is properly set "loaddeployed --historic 2 1", // historic state, check that hash is properly set
"run get 1", "run get 1",
// Check signers parsing: // Check signers parsing:
"loaddeployed 2 "+ownerAddress, // check witness (owner:DefautScope => true) "loaddeployed 2 "+cmdargs.CosignersSeparator,
"loaddeployed 2 "+"not-a-separator",
"loaddeployed 2 "+cmdargs.CosignersSeparator+" not-a-signer",
"loaddeployed 2 "+cmdargs.CosignersSeparator+" "+ownerAddress, // check witness (owner:DefautScope => true)
"run checkWitness", "run checkWitness",
"loaddeployed 2 "+ownerAddress+":None", // check witness (owner:None => false) "loaddeployed 2 "+cmdargs.CosignersSeparator+" "+ownerAddress+":None", // check witness (owner:None => false)
"run checkWitness", "run checkWitness",
"loaddeployed 2 "+ownerAddress+":CalledByEntry", // check witness (owner:CalledByEntry => true) "loaddeployed 2 "+cmdargs.CosignersSeparator+" "+ownerAddress+":CalledByEntry", // check witness (owner:CalledByEntry => true)
"run checkWitness", "run checkWitness",
"loaddeployed 2 "+ownerAcc.StringLE()+":CalledByEntry", // check witness (ownerLE:CalledByEntry => true) "loaddeployed 2 "+cmdargs.CosignersSeparator+" "+ownerAcc.StringLE()+":CalledByEntry", // check witness (ownerLE:CalledByEntry => true)
"run checkWitness", "run checkWitness",
"loaddeployed 2 0x"+ownerAcc.StringLE()+":CalledByEntry", // check witness (owner0xLE:CalledByEntry => true) "loaddeployed 2 "+cmdargs.CosignersSeparator+" "+"0x"+ownerAcc.StringLE()+":CalledByEntry", // check witness (owner0xLE:CalledByEntry => true)
"run checkWitness", "run checkWitness",
"loaddeployed 2 "+sideAcc.StringLE()+":Global", // check witness (sideLE:Global => false) "loaddeployed 2 "+cmdargs.CosignersSeparator+" "+sideAcc.StringLE()+":Global", // check witness (sideLE:Global => false)
"run checkWitness", "run checkWitness",
"loaddeployed", // missing argument "loaddeployed", // missing argument
"exit", "exit",
@ -1186,6 +1232,9 @@ func TestLoaddeployed(t *testing.T) {
e.checkNextLine(t, "READY: loaded \\d+ instructions") e.checkNextLine(t, "READY: loaded \\d+ instructions")
e.checkStack(t, []byte{1}) e.checkStack(t, []byte{1})
// Check signers parsing: // Check signers parsing:
e.checkError(t, ErrInvalidParameter)
e.checkError(t, ErrInvalidParameter)
e.checkError(t, ErrInvalidParameter)
e.checkNextLine(t, "READY: loaded \\d+ instructions") // check witness of owner:DefaultScope e.checkNextLine(t, "READY: loaded \\d+ instructions") // check witness of owner:DefaultScope
e.checkStack(t, true) e.checkStack(t, true)
e.checkNextLine(t, "READY: loaded \\d+ instructions") // check witness of owner:None e.checkNextLine(t, "READY: loaded \\d+ instructions") // check witness of owner:None

View file

@ -80,6 +80,14 @@ $ go mod tidy
By default, the filename will be the name of your .go file with the .nef By default, the filename will be the name of your .go file with the .nef
extension, the file will be located in the same directory with your Go contract. extension, the file will be located in the same directory with your Go contract.
Along with the compiled contract and if the contract configuration file
`contract.yml` exist, the following files will be generated:
* smart-contract manifest file (`contract.manifest.json`) that is needed to deploy
the contract to the network
* bindings configuration file (`contract.bindings.yml`) that is needed to generate
code-based or RPC contract bindings
All of them will be located in the same directory with your Go contract.
If you want another location for your compiled contract: If you want another location for your compiled contract:
``` ```