diff --git a/cli/smartcontract/contract_test.go b/cli/smartcontract/contract_test.go index 917f07221..bb41a4a30 100644 --- a/cli/smartcontract/contract_test.go +++ b/cli/smartcontract/contract_test.go @@ -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 diff --git a/cli/smartcontract/smart_contract.go b/cli/smartcontract/smart_contract.go index 818f07ac2..5a2af4685 100644 --- a/cli/smartcontract/smart_contract.go +++ b/cli/smartcontract/smart_contract.go @@ -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]", - Action: contractCompile, + 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"), diff --git a/cli/vm/cli.go b/cli/vm/cli.go index a8c246b66..50e71ea45 100644 --- a/cli/vm/cli.go +++ b/cli/vm/cli.go @@ -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 ] [--gas ] [, ...]`, + UsageText: `loadnef [--historic ] [--gas ] [] [-- , ...]`, Flags: []cli.Flag{historicFlag, gasFlag}, - Description: ` and parameters are mandatory. + Description: ` parameter is mandatory, parameter (if omitted) will + be guessed from the 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 ] [--gas ] [, ...]`, + UsageText: `loadbase64 [--historic ] [--gas ] [-- , ...]`, Flags: []cli.Flag{historicFlag, gasFlag}, Description: ` 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 ] [--gas ] [, ...]`, + UsageText: `loadhex [--historic ] [--gas ] [-- , ...]`, Flags: []cli.Flag{historicFlag, gasFlag}, Description: ` 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 ] [--gas ] [, ...]`, + UsageText: `loadgo [--historic ] [--gas ] [-- , ...]`, Flags: []cli.Flag{historicFlag, gasFlag}, Description: ` 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 ] [--gas ] [, ...]`, + UsageText: `loaddeployed [--historic ] [--gas ] [-- , ...]`, 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: ", ErrMissingParameter) + if len(args) < 1 { + return fmt.Errorf("%w: 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 } diff --git a/cli/vm/cli_test.go b/cli/vm/cli_test.go index 78f0c30d1..8cae8d017 100644 --- a/cli/vm/cli_test.go +++ b/cli/vm/cli_test.go @@ -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 diff --git a/docs/compiler.md b/docs/compiler.md index a38a2dcf6..d4d17efb4 100644 --- a/docs/compiler.md +++ b/docs/compiler.md @@ -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: ```