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)
})
srcPath := filepath.Join(ctrPath, "main.go")
ctrRootPath := filepath.Join(ctrPath, "main")
srcPath := ctrRootPath + ".go"
cfgPath := filepath.Join(ctrPath, "neo-go.yml")
nefPath := filepath.Join(tmpDir, "testcontract.nef")
manifestPath := filepath.Join(tmpDir, "testcontract.manifest.json")
@ -288,6 +289,19 @@ func TestContractInitAndCompile(t *testing.T) {
e.Run(t, append(cmd, "--verbose")...)
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

View file

@ -126,11 +126,18 @@ func NewCommands() []cli.Command {
Name: "compile",
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]",
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,
Flags: []cli.Flag{
cli.StringFlag{
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{
Name: "out, o",
@ -400,16 +407,42 @@ func contractCompile(ctx *cli.Context) error {
manifestFile := ctx.String("manifest")
confFile := ctx.String("config")
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)
}
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{
Outfile: ctx.String("out"),
Outfile: out,
DebugInfo: debugFile,
ManifestFile: manifestFile,
BindingsFile: ctx.String("bindings"),
BindingsFile: bindings,
NoStandardCheck: ctx.Bool("no-standards"),
NoEventsCheck: ctx.Bool("no-events"),

View file

@ -151,9 +151,11 @@ Example:
{
Name: "loadnef",
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},
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 + `
@ -164,7 +166,7 @@ Example:
{
Name: "loadbase64",
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},
Description: `<string> is mandatory parameter.
@ -177,7 +179,7 @@ Example:
{
Name: "loadhex",
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},
Description: `<string> is mandatory parameter.
@ -190,7 +192,7 @@ Example:
{
Name: "loadgo",
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},
Description: `<file> is mandatory parameter.
@ -220,7 +222,7 @@ Example:
{
Name: "loaddeployed",
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},
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.
@ -671,10 +673,36 @@ func prepareVM(c *cli.Context, tx *transaction.Transaction) error {
func handleLoadNEF(c *cli.Context) error {
args := c.Args()
if len(args) < 2 {
return fmt.Errorf("%w: <file> <manifest>", ErrMissingParameter)
if len(args) < 1 {
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 {
return err
}
@ -682,15 +710,15 @@ func handleLoadNEF(c *cli.Context) error {
if err != nil {
return fmt.Errorf("failed to decode NEF file: %w", err)
}
m, err := getManifestFromFile(args[1])
m, err := getManifestFromFile(manifestFile)
if err != nil {
return fmt.Errorf("failed to read manifest: %w", err)
}
var signers []transaction.Signer
if len(args) > 2 {
signers, err = cmdargs.ParseSigners(c.Args()[2:])
if signersStartOffset != 0 && len(args) > signersStartOffset {
signers, err = cmdargs.ParseSigners(c.Args()[signersStartOffset:])
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))
@ -715,7 +743,13 @@ func handleLoadBase64(c *cli.Context) error {
}
var signers []transaction.Signer
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 {
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
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 {
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
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 {
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() {
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)
h, err := flags.ParseAddress(hashOrID)
if err != nil {
@ -868,8 +915,14 @@ func handleLoadDeployed(c *cli.Context) error {
}
var signers []transaction.Signer
if len(c.Args()) > 1 {
signers, err = cmdargs.ParseSigners(c.Args()[1:])
if len(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 {
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"
"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/internal/basicchain"
"github.com/nspcc-dev/neo-go/internal/random"
@ -298,21 +299,27 @@ func TestLoad(t *testing.T) {
"loadhex",
"loadhex notahex",
"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",
"loadhex "+hex.EncodeToString(checkWitnessScript)+" "+ownerAddress+":None", // owner:None => false
"loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAddress+":None", // owner:None => false
"run",
"loadhex "+hex.EncodeToString(checkWitnessScript)+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true
"loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true
"run",
"loadhex "+hex.EncodeToString(checkWitnessScript)+" 0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true
"loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+"0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true
"run",
"loadhex "+hex.EncodeToString(checkWitnessScript)+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false
"loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false
"run",
)
e.checkError(t, ErrMissingParameter)
e.checkError(t, ErrInvalidParameter)
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.checkStack(t, true)
e.checkNextLine(t, "READY: loaded \\d+ instructions")
@ -330,21 +337,27 @@ func TestLoad(t *testing.T) {
"loadbase64",
"loadbase64 not_a_base64",
"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",
"loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+ownerAddress+":None", // owner:None => false
"loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAddress+":None", // owner:None => false
"run",
"loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true
"loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true
"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",
"loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false
"loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false
"run",
)
e.checkError(t, ErrMissingParameter)
e.checkError(t, ErrInvalidParameter)
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.checkStack(t, true)
e.checkNextLine(t, "READY: loaded \\d+ instructions")
@ -440,12 +453,23 @@ go 1.18`)
}
`
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) {
e := newTestVMCLI(t)
e.runProg(t,
"loadgo "+filename+" "+ownerAddress, // owner:DefaultScope => true
"loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+ownerAddress, // owner:DefaultScope => true
"run main",
"loadgo "+filename+" "+ownerAddress+":None", // owner:None => false
"loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+ownerAddress+":None", // owner:None => false
"run main")
e.checkNextLine(t, "READY: loaded \\d+ instructions")
e.checkStack(t, true)
@ -455,9 +479,9 @@ go 1.18`)
t.Run("string LE", func(t *testing.T) {
e := newTestVMCLI(t)
e.runProg(t,
"loadgo "+filename+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true
"loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true
"run main",
"loadgo "+filename+" 0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true
"loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+"0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true
"run main")
e.checkNextLine(t, "READY: loaded \\d+ instructions")
e.checkStack(t, true)
@ -467,7 +491,7 @@ go 1.18`)
t.Run("nonwitnessed signer", func(t *testing.T) {
e := newTestVMCLI(t)
e.runProg(t,
"loadgo "+filename+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false
"loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false
"run main")
e.checkNextLine(t, "READY: loaded \\d+ instructions")
e.checkStack(t, false)
@ -503,7 +527,17 @@ go 1.18`)
"loadnef "+filename+" "+notExists,
"loadnef "+filename+" "+filename,
"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.checkNextLine(t, "Error:")
@ -511,6 +545,15 @@ go 1.18`)
e.checkNextLine(t, "Error:")
e.checkNextLine(t, "READY: loaded \\d* instructions")
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",
"loaddeployed --gas 420000 "+h.StringLE(), // gas-limited
"run get 1",
"loaddeployed 0x"+h.StringLE(), // hash LE with 0x prefix
"loaddeployed "+"0x"+h.StringLE(), // hash LE with 0x prefix
"run get 1",
"loaddeployed 1", // contract ID
"run get 1",
"loaddeployed --historic 2 1", // historic state, check that hash is properly set
"run get 1",
// 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",
"loaddeployed 2 "+ownerAddress+":None", // check witness (owner:None => false)
"loaddeployed 2 "+cmdargs.CosignersSeparator+" "+ownerAddress+":None", // check witness (owner:None => false)
"run checkWitness",
"loaddeployed 2 "+ownerAddress+":CalledByEntry", // check witness (owner:CalledByEntry => true)
"loaddeployed 2 "+cmdargs.CosignersSeparator+" "+ownerAddress+":CalledByEntry", // check witness (owner:CalledByEntry => true)
"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",
"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",
"loaddeployed 2 "+sideAcc.StringLE()+":Global", // check witness (sideLE:Global => false)
"loaddeployed 2 "+cmdargs.CosignersSeparator+" "+sideAcc.StringLE()+":Global", // check witness (sideLE:Global => false)
"run checkWitness",
"loaddeployed", // missing argument
"exit",
@ -1186,6 +1232,9 @@ func TestLoaddeployed(t *testing.T) {
e.checkNextLine(t, "READY: loaded \\d+ instructions")
e.checkStack(t, []byte{1})
// 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.checkStack(t, true)
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
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:
```