github.com/Finschia/finschia-sdk@v0.48.1/x/staking/types/validator.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "fmt" 6 "sort" 7 "strings" 8 "time" 9 10 abci "github.com/tendermint/tendermint/abci/types" 11 tmprotocrypto "github.com/tendermint/tendermint/proto/tendermint/crypto" 12 13 "gopkg.in/yaml.v2" 14 15 "github.com/Finschia/finschia-sdk/codec" 16 codectypes "github.com/Finschia/finschia-sdk/codec/types" 17 cryptocodec "github.com/Finschia/finschia-sdk/crypto/codec" 18 cryptotypes "github.com/Finschia/finschia-sdk/crypto/types" 19 sdk "github.com/Finschia/finschia-sdk/types" 20 sdkerrors "github.com/Finschia/finschia-sdk/types/errors" 21 ) 22 23 const ( 24 // TODO: Why can't we just have one string description which can be JSON by convention 25 MaxMonikerLength = 70 26 MaxIdentityLength = 3000 27 MaxWebsiteLength = 140 28 MaxSecurityContactLength = 140 29 MaxDetailsLength = 280 30 ) 31 32 var ( 33 BondStatusUnspecified = BondStatus_name[int32(Unspecified)] 34 BondStatusUnbonded = BondStatus_name[int32(Unbonded)] 35 BondStatusUnbonding = BondStatus_name[int32(Unbonding)] 36 BondStatusBonded = BondStatus_name[int32(Bonded)] 37 ) 38 39 var _ ValidatorI = Validator{} 40 41 // NewValidator constructs a new Validator 42 // 43 //nolint:interfacer 44 func NewValidator(operator sdk.ValAddress, pubKey cryptotypes.PubKey, description Description) (Validator, error) { 45 pkAny, err := codectypes.NewAnyWithValue(pubKey) 46 if err != nil { 47 return Validator{}, err 48 } 49 50 return Validator{ 51 OperatorAddress: operator.String(), 52 ConsensusPubkey: pkAny, 53 Jailed: false, 54 Status: Unbonded, 55 Tokens: sdk.ZeroInt(), 56 DelegatorShares: sdk.ZeroDec(), 57 Description: description, 58 UnbondingHeight: int64(0), 59 UnbondingTime: time.Unix(0, 0).UTC(), 60 Commission: NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), 61 MinSelfDelegation: sdk.OneInt(), 62 }, nil 63 } 64 65 // String implements the Stringer interface for a Validator object. 66 func (v Validator) String() string { 67 out, _ := yaml.Marshal(v) 68 return string(out) 69 } 70 71 // Validators is a collection of Validator 72 type Validators []Validator 73 74 func (v Validators) String() (out string) { 75 for _, val := range v { 76 out += val.String() + "\n" 77 } 78 79 return strings.TrimSpace(out) 80 } 81 82 // ToSDKValidators - convenience function convert []Validator to []sdk.ValidatorI 83 func (v Validators) ToSDKValidators() (validators []ValidatorI) { 84 for _, val := range v { 85 validators = append(validators, val) 86 } 87 88 return validators 89 } 90 91 // Sort Validators sorts validator array in ascending operator address order 92 func (v Validators) Sort() { 93 sort.Sort(v) 94 } 95 96 // Implements sort interface 97 func (v Validators) Len() int { 98 return len(v) 99 } 100 101 // Implements sort interface 102 func (v Validators) Less(i, j int) bool { 103 return bytes.Compare(v[i].GetOperator().Bytes(), v[j].GetOperator().Bytes()) == -1 104 } 105 106 // Implements sort interface 107 func (v Validators) Swap(i, j int) { 108 v[i], v[j] = v[j], v[i] 109 } 110 111 // ValidatorsByVotingPower implements sort.Interface for []Validator based on 112 // the VotingPower and Address fields. 113 // The validators are sorted first by their voting power (descending). Secondary index - Address (ascending). 114 // Copied from ostracon/types/validator_set.go 115 type ValidatorsByVotingPower []Validator 116 117 func (valz ValidatorsByVotingPower) Len() int { return len(valz) } 118 119 func (valz ValidatorsByVotingPower) Less(i, j int, r sdk.Int) bool { 120 if valz[i].ConsensusPower(r) == valz[j].ConsensusPower(r) { 121 addrI, errI := valz[i].GetConsAddr() 122 addrJ, errJ := valz[j].GetConsAddr() 123 // If either returns error, then return false 124 if errI != nil || errJ != nil { 125 return false 126 } 127 return bytes.Compare(addrI, addrJ) == -1 128 } 129 return valz[i].ConsensusPower(r) > valz[j].ConsensusPower(r) 130 } 131 132 func (valz ValidatorsByVotingPower) Swap(i, j int) { 133 valz[i], valz[j] = valz[j], valz[i] 134 } 135 136 // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces 137 func (v Validators) UnpackInterfaces(c codectypes.AnyUnpacker) error { 138 for i := range v { 139 if err := v[i].UnpackInterfaces(c); err != nil { 140 return err 141 } 142 } 143 return nil 144 } 145 146 // return the redelegation 147 func MustMarshalValidator(cdc codec.BinaryCodec, validator *Validator) []byte { 148 return cdc.MustMarshal(validator) 149 } 150 151 // unmarshal a redelegation from a store value 152 func MustUnmarshalValidator(cdc codec.BinaryCodec, value []byte) Validator { 153 validator, err := UnmarshalValidator(cdc, value) 154 if err != nil { 155 panic(err) 156 } 157 158 return validator 159 } 160 161 // unmarshal a redelegation from a store value 162 func UnmarshalValidator(cdc codec.BinaryCodec, value []byte) (v Validator, err error) { 163 err = cdc.Unmarshal(value, &v) 164 return v, err 165 } 166 167 // IsBonded checks if the validator status equals Bonded 168 func (v Validator) IsBonded() bool { 169 return v.GetStatus() == Bonded 170 } 171 172 // IsUnbonded checks if the validator status equals Unbonded 173 func (v Validator) IsUnbonded() bool { 174 return v.GetStatus() == Unbonded 175 } 176 177 // IsUnbonding checks if the validator status equals Unbonding 178 func (v Validator) IsUnbonding() bool { 179 return v.GetStatus() == Unbonding 180 } 181 182 // constant used in flags to indicate that description field should not be updated 183 const DoNotModifyDesc = "[do-not-modify]" 184 185 func NewDescription(moniker, identity, website, securityContact, details string) Description { 186 return Description{ 187 Moniker: moniker, 188 Identity: identity, 189 Website: website, 190 SecurityContact: securityContact, 191 Details: details, 192 } 193 } 194 195 // String implements the Stringer interface for a Description object. 196 func (d Description) String() string { 197 out, _ := yaml.Marshal(d) 198 return string(out) 199 } 200 201 // UpdateDescription updates the fields of a given description. An error is 202 // returned if the resulting description contains an invalid length. 203 func (d Description) UpdateDescription(d2 Description) (Description, error) { 204 if d2.Moniker == DoNotModifyDesc { 205 d2.Moniker = d.Moniker 206 } 207 208 if d2.Identity == DoNotModifyDesc { 209 d2.Identity = d.Identity 210 } 211 212 if d2.Website == DoNotModifyDesc { 213 d2.Website = d.Website 214 } 215 216 if d2.SecurityContact == DoNotModifyDesc { 217 d2.SecurityContact = d.SecurityContact 218 } 219 220 if d2.Details == DoNotModifyDesc { 221 d2.Details = d.Details 222 } 223 224 return NewDescription( 225 d2.Moniker, 226 d2.Identity, 227 d2.Website, 228 d2.SecurityContact, 229 d2.Details, 230 ).EnsureLength() 231 } 232 233 // EnsureLength ensures the length of a validator's description. 234 func (d Description) EnsureLength() (Description, error) { 235 if len(d.Moniker) > MaxMonikerLength { 236 return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid moniker length; got: %d, max: %d", len(d.Moniker), MaxMonikerLength) 237 } 238 239 if len(d.Identity) > MaxIdentityLength { 240 return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid identity length; got: %d, max: %d", len(d.Identity), MaxIdentityLength) 241 } 242 243 if len(d.Website) > MaxWebsiteLength { 244 return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid website length; got: %d, max: %d", len(d.Website), MaxWebsiteLength) 245 } 246 247 if len(d.SecurityContact) > MaxSecurityContactLength { 248 return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid security contact length; got: %d, max: %d", len(d.SecurityContact), MaxSecurityContactLength) 249 } 250 251 if len(d.Details) > MaxDetailsLength { 252 return d, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid details length; got: %d, max: %d", len(d.Details), MaxDetailsLength) 253 } 254 255 return d, nil 256 } 257 258 // ABCIValidatorUpdate returns an abci.ValidatorUpdate from a staking validator type 259 // with the full validator power 260 func (v Validator) ABCIValidatorUpdate(r sdk.Int) abci.ValidatorUpdate { 261 ocProtoPk, err := v.OcConsPublicKey() 262 if err != nil { 263 panic(err) 264 } 265 266 return abci.ValidatorUpdate{ 267 PubKey: ocProtoPk, 268 Power: v.ConsensusPower(r), 269 } 270 } 271 272 // ABCIValidatorUpdateZero returns an abci.ValidatorUpdate from a staking validator type 273 // with zero power used for validator updates. 274 func (v Validator) ABCIValidatorUpdateZero() abci.ValidatorUpdate { 275 ocprotoPk, err := v.OcConsPublicKey() 276 if err != nil { 277 panic(err) 278 } 279 280 return abci.ValidatorUpdate{ 281 PubKey: ocprotoPk, 282 Power: 0, 283 } 284 } 285 286 // SetInitialCommission attempts to set a validator's initial commission. An 287 // error is returned if the commission is invalid. 288 func (v Validator) SetInitialCommission(commission Commission) (Validator, error) { 289 if err := commission.Validate(); err != nil { 290 return v, err 291 } 292 293 v.Commission = commission 294 295 return v, nil 296 } 297 298 // In some situations, the exchange rate becomes invalid, e.g. if 299 // Validator loses all tokens due to slashing. In this case, 300 // make all future delegations invalid. 301 func (v Validator) InvalidExRate() bool { 302 return v.Tokens.IsZero() && v.DelegatorShares.IsPositive() 303 } 304 305 // calculate the token worth of provided shares 306 func (v Validator) TokensFromShares(shares sdk.Dec) sdk.Dec { 307 return (shares.MulInt(v.Tokens)).Quo(v.DelegatorShares) 308 } 309 310 // calculate the token worth of provided shares, truncated 311 func (v Validator) TokensFromSharesTruncated(shares sdk.Dec) sdk.Dec { 312 return (shares.MulInt(v.Tokens)).QuoTruncate(v.DelegatorShares) 313 } 314 315 // TokensFromSharesRoundUp returns the token worth of provided shares, rounded 316 // up. 317 func (v Validator) TokensFromSharesRoundUp(shares sdk.Dec) sdk.Dec { 318 return (shares.MulInt(v.Tokens)).QuoRoundUp(v.DelegatorShares) 319 } 320 321 // SharesFromTokens returns the shares of a delegation given a bond amount. It 322 // returns an error if the validator has no tokens. 323 func (v Validator) SharesFromTokens(amt sdk.Int) (sdk.Dec, error) { 324 if v.Tokens.IsZero() { 325 return sdk.ZeroDec(), ErrInsufficientShares 326 } 327 328 return v.GetDelegatorShares().MulInt(amt).QuoInt(v.GetTokens()), nil 329 } 330 331 // SharesFromTokensTruncated returns the truncated shares of a delegation given 332 // a bond amount. It returns an error if the validator has no tokens. 333 func (v Validator) SharesFromTokensTruncated(amt sdk.Int) (sdk.Dec, error) { 334 if v.Tokens.IsZero() { 335 return sdk.ZeroDec(), ErrInsufficientShares 336 } 337 338 return v.GetDelegatorShares().MulInt(amt).QuoTruncate(v.GetTokens().ToDec()), nil 339 } 340 341 // get the bonded tokens which the validator holds 342 func (v Validator) BondedTokens() sdk.Int { 343 if v.IsBonded() { 344 return v.Tokens 345 } 346 347 return sdk.ZeroInt() 348 } 349 350 // ConsensusPower gets the consensus-engine power. Aa reduction of 10^6 from 351 // validator tokens is applied 352 func (v Validator) ConsensusPower(r sdk.Int) int64 { 353 if v.IsBonded() { 354 return v.PotentialConsensusPower(r) 355 } 356 357 return 0 358 } 359 360 // PotentialConsensusPower returns the potential consensus-engine power. 361 func (v Validator) PotentialConsensusPower(r sdk.Int) int64 { 362 return sdk.TokensToConsensusPower(v.Tokens, r) 363 } 364 365 // UpdateStatus updates the location of the shares within a validator 366 // to reflect the new status 367 func (v Validator) UpdateStatus(newStatus BondStatus) Validator { 368 v.Status = newStatus 369 return v 370 } 371 372 // AddTokensFromDel adds tokens to a validator 373 func (v Validator) AddTokensFromDel(amount sdk.Int) (Validator, sdk.Dec) { 374 // calculate the shares to issue 375 var issuedShares sdk.Dec 376 if v.DelegatorShares.IsZero() { 377 // the first delegation to a validator sets the exchange rate to one 378 issuedShares = amount.ToDec() 379 } else { 380 shares, err := v.SharesFromTokens(amount) 381 if err != nil { 382 panic(err) 383 } 384 385 issuedShares = shares 386 } 387 388 v.Tokens = v.Tokens.Add(amount) 389 v.DelegatorShares = v.DelegatorShares.Add(issuedShares) 390 391 return v, issuedShares 392 } 393 394 // RemoveTokens removes tokens from a validator 395 func (v Validator) RemoveTokens(tokens sdk.Int) Validator { 396 if tokens.IsNegative() { 397 panic(fmt.Sprintf("should not happen: trying to remove negative tokens %v", tokens)) 398 } 399 400 if v.Tokens.LT(tokens) { 401 panic(fmt.Sprintf("should not happen: only have %v tokens, trying to remove %v", v.Tokens, tokens)) 402 } 403 404 v.Tokens = v.Tokens.Sub(tokens) 405 406 return v 407 } 408 409 // RemoveDelShares removes delegator shares from a validator. 410 // NOTE: because token fractions are left in the valiadator, 411 // 412 // the exchange rate of future shares of this validator can increase. 413 func (v Validator) RemoveDelShares(delShares sdk.Dec) (Validator, sdk.Int) { 414 remainingShares := v.DelegatorShares.Sub(delShares) 415 416 var issuedTokens sdk.Int 417 if remainingShares.IsZero() { 418 // last delegation share gets any trimmings 419 issuedTokens = v.Tokens 420 v.Tokens = sdk.ZeroInt() 421 } else { 422 // leave excess tokens in the validator 423 // however fully use all the delegator shares 424 issuedTokens = v.TokensFromShares(delShares).TruncateInt() 425 v.Tokens = v.Tokens.Sub(issuedTokens) 426 427 if v.Tokens.IsNegative() { 428 panic("attempting to remove more tokens than available in validator") 429 } 430 } 431 432 v.DelegatorShares = remainingShares 433 434 return v, issuedTokens 435 } 436 437 // MinEqual defines a more minimum set of equality conditions when comparing two 438 // validators. 439 func (v *Validator) MinEqual(other *Validator) bool { 440 return v.OperatorAddress == other.OperatorAddress && 441 v.Status == other.Status && 442 v.Tokens.Equal(other.Tokens) && 443 v.DelegatorShares.Equal(other.DelegatorShares) && 444 v.Description.Equal(other.Description) && 445 v.Commission.Equal(other.Commission) && 446 v.Jailed == other.Jailed && 447 v.MinSelfDelegation.Equal(other.MinSelfDelegation) && 448 v.ConsensusPubkey.Equal(other.ConsensusPubkey) 449 } 450 451 // Equal checks if the receiver equals the parameter 452 func (v *Validator) Equal(v2 *Validator) bool { 453 return v.MinEqual(v2) && 454 v.UnbondingHeight == v2.UnbondingHeight && 455 v.UnbondingTime.Equal(v2.UnbondingTime) 456 } 457 458 func (v Validator) IsJailed() bool { return v.Jailed } 459 func (v Validator) GetMoniker() string { return v.Description.Moniker } 460 func (v Validator) GetStatus() BondStatus { return v.Status } 461 func (v Validator) GetOperator() sdk.ValAddress { 462 if v.OperatorAddress == "" { 463 return nil 464 } 465 addr, err := sdk.ValAddressFromBech32(v.OperatorAddress) 466 if err != nil { 467 panic(err) 468 } 469 return addr 470 } 471 472 // ConsPubKey returns the validator PubKey as a cryptotypes.PubKey. 473 func (v Validator) ConsPubKey() (cryptotypes.PubKey, error) { 474 pk, ok := v.ConsensusPubkey.GetCachedValue().(cryptotypes.PubKey) 475 if !ok { 476 return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expecting cryptotypes.PubKey, got %T", pk) 477 } 478 479 return pk, nil 480 } 481 482 // OcConsPublicKey casts Validator.ConsensusPubkey to tmprotocrypto.PubKey. 483 func (v Validator) OcConsPublicKey() (tmprotocrypto.PublicKey, error) { 484 pk, err := v.ConsPubKey() 485 if err != nil { 486 return tmprotocrypto.PublicKey{}, err 487 } 488 489 tmPk, err := cryptocodec.ToOcProtoPublicKey(pk) 490 if err != nil { 491 return tmprotocrypto.PublicKey{}, err 492 } 493 494 return tmPk, nil 495 } 496 497 // GetConsAddr extracts Consensus key address 498 func (v Validator) GetConsAddr() (sdk.ConsAddress, error) { 499 pk, ok := v.ConsensusPubkey.GetCachedValue().(cryptotypes.PubKey) 500 if !ok { 501 return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expecting cryptotypes.PubKey, got %T", pk) 502 } 503 504 return sdk.ConsAddress(pk.Address()), nil 505 } 506 507 func (v Validator) GetTokens() sdk.Int { return v.Tokens } 508 func (v Validator) GetBondedTokens() sdk.Int { return v.BondedTokens() } 509 func (v Validator) GetConsensusPower(r sdk.Int) int64 { 510 return v.ConsensusPower(r) 511 } 512 func (v Validator) GetCommission() sdk.Dec { return v.Commission.Rate } 513 func (v Validator) GetMinSelfDelegation() sdk.Int { return v.MinSelfDelegation } 514 func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares } 515 516 // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces 517 func (v Validator) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 518 var pk cryptotypes.PubKey 519 return unpacker.UnpackAny(v.ConsensusPubkey, &pk) 520 }