Skip to content

x/slashing/keeper: SlashRedelegation should hoist non-changing ValidatorAddress and DelegatorAddress parsing out of hot loop #18032

@odeke-em

Description

@odeke-em

Is there an existing issue for this?

  • I have searched the existing issues

What happened?

I was auditing and testing out code in x/slashing/keeper over the weekend and I noticed this code in a loop

continue
}
valDstAddr, err := k.validatorAddressCodec.StringToBytes(redelegation.ValidatorDstAddress)
if err != nil {
panic(err)
}
delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(redelegation.DelegatorAddress)
if err != nil {
panic(err)
}

and it doesn't change much so no need to keep it in that loop while redelegating

This fixes it by hoisting that code out

diff --git a/x/staking/keeper/slash.go b/x/staking/keeper/slash.go
index 5a0886141f..e61cbb5181 100644
--- a/x/staking/keeper/slash.go
+++ b/x/staking/keeper/slash.go
math.LegacyNewDecFromInt(tokensToBurn).QuoRoundUp(math.LegacyNewDecFromInt(validator.Tokens))
@@ -287,6 +299,16 @@ func (k Keeper) SlashRedelegation(ctx context.Context, srcValidator types.Valida
 	totalSlashAmount = math.ZeroInt()
 	bondedBurnedAmount, notBondedBurnedAmount := math.ZeroInt(), math.ZeroInt()
 
+	valDstAddr, err := k.validatorAddressCodec.StringToBytes(redelegation.ValidatorDstAddress)
+	if err != nil {
+		return math.ZeroInt(), fmt.Errorf("SlashRedelegation: could not parse validator destination address: %w", err)
+	}
+
+	delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(redelegation.DelegatorAddress)
+	if err != nil {
+		return math.ZeroInt(), fmt.Errorf("SlashRedelegation: could not parse delegator address: %w", err)
+	}
+
 	// perform slashing on all entries within the redelegation
 	for _, entry := range redelegation.Entries {
 		// If redelegation started before this height, stake didn't contribute to infraction
@@ -310,16 +332,7 @@ func (k Keeper) SlashRedelegation(ctx context.Context, srcValidator types.Valida
 			continue
 		}
 
-		valDstAddr, err := k.validatorAddressCodec.StringToBytes(redelegation.ValidatorDstAddress)
-		if err != nil {
-			panic(err)
-		}
-
-		delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(redelegation.DelegatorAddress)
-		if err != nil {
-			panic(err)
-		}
-
+		// Delegations can be dynamic hence need to be looked up on every redelegation entry loop.
 		delegation, err := k.Delegations.Get(ctx, collections.Join(sdk.AccAddress(delegatorAddress), sdk.ValAddress(valDstAddr)))
 		if err != nil {
 			// If deleted, delegation has zero shares, and we can't unbond any more

/cc @elias-orijtech

Cosmos SDK Version

main

How to reproduce?

Auditing the code

Metadata

Metadata

Assignees

No one assigned

    Labels

    T: PerformancePerformance improvementsType: Code HygieneGeneral cleanup and restructuring of code to provide clarity, flexibility, and modularity.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions