github.com/Finschia/finschia-sdk@v0.48.1/x/staking/keeper/delegation.go (about) 1 package keeper 2 3 import ( 4 "bytes" 5 "fmt" 6 "time" 7 8 sdk "github.com/Finschia/finschia-sdk/types" 9 sdkerrors "github.com/Finschia/finschia-sdk/types/errors" 10 "github.com/Finschia/finschia-sdk/x/staking/types" 11 ) 12 13 // GetDelegation returns a specific delegation. 14 func (k Keeper) GetDelegation(ctx sdk.Context, 15 delAddr sdk.AccAddress, valAddr sdk.ValAddress, 16 ) (delegation types.Delegation, found bool) { 17 store := ctx.KVStore(k.storeKey) 18 key := types.GetDelegationKey(delAddr, valAddr) 19 20 value := store.Get(key) 21 if value == nil { 22 return delegation, false 23 } 24 25 delegation = types.MustUnmarshalDelegation(k.cdc, value) 26 27 return delegation, true 28 } 29 30 // IterateAllDelegations iterates through all of the delegations. 31 func (k Keeper) IterateAllDelegations(ctx sdk.Context, cb func(delegation types.Delegation) (stop bool)) { 32 store := ctx.KVStore(k.storeKey) 33 34 iterator := sdk.KVStorePrefixIterator(store, types.DelegationKey) 35 defer iterator.Close() 36 37 for ; iterator.Valid(); iterator.Next() { 38 delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Value()) 39 if cb(delegation) { 40 break 41 } 42 } 43 } 44 45 // GetAllDelegations returns all delegations used during genesis dump. 46 func (k Keeper) GetAllDelegations(ctx sdk.Context) (delegations []types.Delegation) { 47 k.IterateAllDelegations(ctx, func(delegation types.Delegation) bool { 48 delegations = append(delegations, delegation) 49 return false 50 }) 51 52 return delegations 53 } 54 55 // GetValidatorDelegations returns all delegations to a specific validator. 56 // Useful for querier. 57 func (k Keeper) GetValidatorDelegations(ctx sdk.Context, valAddr sdk.ValAddress) (delegations []types.Delegation) { //nolint:interfacer 58 store := ctx.KVStore(k.storeKey) 59 60 iterator := sdk.KVStorePrefixIterator(store, types.DelegationKey) 61 defer iterator.Close() 62 63 for ; iterator.Valid(); iterator.Next() { 64 delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Value()) 65 if delegation.GetValidatorAddr().Equals(valAddr) { 66 delegations = append(delegations, delegation) 67 } 68 } 69 70 return delegations 71 } 72 73 // GetDelegatorDelegations returns a given amount of all the delegations from a 74 // delegator. 75 func (k Keeper) GetDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddress, 76 maxRetrieve uint16, 77 ) (delegations []types.Delegation) { 78 delegations = make([]types.Delegation, maxRetrieve) 79 store := ctx.KVStore(k.storeKey) 80 delegatorPrefixKey := types.GetDelegationsKey(delegator) 81 82 iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) 83 defer iterator.Close() 84 85 i := 0 86 for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() { 87 delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Value()) 88 delegations[i] = delegation 89 i++ 90 } 91 92 return delegations[:i] // trim if the array length < maxRetrieve 93 } 94 95 // SetDelegation sets a delegation. 96 func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { 97 delegatorAddress := sdk.MustAccAddressFromBech32(delegation.DelegatorAddress) 98 99 store := ctx.KVStore(k.storeKey) 100 b := types.MustMarshalDelegation(k.cdc, delegation) 101 store.Set(types.GetDelegationKey(delegatorAddress, delegation.GetValidatorAddr()), b) 102 } 103 104 // RemoveDelegation removes a delegation. 105 func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) { 106 delegatorAddress := sdk.MustAccAddressFromBech32(delegation.DelegatorAddress) 107 108 k.BeforeDelegationRemoved(ctx, delegatorAddress, delegation.GetValidatorAddr()) 109 store := ctx.KVStore(k.storeKey) 110 store.Delete(types.GetDelegationKey(delegatorAddress, delegation.GetValidatorAddr())) 111 } 112 113 // GetUnbondingDelegations returns a given amount of all the delegator unbonding-delegations. 114 func (k Keeper) GetUnbondingDelegations(ctx sdk.Context, delegator sdk.AccAddress, 115 maxRetrieve uint16, 116 ) (unbondingDelegations []types.UnbondingDelegation) { 117 unbondingDelegations = make([]types.UnbondingDelegation, maxRetrieve) 118 119 store := ctx.KVStore(k.storeKey) 120 delegatorPrefixKey := types.GetUBDsKey(delegator) 121 122 iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) 123 defer iterator.Close() 124 125 i := 0 126 for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() { 127 unbondingDelegation := types.MustUnmarshalUBD(k.cdc, iterator.Value()) 128 unbondingDelegations[i] = unbondingDelegation 129 i++ 130 } 131 132 return unbondingDelegations[:i] // trim if the array length < maxRetrieve 133 } 134 135 // GetUnbondingDelegation returns a unbonding delegation. 136 func (k Keeper) GetUnbondingDelegation( 137 ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, 138 ) (ubd types.UnbondingDelegation, found bool) { 139 store := ctx.KVStore(k.storeKey) 140 key := types.GetUBDKey(delAddr, valAddr) 141 value := store.Get(key) 142 143 if value == nil { 144 return ubd, false 145 } 146 147 ubd = types.MustUnmarshalUBD(k.cdc, value) 148 149 return ubd, true 150 } 151 152 // GetUnbondingDelegationsFromValidator returns all unbonding delegations from a 153 // particular validator. 154 func (k Keeper) GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr sdk.ValAddress) (ubds []types.UnbondingDelegation) { 155 store := ctx.KVStore(k.storeKey) 156 157 iterator := sdk.KVStorePrefixIterator(store, types.GetUBDsByValIndexKey(valAddr)) 158 defer iterator.Close() 159 160 for ; iterator.Valid(); iterator.Next() { 161 key := types.GetUBDKeyFromValIndexKey(iterator.Key()) 162 value := store.Get(key) 163 ubd := types.MustUnmarshalUBD(k.cdc, value) 164 ubds = append(ubds, ubd) 165 } 166 167 return ubds 168 } 169 170 // IterateUnbondingDelegations iterates through all of the unbonding delegations. 171 func (k Keeper) IterateUnbondingDelegations(ctx sdk.Context, fn func(index int64, ubd types.UnbondingDelegation) (stop bool)) { 172 store := ctx.KVStore(k.storeKey) 173 174 iterator := sdk.KVStorePrefixIterator(store, types.UnbondingDelegationKey) 175 defer iterator.Close() 176 177 for i := int64(0); iterator.Valid(); iterator.Next() { 178 ubd := types.MustUnmarshalUBD(k.cdc, iterator.Value()) 179 if stop := fn(i, ubd); stop { 180 break 181 } 182 i++ 183 } 184 } 185 186 // GetDelegatorUnbonding returns the total amount a delegator has unbonding. 187 func (k Keeper) GetDelegatorUnbonding(ctx sdk.Context, delegator sdk.AccAddress) sdk.Int { 188 unbonding := sdk.ZeroInt() 189 k.IterateDelegatorUnbondingDelegations(ctx, delegator, func(ubd types.UnbondingDelegation) bool { 190 for _, entry := range ubd.Entries { 191 unbonding = unbonding.Add(entry.Balance) 192 } 193 return false 194 }) 195 return unbonding 196 } 197 198 // IterateDelegatorUnbondingDelegations iterates through a delegator's unbonding delegations. 199 func (k Keeper) IterateDelegatorUnbondingDelegations(ctx sdk.Context, delegator sdk.AccAddress, cb func(ubd types.UnbondingDelegation) (stop bool)) { 200 store := ctx.KVStore(k.storeKey) 201 202 iterator := sdk.KVStorePrefixIterator(store, types.GetUBDsKey(delegator)) 203 defer iterator.Close() 204 205 for ; iterator.Valid(); iterator.Next() { 206 ubd := types.MustUnmarshalUBD(k.cdc, iterator.Value()) 207 if cb(ubd) { 208 break 209 } 210 } 211 } 212 213 // GetDelegatorBonded returs the total amount a delegator has bonded. 214 func (k Keeper) GetDelegatorBonded(ctx sdk.Context, delegator sdk.AccAddress) sdk.Int { 215 bonded := sdk.ZeroDec() 216 217 k.IterateDelegatorDelegations(ctx, delegator, func(delegation types.Delegation) bool { 218 validatorAddr, err := sdk.ValAddressFromBech32(delegation.ValidatorAddress) 219 if err != nil { 220 panic(err) // shouldn't happen 221 } 222 validator, found := k.GetValidator(ctx, validatorAddr) 223 if found { 224 shares := delegation.Shares 225 tokens := validator.TokensFromSharesTruncated(shares) 226 bonded = bonded.Add(tokens) 227 } 228 return false 229 }) 230 return bonded.RoundInt() 231 } 232 233 // IterateDelegatorDelegations iterates through one delegator's delegations. 234 func (k Keeper) IterateDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddress, cb func(delegation types.Delegation) (stop bool)) { 235 store := ctx.KVStore(k.storeKey) 236 delegatorPrefixKey := types.GetDelegationsKey(delegator) 237 iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) 238 defer iterator.Close() 239 240 for ; iterator.Valid(); iterator.Next() { 241 delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Value()) 242 if cb(delegation) { 243 break 244 } 245 } 246 } 247 248 // IterateDelegatorRedelegations iterates through one delegator's redelegations. 249 func (k Keeper) IterateDelegatorRedelegations(ctx sdk.Context, delegator sdk.AccAddress, cb func(red types.Redelegation) (stop bool)) { 250 store := ctx.KVStore(k.storeKey) 251 delegatorPrefixKey := types.GetREDsKey(delegator) 252 253 iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) 254 defer iterator.Close() 255 256 for ; iterator.Valid(); iterator.Next() { 257 red := types.MustUnmarshalRED(k.cdc, iterator.Value()) 258 if cb(red) { 259 break 260 } 261 } 262 } 263 264 // HasMaxUnbondingDelegationEntries - check if unbonding delegation has maximum number of entries. 265 func (k Keeper) HasMaxUnbondingDelegationEntries(ctx sdk.Context, 266 delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress, 267 ) bool { 268 ubd, found := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr) 269 if !found { 270 return false 271 } 272 273 return len(ubd.Entries) >= int(k.MaxEntries(ctx)) 274 } 275 276 // SetUnbondingDelegation sets the unbonding delegation and associated index. 277 func (k Keeper) SetUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDelegation) { 278 delegatorAddress := sdk.MustAccAddressFromBech32(ubd.DelegatorAddress) 279 280 store := ctx.KVStore(k.storeKey) 281 bz := types.MustMarshalUBD(k.cdc, ubd) 282 addr, err := sdk.ValAddressFromBech32(ubd.ValidatorAddress) 283 if err != nil { 284 panic(err) 285 } 286 key := types.GetUBDKey(delegatorAddress, addr) 287 store.Set(key, bz) 288 store.Set(types.GetUBDByValIndexKey(delegatorAddress, addr), []byte{}) // index, store empty bytes 289 } 290 291 // RemoveUnbondingDelegation removes the unbonding delegation object and associated index. 292 func (k Keeper) RemoveUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDelegation) { 293 delegatorAddress := sdk.MustAccAddressFromBech32(ubd.DelegatorAddress) 294 295 store := ctx.KVStore(k.storeKey) 296 addr, err := sdk.ValAddressFromBech32(ubd.ValidatorAddress) 297 if err != nil { 298 panic(err) 299 } 300 key := types.GetUBDKey(delegatorAddress, addr) 301 store.Delete(key) 302 store.Delete(types.GetUBDByValIndexKey(delegatorAddress, addr)) 303 } 304 305 // SetUnbondingDelegationEntry adds an entry to the unbonding delegation at 306 // the given addresses. It creates the unbonding delegation if it does not exist. 307 func (k Keeper) SetUnbondingDelegationEntry( 308 ctx sdk.Context, delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress, 309 creationHeight int64, minTime time.Time, balance sdk.Int, 310 ) types.UnbondingDelegation { 311 ubd, found := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr) 312 if found { 313 ubd.AddEntry(creationHeight, minTime, balance) 314 } else { 315 ubd = types.NewUnbondingDelegation(delegatorAddr, validatorAddr, creationHeight, minTime, balance) 316 } 317 318 k.SetUnbondingDelegation(ctx, ubd) 319 320 return ubd 321 } 322 323 // unbonding delegation queue timeslice operations 324 325 // GetUBDQueueTimeSlice gets a specific unbonding queue timeslice. A timeslice 326 // is a slice of DVPairs corresponding to unbonding delegations that expire at a 327 // certain time. 328 func (k Keeper) GetUBDQueueTimeSlice(ctx sdk.Context, timestamp time.Time) (dvPairs []types.DVPair) { 329 store := ctx.KVStore(k.storeKey) 330 331 bz := store.Get(types.GetUnbondingDelegationTimeKey(timestamp)) 332 if bz == nil { 333 return []types.DVPair{} 334 } 335 336 pairs := types.DVPairs{} 337 k.cdc.MustUnmarshal(bz, &pairs) 338 339 return pairs.Pairs 340 } 341 342 // SetUBDQueueTimeSlice sets a specific unbonding queue timeslice. 343 func (k Keeper) SetUBDQueueTimeSlice(ctx sdk.Context, timestamp time.Time, keys []types.DVPair) { 344 store := ctx.KVStore(k.storeKey) 345 bz := k.cdc.MustMarshal(&types.DVPairs{Pairs: keys}) 346 store.Set(types.GetUnbondingDelegationTimeKey(timestamp), bz) 347 } 348 349 // InsertUBDQueue inserts an unbonding delegation to the appropriate timeslice 350 // in the unbonding queue. 351 func (k Keeper) InsertUBDQueue(ctx sdk.Context, ubd types.UnbondingDelegation, 352 completionTime time.Time, 353 ) { 354 dvPair := types.DVPair{DelegatorAddress: ubd.DelegatorAddress, ValidatorAddress: ubd.ValidatorAddress} 355 356 timeSlice := k.GetUBDQueueTimeSlice(ctx, completionTime) 357 if len(timeSlice) == 0 { 358 k.SetUBDQueueTimeSlice(ctx, completionTime, []types.DVPair{dvPair}) 359 } else { 360 timeSlice = append(timeSlice, dvPair) 361 k.SetUBDQueueTimeSlice(ctx, completionTime, timeSlice) 362 } 363 } 364 365 // UBDQueueIterator returns all the unbonding queue timeslices from time 0 until endTime. 366 func (k Keeper) UBDQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator { 367 store := ctx.KVStore(k.storeKey) 368 return store.Iterator(types.UnbondingQueueKey, 369 sdk.InclusiveEndBytes(types.GetUnbondingDelegationTimeKey(endTime))) 370 } 371 372 // DequeueAllMatureUBDQueue returns a concatenated list of all the timeslices inclusively previous to 373 // currTime, and deletes the timeslices from the queue. 374 func (k Keeper) DequeueAllMatureUBDQueue(ctx sdk.Context, currTime time.Time) (matureUnbonds []types.DVPair) { 375 store := ctx.KVStore(k.storeKey) 376 377 // gets an iterator for all timeslices from time 0 until the current Blockheader time 378 unbondingTimesliceIterator := k.UBDQueueIterator(ctx, ctx.BlockHeader().Time) 379 defer unbondingTimesliceIterator.Close() 380 381 for ; unbondingTimesliceIterator.Valid(); unbondingTimesliceIterator.Next() { 382 timeslice := types.DVPairs{} 383 value := unbondingTimesliceIterator.Value() 384 k.cdc.MustUnmarshal(value, ×lice) 385 386 matureUnbonds = append(matureUnbonds, timeslice.Pairs...) 387 388 store.Delete(unbondingTimesliceIterator.Key()) 389 } 390 391 return matureUnbonds 392 } 393 394 // GetRedelegations returns a given amount of all the delegator redelegations. 395 func (k Keeper) GetRedelegations(ctx sdk.Context, delegator sdk.AccAddress, 396 maxRetrieve uint16, 397 ) (redelegations []types.Redelegation) { 398 redelegations = make([]types.Redelegation, maxRetrieve) 399 400 store := ctx.KVStore(k.storeKey) 401 delegatorPrefixKey := types.GetREDsKey(delegator) 402 403 iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) 404 defer iterator.Close() 405 406 i := 0 407 for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() { 408 redelegation := types.MustUnmarshalRED(k.cdc, iterator.Value()) 409 redelegations[i] = redelegation 410 i++ 411 } 412 413 return redelegations[:i] // trim if the array length < maxRetrieve 414 } 415 416 // GetRedelegation returns a redelegation. 417 func (k Keeper) GetRedelegation(ctx sdk.Context, 418 delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, 419 ) (red types.Redelegation, found bool) { 420 store := ctx.KVStore(k.storeKey) 421 key := types.GetREDKey(delAddr, valSrcAddr, valDstAddr) 422 423 value := store.Get(key) 424 if value == nil { 425 return red, false 426 } 427 428 red = types.MustUnmarshalRED(k.cdc, value) 429 430 return red, true 431 } 432 433 // GetRedelegationsFromSrcValidator returns all redelegations from a particular 434 // validator. 435 func (k Keeper) GetRedelegationsFromSrcValidator(ctx sdk.Context, valAddr sdk.ValAddress) (reds []types.Redelegation) { 436 store := ctx.KVStore(k.storeKey) 437 438 iterator := sdk.KVStorePrefixIterator(store, types.GetREDsFromValSrcIndexKey(valAddr)) 439 defer iterator.Close() 440 441 for ; iterator.Valid(); iterator.Next() { 442 key := types.GetREDKeyFromValSrcIndexKey(iterator.Key()) 443 value := store.Get(key) 444 red := types.MustUnmarshalRED(k.cdc, value) 445 reds = append(reds, red) 446 } 447 448 return reds 449 } 450 451 // HasReceivingRedelegation checks if validator is receiving a redelegation. 452 func (k Keeper) HasReceivingRedelegation(ctx sdk.Context, 453 delAddr sdk.AccAddress, valDstAddr sdk.ValAddress, 454 ) bool { 455 store := ctx.KVStore(k.storeKey) 456 prefix := types.GetREDsByDelToValDstIndexKey(delAddr, valDstAddr) 457 458 iterator := sdk.KVStorePrefixIterator(store, prefix) 459 defer iterator.Close() 460 461 return iterator.Valid() 462 } 463 464 // HasMaxRedelegationEntries checks if redelegation has maximum number of entries. 465 func (k Keeper) HasMaxRedelegationEntries(ctx sdk.Context, 466 delegatorAddr sdk.AccAddress, validatorSrcAddr, 467 validatorDstAddr sdk.ValAddress, 468 ) bool { 469 red, found := k.GetRedelegation(ctx, delegatorAddr, validatorSrcAddr, validatorDstAddr) 470 if !found { 471 return false 472 } 473 474 return len(red.Entries) >= int(k.MaxEntries(ctx)) 475 } 476 477 // SetRedelegation set a redelegation and associated index. 478 func (k Keeper) SetRedelegation(ctx sdk.Context, red types.Redelegation) { 479 delegatorAddress := sdk.MustAccAddressFromBech32(red.DelegatorAddress) 480 481 store := ctx.KVStore(k.storeKey) 482 bz := types.MustMarshalRED(k.cdc, red) 483 valSrcAddr, err := sdk.ValAddressFromBech32(red.ValidatorSrcAddress) 484 if err != nil { 485 panic(err) 486 } 487 valDestAddr, err := sdk.ValAddressFromBech32(red.ValidatorDstAddress) 488 if err != nil { 489 panic(err) 490 } 491 key := types.GetREDKey(delegatorAddress, valSrcAddr, valDestAddr) 492 store.Set(key, bz) 493 store.Set(types.GetREDByValSrcIndexKey(delegatorAddress, valSrcAddr, valDestAddr), []byte{}) 494 store.Set(types.GetREDByValDstIndexKey(delegatorAddress, valSrcAddr, valDestAddr), []byte{}) 495 } 496 497 // SetRedelegationEntry adds an entry to the unbonding delegation at the given 498 // addresses. It creates the unbonding delegation if it does not exist. 499 func (k Keeper) SetRedelegationEntry(ctx sdk.Context, 500 delegatorAddr sdk.AccAddress, validatorSrcAddr, 501 validatorDstAddr sdk.ValAddress, creationHeight int64, 502 minTime time.Time, balance sdk.Int, 503 sharesSrc, sharesDst sdk.Dec, 504 ) types.Redelegation { 505 red, found := k.GetRedelegation(ctx, delegatorAddr, validatorSrcAddr, validatorDstAddr) 506 if found { 507 red.AddEntry(creationHeight, minTime, balance, sharesDst) 508 } else { 509 red = types.NewRedelegation(delegatorAddr, validatorSrcAddr, 510 validatorDstAddr, creationHeight, minTime, balance, sharesDst) 511 } 512 513 k.SetRedelegation(ctx, red) 514 515 return red 516 } 517 518 // IterateRedelegations iterates through all redelegations. 519 func (k Keeper) IterateRedelegations(ctx sdk.Context, fn func(index int64, red types.Redelegation) (stop bool)) { 520 store := ctx.KVStore(k.storeKey) 521 522 iterator := sdk.KVStorePrefixIterator(store, types.RedelegationKey) 523 defer iterator.Close() 524 525 for i := int64(0); iterator.Valid(); iterator.Next() { 526 red := types.MustUnmarshalRED(k.cdc, iterator.Value()) 527 if stop := fn(i, red); stop { 528 break 529 } 530 i++ 531 } 532 } 533 534 // RemoveRedelegation removes a redelegation object and associated index. 535 func (k Keeper) RemoveRedelegation(ctx sdk.Context, red types.Redelegation) { 536 delegatorAddress := sdk.MustAccAddressFromBech32(red.DelegatorAddress) 537 538 store := ctx.KVStore(k.storeKey) 539 valSrcAddr, err := sdk.ValAddressFromBech32(red.ValidatorSrcAddress) 540 if err != nil { 541 panic(err) 542 } 543 valDestAddr, err := sdk.ValAddressFromBech32(red.ValidatorDstAddress) 544 if err != nil { 545 panic(err) 546 } 547 redKey := types.GetREDKey(delegatorAddress, valSrcAddr, valDestAddr) 548 store.Delete(redKey) 549 store.Delete(types.GetREDByValSrcIndexKey(delegatorAddress, valSrcAddr, valDestAddr)) 550 store.Delete(types.GetREDByValDstIndexKey(delegatorAddress, valSrcAddr, valDestAddr)) 551 } 552 553 // redelegation queue timeslice operations 554 555 // GetRedelegationQueueTimeSlice gets a specific redelegation queue timeslice. A 556 // timeslice is a slice of DVVTriplets corresponding to redelegations that 557 // expire at a certain time. 558 func (k Keeper) GetRedelegationQueueTimeSlice(ctx sdk.Context, timestamp time.Time) (dvvTriplets []types.DVVTriplet) { 559 store := ctx.KVStore(k.storeKey) 560 561 bz := store.Get(types.GetRedelegationTimeKey(timestamp)) 562 if bz == nil { 563 return []types.DVVTriplet{} 564 } 565 566 triplets := types.DVVTriplets{} 567 k.cdc.MustUnmarshal(bz, &triplets) 568 569 return triplets.Triplets 570 } 571 572 // SetRedelegationQueueTimeSlice sets a specific redelegation queue timeslice. 573 func (k Keeper) SetRedelegationQueueTimeSlice(ctx sdk.Context, timestamp time.Time, keys []types.DVVTriplet) { 574 store := ctx.KVStore(k.storeKey) 575 bz := k.cdc.MustMarshal(&types.DVVTriplets{Triplets: keys}) 576 store.Set(types.GetRedelegationTimeKey(timestamp), bz) 577 } 578 579 // InsertRedelegationQueue insert an redelegation delegation to the appropriate 580 // timeslice in the redelegation queue. 581 func (k Keeper) InsertRedelegationQueue(ctx sdk.Context, red types.Redelegation, 582 completionTime time.Time, 583 ) { 584 timeSlice := k.GetRedelegationQueueTimeSlice(ctx, completionTime) 585 dvvTriplet := types.DVVTriplet{ 586 DelegatorAddress: red.DelegatorAddress, 587 ValidatorSrcAddress: red.ValidatorSrcAddress, 588 ValidatorDstAddress: red.ValidatorDstAddress, 589 } 590 591 if len(timeSlice) == 0 { 592 k.SetRedelegationQueueTimeSlice(ctx, completionTime, []types.DVVTriplet{dvvTriplet}) 593 } else { 594 timeSlice = append(timeSlice, dvvTriplet) 595 k.SetRedelegationQueueTimeSlice(ctx, completionTime, timeSlice) 596 } 597 } 598 599 // RedelegationQueueIterator returns all the redelegation queue timeslices from 600 // time 0 until endTime. 601 func (k Keeper) RedelegationQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator { 602 store := ctx.KVStore(k.storeKey) 603 return store.Iterator(types.RedelegationQueueKey, sdk.InclusiveEndBytes(types.GetRedelegationTimeKey(endTime))) 604 } 605 606 // DequeueAllMatureRedelegationQueue returns a concatenated list of all the 607 // timeslices inclusively previous to currTime, and deletes the timeslices from 608 // the queue. 609 func (k Keeper) DequeueAllMatureRedelegationQueue(ctx sdk.Context, currTime time.Time) (matureRedelegations []types.DVVTriplet) { 610 store := ctx.KVStore(k.storeKey) 611 612 // gets an iterator for all timeslices from time 0 until the current Blockheader time 613 redelegationTimesliceIterator := k.RedelegationQueueIterator(ctx, ctx.BlockHeader().Time) 614 defer redelegationTimesliceIterator.Close() 615 616 for ; redelegationTimesliceIterator.Valid(); redelegationTimesliceIterator.Next() { 617 timeslice := types.DVVTriplets{} 618 value := redelegationTimesliceIterator.Value() 619 k.cdc.MustUnmarshal(value, ×lice) 620 621 matureRedelegations = append(matureRedelegations, timeslice.Triplets...) 622 623 store.Delete(redelegationTimesliceIterator.Key()) 624 } 625 626 return matureRedelegations 627 } 628 629 // Delegate performs a delegation, set/update everything necessary within the store. 630 // tokenSrc indicates the bond status of the incoming funds. 631 func (k Keeper) Delegate( 632 ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Int, tokenSrc types.BondStatus, 633 validator types.Validator, subtractAccount bool, 634 ) (newShares sdk.Dec, err error) { 635 // In some situations, the exchange rate becomes invalid, e.g. if 636 // Validator loses all tokens due to slashing. In this case, 637 // make all future delegations invalid. 638 if validator.InvalidExRate() { 639 return sdk.ZeroDec(), types.ErrDelegatorShareExRateInvalid 640 } 641 642 // Get or create the delegation object 643 delegation, found := k.GetDelegation(ctx, delAddr, validator.GetOperator()) 644 if !found { 645 delegation = types.NewDelegation(delAddr, validator.GetOperator(), sdk.ZeroDec()) 646 } 647 648 // call the appropriate hook if present 649 if found { 650 k.BeforeDelegationSharesModified(ctx, delAddr, validator.GetOperator()) 651 } else { 652 k.BeforeDelegationCreated(ctx, delAddr, validator.GetOperator()) 653 } 654 655 delegatorAddress := sdk.MustAccAddressFromBech32(delegation.DelegatorAddress) 656 657 // if subtractAccount is true then we are 658 // performing a delegation and not a redelegation, thus the source tokens are 659 // all non bonded 660 if subtractAccount { 661 if tokenSrc == types.Bonded { 662 panic("delegation token source cannot be bonded") 663 } 664 665 var sendName string 666 667 switch { 668 case validator.IsBonded(): 669 sendName = types.BondedPoolName 670 case validator.IsUnbonding(), validator.IsUnbonded(): 671 sendName = types.NotBondedPoolName 672 default: 673 panic("invalid validator status") 674 } 675 676 coins := sdk.NewCoins(sdk.NewCoin(k.BondDenom(ctx), bondAmt)) 677 if err := k.bankKeeper.DelegateCoinsFromAccountToModule(ctx, delegatorAddress, sendName, coins); err != nil { 678 return sdk.Dec{}, err 679 } 680 } else { 681 // potentially transfer tokens between pools, if 682 switch { 683 case tokenSrc == types.Bonded && validator.IsBonded(): 684 // do nothing 685 case (tokenSrc == types.Unbonded || tokenSrc == types.Unbonding) && !validator.IsBonded(): 686 // do nothing 687 case (tokenSrc == types.Unbonded || tokenSrc == types.Unbonding) && validator.IsBonded(): 688 // transfer pools 689 k.notBondedTokensToBonded(ctx, bondAmt) 690 case tokenSrc == types.Bonded && !validator.IsBonded(): 691 // transfer pools 692 k.bondedTokensToNotBonded(ctx, bondAmt) 693 default: 694 panic("unknown token source bond status") 695 } 696 } 697 698 _, newShares = k.AddValidatorTokensAndShares(ctx, validator, bondAmt) 699 700 // Update delegation 701 delegation.Shares = delegation.Shares.Add(newShares) 702 k.SetDelegation(ctx, delegation) 703 704 // Call the after-modification hook 705 k.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr()) 706 707 return newShares, nil 708 } 709 710 // Unbond unbonds a particular delegation and perform associated store operations. 711 func (k Keeper) Unbond( 712 ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, shares sdk.Dec, 713 ) (amount sdk.Int, err error) { 714 // check if a delegation object exists in the store 715 delegation, found := k.GetDelegation(ctx, delAddr, valAddr) 716 if !found { 717 return amount, types.ErrNoDelegatorForAddress 718 } 719 720 // call the before-delegation-modified hook 721 k.BeforeDelegationSharesModified(ctx, delAddr, valAddr) 722 723 // ensure that we have enough shares to remove 724 if delegation.Shares.LT(shares) { 725 return amount, sdkerrors.Wrap(types.ErrNotEnoughDelegationShares, delegation.Shares.String()) 726 } 727 728 // get validator 729 validator, found := k.GetValidator(ctx, valAddr) 730 if !found { 731 return amount, types.ErrNoValidatorFound 732 } 733 734 // subtract shares from delegation 735 delegation.Shares = delegation.Shares.Sub(shares) 736 737 delegatorAddress, err := sdk.AccAddressFromBech32(delegation.DelegatorAddress) 738 if err != nil { 739 return amount, err 740 } 741 742 isValidatorOperator := delegatorAddress.Equals(validator.GetOperator()) 743 744 // If the delegation is the operator of the validator and undelegating will decrease the validator's 745 // self-delegation below their minimum, we jail the validator. 746 if isValidatorOperator && !validator.Jailed && 747 validator.TokensFromShares(delegation.Shares).TruncateInt().LT(validator.MinSelfDelegation) { 748 k.jailValidator(ctx, validator) 749 validator = k.mustGetValidator(ctx, validator.GetOperator()) 750 } 751 752 // remove the delegation 753 if delegation.Shares.IsZero() { 754 k.RemoveDelegation(ctx, delegation) 755 } else { 756 k.SetDelegation(ctx, delegation) 757 // call the after delegation modification hook 758 k.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr()) 759 } 760 761 // remove the shares and coins from the validator 762 // NOTE that the amount is later (in keeper.Delegation) moved between staking module pools 763 validator, amount = k.RemoveValidatorTokensAndShares(ctx, validator, shares) 764 765 if validator.DelegatorShares.IsZero() && validator.IsUnbonded() { 766 // if not unbonded, we must instead remove validator in EndBlocker once it finishes its unbonding period 767 k.RemoveValidator(ctx, validator.GetOperator()) 768 } 769 770 return amount, nil 771 } 772 773 // getBeginInfo returns the completion time and height of a redelegation, along 774 // with a boolean signaling if the redelegation is complete based on the source 775 // validator. 776 func (k Keeper) getBeginInfo( 777 ctx sdk.Context, valSrcAddr sdk.ValAddress, 778 ) (completionTime time.Time, height int64, completeNow bool) { 779 validator, found := k.GetValidator(ctx, valSrcAddr) 780 781 // TODO: When would the validator not be found? 782 switch { 783 case !found || validator.IsBonded(): 784 // the longest wait - just unbonding period from now 785 completionTime = ctx.BlockHeader().Time.Add(k.UnbondingTime(ctx)) 786 height = ctx.BlockHeight() 787 788 return completionTime, height, false 789 790 case validator.IsUnbonded(): 791 return completionTime, height, true 792 793 case validator.IsUnbonding(): 794 return validator.UnbondingTime, validator.UnbondingHeight, false 795 796 default: 797 panic(fmt.Sprintf("unknown validator status: %s", validator.Status)) 798 } 799 } 800 801 // Undelegate unbonds an amount of delegator shares from a given validator. It 802 // will verify that the unbonding entries between the delegator and validator 803 // are not exceeded and unbond the staked tokens (based on shares) by creating 804 // an unbonding object and inserting it into the unbonding queue which will be 805 // processed during the staking EndBlocker. 806 func (k Keeper) Undelegate( 807 ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount sdk.Dec, 808 ) (time.Time, error) { 809 validator, found := k.GetValidator(ctx, valAddr) 810 if !found { 811 return time.Time{}, types.ErrNoDelegatorForAddress 812 } 813 814 if k.HasMaxUnbondingDelegationEntries(ctx, delAddr, valAddr) { 815 return time.Time{}, types.ErrMaxUnbondingDelegationEntries 816 } 817 818 returnAmount, err := k.Unbond(ctx, delAddr, valAddr, sharesAmount) 819 if err != nil { 820 return time.Time{}, err 821 } 822 823 // transfer the validator tokens to the not bonded pool 824 if validator.IsBonded() { 825 k.bondedTokensToNotBonded(ctx, returnAmount) 826 } 827 828 completionTime := ctx.BlockHeader().Time.Add(k.UnbondingTime(ctx)) 829 ubd := k.SetUnbondingDelegationEntry(ctx, delAddr, valAddr, ctx.BlockHeight(), completionTime, returnAmount) 830 k.InsertUBDQueue(ctx, ubd, completionTime) 831 832 return completionTime, nil 833 } 834 835 // CompleteUnbonding completes the unbonding of all mature entries in the 836 // retrieved unbonding delegation object and returns the total unbonding balance 837 // or an error upon failure. 838 func (k Keeper) CompleteUnbonding(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (sdk.Coins, error) { 839 ubd, found := k.GetUnbondingDelegation(ctx, delAddr, valAddr) 840 if !found { 841 return nil, types.ErrNoUnbondingDelegation 842 } 843 844 bondDenom := k.GetParams(ctx).BondDenom 845 balances := sdk.NewCoins() 846 ctxTime := ctx.BlockHeader().Time 847 848 delegatorAddress, err := sdk.AccAddressFromBech32(ubd.DelegatorAddress) 849 if err != nil { 850 return nil, err 851 } 852 853 // loop through all the entries and complete unbonding mature entries 854 for i := 0; i < len(ubd.Entries); i++ { 855 entry := ubd.Entries[i] 856 if entry.IsMature(ctxTime) { 857 ubd.RemoveEntry(int64(i)) 858 i-- 859 860 // track undelegation only when remaining or truncated shares are non-zero 861 if !entry.Balance.IsZero() { 862 amt := sdk.NewCoin(bondDenom, entry.Balance) 863 if err := k.bankKeeper.UndelegateCoinsFromModuleToAccount( 864 ctx, types.NotBondedPoolName, delegatorAddress, sdk.NewCoins(amt), 865 ); err != nil { 866 return nil, err 867 } 868 869 balances = balances.Add(amt) 870 } 871 } 872 } 873 874 // set the unbonding delegation or remove it if there are no more entries 875 if len(ubd.Entries) == 0 { 876 k.RemoveUnbondingDelegation(ctx, ubd) 877 } else { 878 k.SetUnbondingDelegation(ctx, ubd) 879 } 880 881 return balances, nil 882 } 883 884 // BeginRedelegation begins unbonding / redelegation and creates a redelegation 885 // record. 886 func (k Keeper) BeginRedelegation( 887 ctx sdk.Context, delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, sharesAmount sdk.Dec, 888 ) (completionTime time.Time, err error) { 889 if bytes.Equal(valSrcAddr, valDstAddr) { 890 return time.Time{}, types.ErrSelfRedelegation 891 } 892 893 dstValidator, found := k.GetValidator(ctx, valDstAddr) 894 if !found { 895 return time.Time{}, types.ErrBadRedelegationDst 896 } 897 898 srcValidator, found := k.GetValidator(ctx, valSrcAddr) 899 if !found { 900 return time.Time{}, types.ErrBadRedelegationDst 901 } 902 903 // check if this is a transitive redelegation 904 if k.HasReceivingRedelegation(ctx, delAddr, valSrcAddr) { 905 return time.Time{}, types.ErrTransitiveRedelegation 906 } 907 908 if k.HasMaxRedelegationEntries(ctx, delAddr, valSrcAddr, valDstAddr) { 909 return time.Time{}, types.ErrMaxRedelegationEntries 910 } 911 912 returnAmount, err := k.Unbond(ctx, delAddr, valSrcAddr, sharesAmount) 913 if err != nil { 914 return time.Time{}, err 915 } 916 917 if returnAmount.IsZero() { 918 return time.Time{}, types.ErrTinyRedelegationAmount 919 } 920 921 sharesCreated, err := k.Delegate(ctx, delAddr, returnAmount, srcValidator.GetStatus(), dstValidator, false) 922 if err != nil { 923 return time.Time{}, err 924 } 925 926 // create the unbonding delegation 927 completionTime, height, completeNow := k.getBeginInfo(ctx, valSrcAddr) 928 929 if completeNow { // no need to create the redelegation object 930 return completionTime, nil 931 } 932 933 red := k.SetRedelegationEntry( 934 ctx, delAddr, valSrcAddr, valDstAddr, 935 height, completionTime, returnAmount, sharesAmount, sharesCreated, 936 ) 937 k.InsertRedelegationQueue(ctx, red, completionTime) 938 939 return completionTime, nil 940 } 941 942 // CompleteRedelegation completes the redelegations of all mature entries in the 943 // retrieved redelegation object and returns the total redelegation (initial) 944 // balance or an error upon failure. 945 func (k Keeper) CompleteRedelegation( 946 ctx sdk.Context, delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, 947 ) (sdk.Coins, error) { 948 red, found := k.GetRedelegation(ctx, delAddr, valSrcAddr, valDstAddr) 949 if !found { 950 return nil, types.ErrNoRedelegation 951 } 952 953 bondDenom := k.GetParams(ctx).BondDenom 954 balances := sdk.NewCoins() 955 ctxTime := ctx.BlockHeader().Time 956 957 // loop through all the entries and complete mature redelegation entries 958 for i := 0; i < len(red.Entries); i++ { 959 entry := red.Entries[i] 960 if entry.IsMature(ctxTime) { 961 red.RemoveEntry(int64(i)) 962 i-- 963 964 if !entry.InitialBalance.IsZero() { 965 balances = balances.Add(sdk.NewCoin(bondDenom, entry.InitialBalance)) 966 } 967 } 968 } 969 970 // set the redelegation or remove it if there are no more entries 971 if len(red.Entries) == 0 { 972 k.RemoveRedelegation(ctx, red) 973 } else { 974 k.SetRedelegation(ctx, red) 975 } 976 977 return balances, nil 978 } 979 980 // ValidateUnbondAmount validates that a given unbond or redelegation amount is 981 // valied based on upon the converted shares. If the amount is valid, the total 982 // amount of respective shares is returned, otherwise an error is returned. 983 func (k Keeper) ValidateUnbondAmount( 984 ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, amt sdk.Int, 985 ) (shares sdk.Dec, err error) { 986 validator, found := k.GetValidator(ctx, valAddr) 987 if !found { 988 return shares, types.ErrNoValidatorFound 989 } 990 991 del, found := k.GetDelegation(ctx, delAddr, valAddr) 992 if !found { 993 return shares, types.ErrNoDelegation 994 } 995 996 shares, err = validator.SharesFromTokens(amt) 997 if err != nil { 998 return shares, err 999 } 1000 1001 sharesTruncated, err := validator.SharesFromTokensTruncated(amt) 1002 if err != nil { 1003 return shares, err 1004 } 1005 1006 delShares := del.GetShares() 1007 if sharesTruncated.GT(delShares) { 1008 return shares, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid shares amount") 1009 } 1010 1011 // Cap the shares at the delegation's shares. Shares being greater could occur 1012 // due to rounding, however we don't want to truncate the shares or take the 1013 // minimum because we want to allow for the full withdraw of shares from a 1014 // delegation. 1015 if shares.GT(delShares) { 1016 shares = delShares 1017 } 1018 1019 return shares, nil 1020 }