mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-27 15:42:54 +00:00
58dc8d0c9b
Fix #2631.
116 lines
2.8 KiB
Go
116 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, w, err := getAccFromContext(ctx)
|
|
if err != nil {
|
|
return cli.NewExitError(fmt.Errorf("can't get account to sign group with: %w", err), 1)
|
|
}
|
|
defer w.Close()
|
|
|
|
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
|
|
}
|