github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/staking/types/validator.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "errors" 7 "fmt" 8 "sort" 9 "strings" 10 "time" 11 12 cryptoamino "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/encoding/amino" 13 14 "github.com/tendermint/go-amino" 15 16 abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 17 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto" 18 tmtypes "github.com/fibonacci-chain/fbc/libs/tendermint/types" 19 "gopkg.in/yaml.v2" 20 21 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 22 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 23 "github.com/fibonacci-chain/fbc/x/staking/exported" 24 ) 25 26 // nolint 27 const ( 28 // TODO: Why can't we just have one string description which can be JSON by convention 29 MaxMonikerLength = 70 30 MaxIdentityLength = 3000 31 MaxWebsiteLength = 140 32 MaxDetailsLength = 280 33 ) 34 35 // Implements Validator interface 36 var _ exported.ValidatorI = Validator{} 37 38 // Validator defines the total amount of bond shares and their exchange rate to 39 // coins. Slashing results in a decrease in the exchange rate, allowing correct 40 // calculation of future undelegations without iterating over delegators. 41 // When coins are delegated to this validator, the validator is credited with a 42 // delegation whose number of bond shares is based on the amount of coins delegated 43 // divided by the current exchange rate. Voting power can be calculated as total 44 // bonded shares multiplied by exchange rate. 45 type Validator struct { 46 // address of the validator's operator; bech encoded in JSON 47 OperatorAddress sdk.ValAddress `json:"operator_address" yaml:"operator_address"` 48 // the consensus public key of the validator; bech encoded in JSON 49 ConsPubKey crypto.PubKey `json:"consensus_pubkey" yaml:"consensus_pubkey"` 50 // has the validator been jailed from bonded status? 51 Jailed bool `json:"jailed" yaml:"jailed"` 52 // validator status (bonded/unbonding/unbonded) 53 Status sdk.BondStatus `json:"status" yaml:"status"` 54 // delegated tokens (incl. self-delegation) 55 Tokens sdk.Int `json:"tokens" yaml:"tokens"` 56 // total shares added to a validator 57 DelegatorShares sdk.Dec `json:"delegator_shares" yaml:"delegator_shares"` 58 // description terms for the validator 59 Description Description `json:"description" yaml:"description"` 60 // if unbonding, height at which this validator has begun unbonding 61 UnbondingHeight int64 `json:"unbonding_height" yaml:"unbonding_height"` 62 // if unbonding, min time for the validator to complete unbonding 63 UnbondingCompletionTime time.Time `json:"unbonding_time" yaml:"unbonding_time"` 64 // commission parameters 65 Commission Commission `json:"commission" yaml:"commission"` 66 // validator's self declared minimum self delegation 67 MinSelfDelegation sdk.Dec `json:"min_self_delegation" yaml:"min_self_delegation"` 68 } 69 70 // MarshalYAML implements the text format for yaml marshaling due to consensus pubkey 71 func (v Validator) MarshalYAML() (interface{}, error) { 72 bs, err := yaml.Marshal(struct { 73 Status sdk.BondStatus 74 Jailed bool 75 UnbondingHeight int64 76 ConsPubKey string 77 OperatorAddress sdk.ValAddress 78 Tokens sdk.Int 79 DelegatorShares sdk.Dec 80 Description Description 81 UnbondingCompletionTime time.Time 82 Commission Commission 83 MinSelfDelegation sdk.Dec 84 }{ 85 OperatorAddress: v.OperatorAddress, 86 ConsPubKey: MustBech32ifyConsPub(v.ConsPubKey), 87 Jailed: v.Jailed, 88 Status: v.Status, 89 Tokens: v.Tokens, 90 DelegatorShares: v.DelegatorShares, 91 Description: v.Description, 92 UnbondingHeight: v.UnbondingHeight, 93 UnbondingCompletionTime: v.UnbondingCompletionTime, 94 Commission: v.Commission, 95 MinSelfDelegation: v.MinSelfDelegation, 96 }) 97 if err != nil { 98 return nil, err 99 } 100 101 return string(bs), nil 102 } 103 104 // Validators is a collection of Validator 105 type Validators []Validator 106 107 // String returns a human readable string representation of Validators 108 func (v Validators) String() (out string) { 109 for _, val := range v { 110 out += val.String() + "\n" 111 } 112 return strings.TrimSpace(out) 113 } 114 115 // ToSDKValidators converts []Validators to []sdk.Validators 116 func (v Validators) ToSDKValidators() (validators []exported.ValidatorI) { 117 for _, val := range v { 118 validators = append(validators, val) 119 } 120 return validators 121 } 122 123 // NewValidator initializes a new validator 124 func NewValidator(operator sdk.ValAddress, pubKey crypto.PubKey, description Description, minSelfDelegation sdk.Dec) Validator { 125 return Validator{ 126 OperatorAddress: operator, 127 ConsPubKey: pubKey, 128 Jailed: false, 129 Status: sdk.Unbonded, 130 Tokens: sdk.ZeroInt(), 131 DelegatorShares: sdk.ZeroDec(), 132 Description: description, 133 UnbondingHeight: int64(0), 134 UnbondingCompletionTime: time.Unix(0, 0).UTC(), 135 Commission: NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), 136 MinSelfDelegation: minSelfDelegation, 137 } 138 } 139 140 // Sort Validators sorts validator array in ascending operator address order 141 func (v Validators) Sort() { 142 sort.Sort(v) 143 } 144 145 // Implements sort interface 146 func (v Validators) Len() int { 147 return len(v) 148 } 149 150 // Implements sort interface 151 func (v Validators) Less(i, j int) bool { 152 return bytes.Compare(v[i].OperatorAddress, v[j].OperatorAddress) == -1 153 } 154 155 // Implements sort interface 156 func (v Validators) Swap(i, j int) { 157 it := v[i] 158 v[i] = v[j] 159 v[j] = it 160 } 161 162 // MustMarshalValidator must return the marshaling bytes of a validator 163 func MustMarshalValidator(cdc *codec.Codec, validator Validator) []byte { 164 return cdc.MustMarshalBinaryLengthPrefixed(validator) 165 } 166 167 // MustUnmarshalValidator must return the validator entity by unmarshaling 168 func MustUnmarshalValidator(cdc *codec.Codec, value []byte) Validator { 169 validator, err := UnmarshalValidator(cdc, value) 170 if err != nil { 171 panic(err) 172 } 173 return validator 174 } 175 176 // UnmarshalValidator unmarshals a validator from a store value 177 func UnmarshalValidator(cdc *codec.Codec, value []byte) (validator Validator, err error) { 178 if len(value) == 0 { 179 err = errors.New("UnmarshalValidator cannot decode empty bytes") 180 return 181 } 182 183 // Read byte-length prefix. 184 u64, n := binary.Uvarint(value) 185 if n < 0 { 186 err = fmt.Errorf("Error reading msg byte-length prefix: got code %v", n) 187 return 188 } 189 if u64 > uint64(len(value)-n) { 190 err = fmt.Errorf("Not enough bytes to read in UnmarshalValidator, want %v more bytes but only have %v", 191 u64, len(value)-n) 192 return 193 } else if u64 < uint64(len(value)-n) { 194 err = fmt.Errorf("Bytes left over in UnmarshalValidator, should read %v more bytes but have %v", 195 u64, len(value)-n) 196 return 197 } 198 value = value[n:] 199 200 if err = validator.UnmarshalFromAmino(cdc, value); err != nil { 201 err = cdc.UnmarshalBinaryBare(value, &validator) 202 } 203 return validator, err 204 } 205 206 // String returns a human readable string representation of a validator. 207 func (v Validator) String() string { 208 bechConsPubKey, err := Bech32ifyConsPub(v.ConsPubKey) 209 if err != nil { 210 panic(err) 211 } 212 return fmt.Sprintf(`Validator 213 Operator Address: %s 214 Validator Consensus Pubkey: %s 215 Jailed: %v 216 Status: %s 217 Tokens: %s 218 Delegator Shares: %s 219 Description: %s 220 Unbonding Height: %d 221 Unbonding Completion Time: %v 222 Minimum Self Delegation: %v 223 Commission: %s`, 224 v.OperatorAddress, bechConsPubKey, 225 v.Jailed, v.Status, v.Tokens, 226 v.DelegatorShares, v.Description, 227 v.UnbondingHeight, v.UnbondingCompletionTime, v.MinSelfDelegation, 228 v.Commission) 229 } 230 231 // this is a helper struct used for JSON de- and encoding only 232 type bechValidator struct { 233 // the bech32 address of the validator's operator 234 OperatorAddress sdk.ValAddress `json:"operator_address" yaml:"operator_address"` 235 // the bech32 consensus public key of the validator 236 ConsPubKey string `json:"consensus_pubkey" yaml:"consensus_pubkey"` 237 // has the validator been jailed from bonded status? 238 Jailed bool `json:"jailed" yaml:"jailed"` 239 // validator status (bonded/unbonding/unbonded) 240 Status sdk.BondStatus `json:"status" yaml:"status"` 241 // delegated tokens (incl. self-delegation) 242 Tokens sdk.Int `json:"tokens" yaml:"tokens"` 243 // total shares on a validator 244 DelegatorShares sdk.Dec `json:"delegator_shares" yaml:"delegator_shares"` 245 // description terms for the validator 246 Description Description `json:"description" yaml:"description"` 247 // if unbonding, height at which this validator has begun unbonding 248 UnbondingHeight int64 `json:"unbonding_height" yaml:"unbonding_height"` 249 // if unbonding, min time for the validator to complete unbonding 250 UnbondingCompletionTime time.Time `json:"unbonding_time" yaml:"unbonding_time"` 251 // commission parameters 252 Commission Commission `json:"commission" yaml:"commission"` 253 // minimum self delegation 254 MinSelfDelegation sdk.Dec `json:"min_self_delegation" yaml:"min_self_delegation"` 255 } 256 257 // MarshalJSON marshals the validator to JSON using Bech32 258 func (v Validator) MarshalJSON() ([]byte, error) { 259 bechConsPubKey, err := Bech32ifyConsPub(v.ConsPubKey) 260 if err != nil { 261 return nil, err 262 } 263 264 return codec.Cdc.MarshalJSON(bechValidator{ 265 OperatorAddress: v.OperatorAddress, 266 ConsPubKey: bechConsPubKey, 267 Jailed: v.Jailed, 268 Status: v.Status, 269 Tokens: v.Tokens, 270 DelegatorShares: v.DelegatorShares, 271 Description: v.Description, 272 UnbondingHeight: v.UnbondingHeight, 273 UnbondingCompletionTime: v.UnbondingCompletionTime, 274 MinSelfDelegation: v.MinSelfDelegation, 275 Commission: v.Commission, 276 }) 277 } 278 279 // UnmarshalJSON unmarshals the validator from JSON using Bech32 280 func (v *Validator) UnmarshalJSON(data []byte) error { 281 bv := &bechValidator{} 282 if err := codec.Cdc.UnmarshalJSON(data, bv); err != nil { 283 return err 284 } 285 consPubKey, err := GetConsPubKeyBech32(bv.ConsPubKey) 286 if err != nil { 287 return err 288 } 289 *v = Validator{ 290 OperatorAddress: bv.OperatorAddress, 291 ConsPubKey: consPubKey, 292 Jailed: bv.Jailed, 293 Tokens: bv.Tokens, 294 Status: bv.Status, 295 DelegatorShares: bv.DelegatorShares, 296 Description: bv.Description, 297 UnbondingHeight: bv.UnbondingHeight, 298 UnbondingCompletionTime: bv.UnbondingCompletionTime, 299 Commission: bv.Commission, 300 MinSelfDelegation: bv.MinSelfDelegation, 301 } 302 return nil 303 } 304 305 func (v *Validator) UnmarshalFromAmino(cdc *amino.Codec, data []byte) error { 306 var dataLen uint64 = 0 307 var subData []byte 308 var unbondingCompletionTimeUpdated bool 309 310 for { 311 data = data[dataLen:] 312 if len(data) == 0 { 313 break 314 } 315 316 pos, pbType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 317 if err != nil { 318 return err 319 } 320 data = data[1:] 321 322 if pbType == amino.Typ3_ByteLength { 323 var n int 324 dataLen, n, err = amino.DecodeUvarint(data) 325 if err != nil { 326 return err 327 } 328 data = data[n:] 329 if len(data) < int(dataLen) { 330 return fmt.Errorf("invalid data len") 331 } 332 subData = data[:dataLen] 333 } 334 335 switch pos { 336 case 1: 337 v.OperatorAddress = make([]byte, dataLen) 338 copy(v.OperatorAddress, subData) 339 case 2: 340 v.ConsPubKey, err = cryptoamino.UnmarshalPubKeyFromAmino(cdc, subData) 341 if err != nil { 342 return err 343 } 344 case 3: 345 if len(data) == 0 { 346 return fmt.Errorf("Validator : Jailed, not enough data") 347 } 348 if data[0] == 0 { 349 v.Jailed = false 350 } else if data[0] == 1 { 351 v.Jailed = true 352 } else { 353 return fmt.Errorf("Validator : Jailed, invalid data") 354 } 355 dataLen = 1 356 case 4: 357 status, n, err := amino.DecodeUvarint(data) 358 if err != nil { 359 return err 360 } 361 v.Status = sdk.BondStatus(status) 362 dataLen = uint64(n) 363 case 5: 364 if err = v.Tokens.UnmarshalFromAmino(cdc, subData); err != nil { 365 return err 366 } 367 case 6: 368 if err = v.DelegatorShares.UnmarshalFromAmino(cdc, subData); err != nil { 369 return err 370 } 371 case 7: 372 if err = v.Description.UnmarshalFromAmino(cdc, subData); err != nil { 373 return err 374 } 375 case 8: 376 u64, n, err := amino.DecodeUvarint(data) 377 if err != nil { 378 return err 379 } 380 v.UnbondingHeight = int64(u64) 381 dataLen = uint64(n) 382 case 9: 383 v.UnbondingCompletionTime, _, err = amino.DecodeTime(subData) 384 if err != nil { 385 return err 386 } 387 unbondingCompletionTimeUpdated = true 388 case 10: 389 if err = v.Commission.UnmarshalFromAmino(cdc, subData); err != nil { 390 return err 391 } 392 case 11: 393 if err = v.MinSelfDelegation.UnmarshalFromAmino(cdc, subData); err != nil { 394 return err 395 } 396 default: 397 return fmt.Errorf("unexpect feild num %d", pos) 398 } 399 } 400 if !unbondingCompletionTimeUpdated { 401 v.UnbondingCompletionTime = amino.ZeroTime 402 } 403 return nil 404 } 405 406 // TestEquivalent is only for the ut 407 func (v Validator) TestEquivalent(v2 Validator) bool { 408 return v.ConsPubKey.Equals(v2.ConsPubKey) && 409 bytes.Equal(v.OperatorAddress, v2.OperatorAddress) && 410 v.Status.Equal(v2.Status) && 411 v.Tokens.Equal(v2.Tokens) && 412 v.DelegatorShares.Equal(v2.DelegatorShares) && 413 v.Description == v2.Description && 414 v.Commission.Equal(v2.Commission) 415 } 416 417 // ConsAddress returns the TM validator address 418 func (v Validator) ConsAddress() sdk.ConsAddress { 419 return sdk.ConsAddress(v.ConsPubKey.Address()) 420 } 421 422 // IsBonded checks if the validator status equals Bonded 423 func (v Validator) IsBonded() bool { 424 return v.GetStatus().Equal(sdk.Bonded) 425 } 426 427 // IsUnbonded checks if the validator status equals Unbonded 428 func (v Validator) IsUnbonded() bool { 429 return v.GetStatus().Equal(sdk.Unbonded) 430 } 431 432 // IsUnbonding checks if the validator status equals Unbonding 433 func (v Validator) IsUnbonding() bool { 434 return v.GetStatus().Equal(sdk.Unbonding) 435 } 436 437 // DoNotModifyDesc is the constant used in flags to indicate that description field should not be updated 438 const DoNotModifyDesc = "[do-not-modify]" 439 440 // Description - description fields for a validator 441 type Description struct { 442 Moniker string `json:"moniker" yaml:"moniker"` // name 443 Identity string `json:"identity" yaml:"identity"` // optional identity signature (ex. UPort or Keybase) 444 Website string `json:"website" yaml:"website"` // optional website link 445 Details string `json:"details" yaml:"details"` // optional details 446 } 447 448 // NewDescription returns a new Description with the provided values. 449 func NewDescription(moniker, identity, website, details string) Description { 450 return Description{ 451 Moniker: moniker, 452 Identity: identity, 453 Website: website, 454 Details: details, 455 } 456 } 457 458 // UpdateDescription updates the fields of a given description. An error is 459 // returned if the resulting description contains an invalid length. 460 func (d Description) UpdateDescription(d2 Description) (Description, error) { 461 if d2.Moniker == DoNotModifyDesc { 462 d2.Moniker = d.Moniker 463 } 464 if d2.Identity == DoNotModifyDesc { 465 d2.Identity = d.Identity 466 } 467 if d2.Website == DoNotModifyDesc { 468 d2.Website = d.Website 469 } 470 if d2.Details == DoNotModifyDesc { 471 d2.Details = d.Details 472 } 473 474 return Description{ 475 Moniker: d2.Moniker, 476 Identity: d2.Identity, 477 Website: d2.Website, 478 Details: d2.Details, 479 }.EnsureLength() 480 } 481 482 // EnsureLength ensures the length of a validator's description. 483 func (d Description) EnsureLength() (Description, error) { 484 if len(d.Moniker) > MaxMonikerLength { 485 return d, ErrDescriptionLength("moniker", len(d.Moniker), MaxMonikerLength) 486 } 487 if len(d.Identity) > MaxIdentityLength { 488 return d, ErrDescriptionLength("identity", len(d.Identity), MaxIdentityLength) 489 } 490 if len(d.Website) > MaxWebsiteLength { 491 return d, ErrDescriptionLength("website", len(d.Website), MaxWebsiteLength) 492 } 493 if len(d.Details) > MaxDetailsLength { 494 return d, ErrDescriptionLength("details", len(d.Details), MaxDetailsLength) 495 } 496 497 return d, nil 498 } 499 500 func (d *Description) UnmarshalFromAmino(_ *amino.Codec, data []byte) error { 501 var dataLen uint64 = 0 502 var subData []byte 503 504 for { 505 data = data[dataLen:] 506 507 if len(data) == 0 { 508 break 509 } 510 511 pos, pbType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 512 if err != nil { 513 return err 514 } 515 data = data[1:] 516 517 if pbType != amino.Typ3_ByteLength { 518 return fmt.Errorf("expect proto3 type 2") 519 } 520 521 var n int 522 dataLen, n, err = amino.DecodeUvarint(data) 523 if err != nil { 524 return err 525 } 526 data = data[n:] 527 if len(data) < int(dataLen) { 528 return fmt.Errorf("invalid data len") 529 } 530 subData = data[:dataLen] 531 532 switch pos { 533 case 1: 534 d.Moniker = string(subData) 535 case 2: 536 d.Identity = string(subData) 537 case 3: 538 d.Website = string(subData) 539 case 4: 540 d.Details = string(subData) 541 default: 542 return fmt.Errorf("unexpect feild num %d", pos) 543 } 544 } 545 return nil 546 } 547 548 // ABCIValidatorUpdate returns an abci.ValidatorUpdate from a staking validator type 549 // with the full validator power 550 func (v Validator) ABCIValidatorUpdate() abci.ValidatorUpdate { 551 return abci.ValidatorUpdate{ 552 PubKey: tmtypes.TM2PB.PubKey(v.ConsPubKey), 553 Power: v.ConsensusPower(), 554 } 555 } 556 557 // ABCIValidatorUpdateZero returns an abci.ValidatorUpdate from a staking validator type 558 // with zero power used for validator updates. 559 func (v Validator) ABCIValidatorUpdateZero() abci.ValidatorUpdate { 560 return abci.ValidatorUpdate{ 561 PubKey: tmtypes.TM2PB.PubKey(v.ConsPubKey), 562 Power: 0, 563 } 564 } 565 566 // SetInitialCommission attempts to set a validator's initial commission. An 567 // error is returned if the commission is invalid. 568 func (v Validator) SetInitialCommission(commission Commission) (Validator, error) { 569 if err := commission.Validate(); err != nil { 570 return v, err 571 } 572 573 v.Commission = commission 574 return v, nil 575 } 576 577 // TODO : remove these functions that implements some origin interface later 578 579 // TokensFromShares calculates the token worth of provided shares 580 func (v Validator) TokensFromShares(shares sdk.Dec) sdk.Dec { 581 return (shares.MulInt(v.Tokens)).Quo(v.DelegatorShares) 582 } 583 584 // TokensFromSharesTruncated calculates the token worth of provided shares, truncated 585 func (v Validator) TokensFromSharesTruncated(shares sdk.Dec) sdk.Dec { 586 return (shares.MulInt(v.Tokens)).QuoTruncate(v.DelegatorShares) 587 } 588 589 // TokensFromSharesRoundUp returns the token worth of provided shares, rounded up 590 // No usage found in All Places 591 func (v Validator) TokensFromSharesRoundUp(shares sdk.Dec) sdk.Dec { 592 return sdk.ZeroDec() 593 //return (shares.MulInt(v.Tokens)).QuoRoundUp(v.DelegatorShares) 594 } 595 596 // SharesFromTokens returns the shares of a delegation given a bond amount 597 // It returns an error if the validator has no tokens 598 // No usage found in All Places 599 func (v Validator) SharesFromTokens(amt sdk.Int) (sdk.Dec, error) { 600 return sdk.ZeroDec(), nil 601 //if v.Tokens.IsZero() { 602 // return sdk.ZeroDec(), ErrInsufficientShares(DefaultCodespace) 603 //} 604 // 605 //return v.GetDelegatorShares().MulInt(amt).QuoInt(v.GetTokens()), nil 606 } 607 608 // SharesFromTokensTruncated returns the truncated shares of a delegation given a bond amount 609 // It returns an error if the validator has no tokens 610 // No usage found in All Places 611 func (v Validator) SharesFromTokensTruncated(amt sdk.Int) (sdk.Dec, error) { 612 return sdk.ZeroDec(), nil 613 //if v.Tokens.IsZero() { 614 // return sdk.ZeroDec(), ErrInsufficientShares(DefaultCodespace) 615 //} 616 // 617 //return v.GetDelegatorShares().MulInt(amt).QuoTruncate(v.GetTokens().ToDec()), nil 618 } 619 620 // BondedTokens gets the bonded tokens which the validator holds 621 func (v Validator) BondedTokens() sdk.Int { 622 if v.IsBonded() { 623 return v.Tokens 624 } 625 return sdk.ZeroInt() 626 } 627 628 // ConsensusPower gets the consensus-engine power 629 func (v Validator) ConsensusPower() int64 { 630 if v.IsBonded() { 631 return v.PotentialConsensusPowerByShares() 632 } 633 return 0 634 } 635 636 // UpdateStatus updates the location of the shares within a validator 637 // to reflect the new status 638 func (v Validator) UpdateStatus(newStatus sdk.BondStatus) Validator { 639 v.Status = newStatus 640 return v 641 } 642 643 // nolint - for ValidatorI 644 func (v Validator) IsJailed() bool { return v.Jailed } 645 func (v Validator) GetMoniker() string { return v.Description.Moniker } 646 func (v Validator) GetStatus() sdk.BondStatus { return v.Status } 647 func (v Validator) GetOperator() sdk.ValAddress { return v.OperatorAddress } 648 func (v Validator) GetConsPubKey() crypto.PubKey { return v.ConsPubKey } 649 func (v Validator) GetConsAddr() sdk.ConsAddress { return sdk.ConsAddress(v.ConsPubKey.Address()) } 650 func (v Validator) GetTokens() sdk.Int { return v.Tokens } 651 func (v Validator) GetBondedTokens() sdk.Int { return sdk.ZeroInt() } 652 func (v Validator) GetConsensusPower() int64 { return v.ConsensusPower() } 653 func (v Validator) GetCommission() sdk.Dec { return v.Commission.Rate } 654 func (v Validator) GetMinSelfDelegation() sdk.Dec { return v.MinSelfDelegation } 655 func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares }