git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/netmap/network_info.go (about)

     1  package netmap
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"errors"
     7  	"fmt"
     8  
     9  	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
    10  	"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
    11  )
    12  
    13  // NetworkInfo groups information about the FrostFS network state. Mainly used to
    14  // describe the current state of the network.
    15  //
    16  // NetworkInfo is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap.NetworkInfo
    17  // message. See ReadFromV2 / WriteToV2 methods.
    18  //
    19  // Instances can be created using built-in var declaration.
    20  type NetworkInfo struct {
    21  	m netmap.NetworkInfo
    22  }
    23  
    24  // reads NetworkInfo from netmap.NetworkInfo message. If checkFieldPresence is set,
    25  // returns an error on absence of any protocol-required field. Verifies format of any
    26  // presented field according to FrostFS API V2 protocol.
    27  func (x *NetworkInfo) readFromV2(m netmap.NetworkInfo, checkFieldPresence bool) error {
    28  	c := m.GetNetworkConfig()
    29  	if checkFieldPresence && c == nil {
    30  		return errors.New("missing network config")
    31  	}
    32  
    33  	if checkFieldPresence && c.NumberOfParameters() <= 0 {
    34  		return errors.New("missing network parameters")
    35  	}
    36  
    37  	var err error
    38  	mNames := make(map[string]struct{}, c.NumberOfParameters())
    39  
    40  	c.IterateParameters(func(prm *netmap.NetworkParameter) bool {
    41  		name := string(prm.GetKey())
    42  
    43  		_, was := mNames[name]
    44  		if was {
    45  			err = fmt.Errorf("duplicated parameter name: %s", name)
    46  			return true
    47  		}
    48  
    49  		mNames[name] = struct{}{}
    50  
    51  		switch name {
    52  		case
    53  			configAuditFee,
    54  			configStoragePrice,
    55  			configContainerFee,
    56  			configNamedContainerFee,
    57  			configEpochDuration,
    58  			configIRCandidateFee,
    59  			configMaxObjSize,
    60  			configMaxECDataCount,
    61  			configMaxECParityCount,
    62  			configWithdrawalFee:
    63  			_, err = decodeConfigValueUint64(prm.GetValue())
    64  		case configHomomorphicHashingDisabled,
    65  			configMaintenanceModeAllowed:
    66  			_, err = decodeConfigValueBool(prm.GetValue())
    67  		}
    68  
    69  		if err != nil {
    70  			err = fmt.Errorf("invalid %s parameter: %w", name, err)
    71  		}
    72  
    73  		return err != nil
    74  	})
    75  
    76  	if err != nil {
    77  		return err
    78  	}
    79  
    80  	x.m = m
    81  
    82  	return nil
    83  }
    84  
    85  // ReadFromV2 reads NetworkInfo from the netmap.NetworkInfo message. Checks if the
    86  // message conforms to FrostFS API V2 protocol.
    87  //
    88  // See also WriteToV2.
    89  func (x *NetworkInfo) ReadFromV2(m netmap.NetworkInfo) error {
    90  	return x.readFromV2(m, true)
    91  }
    92  
    93  // WriteToV2 writes NetworkInfo to the netmap.NetworkInfo message. The message
    94  // MUST NOT be nil.
    95  //
    96  // See also ReadFromV2.
    97  func (x NetworkInfo) WriteToV2(m *netmap.NetworkInfo) {
    98  	*m = x.m
    99  }
   100  
   101  // CurrentEpoch returns epoch set using SetCurrentEpoch.
   102  //
   103  // Zero NetworkInfo has zero current epoch.
   104  func (x NetworkInfo) CurrentEpoch() uint64 {
   105  	return x.m.GetCurrentEpoch()
   106  }
   107  
   108  // SetCurrentEpoch sets current epoch of the FrostFS network.
   109  func (x *NetworkInfo) SetCurrentEpoch(epoch uint64) {
   110  	x.m.SetCurrentEpoch(epoch)
   111  }
   112  
   113  // MagicNumber returns magic number set using SetMagicNumber.
   114  //
   115  // Zero NetworkInfo has zero magic.
   116  func (x NetworkInfo) MagicNumber() uint64 {
   117  	return x.m.GetMagicNumber()
   118  }
   119  
   120  // SetMagicNumber sets magic number of the FrostFS Sidechain.
   121  //
   122  // See also MagicNumber.
   123  func (x *NetworkInfo) SetMagicNumber(epoch uint64) {
   124  	x.m.SetMagicNumber(epoch)
   125  }
   126  
   127  // MsPerBlock returns network parameter set using SetMsPerBlock.
   128  func (x NetworkInfo) MsPerBlock() int64 {
   129  	return x.m.GetMsPerBlock()
   130  }
   131  
   132  // SetMsPerBlock sets MillisecondsPerBlock network parameter of the FrostFS Sidechain.
   133  //
   134  // See also MsPerBlock.
   135  func (x *NetworkInfo) SetMsPerBlock(v int64) {
   136  	x.m.SetMsPerBlock(v)
   137  }
   138  
   139  func (x *NetworkInfo) setConfig(name string, val []byte) {
   140  	c := x.m.GetNetworkConfig()
   141  	if c == nil {
   142  		c = new(netmap.NetworkConfig)
   143  
   144  		var prm netmap.NetworkParameter
   145  		prm.SetKey([]byte(name))
   146  		prm.SetValue(val)
   147  
   148  		c.SetParameters(prm)
   149  
   150  		x.m.SetNetworkConfig(c)
   151  
   152  		return
   153  	}
   154  
   155  	found := false
   156  	prms := make([]netmap.NetworkParameter, 0, c.NumberOfParameters())
   157  
   158  	c.IterateParameters(func(prm *netmap.NetworkParameter) bool {
   159  		found = bytes.Equal(prm.GetKey(), []byte(name))
   160  		if found {
   161  			prm.SetValue(val)
   162  		} else {
   163  			prms = append(prms, *prm)
   164  		}
   165  
   166  		return found
   167  	})
   168  
   169  	if !found {
   170  		prms = append(prms, netmap.NetworkParameter{})
   171  		prms[len(prms)-1].SetKey([]byte(name))
   172  		prms[len(prms)-1].SetValue(val)
   173  
   174  		c.SetParameters(prms...)
   175  	}
   176  }
   177  
   178  func (x NetworkInfo) configValue(name string) (res []byte) {
   179  	x.m.GetNetworkConfig().IterateParameters(func(prm *netmap.NetworkParameter) bool {
   180  		if string(prm.GetKey()) == name {
   181  			res = prm.GetValue()
   182  
   183  			return true
   184  		}
   185  
   186  		return false
   187  	})
   188  
   189  	return
   190  }
   191  
   192  // SetRawNetworkParameter sets named FrostFS network parameter whose value is
   193  // transmitted but not interpreted by the FrostFS API protocol.
   194  //
   195  // Argument MUST NOT be mutated, make a copy first.
   196  //
   197  // See also RawNetworkParameter, IterateRawNetworkParameters.
   198  func (x *NetworkInfo) SetRawNetworkParameter(name string, value []byte) {
   199  	x.setConfig(name, value)
   200  }
   201  
   202  // RawNetworkParameter reads raw network parameter set using SetRawNetworkParameter
   203  // by its name. Returns nil if value is missing.
   204  //
   205  // Return value MUST NOT be mutated, make a copy first.
   206  //
   207  // Zero NetworkInfo has no network parameters.
   208  func (x *NetworkInfo) RawNetworkParameter(name string) []byte {
   209  	return x.configValue(name)
   210  }
   211  
   212  // IterateRawNetworkParameters iterates over all raw networks parameters set
   213  // using SetRawNetworkParameter and passes them into f.
   214  //
   215  // Handler MUST NOT be nil. Handler MUST NOT mutate value parameter.
   216  //
   217  // Zero NetworkInfo has no network parameters.
   218  func (x *NetworkInfo) IterateRawNetworkParameters(f func(name string, value []byte)) {
   219  	c := x.m.GetNetworkConfig()
   220  
   221  	c.IterateParameters(func(prm *netmap.NetworkParameter) bool {
   222  		name := string(prm.GetKey())
   223  		switch name {
   224  		default:
   225  			f(name, prm.GetValue())
   226  		case
   227  			configAuditFee,
   228  			configStoragePrice,
   229  			configContainerFee,
   230  			configNamedContainerFee,
   231  			configEpochDuration,
   232  			configIRCandidateFee,
   233  			configMaxObjSize,
   234  			configMaxECDataCount,
   235  			configMaxECParityCount,
   236  			configWithdrawalFee,
   237  			configHomomorphicHashingDisabled,
   238  			configMaintenanceModeAllowed:
   239  		}
   240  
   241  		return false
   242  	})
   243  }
   244  
   245  func (x *NetworkInfo) setConfigUint64(name string, num uint64) {
   246  	val := make([]byte, 8)
   247  	binary.LittleEndian.PutUint64(val, num)
   248  
   249  	x.setConfig(name, val)
   250  }
   251  
   252  func (x *NetworkInfo) setConfigBool(name string, val bool) {
   253  	v := stackitem.NewBool(val)
   254  	x.setConfig(name, v.Bytes())
   255  }
   256  
   257  // decodeConfigValueUint64 parses val as little-endian uint64.
   258  // val must be less than 8 bytes in size.
   259  func decodeConfigValueUint64(val []byte) (uint64, error) {
   260  	if ln := len(val); ln > 8 {
   261  		return 0, fmt.Errorf("invalid uint64 parameter length %d", ln)
   262  	}
   263  
   264  	res := uint64(0)
   265  	for i := len(val) - 1; i >= 0; i-- {
   266  		res = res*256 + uint64(val[i])
   267  	}
   268  
   269  	return res, nil
   270  }
   271  
   272  // decodeConfigValueBool parses val as boolean contract storage value.
   273  func decodeConfigValueBool(val []byte) (bool, error) {
   274  	arr := stackitem.NewByteArray(val)
   275  
   276  	res, err := arr.TryBool()
   277  	if err != nil {
   278  		return false, fmt.Errorf("invalid bool parameter contract format %s", err)
   279  	}
   280  
   281  	return res, nil
   282  }
   283  
   284  func (x NetworkInfo) configUint64(name string) uint64 {
   285  	val := x.configValue(name)
   286  	if val == nil {
   287  		return 0
   288  	}
   289  
   290  	res, err := decodeConfigValueUint64(val)
   291  	if err != nil {
   292  		// potential panic is OK since value MUST be correct since it is
   293  		// verified in ReadFromV2 or set by provided method.
   294  		panic(err)
   295  	}
   296  
   297  	return res
   298  }
   299  
   300  func (x NetworkInfo) configBool(name string) bool {
   301  	val := x.configValue(name)
   302  	if val == nil {
   303  		return false
   304  	}
   305  
   306  	res, err := decodeConfigValueBool(val)
   307  	if err != nil {
   308  		// potential panic is OK since value MUST be correct since it is
   309  		// verified in ReadFromV2 or set by provided method.
   310  		panic(err)
   311  	}
   312  
   313  	return res
   314  }
   315  
   316  const configAuditFee = "AuditFee"
   317  
   318  // SetAuditFee sets the configuration value of the audit fee for the Inner Ring.
   319  //
   320  // See also AuditFee.
   321  func (x *NetworkInfo) SetAuditFee(fee uint64) {
   322  	x.setConfigUint64(configAuditFee, fee)
   323  }
   324  
   325  // AuditFee returns audit fee set using SetAuditFee.
   326  //
   327  // Zero NetworkInfo has zero audit fee.
   328  func (x NetworkInfo) AuditFee() uint64 {
   329  	return x.configUint64(configAuditFee)
   330  }
   331  
   332  const configStoragePrice = "BasicIncomeRate"
   333  
   334  // SetStoragePrice sets the price per gigabyte of data storage that data owners
   335  // pay to storage nodes.
   336  //
   337  // See also StoragePrice.
   338  func (x *NetworkInfo) SetStoragePrice(price uint64) {
   339  	x.setConfigUint64(configStoragePrice, price)
   340  }
   341  
   342  // StoragePrice returns storage price set using SetStoragePrice.
   343  //
   344  // Zero NetworkInfo has zero storage price.
   345  func (x NetworkInfo) StoragePrice() uint64 {
   346  	return x.configUint64(configStoragePrice)
   347  }
   348  
   349  const configContainerFee = "ContainerFee"
   350  
   351  // SetContainerFee sets fee for the container creation that creator pays to
   352  // each Alphabet node.
   353  //
   354  // See also ContainerFee.
   355  func (x *NetworkInfo) SetContainerFee(fee uint64) {
   356  	x.setConfigUint64(configContainerFee, fee)
   357  }
   358  
   359  // ContainerFee returns container fee set using SetContainerFee.
   360  //
   361  // Zero NetworkInfo has zero container fee.
   362  func (x NetworkInfo) ContainerFee() uint64 {
   363  	return x.configUint64(configContainerFee)
   364  }
   365  
   366  const configNamedContainerFee = "ContainerAliasFee"
   367  
   368  // SetNamedContainerFee sets fee for creation of the named container creation
   369  // that creator pays to each Alphabet node.
   370  //
   371  // See also NamedContainerFee.
   372  func (x *NetworkInfo) SetNamedContainerFee(fee uint64) {
   373  	x.setConfigUint64(configNamedContainerFee, fee)
   374  }
   375  
   376  // NamedContainerFee returns container fee set using SetNamedContainerFee.
   377  //
   378  // Zero NetworkInfo has zero container fee.
   379  func (x NetworkInfo) NamedContainerFee() uint64 {
   380  	return x.configUint64(configNamedContainerFee)
   381  }
   382  
   383  const configEpochDuration = "EpochDuration"
   384  
   385  // SetEpochDuration sets FrostFS epoch duration measured in number of blocks of
   386  // the FrostFS Sidechain.
   387  //
   388  // See also EpochDuration.
   389  func (x *NetworkInfo) SetEpochDuration(blocks uint64) {
   390  	x.setConfigUint64(configEpochDuration, blocks)
   391  }
   392  
   393  // EpochDuration returns epoch duration set using SetEpochDuration.
   394  //
   395  // Zero NetworkInfo has zero iteration number.
   396  func (x NetworkInfo) EpochDuration() uint64 {
   397  	return x.configUint64(configEpochDuration)
   398  }
   399  
   400  const configIRCandidateFee = "InnerRingCandidateFee"
   401  
   402  // SetIRCandidateFee sets fee for Inner Ring entrance paid by a new member.
   403  //
   404  // See also IRCandidateFee.
   405  func (x *NetworkInfo) SetIRCandidateFee(fee uint64) {
   406  	x.setConfigUint64(configIRCandidateFee, fee)
   407  }
   408  
   409  // IRCandidateFee returns IR entrance fee set using SetIRCandidateFee.
   410  //
   411  // Zero NetworkInfo has zero fee.
   412  func (x NetworkInfo) IRCandidateFee() uint64 {
   413  	return x.configUint64(configIRCandidateFee)
   414  }
   415  
   416  const configMaxObjSize = "MaxObjectSize"
   417  
   418  // SetMaxObjectSize sets maximum size of the object stored locally on the
   419  // storage nodes (physical objects). Binary representation of any physically
   420  // stored object MUST NOT overflow the limit.
   421  //
   422  // See also MaxObjectSize.
   423  func (x *NetworkInfo) SetMaxObjectSize(sz uint64) {
   424  	x.setConfigUint64(configMaxObjSize, sz)
   425  }
   426  
   427  // MaxObjectSize returns maximum object size set using SetMaxObjectSize.
   428  //
   429  // Zero NetworkInfo has zero maximum size.
   430  func (x NetworkInfo) MaxObjectSize() uint64 {
   431  	return x.configUint64(configMaxObjSize)
   432  }
   433  
   434  const configMaxECDataCount = "MaxECDataCount"
   435  
   436  // SetMaxECDataCount sets maximum number of data shards for erasure codes.
   437  //
   438  // Zero means no restrictions.
   439  func (x *NetworkInfo) SetMaxECDataCount(dataCount uint64) {
   440  	x.setConfigUint64(configMaxECDataCount, dataCount)
   441  }
   442  
   443  // MaxECDataCount returns maximum number of data shards for erasure codes.
   444  func (x NetworkInfo) MaxECDataCount() uint64 {
   445  	return x.configUint64(configMaxECDataCount)
   446  }
   447  
   448  const configMaxECParityCount = "MaxECParityCount"
   449  
   450  // SetMaxECParityCount sets maximum number of parity shards for erasure codes.
   451  //
   452  // Zero means no restrictions.
   453  func (x *NetworkInfo) SetMaxECParityCount(parityCount uint64) {
   454  	x.setConfigUint64(configMaxECParityCount, parityCount)
   455  }
   456  
   457  // MaxECParityCount returns maximum number of parity shards for erasure codes.
   458  func (x NetworkInfo) MaxECParityCount() uint64 {
   459  	return x.configUint64(configMaxECParityCount)
   460  }
   461  
   462  const configWithdrawalFee = "WithdrawFee"
   463  
   464  // SetWithdrawalFee sets fee for withdrawals from the FrostFS accounts that
   465  // account owners pay to each Alphabet node.
   466  //
   467  // See also WithdrawalFee.
   468  func (x *NetworkInfo) SetWithdrawalFee(sz uint64) {
   469  	x.setConfigUint64(configWithdrawalFee, sz)
   470  }
   471  
   472  // WithdrawalFee returns withdrawal fee set using SetWithdrawalFee.
   473  //
   474  // Zero NetworkInfo has zero fee.
   475  func (x NetworkInfo) WithdrawalFee() uint64 {
   476  	return x.configUint64(configWithdrawalFee)
   477  }
   478  
   479  const configHomomorphicHashingDisabled = "HomomorphicHashingDisabled"
   480  
   481  // DisableHomomorphicHashing sets flag requiring to disable homomorphic
   482  // hashing of the containers in the network.
   483  //
   484  // See also HomomorphicHashingDisabled.
   485  func (x *NetworkInfo) DisableHomomorphicHashing() {
   486  	x.setConfigBool(configHomomorphicHashingDisabled, true)
   487  }
   488  
   489  // HomomorphicHashingDisabled returns the state of the homomorphic
   490  // hashing network setting.
   491  //
   492  // Zero NetworkInfo has enabled homomorphic hashing.
   493  func (x NetworkInfo) HomomorphicHashingDisabled() bool {
   494  	return x.configBool(configHomomorphicHashingDisabled)
   495  }
   496  
   497  const configMaintenanceModeAllowed = "MaintenanceModeAllowed"
   498  
   499  // AllowMaintenanceMode sets the flag allowing nodes to go into maintenance mode.
   500  //
   501  // See also MaintenanceModeAllowed.
   502  func (x *NetworkInfo) AllowMaintenanceMode() {
   503  	x.setConfigBool(configMaintenanceModeAllowed, true)
   504  }
   505  
   506  // MaintenanceModeAllowed returns true iff network config allows
   507  // maintenance mode for storage nodes.
   508  //
   509  // Zero NetworkInfo has disallows maintenance mode.
   510  func (x NetworkInfo) MaintenanceModeAllowed() bool {
   511  	return x.configBool(configMaintenanceModeAllowed)
   512  }