Merge pull request #3013 from nspcc-dev/loadnef-enh
cli: autocomplete contract-related filenames for `compile` and `loadnef` commands
This commit is contained in:
commit
d463bad96f
5 changed files with 205 additions and 48 deletions
|
@ -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
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
Loading…
Reference in a new issue