package util import ( "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/spf13/viper" ) var NetmapConfigKeys = []string{ netmap.EpochDurationConfig, netmap.MaxObjectSizeConfig, netmap.ContainerFeeConfig, netmap.ContainerAliasFeeConfig, netmap.IrCandidateFeeConfig, netmap.WithdrawFeeConfig, netmap.HomomorphicHashingDisabledKey, netmap.MaintenanceModeAllowedConfig, } func GetDefaultNetmapContractConfigMap() map[string]any { m := make(map[string]any) m[netmap.EpochDurationConfig] = viper.GetInt64(commonflags.EpochDurationInitFlag) m[netmap.MaxObjectSizeConfig] = viper.GetInt64(commonflags.MaxObjectSizeInitFlag) m[netmap.ContainerFeeConfig] = viper.GetInt64(commonflags.ContainerFeeInitFlag) m[netmap.ContainerAliasFeeConfig] = viper.GetInt64(commonflags.ContainerAliasFeeInitFlag) m[netmap.IrCandidateFeeConfig] = viper.GetInt64(commonflags.CandidateFeeInitFlag) m[netmap.WithdrawFeeConfig] = viper.GetInt64(commonflags.WithdrawFeeInitFlag) m[netmap.HomomorphicHashingDisabledKey] = viper.GetBool(commonflags.HomomorphicHashDisabledInitFlag) m[netmap.MaintenanceModeAllowedConfig] = viper.GetBool(commonflags.MaintenanceModeAllowedInitFlag) return m } func ParseConfigFromNetmapContract(arr []stackitem.Item) (map[string][]byte, error) { m := make(map[string][]byte, len(arr)) for _, param := range arr { tuple, ok := param.Value().([]stackitem.Item) if !ok || len(tuple) != 2 { return nil, errors.New("invalid ListConfig response from netmap contract") } k, err := tuple[0].TryBytes() if err != nil { return nil, errors.New("invalid config key from netmap contract") } v, err := tuple[1].TryBytes() if err != nil { return nil, InvalidConfigValueErr(string(k)) } m[string(k)] = v } return m, nil } func InvalidConfigValueErr(key string) error { return fmt.Errorf("invalid %s config value from netmap contract", key) } func EmitNewEpochCall(bw *io.BufBinWriter, wCtx *InitializeContext, nmHash util.Uint160) error { curr, err := unwrap.Int64(wCtx.ReadOnlyInvoker.Call(nmHash, "epoch")) if err != nil { return errors.New("can't fetch current epoch from the netmap contract") } newEpoch := curr + 1 wCtx.Command.Printf("Current epoch: %d, increase to %d.\n", curr, newEpoch) // In NeoFS this is done via Notary contract. Here, however, we can form the // transaction locally. emit.AppCall(bw.BinWriter, nmHash, "newEpoch", callflag.All, newEpoch) return bw.Err } func GetNetConfigFromNetmapContract(roInvoker *invoker.Invoker) ([]stackitem.Item, error) { r := management.NewReader(roInvoker) cs, err := r.GetContractByID(1) if err != nil { return nil, fmt.Errorf("get nns contract: %w", err) } nmHash, err := NNSResolveHash(roInvoker, cs.Hash, DomainOf(NetmapContract)) if err != nil { return nil, fmt.Errorf("can't get netmap contract hash: %w", err) } arr, err := unwrap.Array(roInvoker.Call(nmHash, "listConfig")) if err != nil { return nil, fmt.Errorf("can't fetch list of network config keys from the netmap contract") } return arr, err } func MergeNetmapConfig(roInvoker *invoker.Invoker, md map[string]any) error { arr, err := GetNetConfigFromNetmapContract(roInvoker) if err != nil { return err } m, err := ParseConfigFromNetmapContract(arr) if err != nil { return err } for k, v := range m { for _, key := range NetmapConfigKeys { if k == key { md[k] = v break } } } return nil }