Skip to content

Commit

Permalink
feat(staking): make staking keeper endblocker return unbonded entry (c…
Browse files Browse the repository at this point in the history
…osmos#4)

* chore(staking): add error log when unbonding and redelegation failed

* feat(staking): make staking keeper endblocker return unbonded entry
  • Loading branch information
0xHansLee authored Oct 16, 2024
1 parent 18efdf9 commit 77940b3
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 23 deletions.
2 changes: 1 addition & 1 deletion tests/integration/staking/keeper/delegation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func TestUnbondingDelegationsMaxEntries(t *testing.T) {

// mature unbonding delegations
ctx = ctx.WithBlockTime(completionTime)
_, err = f.stakingKeeper.CompleteUnbonding(ctx, addrDel, addrVal)
_, _, err = f.stakingKeeper.CompleteUnbonding(ctx, addrDel, addrVal)
assert.NilError(t, err)

newBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/staking/keeper/unbonding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ func TestUnbondingDelegationOnHold1(t *testing.T) {

// PROVIDER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE
f.sdkCtx = f.sdkCtx.WithBlockTime(completionTime)
_, err = f.stakingKeeper.CompleteUnbonding(f.sdkCtx, addrDels[0], addrVals[0])
_, _, err = f.stakingKeeper.CompleteUnbonding(f.sdkCtx, addrDels[0], addrVals[0])
assert.NilError(t, err)

// Check that the unbonding was finally completed
Expand All @@ -430,7 +430,7 @@ func TestUnbondingDelegationOnHold2(t *testing.T) {

// PROVIDER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE
f.sdkCtx = f.sdkCtx.WithBlockTime(completionTime)
_, err := f.stakingKeeper.CompleteUnbonding(f.sdkCtx, addrDels[0], addrVals[0])
_, _, err := f.stakingKeeper.CompleteUnbonding(f.sdkCtx, addrDels[0], addrVals[0])
assert.NilError(t, err)

bondedAmt3 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount
Expand Down
9 changes: 9 additions & 0 deletions x/staking/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ func (k *Keeper) BeginBlocker(ctx context.Context) error {

// EndBlocker called at every block, update validator set
func (k *Keeper) EndBlocker(ctx context.Context) ([]abci.ValidatorUpdate, error) {
valUpdates, _, err := k.EndBlockerWithUnbondedEntries(ctx)
if err != nil {
return nil, err
}

return valUpdates, nil
}

func (k Keeper) EndBlockerWithUnbondedEntries(ctx context.Context) ([]abci.ValidatorUpdate, []types.UnbondedEntry, error) {
defer telemetry.ModuleMeasureSince(types.ModuleName, telemetry.Now(), telemetry.MetricKeyEndBlocker)
return k.BlockValidatorUpdates(ctx)
}
23 changes: 15 additions & 8 deletions x/staking/keeper/delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -1239,15 +1239,15 @@ func (k Keeper) Undelegate(
// CompleteUnbonding completes the unbonding of all mature entries in the
// retrieved unbonding delegation object and returns the total unbonding balance
// or an error upon failure.
func (k Keeper) CompleteUnbonding(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (sdk.Coins, error) {
func (k Keeper) CompleteUnbonding(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (sdk.Coins, *types.UnbondedEntry, error) {
ubd, err := k.GetUnbondingDelegation(ctx, delAddr, valAddr)
if err != nil {
return nil, err
return nil, nil, err
}

bondDenom, err := k.BondDenom(ctx)
if err != nil {
return nil, err
return nil, nil, err
}

balances := sdk.NewCoins()
Expand All @@ -1256,7 +1256,13 @@ func (k Keeper) CompleteUnbonding(ctx context.Context, delAddr sdk.AccAddress, v

delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(ubd.DelegatorAddress)
if err != nil {
return nil, err
return nil, nil, err
}

unbondedEntry := &types.UnbondedEntry{
DelegatorAddress: delAddr.String(),
ValidatorAddress: valAddr.String(),
Amount: math.NewInt(0),
}

// loop through all the entries and complete unbonding mature entries
Expand All @@ -1266,7 +1272,7 @@ func (k Keeper) CompleteUnbonding(ctx context.Context, delAddr sdk.AccAddress, v
ubd.RemoveEntry(int64(i))
i--
if err = k.DeleteUnbondingIndex(ctx, entry.UnbondingId); err != nil {
return nil, err
return nil, unbondedEntry, err
}

// track undelegation only when remaining or truncated shares are non-zero
Expand All @@ -1275,10 +1281,11 @@ func (k Keeper) CompleteUnbonding(ctx context.Context, delAddr sdk.AccAddress, v
if err := k.bankKeeper.UndelegateCoinsFromModuleToAccount(
ctx, types.NotBondedPoolName, delegatorAddress, sdk.NewCoins(amt),
); err != nil {
return nil, err
return nil, unbondedEntry, err
}

balances = balances.Add(amt)
unbondedEntry.Amount = balances.AmountOf(bondDenom)
}
}
}
Expand All @@ -1291,10 +1298,10 @@ func (k Keeper) CompleteUnbonding(ctx context.Context, delAddr sdk.AccAddress, v
}

if err != nil {
return nil, err
return nil, unbondedEntry, err
}

return balances, nil
return balances, unbondedEntry, nil
}

// BeginRedelegation begins unbonding / redelegation and creates a redelegation
Expand Down
39 changes: 27 additions & 12 deletions x/staking/keeper/val_state_change.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (

// BlockValidatorUpdates calculates the ValidatorUpdates for the current block
// Called in each EndBlock
func (k Keeper) BlockValidatorUpdates(ctx context.Context) ([]abci.ValidatorUpdate, error) {
func (k Keeper) BlockValidatorUpdates(ctx context.Context) ([]abci.ValidatorUpdate, []types.UnbondedEntry, error) {
// Calculate validator set changes.
//
// NOTE: ApplyAndReturnValidatorSetUpdates has to come before
Expand All @@ -30,37 +30,46 @@ func (k Keeper) BlockValidatorUpdates(ctx context.Context) ([]abci.ValidatorUpda
// UnbondAllMatureValidatorQueue).
validatorUpdates, err := k.ApplyAndReturnValidatorSetUpdates(ctx)
if err != nil {
return nil, err
return nil, nil, err
}

// unbond all mature validators from the unbonding queue
err = k.UnbondAllMatureValidators(ctx)
if err != nil {
return nil, err
return nil, nil, err
}

sdkCtx := sdk.UnwrapSDKContext(ctx)
// Remove all mature unbonding delegations from the ubd queue.
matureUnbonds, err := k.DequeueAllMatureUBDQueue(ctx, sdkCtx.BlockHeader().Time)
if err != nil {
return nil, err
return nil, nil, err
}

var unbondedEntries []types.UnbondedEntry

for _, dvPair := range matureUnbonds {
addr, err := k.validatorAddressCodec.StringToBytes(dvPair.ValidatorAddress)
if err != nil {
return nil, err
return nil, nil, err
}
delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(dvPair.DelegatorAddress)
if err != nil {
return nil, err
return nil, nil, err
}

balances, err := k.CompleteUnbonding(ctx, delegatorAddress, addr)
balances, unbondedEntry, err := k.CompleteUnbonding(ctx, delegatorAddress, addr)
if err != nil {
k.Logger(ctx).Error(
"failed to complete unbonding",
"error", err,
"val_addr", string(addr),
"del_addr", string(delegatorAddress))
continue
}

unbondedEntries = append(unbondedEntries, *unbondedEntry)

sdkCtx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeCompleteUnbonding,
Expand All @@ -74,21 +83,21 @@ func (k Keeper) BlockValidatorUpdates(ctx context.Context) ([]abci.ValidatorUpda
// Remove all mature redelegations from the red queue.
matureRedelegations, err := k.DequeueAllMatureRedelegationQueue(ctx, sdkCtx.BlockHeader().Time)
if err != nil {
return nil, err
return nil, nil, err
}

for _, dvvTriplet := range matureRedelegations {
valSrcAddr, err := k.validatorAddressCodec.StringToBytes(dvvTriplet.ValidatorSrcAddress)
if err != nil {
return nil, err
return nil, nil, err
}
valDstAddr, err := k.validatorAddressCodec.StringToBytes(dvvTriplet.ValidatorDstAddress)
if err != nil {
return nil, err
return nil, nil, err
}
delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(dvvTriplet.DelegatorAddress)
if err != nil {
return nil, err
return nil, nil, err
}

balances, err := k.CompleteRedelegation(
Expand All @@ -98,6 +107,12 @@ func (k Keeper) BlockValidatorUpdates(ctx context.Context) ([]abci.ValidatorUpda
valDstAddr,
)
if err != nil {
k.Logger(ctx).Error(
"failed to complete redelegation",
"error", err,
"val_src_addr", string(valSrcAddr),
"val_dst_addr", string(valDstAddr),
"del_addr", string(delegatorAddress))
continue
}

Expand All @@ -112,7 +127,7 @@ func (k Keeper) BlockValidatorUpdates(ctx context.Context) ([]abci.ValidatorUpda
)
}

return validatorUpdates, nil
return validatorUpdates, unbondedEntries, nil
}

// ApplyAndReturnValidatorSetUpdates applies and return accumulated updates to the bonded validator set. Also,
Expand Down
6 changes: 6 additions & 0 deletions x/staking/types/delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,3 +384,9 @@ func (r RedelegationResponses) String() (out string) {

return strings.TrimSpace(out)
}

type UnbondedEntry struct {
ValidatorAddress string
DelegatorAddress string
Amount math.Int
}

0 comments on commit 77940b3

Please sign in to comment.