cli: check manifest for validness if it's got from user input

And adjust the test case along the way, unnamed arguments are not
allowed for valid manifest.
This commit is contained in:
Anna Shaleva 2022-08-22 13:41:57 +03:00
parent 15732580eb
commit 40315fe092
4 changed files with 36 additions and 29 deletions

View file

@ -43,7 +43,11 @@ func contractGenerateWrapper(ctx *cli.Context) error {
if err := cmdargs.EnsureNone(ctx); err != nil {
return err
}
m, _, err := readManifest(ctx.String("manifest"))
h, err := util.Uint160DecodeStringLE(strings.TrimPrefix(ctx.String("hash"), "0x"))
if err != nil {
return cli.NewExitError(fmt.Errorf("invalid contract hash: %w", err), 1)
}
m, _, err := readManifest(ctx.String("manifest"), h)
if err != nil {
return cli.NewExitError(fmt.Errorf("can't read contract manifest: %w", err), 1)
}
@ -59,13 +63,7 @@ func contractGenerateWrapper(ctx *cli.Context) error {
return cli.NewExitError(fmt.Errorf("can't parse config file: %w", err), 1)
}
}
cfg.Manifest = m
h, err := util.Uint160DecodeStringLE(strings.TrimPrefix(ctx.String("hash"), "0x"))
if err != nil {
return cli.NewExitError(fmt.Errorf("invalid contract hash: %w", err), 1)
}
cfg.Hash = h
f, err := os.Create(ctx.String("out"))

View file

@ -66,13 +66,6 @@ func TestGenerate(t *testing.T) {
},
ReturnType: smartcontract.BoolType,
},
manifest.Method{
Name: "emptyName",
Parameters: []manifest.Parameter{
manifest.NewParameter("", smartcontract.MapType),
},
ReturnType: smartcontract.AnyType,
},
manifest.Method{
Name: "searchStorage",
Parameters: []manifest.Parameter{
@ -193,11 +186,6 @@ func OtherTypes(ctr interop.Hash160, tx interop.Hash256, sig interop.Signature,
return neogointernal.CallWithToken(Hash, "otherTypes", int(contract.All), ctr, tx, sig, data).(bool)
}
// EmptyName invokes ` + "`emptyName`" + ` method of contract.
func EmptyName(arg0 map[string]interface{}) interface{} {
return neogointernal.CallWithToken(Hash, "emptyName", int(contract.All), arg0).(interface{})
}
// SearchStorage invokes ` + "`searchStorage`" + ` method of contract.
func SearchStorage(ctx storage.Context) iterator.Iterator {
return neogointernal.CallWithToken(Hash, "searchStorage", int(contract.All), ctx).(iterator.Iterator)
@ -288,27 +276,41 @@ func TestGenerate_Errors(t *testing.T) {
err := app.Run(append([]string{"", "generate-wrapper"}, args...))
require.True(t, strings.Contains(err.Error(), msg), "got: %v", err)
}
t.Run("invalid hash", func(t *testing.T) {
checkError(t, "invalid contract hash", "--hash", "xxx")
})
t.Run("missing manifest argument", func(t *testing.T) {
checkError(t, errNoManifestFile.Error())
checkError(t, errNoManifestFile.Error(), "--hash", util.Uint160{}.StringLE())
})
t.Run("missing manifest file", func(t *testing.T) {
checkError(t, "can't read contract manifest", "--manifest", "notexists")
checkError(t, "can't read contract manifest", "--manifest", "notexists", "--hash", util.Uint160{}.StringLE())
})
t.Run("empty manifest", func(t *testing.T) {
manifestFile := filepath.Join(t.TempDir(), "invalid.json")
require.NoError(t, os.WriteFile(manifestFile, []byte("[]"), os.ModePerm))
checkError(t, "json: cannot unmarshal array into Go value of type manifest.Manifest", "--manifest", manifestFile, "--hash", util.Uint160{}.StringLE())
})
t.Run("invalid manifest", func(t *testing.T) {
manifestFile := filepath.Join(t.TempDir(), "invalid.json")
require.NoError(t, os.WriteFile(manifestFile, []byte("[]"), os.ModePerm))
checkError(t, "", "--manifest", manifestFile)
m := manifest.NewManifest("MyContract") // no methods
rawManifest, err := json.Marshal(m)
require.NoError(t, err)
require.NoError(t, os.WriteFile(manifestFile, rawManifest, os.ModePerm))
checkError(t, "ABI: no methods", "--manifest", manifestFile, "--hash", util.Uint160{}.StringLE())
})
manifestFile := filepath.Join(t.TempDir(), "manifest.json")
m := manifest.NewManifest("MyContract")
m.ABI.Methods = append(m.ABI.Methods, manifest.Method{
Name: "method0",
Offset: 0,
ReturnType: smartcontract.AnyType,
Safe: true,
})
rawManifest, err := json.Marshal(m)
require.NoError(t, err)
require.NoError(t, os.WriteFile(manifestFile, rawManifest, os.ModePerm))
t.Run("invalid hash", func(t *testing.T) {
checkError(t, "invalid contract hash", "--manifest", manifestFile, "--hash", "xxx")
})
t.Run("missing config", func(t *testing.T) {
checkError(t, "can't read config file",
"--manifest", manifestFile, "--hash", util.Uint160{}.StringLE(),

View file

@ -11,6 +11,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/urfave/cli"
)
@ -29,7 +30,7 @@ func manifestAddGroup(ctx *cli.Context) error {
}
mPath := ctx.String("manifest")
m, _, err := readManifest(mPath)
m, _, err := readManifest(mPath, util.Uint160{})
if err != nil {
return cli.NewExitError(fmt.Errorf("can't read contract manifest: %w", err), 1)
}
@ -89,7 +90,10 @@ func readNEFFile(filename string) (*nef.File, []byte, error) {
return &nefFile, f, nil
}
func readManifest(filename string) (*manifest.Manifest, []byte, error) {
// readManifest unmarshalls manifest got from the provided filename and checks
// it for validness against the provided contract hash. If empty hash is specified
// then no hash-related manifest groups check is performed.
func readManifest(filename string, hash util.Uint160) (*manifest.Manifest, []byte, error) {
if len(filename) == 0 {
return nil, nil, errNoManifestFile
}
@ -104,5 +108,8 @@ func readManifest(filename string) (*manifest.Manifest, []byte, error) {
if err != nil {
return nil, nil, err
}
if err := m.IsValid(hash); err != nil {
return nil, nil, fmt.Errorf("manifest is invalid: %w", err)
}
return m, manifestBytes, nil
}

View file

@ -922,7 +922,7 @@ func contractDeploy(ctx *cli.Context) error {
return cli.NewExitError(err, 1)
}
m, manifestBytes, err := readManifest(ctx.String("manifest"))
m, manifestBytes, err := readManifest(ctx.String("manifest"), util.Uint160{})
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to read manifest file: %w", err), 1)
}