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 }