From 2ab420ed18feb436270f4fe50b93c5dddbabeafe Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 21 Apr 2021 10:54:10 +0300 Subject: [PATCH] cli: move cosigners parsing to a separate function We have a lot of common code which is shared between `smartcontract` and `wallet` cli packages. It's convinient to keep it in a separate helper package in order to avoid functional cli packages dependencies. --- cli/cmdargs/parser.go | 49 +++++++++++++++++++++ cli/cmdargs/parser_test.go | 54 ++++++++++++++++++++++++ cli/smartcontract/smart_contract.go | 48 ++++----------------- cli/smartcontract/smart_contract_test.go | 47 --------------------- 4 files changed, 111 insertions(+), 87 deletions(-) create mode 100644 cli/cmdargs/parser.go create mode 100644 cli/cmdargs/parser_test.go diff --git a/cli/cmdargs/parser.go b/cli/cmdargs/parser.go new file mode 100644 index 000000000..9993466e3 --- /dev/null +++ b/cli/cmdargs/parser.go @@ -0,0 +1,49 @@ +package cmdargs + +import ( + "fmt" + "strings" + + "github.com/nspcc-dev/neo-go/cli/flags" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/urfave/cli" +) + +// GetSignersFromContext returns signers parsed from context args starting +// from the specified offset. +func GetSignersFromContext(ctx *cli.Context, offset int) ([]transaction.Signer, *cli.ExitError) { + args := ctx.Args() + var signers []transaction.Signer + if args.Present() && len(args) > offset { + for i, c := range args[offset:] { + cosigner, err := parseCosigner(c) + if err != nil { + return nil, cli.NewExitError(fmt.Errorf("failed to parse signer #%d: %w", i, err), 1) + } + signers = append(signers, cosigner) + } + } + return signers, nil +} + +func parseCosigner(c string) (transaction.Signer, error) { + var ( + err error + res = transaction.Signer{ + Scopes: transaction.CalledByEntry, + } + ) + data := strings.SplitN(c, ":", 2) + s := data[0] + res.Account, err = flags.ParseAddress(s) + if err != nil { + return res, err + } + if len(data) > 1 { + res.Scopes, err = transaction.ScopesFromString(data[1]) + if err != nil { + return transaction.Signer{}, err + } + } + return res, nil +} diff --git a/cli/cmdargs/parser_test.go b/cli/cmdargs/parser_test.go new file mode 100644 index 000000000..31cfc7f6b --- /dev/null +++ b/cli/cmdargs/parser_test.go @@ -0,0 +1,54 @@ +package cmdargs + +import ( + "testing" + + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/stretchr/testify/require" +) + +func TestParseCosigner(t *testing.T) { + acc := util.Uint160{1, 3, 5, 7} + testCases := map[string]transaction.Signer{ + acc.StringLE(): { + Account: acc, + Scopes: transaction.CalledByEntry, + }, + "0x" + acc.StringLE(): { + Account: acc, + Scopes: transaction.CalledByEntry, + }, + acc.StringLE() + ":Global": { + Account: acc, + Scopes: transaction.Global, + }, + acc.StringLE() + ":CalledByEntry": { + Account: acc, + Scopes: transaction.CalledByEntry, + }, + acc.StringLE() + ":None": { + Account: acc, + Scopes: transaction.None, + }, + acc.StringLE() + ":CalledByEntry,CustomContracts": { + Account: acc, + Scopes: transaction.CalledByEntry | transaction.CustomContracts, + }, + } + for s, expected := range testCases { + actual, err := parseCosigner(s) + require.NoError(t, err) + require.Equal(t, expected, actual) + } + errorCases := []string{ + acc.StringLE() + "0", + acc.StringLE() + ":Unknown", + acc.StringLE() + ":Global,CustomContracts", + acc.StringLE() + ":Global,None", + } + for _, s := range errorCases { + _, err := parseCosigner(s) + require.Error(t, err) + } +} diff --git a/cli/smartcontract/smart_contract.go b/cli/smartcontract/smart_contract.go index a3306fe0d..ed0bad0c1 100644 --- a/cli/smartcontract/smart_contract.go +++ b/cli/smartcontract/smart_contract.go @@ -11,6 +11,7 @@ import ( "path/filepath" "strings" + "github.com/nspcc-dev/neo-go/cli/cmdargs" "github.com/nspcc-dev/neo-go/cli/flags" "github.com/nspcc-dev/neo-go/cli/input" "github.com/nspcc-dev/neo-go/cli/options" @@ -513,6 +514,7 @@ func invokeFunction(ctx *cli.Context) error { func invokeInternal(ctx *cli.Context, signAndPush bool) error { var ( err error + exitErr *cli.ExitError gas fixedn.Fixed8 operation string params = make([]smartcontract.Parameter, 0) @@ -547,14 +549,9 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error { } cosignersStart := paramsStart + cosignersOffset - if len(args) > cosignersStart { - for i, c := range args[cosignersStart:] { - cosigner, err := parseCosigner(c) - if err != nil { - return cli.NewExitError(fmt.Errorf("failed to parse cosigner #%d: %w", i+1, err), 1) - } - cosigners = append(cosigners, cosigner) - } + cosigners, exitErr = cmdargs.GetSignersFromContext(ctx, cosignersStart) + if exitErr != nil { + return exitErr } if signAndPush { @@ -686,16 +683,9 @@ func testInvokeScript(ctx *cli.Context) error { return cli.NewExitError(fmt.Errorf("failed to restore .nef file: %w", err), 1) } - args := ctx.Args() - var signers []transaction.Signer - if args.Present() { - for i, c := range args[:] { - cosigner, err := parseCosigner(c) - if err != nil { - return cli.NewExitError(fmt.Errorf("failed to parse signer #%d: %w", i+1, err), 1) - } - signers = append(signers, cosigner) - } + signers, exitErr := cmdargs.GetSignersFromContext(ctx, 0) + if exitErr != nil { + return exitErr } gctx, cancel := options.GetTimeoutContext(ctx) @@ -932,25 +922,3 @@ func ParseContractConfig(confFile string) (ProjectConfig, error) { } return conf, nil } - -func parseCosigner(c string) (transaction.Signer, error) { - var ( - err error - res = transaction.Signer{ - Scopes: transaction.CalledByEntry, - } - ) - data := strings.SplitN(c, ":", 2) - s := data[0] - res.Account, err = flags.ParseAddress(s) - if err != nil { - return res, err - } - if len(data) > 1 { - res.Scopes, err = transaction.ScopesFromString(data[1]) - if err != nil { - return transaction.Signer{}, err - } - } - return res, nil -} diff --git a/cli/smartcontract/smart_contract_test.go b/cli/smartcontract/smart_contract_test.go index e00ea71ec..54e70f340 100644 --- a/cli/smartcontract/smart_contract_test.go +++ b/cli/smartcontract/smart_contract_test.go @@ -7,9 +7,7 @@ import ( "strings" "testing" - "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/smartcontract" - "github.com/nspcc-dev/neo-go/pkg/util" "github.com/stretchr/testify/require" "github.com/urfave/cli" ) @@ -69,51 +67,6 @@ events: `, string(manifest)) } -func TestParseCosigner(t *testing.T) { - acc := util.Uint160{1, 3, 5, 7} - testCases := map[string]transaction.Signer{ - acc.StringLE(): { - Account: acc, - Scopes: transaction.CalledByEntry, - }, - "0x" + acc.StringLE(): { - Account: acc, - Scopes: transaction.CalledByEntry, - }, - acc.StringLE() + ":Global": { - Account: acc, - Scopes: transaction.Global, - }, - acc.StringLE() + ":CalledByEntry": { - Account: acc, - Scopes: transaction.CalledByEntry, - }, - acc.StringLE() + ":None": { - Account: acc, - Scopes: transaction.None, - }, - acc.StringLE() + ":CalledByEntry,CustomContracts": { - Account: acc, - Scopes: transaction.CalledByEntry | transaction.CustomContracts, - }, - } - for s, expected := range testCases { - actual, err := parseCosigner(s) - require.NoError(t, err) - require.Equal(t, expected, actual) - } - errorCases := []string{ - acc.StringLE() + "0", - acc.StringLE() + ":Unknown", - acc.StringLE() + ":Global,CustomContracts", - acc.StringLE() + ":Global,None", - } - for _, s := range errorCases { - _, err := parseCosigner(s) - require.Error(t, err) - } -} - func TestParseParams_CalledFromItself(t *testing.T) { testCases := map[string]struct { WordsRead int