From 0c6aeaaf18a708d051b72bb4a75c452611d1617d Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 13 Apr 2023 17:42:59 +0300 Subject: [PATCH] [#100] adm: Take net settings into account during netmap contract update Signed-off-by: Anton Nikiforov --- CHANGELOG.md | 2 + .../internal/modules/morph/config.go | 32 +++----- .../modules/morph/initialize_deploy.go | 77 +++++++++++++++---- .../internal/modules/morph/netmap_util.go | 47 +++++++++++ 4 files changed, 118 insertions(+), 40 deletions(-) create mode 100644 cmd/frostfs-adm/internal/modules/morph/netmap_util.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 01a36c66d..9d284f6fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ Changelog for FrostFS Node ### Added ### Changed ### Fixed +- Take network settings into account during netmap contract update (#100) + ### Removed ### Updated ### Updating from v0.36.0 diff --git a/cmd/frostfs-adm/internal/modules/morph/config.go b/cmd/frostfs-adm/internal/modules/morph/config.go index 8a888ab2c..11e1bd4f6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config.go @@ -15,7 +15,6 @@ import ( "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/vm/emit" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -48,23 +47,12 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { buf := bytes.NewBuffer(nil) tw := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0) - for _, param := range arr { - tuple, ok := param.Value().([]stackitem.Item) - if !ok || len(tuple) != 2 { - return errors.New("invalid ListConfig response from netmap contract") - } - - k, err := tuple[0].TryBytes() - if err != nil { - return errors.New("invalid config key from netmap contract") - } - - v, err := tuple[1].TryBytes() - if err != nil { - return invalidConfigValueErr(k) - } - - switch string(k) { + m, err := parseConfigFromNetmapContract(arr) + if err != nil { + return err + } + for k, v := range m { + switch k { case netmapAuditFeeKey, netmapBasicIncomeRateKey, netmapContainerFeeKey, netmapContainerAliasFeeKey, netmapEigenTrustIterationsKey, @@ -77,12 +65,10 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { case netmapEigenTrustAlphaKey: _, _ = tw.Write([]byte(fmt.Sprintf("%s:\t%s (str)\n", k, v))) case netmapHomomorphicHashDisabledKey, netmapMaintenanceAllowedKey: - vBool, err := tuple[1].TryBool() - if err != nil { + if len(v) == 0 || len(v) > 1 { return invalidConfigValueErr(k) } - - _, _ = tw.Write([]byte(fmt.Sprintf("%s:\t%t (bool)\n", k, vBool))) + _, _ = tw.Write([]byte(fmt.Sprintf("%s:\t%t (bool)\n", k, v[0] == 1))) default: _, _ = tw.Write([]byte(fmt.Sprintf("%s:\t%s (hex)\n", k, hex.EncodeToString(v)))) } @@ -187,6 +173,6 @@ func parseConfigPair(kvStr string, force bool) (key string, val any, err error) return } -func invalidConfigValueErr(key []byte) error { +func invalidConfigValueErr(key string) error { return fmt.Errorf("invalid %s config value from netmap contract", key) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index ae80c2ffd..3446cd0b8 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -23,6 +23,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "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" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" @@ -30,8 +31,8 @@ import ( "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/opcode" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" - "github.com/spf13/viper" ) const ( @@ -85,6 +86,21 @@ var ( nnsContract, alphabetContract, }, contractList...) + + netmapConfigKeys = []string{ + netmapEpochKey, + netmapMaxObjectSizeKey, + netmapAuditFeeKey, + netmapContainerFeeKey, + netmapContainerAliasFeeKey, + netmapEigenTrustIterationsKey, + netmapEigenTrustAlphaKey, + netmapBasicIncomeRateKey, + netmapInnerRingCandidateFeeKey, + netmapWithdrawFeeKey, + netmapHomomorphicHashDisabledKey, + netmapMaintenanceAllowedKey, + } ) type contractState struct { @@ -239,7 +255,7 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash invokeHash = ctrHash } - params := getContractDeployParameters(cs, c.getContractDeployData(ctrName, keysParam)) + params := getContractDeployParameters(cs, c.getContractDeployData(ctrName, keysParam, updateMethodName)) res, err := c.CommitteeAct.MakeCall(invokeHash, method, params...) if err != nil { if method != updateMethodName || !strings.Contains(err.Error(), common.ErrAlreadyUpdated) { @@ -362,7 +378,7 @@ func (c *initializeContext) deployContracts() error { return fmt.Errorf("can't sign manifest group: %v", err) } - params := getContractDeployParameters(cs, c.getContractDeployData(ctrName, keysParam)) + params := getContractDeployParameters(cs, c.getContractDeployData(ctrName, keysParam, deployMethodName)) res, err := c.CommitteeAct.MakeCall(management.Hash, deployMethodName, params...) if err != nil { return fmt.Errorf("can't deploy %s contract: %w", ctrName, err) @@ -529,7 +545,7 @@ func getContractDeployParameters(cs *contractState, deployData []any) []any { return []any{cs.RawNEF, cs.RawManifest, deployData} } -func (c *initializeContext) getContractDeployData(ctrName string, keysParam []any) []any { +func (c *initializeContext) getContractDeployData(ctrName string, keysParam []any, method string) []any { items := make([]any, 1, 6) items[0] = false // notaryDisabled is false @@ -566,20 +582,31 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an c.Contracts[netmapContract].Hash, c.Contracts[containerContract].Hash) case netmapContract: - configParam := []any{ - netmapEpochKey, viper.GetInt64(epochDurationInitFlag), - netmapMaxObjectSizeKey, viper.GetInt64(maxObjectSizeInitFlag), - netmapAuditFeeKey, viper.GetInt64(auditFeeInitFlag), - netmapContainerFeeKey, viper.GetInt64(containerFeeInitFlag), - netmapContainerAliasFeeKey, viper.GetInt64(containerAliasFeeInitFlag), - netmapEigenTrustIterationsKey, int64(defaultEigenTrustIterations), - netmapEigenTrustAlphaKey, defaultEigenTrustAlpha, - netmapBasicIncomeRateKey, viper.GetInt64(incomeRateInitFlag), - netmapInnerRingCandidateFeeKey, viper.GetInt64(candidateFeeInitFlag), - netmapWithdrawFeeKey, viper.GetInt64(withdrawFeeInitFlag), - netmapHomomorphicHashDisabledKey, viper.GetBool(homomorphicHashDisabledInitFlag), - netmapMaintenanceAllowedKey, viper.GetBool(maintenanceModeAllowedInitFlag), + md := getDefaultNetmapContractConfigMap() + if method == updateMethodName { + arr, err := c.getNetConfigFromNetmapContract() + if err != nil { + panic(err) + } + m, err := parseConfigFromNetmapContract(arr) + if err != nil { + panic(err) + } + for k, v := range m { + for _, key := range netmapConfigKeys { + if k == key { + md[k] = v + break + } + } + } } + + var configParam []any + for k, v := range md { + configParam = append(configParam, k, v) + } + items = append(items, c.Contracts[balanceContract].Hash, c.Contracts[containerContract].Hash, @@ -595,6 +622,22 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an return items } +func (c *initializeContext) getNetConfigFromNetmapContract() ([]stackitem.Item, error) { + cs, err := c.Client.GetContractStateByID(1) + if err != nil { + return nil, fmt.Errorf("NNS is not yet deployed: %w", err) + } + nmHash, err := nnsResolveHash(c.ReadOnlyInvoker, cs.Hash, netmapContract+".frostfs") + if err != nil { + return nil, fmt.Errorf("can't get netmap contract hash: %w", err) + } + arr, err := unwrap.Array(c.ReadOnlyInvoker.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 (c *initializeContext) getAlphabetDeployItems(i, n int) []any { items := make([]any, 6) items[0] = false diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap_util.go b/cmd/frostfs-adm/internal/modules/morph/netmap_util.go new file mode 100644 index 000000000..2ba48b542 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/netmap_util.go @@ -0,0 +1,47 @@ +package morph + +import ( + "errors" + + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/spf13/viper" +) + +func getDefaultNetmapContractConfigMap() map[string]any { + m := make(map[string]any) + m[netmapEpochKey] = viper.GetInt64(epochDurationInitFlag) + m[netmapMaxObjectSizeKey] = viper.GetInt64(maxObjectSizeInitFlag) + m[netmapAuditFeeKey] = viper.GetInt64(auditFeeInitFlag) + m[netmapContainerFeeKey] = viper.GetInt64(containerFeeInitFlag) + m[netmapContainerAliasFeeKey] = viper.GetInt64(containerAliasFeeInitFlag) + m[netmapEigenTrustIterationsKey] = int64(defaultEigenTrustIterations) + m[netmapEigenTrustAlphaKey] = defaultEigenTrustAlpha + m[netmapBasicIncomeRateKey] = viper.GetInt64(incomeRateInitFlag) + m[netmapInnerRingCandidateFeeKey] = viper.GetInt64(candidateFeeInitFlag) + m[netmapWithdrawFeeKey] = viper.GetInt64(withdrawFeeInitFlag) + m[netmapHomomorphicHashDisabledKey] = viper.GetBool(homomorphicHashDisabledInitFlag) + m[netmapMaintenanceAllowedKey] = viper.GetBool(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 +}