cli: use cosigners separator for VM CLI commands where appropriate

Needed for further VM CLI commands improvement, we'll add another
positional args.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
This commit is contained in:
Anna Shaleva 2023-05-16 17:54:41 +03:00
parent a2449ae8ae
commit ed2b59e077
2 changed files with 95 additions and 34 deletions

View file

@ -151,7 +151,7 @@ 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> and <manifest> parameters are mandatory.
@ -164,7 +164,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 +177,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 +190,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 +220,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.
@ -688,7 +688,13 @@ func handleLoadNEF(c *cli.Context) error {
} }
var signers []transaction.Signer var signers []transaction.Signer
if len(args) > 2 { if len(args) > 2 {
signers, err = cmdargs.ParseSigners(c.Args()[2:]) if args[2] != cmdargs.CosignersSeparator {
return fmt.Errorf("%w: `%s` was expected as the third parameter, got %s", ErrInvalidParameter, cmdargs.CosignersSeparator, args[2])
}
if len(args) < 4 {
return fmt.Errorf("%w: signers expected after `%s`, got none", ErrInvalidParameter, cmdargs.CosignersSeparator)
}
signers, err = cmdargs.ParseSigners(c.Args()[3:])
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
} }
@ -715,7 +721,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 +761,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 +801,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 +873,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 +893,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)
@ -1153,24 +1177,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 +1213,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