neoneo-go/cli/smartcontract/manifest.go
Anna Shaleva 40315fe092 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.
2022-08-22 14:59:34 +03:00

115 lines
2.8 KiB
Go

package smartcontract
import (
"encoding/json"
"errors"
"fmt"
"os"
"github.com/nspcc-dev/neo-go/cli/cmdargs"
"github.com/nspcc-dev/neo-go/cli/flags"
"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"
)
func manifestAddGroup(ctx *cli.Context) error {
if err := cmdargs.EnsureNone(ctx); err != nil {
return err
}
sender, err := flags.ParseAddress(ctx.String("sender"))
if err != nil {
return cli.NewExitError(fmt.Errorf("invalid sender: %w", err), 1)
}
nf, _, err := readNEFFile(ctx.String("nef"))
if err != nil {
return cli.NewExitError(fmt.Errorf("can't read NEF file: %w", err), 1)
}
mPath := ctx.String("manifest")
m, _, err := readManifest(mPath, util.Uint160{})
if err != nil {
return cli.NewExitError(fmt.Errorf("can't read contract manifest: %w", err), 1)
}
h := state.CreateContractHash(sender, nf.Checksum, m.Name)
gAcc, _, err := getAccFromContext(ctx)
if err != nil {
return cli.NewExitError(fmt.Errorf("can't get account to sign group with: %w", err), 1)
}
var found bool
sig := gAcc.PrivateKey().Sign(h.BytesBE())
pub := gAcc.PrivateKey().PublicKey()
for i := range m.Groups {
if m.Groups[i].PublicKey.Equal(pub) {
m.Groups[i].Signature = sig
found = true
break
}
}
if !found {
m.Groups = append(m.Groups, manifest.Group{
PublicKey: pub,
Signature: sig,
})
}
rawM, err := json.Marshal(m)
if err != nil {
return cli.NewExitError(fmt.Errorf("can't marshal manifest: %w", err), 1)
}
err = os.WriteFile(mPath, rawM, os.ModePerm)
if err != nil {
return cli.NewExitError(fmt.Errorf("can't write manifest file: %w", err), 1)
}
return nil
}
func readNEFFile(filename string) (*nef.File, []byte, error) {
if len(filename) == 0 {
return nil, nil, errors.New("no nef file was provided")
}
f, err := os.ReadFile(filename)
if err != nil {
return nil, nil, err
}
nefFile, err := nef.FileFromBytes(f)
if err != nil {
return nil, nil, fmt.Errorf("can't parse NEF file: %w", err)
}
return &nefFile, f, nil
}
// 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
}
manifestBytes, err := os.ReadFile(filename)
if err != nil {
return nil, nil, err
}
m := new(manifest.Manifest)
err = json.Unmarshal(manifestBytes, m)
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
}