github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/staking/keeper/proxy.go (about)

     1  package keeper
     2  
     3  import (
     4  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     5  	"github.com/fibonacci-chain/fbc/x/staking/types"
     6  )
     7  
     8  // ClearProxy clears the ProxyAddress on the delegator who has bound
     9  func (k Keeper) ClearProxy(ctx sdk.Context, proxyAddr sdk.AccAddress) {
    10  	k.IterateProxy(ctx, proxyAddr, true, func(_ int64, delAddr, _ sdk.AccAddress) (stop bool) {
    11  		delegator, found := k.GetDelegator(ctx, delAddr)
    12  		if found {
    13  			delegator.UnbindProxy()
    14  			k.SetDelegator(ctx, delegator)
    15  		}
    16  		return false
    17  	})
    18  }
    19  
    20  // SetProxyBinding sets or deletes the key of proxy relationship
    21  func (k Keeper) SetProxyBinding(ctx sdk.Context, proxyAddress, delegatorAddress sdk.AccAddress, isRemove bool) {
    22  	store := ctx.KVStore(k.storeKey)
    23  	key := types.GetProxyDelegatorKey(proxyAddress, delegatorAddress)
    24  
    25  	if isRemove {
    26  		store.Delete(key)
    27  	} else {
    28  		store.Set(key, []byte(""))
    29  	}
    30  }
    31  
    32  // IterateProxy iterates all the info between delegator and its proxy
    33  func (k Keeper) IterateProxy(ctx sdk.Context, proxyAddr sdk.AccAddress, isClear bool,
    34  	fn func(index int64, delAddr, proxyAddr sdk.AccAddress) (stop bool)) {
    35  	store := ctx.KVStore(k.storeKey)
    36  	iterator := sdk.KVStorePrefixIterator(store, types.GetProxyDelegatorKey(proxyAddr, []byte{}))
    37  	defer iterator.Close()
    38  
    39  	index := sdk.AddrLen + 1
    40  	for i := int64(0); iterator.Valid(); iterator.Next() {
    41  		key := iterator.Key()
    42  		if stop := fn(i, key[index:], key[1:index]); stop {
    43  			break
    44  		}
    45  		if isClear {
    46  			store.Delete(key)
    47  		}
    48  		i++
    49  	}
    50  }
    51  
    52  // UpdateShares withdraws and adds shares continuously on the same validator set with different amount of shares
    53  func (k Keeper) UpdateShares(ctx sdk.Context, delAddr sdk.AccAddress, tokens sdk.Dec) error {
    54  	// get last validators that were added shares to and existing in the store
    55  	vals, lastShares := k.GetLastValsAddedSharesExisted(ctx, delAddr)
    56  	if vals == nil {
    57  		// if the delegator never adds shares, just pass
    58  		return nil
    59  	}
    60  	delegatorValAddresses := vals.ToValAddresses()
    61  	// withdraw delegation rewards, increments period, remove delegator starting info
    62  	k.BeforeDelegationSharesModified(ctx, delAddr, delegatorValAddresses)
    63  
    64  	lenVals := len(vals)
    65  	shares, sdkErr := calculateWeight(ctx.BlockTime().Unix(), tokens)
    66  	if sdkErr != nil {
    67  		return sdkErr
    68  	}
    69  
    70  	delegator, found := k.GetDelegator(ctx, delAddr)
    71  	if !found {
    72  		return types.ErrNoDelegatorExisted(delAddr.String())
    73  	}
    74  
    75  	for i := 0; i < lenVals; i++ {
    76  		if vals[i].MinSelfDelegation.IsZero() {
    77  			return types.ErrAddSharesToDismission(vals[i].OperatorAddress.String())
    78  		}
    79  
    80  		// 1.delete related store
    81  		k.DeleteValidatorByPowerIndex(ctx, vals[i])
    82  
    83  		// 2.update shares
    84  		k.SetShares(ctx, delAddr, vals[i].OperatorAddress, shares)
    85  
    86  		// 3.update validator
    87  		vals[i].DelegatorShares = vals[i].DelegatorShares.Sub(lastShares).Add(shares)
    88  		k.SetValidator(ctx, vals[i])
    89  		k.SetValidatorByPowerIndex(ctx, vals[i])
    90  	}
    91  
    92  	// update the delegator struct
    93  	delegator.Shares = shares
    94  	k.SetDelegator(ctx, delegator)
    95  
    96  	// initialize starting info for a new delegation
    97  	k.AfterDelegationModified(ctx, delegator.DelegatorAddress, delegatorValAddresses)
    98  
    99  	return nil
   100  }
   101  
   102  // AddSharesToValidators adds shares to validators and return the amount of the shares
   103  func (k Keeper) AddSharesToValidators(ctx sdk.Context, delAddr sdk.AccAddress, vals types.Validators, tokens sdk.Dec) (
   104  	shares types.Shares, sdkErr error) {
   105  	lenVals := len(vals)
   106  	shares, sdkErr = calculateWeight(ctx.BlockTime().Unix(), tokens)
   107  	if sdkErr != nil {
   108  		return
   109  	}
   110  	for i := 0; i < lenVals; i++ {
   111  		k.addShares(ctx, delAddr, vals[i], shares)
   112  	}
   113  	return
   114  }
   115  
   116  // WithdrawLastShares withdraws the shares last time from the validators
   117  func (k Keeper) WithdrawLastShares(ctx sdk.Context, delAddr sdk.AccAddress, lastValsAddedSharesTo types.Validators,
   118  	lastShares types.Shares) {
   119  	lenLastVals := len(lastValsAddedSharesTo)
   120  	if lenLastVals > 0 {
   121  		// withdraw delegation rewards, remove delegator starting info
   122  		k.BeforeDelegationSharesModified(ctx, delAddr, lastValsAddedSharesTo.ToValAddresses())
   123  	}
   124  
   125  	for i := 0; i < lenLastVals; i++ {
   126  		k.withdrawShares(ctx, delAddr, lastValsAddedSharesTo[i], lastShares)
   127  	}
   128  }
   129  
   130  func (k Keeper) withdrawShares(ctx sdk.Context, delAddr sdk.AccAddress, val types.Validator, shares types.Shares) {
   131  	// 1.delete shares entity
   132  	k.DeleteShares(ctx, val.OperatorAddress, delAddr)
   133  
   134  	// 2.update validator entity
   135  	k.DeleteValidatorByPowerIndex(ctx, val)
   136  
   137  	// 3.update validator's shares
   138  	val.DelegatorShares = val.GetDelegatorShares().Sub(shares)
   139  
   140  	// 3.check whether the validator should be removed
   141  	if val.IsUnbonded() && val.GetMinSelfDelegation().IsZero() && val.GetDelegatorShares().IsZero() {
   142  		k.RemoveValidator(ctx, val.OperatorAddress)
   143  		return
   144  	}
   145  
   146  	k.SetValidator(ctx, val)
   147  	k.SetValidatorByPowerIndex(ctx, val)
   148  }
   149  
   150  func (k Keeper) addShares(ctx sdk.Context, delAddr sdk.AccAddress, val types.Validator, shares types.Shares) {
   151  	// 1.update shares entity
   152  	k.SetShares(ctx, delAddr, val.OperatorAddress, shares)
   153  
   154  	// 2.update validator entity
   155  	k.DeleteValidatorByPowerIndex(ctx, val)
   156  	val.DelegatorShares = val.GetDelegatorShares().Add(shares)
   157  	k.SetValidator(ctx, val)
   158  	k.SetValidatorByPowerIndex(ctx, val)
   159  }
   160  
   161  // GetLastValsAddedSharesExisted gets last validators that the delegator added shares to last time
   162  func (k Keeper) GetLastValsAddedSharesExisted(ctx sdk.Context, delAddr sdk.AccAddress) (types.Validators, types.Shares) {
   163  	// 1.get delegator entity
   164  	delegator, found := k.GetDelegator(ctx, delAddr)
   165  
   166  	// if not found
   167  	if !found {
   168  		return nil, sdk.ZeroDec()
   169  	}
   170  
   171  	// 2.get validators that were added shares to and existing in the store
   172  	lenVals := len(delegator.ValidatorAddresses)
   173  	var vals types.Validators
   174  	for i := 0; i < lenVals; i++ {
   175  		val, found := k.GetValidator(ctx, delegator.ValidatorAddresses[i])
   176  		if found {
   177  			// the validator that were added shares to hasn't been removed
   178  			vals = append(vals, val)
   179  		}
   180  	}
   181  
   182  	return vals, delegator.Shares
   183  }
   184  
   185  // GetValidatorsToAddShares gets the validators from their validator addresses
   186  func (k Keeper) GetValidatorsToAddShares(ctx sdk.Context, valAddrs []sdk.ValAddress) (types.Validators, error) {
   187  	lenVals := len(valAddrs)
   188  	vals := make(types.Validators, lenVals)
   189  	for i := 0; i < lenVals; i++ {
   190  		val, found := k.GetValidator(ctx, valAddrs[i])
   191  		if found {
   192  			// get the validator hasn't been removed
   193  			vals[i] = val
   194  		} else {
   195  			return nil, types.ErrNoValidatorFound(valAddrs[i].String())
   196  		}
   197  	}
   198  
   199  	return vals, nil
   200  }