package node import ( "errors" "fmt" netmapcontract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "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 RemoveNodesCmd(cmd *cobra.Command, args []string) error { if len(args) == 0 { return errors.New("at least one node key must be provided") } nodeKeys := make(keys.PublicKeys, len(args)) for i := range args { var err error nodeKeys[i], err = keys.NewPublicKeyFromString(args[i]) if err != nil { return fmt.Errorf("can't parse node public key: %w", err) } } wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't initialize context: %w", err) } defer wCtx.Close() r := management.NewReader(wCtx.ReadOnlyInvoker) cs, err := r.GetContractByID(1) if err != nil { return fmt.Errorf("can't get NNS contract info: %w", err) } nmHash, err := helper.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, helper.DomainOf(constants.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } bw := io.NewBufBinWriter() for i := range nodeKeys { emit.AppCall(bw.BinWriter, nmHash, "updateStateIR", callflag.All, int64(netmapcontract.NodeStateOffline), nodeKeys[i].Bytes()) } if err := helper.EmitNewEpochCall(bw, wCtx, nmHash); err != nil { return err } if err := wCtx.SendConsensusTx(bw.Bytes()); err != nil { return err } return wCtx.AwaitTx() }