neoneo-go/cli/smartcontract/manifest.go
Roman Khimov 8d33206bb8 *: don't get private key from account if just public one is needed
Add PublicKey() API to the Account and use it as appropriate, avoid creating
additional references to the private key.
2022-09-02 14:43:28 +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.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
}