diff --git a/cmd/neofs-adm/internal/modules/morph/dump.go b/cmd/neofs-adm/internal/modules/morph/dump.go new file mode 100644 index 000000000..70d6e1777 --- /dev/null +++ b/cmd/neofs-adm/internal/modules/morph/dump.go @@ -0,0 +1,59 @@ +package morph + +import ( + "bytes" + "errors" + "fmt" + "text/tabwriter" + + nns "github.com/nspcc-dev/neo-go/examples/nft-nd-nns" + "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" + "github.com/nspcc-dev/neo-go/pkg/vm/emit" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func dumpContractHashes(cmd *cobra.Command, _ []string) error { + c, err := getN3Client(viper.GetViper()) + if err != nil { + return fmt.Errorf("can't create N3 client: %w", err) + } + + cs, err := c.GetContractStateByID(1) + if err != nil { + return err + } + + bw := io.NewBufBinWriter() + for _, ctrName := range contractList { + emit.AppCall(bw.BinWriter, cs.Hash, "resolve", callflag.ReadOnly, + ctrName+".neofs", int64(nns.TXT)) + } + + res, err := c.InvokeScript(bw.Bytes(), nil) + if err != nil { + return fmt.Errorf("can't fetch info from NNS: %w", err) + } + + if len(res.Stack) != len(contractList) { + return errors.New("invalid response from NNS contract: length mismatch") + } + + buf := bytes.NewBuffer(nil) + tw := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0) + for i := range contractList { + ctrHash := "hash is invalid" + bs, err := res.Stack[i].TryBytes() + if err == nil { + ctrHash = string(bs) // hashes are stored as hex-encoded LE string + } + + _, _ = tw.Write([]byte(fmt.Sprintf("%s:\t%s\n", contractList[i], ctrHash))) + } + + _ = tw.Flush() + cmd.Print(buf.String()) + + return nil +} diff --git a/cmd/neofs-adm/internal/modules/morph/root.go b/cmd/neofs-adm/internal/modules/morph/root.go index 0911a3385..4fbdc3bda 100644 --- a/cmd/neofs-adm/internal/modules/morph/root.go +++ b/cmd/neofs-adm/internal/modules/morph/root.go @@ -65,6 +65,15 @@ var ( }, RunE: forceNewEpochCmd, } + + dumpContractHashesCmd = &cobra.Command{ + Use: "dump-hashes", + Short: "Dump deployed contract hashes.", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + }, + RunE: dumpContractHashes, + } ) func init() { @@ -87,4 +96,7 @@ func init() { RootCmd.AddCommand(forceNewEpoch) forceNewEpoch.Flags().String(alphabetWalletsFlag, "", "path to alphabet wallets dir") forceNewEpoch.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + + RootCmd.AddCommand(dumpContractHashesCmd) + dumpContractHashesCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") }