Skip to content

Commit

Permalink
fix(evmstaking): prevent partial state on failure txn (#339)
Browse files Browse the repository at this point in the history
use `CachedContext` to prevent partial state on failure txn

issue: none
  • Loading branch information
ezreal1997 authored Nov 7, 2024
1 parent 5c38893 commit 4d2e482
Show file tree
Hide file tree
Showing 13 changed files with 431 additions and 387 deletions.
27 changes: 16 additions & 11 deletions client/x/evmengine/keeper/ubi.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//nolint:contextcheck // use cached context
package keeper

import (
Expand Down Expand Up @@ -46,23 +47,27 @@ func (k *Keeper) ProcessUbiEvents(ctx context.Context, height uint64, logs []*ty
}

func (k *Keeper) ProcessUBIPercentageSet(ctx context.Context, ev *bindings.UBIPoolUBIPercentageSet) (err error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
cachedCtx, writeCache := sdkCtx.CacheContext()

defer func() {
sdkCtx := sdk.UnwrapSDKContext(ctx)
if err != nil {
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeUpdateUbiFailure,
sdk.NewAttribute(types.AttributeKeyBlockHeight, strconv.FormatInt(sdkCtx.BlockHeight(), 10)),
sdk.NewAttribute(types.AttributeKeyUbiPercentage, strconv.FormatUint(uint64(ev.Percentage), 10)),
sdk.NewAttribute(types.AttributeKeyStatusCode, errors.UnwrapErrCode(err).String()),
),
})
if err == nil {
writeCache()
return
}
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeUpdateUbiFailure,
sdk.NewAttribute(types.AttributeKeyBlockHeight, strconv.FormatInt(sdkCtx.BlockHeight(), 10)),
sdk.NewAttribute(types.AttributeKeyUbiPercentage, strconv.FormatUint(uint64(ev.Percentage), 10)),
sdk.NewAttribute(types.AttributeKeyStatusCode, errors.UnwrapErrCode(err).String()),
),
})
}()

newUBI := math.LegacyNewDecWithPrec(int64(ev.Percentage), 4)

if err = k.distrKeeper.SetUbi(ctx, newUBI); errors.Is(err, sdkerrors.ErrInvalidRequest) {
if err = k.distrKeeper.SetUbi(cachedCtx, newUBI); errors.Is(err, sdkerrors.ErrInvalidRequest) {
return errors.WrapErrWithCode(errors.InvalidRequest, err)
} else if err != nil {
return errors.Wrap(err, "set new UBI percentage")
Expand Down
31 changes: 18 additions & 13 deletions client/x/evmengine/keeper/upgrades.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//nolint:contextcheck // use cached context
package keeper

import (
Expand Down Expand Up @@ -46,23 +47,27 @@ func (k *Keeper) ProcessUpgradeEvents(ctx context.Context, height uint64, logs [
}

func (k *Keeper) ProcessSoftwareUpgrade(ctx context.Context, ev *bindings.UpgradeEntrypointSoftwareUpgrade) (err error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
cachedCtx, writeCache := sdkCtx.CacheContext()

defer func() {
sdkCtx := sdk.UnwrapSDKContext(ctx)
if err != nil {
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeUpgradeFailure,
sdk.NewAttribute(types.AttributeKeyBlockHeight, strconv.FormatInt(sdkCtx.BlockHeight(), 10)),
sdk.NewAttribute(types.AttributeKeyUpgradeName, ev.Name),
sdk.NewAttribute(types.AttributeKeyUpgradeHeight, strconv.FormatInt(ev.Height, 10)),
sdk.NewAttribute(types.AttributeKeyUpgradeInfo, ev.Info),
sdk.NewAttribute(types.AttributeKeyStatusCode, errors.UnwrapErrCode(err).String()),
),
})
if err == nil {
writeCache()
return
}
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeUpgradeFailure,
sdk.NewAttribute(types.AttributeKeyBlockHeight, strconv.FormatInt(sdkCtx.BlockHeight(), 10)),
sdk.NewAttribute(types.AttributeKeyUpgradeName, ev.Name),
sdk.NewAttribute(types.AttributeKeyUpgradeHeight, strconv.FormatInt(ev.Height, 10)),
sdk.NewAttribute(types.AttributeKeyUpgradeInfo, ev.Info),
sdk.NewAttribute(types.AttributeKeyStatusCode, errors.UnwrapErrCode(err).String()),
),
})
}()

if err = k.upgradeKeeper.ScheduleUpgrade(ctx, upgradetypes.Plan{
if err = k.upgradeKeeper.ScheduleUpgrade(cachedCtx, upgradetypes.Plan{
Name: ev.Name,
Info: ev.Info,
Height: ev.Height,
Expand Down
4 changes: 4 additions & 0 deletions client/x/evmengine/testutil/expected_keepers_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

114 changes: 65 additions & 49 deletions client/x/evmstaking/keeper/delegator_address.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//nolint:dupl // event log
//nolint:dupl,contextcheck // event log
package keeper

import (
Expand All @@ -16,19 +16,23 @@ import (
)

func (k Keeper) ProcessSetWithdrawalAddress(ctx context.Context, ev *bindings.IPTokenStakingSetWithdrawalAddress) (err error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
cachedCtx, writeCache := sdkCtx.CacheContext()

defer func() {
sdkCtx := sdk.UnwrapSDKContext(ctx)
if err != nil {
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeSetWithdrawalAddressFailure,
sdk.NewAttribute(types.AttributeKeyBlockHeight, strconv.FormatInt(sdkCtx.BlockHeight(), 10)),
sdk.NewAttribute(types.AttributeKeyDelegatorUncmpPubKey, hex.EncodeToString(ev.DelegatorUncmpPubkey)),
sdk.NewAttribute(types.AttributeKeyRewardAddress, hex.EncodeToString(ev.ExecutionAddress[:])),
sdk.NewAttribute(types.AttributeKeyStatusCode, errors.UnwrapErrCode(err).String()),
),
})
if err == nil {
writeCache()
return
}
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeSetWithdrawalAddressFailure,
sdk.NewAttribute(types.AttributeKeyBlockHeight, strconv.FormatInt(sdkCtx.BlockHeight(), 10)),
sdk.NewAttribute(types.AttributeKeyDelegatorUncmpPubKey, hex.EncodeToString(ev.DelegatorUncmpPubkey)),
sdk.NewAttribute(types.AttributeKeyRewardAddress, hex.EncodeToString(ev.ExecutionAddress[:])),
sdk.NewAttribute(types.AttributeKeyStatusCode, errors.UnwrapErrCode(err).String()),
),
})
}()

delCmpPubkey, err := UncmpPubKeyToCmpPubKey(ev.DelegatorUncmpPubkey)
Expand All @@ -43,27 +47,31 @@ func (k Keeper) ProcessSetWithdrawalAddress(ctx context.Context, ev *bindings.IP
depositorAddr := sdk.AccAddress(depositorPubkey.Address().Bytes())
executionAddr := common.BytesToAddress(ev.ExecutionAddress[:])

if err := k.DelegatorWithdrawAddress.Set(ctx, depositorAddr.String(), executionAddr.String()); err != nil {
if err := k.DelegatorWithdrawAddress.Set(cachedCtx, depositorAddr.String(), executionAddr.String()); err != nil {
return errors.Wrap(err, "delegator withdraw address map set")
}

return nil
}

func (k Keeper) ProcessSetRewardAddress(ctx context.Context, ev *bindings.IPTokenStakingSetRewardAddress) (err error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
cachedCtx, writeCache := sdkCtx.CacheContext()

defer func() {
sdkCtx := sdk.UnwrapSDKContext(ctx)
if err != nil {
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeSetRewardAddressFailure,
sdk.NewAttribute(types.AttributeKeyBlockHeight, strconv.FormatInt(sdkCtx.BlockHeight(), 10)),
sdk.NewAttribute(types.AttributeKeyDelegatorUncmpPubKey, hex.EncodeToString(ev.DelegatorUncmpPubkey)),
sdk.NewAttribute(types.AttributeKeyWithdrawalAddress, hex.EncodeToString(ev.ExecutionAddress[:])),
sdk.NewAttribute(types.AttributeKeyStatusCode, errors.UnwrapErrCode(err).String()),
),
})
if err == nil {
writeCache()
return
}
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeSetRewardAddressFailure,
sdk.NewAttribute(types.AttributeKeyBlockHeight, strconv.FormatInt(sdkCtx.BlockHeight(), 10)),
sdk.NewAttribute(types.AttributeKeyDelegatorUncmpPubKey, hex.EncodeToString(ev.DelegatorUncmpPubkey)),
sdk.NewAttribute(types.AttributeKeyWithdrawalAddress, hex.EncodeToString(ev.ExecutionAddress[:])),
sdk.NewAttribute(types.AttributeKeyStatusCode, errors.UnwrapErrCode(err).String()),
),
})
}()

delCmpPubkey, err := UncmpPubKeyToCmpPubKey(ev.DelegatorUncmpPubkey)
Expand All @@ -78,27 +86,31 @@ func (k Keeper) ProcessSetRewardAddress(ctx context.Context, ev *bindings.IPToke
depositorAddr := sdk.AccAddress(depositorPubkey.Address().Bytes())
executionAddr := common.BytesToAddress(ev.ExecutionAddress[:])

if err := k.DelegatorRewardAddress.Set(ctx, depositorAddr.String(), executionAddr.String()); err != nil {
if err := k.DelegatorRewardAddress.Set(cachedCtx, depositorAddr.String(), executionAddr.String()); err != nil {
return errors.Wrap(err, "delegator reward address map set")
}

return nil
}

func (k Keeper) ProcessAddOperator(ctx context.Context, ev *bindings.IPTokenStakingAddOperator) (err error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
cachedCtx, writeCache := sdkCtx.CacheContext()

defer func() {
sdkCtx := sdk.UnwrapSDKContext(ctx)
if err != nil {
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeAddOperatorFailure,
sdk.NewAttribute(types.AttributeKeyBlockHeight, strconv.FormatInt(sdkCtx.BlockHeight(), 10)),
sdk.NewAttribute(types.AttributeKeyDelegatorUncmpPubKey, hex.EncodeToString(ev.UncmpPubkey)),
sdk.NewAttribute(types.AttributeKeyOperatorAddress, ev.Operator.Hex()),
sdk.NewAttribute(types.AttributeKeyStatusCode, errors.UnwrapErrCode(err).String()),
),
})
if err == nil {
writeCache()
return
}
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeAddOperatorFailure,
sdk.NewAttribute(types.AttributeKeyBlockHeight, strconv.FormatInt(sdkCtx.BlockHeight(), 10)),
sdk.NewAttribute(types.AttributeKeyDelegatorUncmpPubKey, hex.EncodeToString(ev.UncmpPubkey)),
sdk.NewAttribute(types.AttributeKeyOperatorAddress, ev.Operator.Hex()),
sdk.NewAttribute(types.AttributeKeyStatusCode, errors.UnwrapErrCode(err).String()),
),
})
}()

delCmpPubkey, err := UncmpPubKeyToCmpPubKey(ev.UncmpPubkey)
Expand All @@ -112,27 +124,31 @@ func (k Keeper) ProcessAddOperator(ctx context.Context, ev *bindings.IPTokenStak

depositorAddr := sdk.AccAddress(depositorPubkey.Address().Bytes())

if err := k.DelegatorOperatorAddress.Set(ctx, depositorAddr.String(), ev.Operator.String()); err != nil {
if err := k.DelegatorOperatorAddress.Set(cachedCtx, depositorAddr.String(), ev.Operator.String()); err != nil {
return errors.Wrap(err, "delegator operator address map set")
}

return nil
}

func (k Keeper) ProcessRemoveOperator(ctx context.Context, ev *bindings.IPTokenStakingRemoveOperator) (err error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
cachedCtx, writeCache := sdkCtx.CacheContext()

defer func() {
sdkCtx := sdk.UnwrapSDKContext(ctx)
if err != nil {
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeRemoveOperatorFailure,
sdk.NewAttribute(types.AttributeKeyBlockHeight, strconv.FormatInt(sdkCtx.BlockHeight(), 10)),
sdk.NewAttribute(types.AttributeKeyDelegatorUncmpPubKey, hex.EncodeToString(ev.UncmpPubkey)),
sdk.NewAttribute(types.AttributeKeyOperatorAddress, ev.Operator.Hex()),
sdk.NewAttribute(types.AttributeKeyStatusCode, errors.UnwrapErrCode(err).String()),
),
})
if err == nil {
writeCache()
return
}
sdkCtx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeRemoveOperatorFailure,
sdk.NewAttribute(types.AttributeKeyBlockHeight, strconv.FormatInt(sdkCtx.BlockHeight(), 10)),
sdk.NewAttribute(types.AttributeKeyDelegatorUncmpPubKey, hex.EncodeToString(ev.UncmpPubkey)),
sdk.NewAttribute(types.AttributeKeyOperatorAddress, ev.Operator.Hex()),
sdk.NewAttribute(types.AttributeKeyStatusCode, errors.UnwrapErrCode(err).String()),
),
})
}()

delCmpPubkey, err := UncmpPubKeyToCmpPubKey(ev.UncmpPubkey)
Expand All @@ -146,7 +162,7 @@ func (k Keeper) ProcessRemoveOperator(ctx context.Context, ev *bindings.IPTokenS

depositorAddr := sdk.AccAddress(depositorPubkey.Address().Bytes())

if err := k.DelegatorOperatorAddress.Remove(ctx, depositorAddr.String()); err != nil {
if err := k.DelegatorOperatorAddress.Remove(cachedCtx, depositorAddr.String()); err != nil {
return errors.Wrap(err, "delegator operator address map remove")
}

Expand Down
Loading

0 comments on commit 4d2e482

Please sign in to comment.