Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sdk v0.46.* and ibc-go v5.1.0 #349

Merged
merged 77 commits into from
Jan 11, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
34d23df
bump version: sdk => 0.46.4, ibc => 5.1.0
hieuvubk Nov 17, 2022
87a5a23
update version grpc
hieuvubk Nov 17, 2022
33a6066
fix keychain import
hieuvubk Nov 17, 2022
c11dd19
change import govtypes & store keys
hieuvubk Nov 17, 2022
2d82b3f
fixing
hieuvubk Nov 17, 2022
3c30499
fix OnChanOpenInit
hieuvubk Nov 17, 2022
91a46f4
NewIBCModule => NewIBCMiddleware
hieuvubk Nov 17, 2022
66a4bd8
remove register rest api
hieuvubk Nov 17, 2022
7c3ebd2
fix testutil network prunning
Nov 17, 2022
5f81dd4
fix pruning testutil
Nov 17, 2022
d92b389
fix RegisterTendermintService
hieuvubk Nov 17, 2022
553c297
Merge branch 'upgrade_ibc_v5' of https://github.com/notional-labs/str…
hieuvubk Nov 17, 2022
a378c78
fix app.go
hieuvubk Nov 17, 2022
dad9eef
fix genaccount & main cmd
hieuvubk Nov 17, 2022
a5edb43
fix root.go in cmd
Nov 17, 2022
82d08c1
pull upstream
Nov 17, 2022
b70b627
fix empty valset
hieuvubk Nov 18, 2022
67fbece
fixing
hieuvubk Nov 18, 2022
9f7b932
get appVersion
hieuvubk Nov 21, 2022
e65581d
fixing parse coin
hieuvubk Nov 21, 2022
da8a4be
fix test for ibc denom
hieuvubk Nov 21, 2022
e43200c
remove fmt
hieuvubk Nov 21, 2022
52e9759
fix merge confilct
Nov 21, 2022
b7433c1
fix lint error
Nov 21, 2022
948675c
upgrade to v0.46.6 to avoid err
hieuvubk Nov 22, 2022
ca2fe15
Merge branch 'upgrade_ibc_v5' of https://github.com/notional-labs/str…
hieuvubk Nov 22, 2022
ec3fb68
add no lint check for sdk.MsgData
Nov 22, 2022
15eebd6
Merge branch 'main' into upgrade_ibc_v5
hieuvubk Nov 22, 2022
1bfff01
fix lint: check func return err
hieuvubk Nov 22, 2022
e0d2d8b
Merge branch 'upgrade_ibc_v5' of https://github.com/notional-labs/str…
hieuvubk Nov 22, 2022
b4232fa
rebuild protos now that we refer to v4
faddat Dec 4, 2022
6812ee1
tidy and correct versions in go.mod
faddat Dec 4, 2022
acd8c57
update stride
faddat Dec 4, 2022
bafb8d4
further bumps
faddat Dec 4, 2022
e032969
fixes
faddat Dec 4, 2022
1fcdc2e
fix queries.go
faddat Dec 4, 2022
d56efb6
fix abci types
faddat Dec 4, 2022
92daa30
revert change bats
hieuvubk Dec 4, 2022
f6723f4
fix queries.go
hieuvubk Dec 4, 2022
f304ca9
lint: remove unused field
hieuvubk Dec 4, 2022
b5c9574
Merge branch 'main' into upgrade_ibc_v5
asalzmann Dec 6, 2022
86ac940
Add test for err MintStAsset
DongLieu Dec 9, 2022
a4b0672
Merge pull request #12 from notional-labs/Unit-test-LiquidStake
ThanhNhann Dec 13, 2022
58e4fda
merge
hieuvubk Dec 20, 2022
f0b4247
Merge branch 'main' of https://github.com/notional-labs/stride into main
hieuvubk Jan 2, 2023
23be8f3
rebase
hieuvubk Jan 2, 2023
5704e44
fix err message
hieuvubk Jan 2, 2023
68c1eef
remove unused test
hieuvubk Jan 2, 2023
8cb8472
sdk 0.46.7
hieuvubk Jan 2, 2023
bed03d2
use cosmosmath.Int to fix lint
hieuvubk Jan 4, 2023
921b0f6
use cosmosmath
hieuvubk Jan 6, 2023
ee0df1d
remove unused cmt
hieuvubk Jan 6, 2023
a0d2adf
Merge branch 'main' into upgrade_ibc_v5
asalzmann Jan 6, 2023
198f5ac
sam comments
asalzmann Jan 6, 2023
0f49cc1
update handle ack
hieuvubk Jan 6, 2023
7e5aa93
pull
hieuvubk Jan 6, 2023
1e3be24
remove nolint flags
hieuvubk Jan 6, 2023
70d2e45
fix lint
hieuvubk Jan 6, 2023
f8cd873
remove comments
hieuvubk Jan 6, 2023
11b6209
Merge branch 'main' into upgrade_ibc_v5
hieuvubk Jan 6, 2023
cd36b83
cosmosmath => sdkmath
hieuvubk Jan 6, 2023
d52dd5b
add ICATxResponse type, branch sdk 45/46 logic
asalzmann Jan 6, 2023
2d185ab
refactored ica callback ack handling
sampocs Jan 6, 2023
8e356f2
updated relayer for v5
sampocs Jan 6, 2023
36c379d
pr comments and integration test fixes
sampocs Jan 7, 2023
af6f288
rm nil ack
asalzmann Jan 7, 2023
28ffb8d
added debugging logs in ack unwrapper
sampocs Jan 9, 2023
d1af58c
added unit tests for UnpackAck
sampocs Jan 10, 2023
025e373
added parse tx msg data function and more unit tests
sampocs Jan 10, 2023
782d385
fixed unit tests
sampocs Jan 10, 2023
167caee
Merge branch 'main' into upgrade_ibc_v5
sampocs Jan 10, 2023
e9af2cf
added no lint annotation for sdk.MsgData
sampocs Jan 10, 2023
cfc9861
Merge remote-tracking branch 'upstream/main' into upgrade_ibc_v5
sampocs Jan 10, 2023
b6ce2d0
added logging helper to print ICA status
sampocs Jan 10, 2023
593429f
Merge remote-tracking branch 'upstream/main' into upgrade_ibc_v5
sampocs Jan 10, 2023
1717780
fixed bug in counterparty connection with registering a host zone/res…
sampocs Jan 10, 2023
5fc4413
fixed unit tests
sampocs Jan 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions x/icacallbacks/module_ibc.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"github.com/gogo/protobuf/proto"
"github.com/tendermint/tendermint/libs/log"

"github.com/Stride-Labs/stride/v4/x/icacallbacks/types"

"github.com/Stride-Labs/stride/v4/x/icacallbacks/keeper"
)

Expand Down Expand Up @@ -92,7 +94,11 @@ func (im IBCModule) NegotiateAppVersion(
}

// GetTxMsgData returns the msgs from an ICA transaction and can be reused across authentication modules
func GetTxMsgData(ctx sdk.Context, ack channeltypes.Acknowledgement, logger log.Logger) (*sdk.TxMsgData, error) {
func GetTxMsgData(ctx sdk.Context, ack channeltypes.Acknowledgement, logger log.Logger) (*types.ICATxResponse, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're on board with moving the ack unmarshaling out, I think we should add it to the top of this function and rename it to something more generic like UnpackICAAcknowledgement(I'm sure you can think of a much better name)

And then each callback would take types.ICATxResponse as the argument instead of the Ack packet type

// if ack is nil, a timeout occurred
if &ack == nil {
asalzmann marked this conversation as resolved.
Show resolved Hide resolved
return &types.ICATxResponse{Status: types.TIMEOUT}, nil
}
txMsgData := &sdk.TxMsgData{}
switch response := ack.Response.(type) {
case *channeltypes.Acknowledgement_Result:
Expand All @@ -104,11 +110,13 @@ func GetTxMsgData(ctx sdk.Context, ack channeltypes.Acknowledgement, logger log.
logger.Error(fmt.Sprintf("cannot unmarshal ICS-27 tx message data: %s", err.Error()))
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-27 tx message data: %s", err.Error())
}
return txMsgData, nil
// NOTE: Is this safe to assume? According to the ics-27 spec, errors on host chains should be reflected in the acknowledgement type
asalzmann marked this conversation as resolved.
Show resolved Hide resolved
// so Acknowledgement_Result should only be returned if the transaction was successful
// However, I recall seeing a case where the acknowledgement type was Acknowledgement_Result but the transaction failed
return &types.ICATxResponse{Status: types.SUCCESS, Data: *txMsgData}, nil
case *channeltypes.Acknowledgement_Error:
logger.Error(fmt.Sprintf("acknowledgement error: %s", response.Error))
return txMsgData, nil

return &types.ICATxResponse{Status: types.FAILURE}, nil
default:
return nil, sdkerrors.Wrapf(channeltypes.ErrInvalidAcknowledgement, "unsupported acknowledgement response field type %T", response)
}
Expand Down
15 changes: 15 additions & 0 deletions x/icacallbacks/types/ICATxResponseStatus.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package types

import sdk "github.com/cosmos/cosmos-sdk/types"


type ICATxResponseStatus int
const (
SUCCESS ICATxResponseStatus = iota
TIMEOUT
FAILURE
)
type ICATxResponse struct {
Status ICATxResponseStatus // enum of SUCCESS, TIMEOUT, FAILURE
Data sdk.TxMsgData // TxMsgData
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And then I think you want data to be a byte array here

}
18 changes: 9 additions & 9 deletions x/stakeibc/keeper/icacallbacks_claim.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,24 +44,24 @@ func ClaimCallback(k Keeper, ctx sdk.Context, packet channeltypes.Packet, ack *c
return sdkerrors.Wrapf(types.ErrRecordNotFound, "user redemption record not found %s", claimCallback.GetUserRedemptionRecordId())
}

icaTxResponse, err := icacallbacks.GetTxMsgData(ctx, *ack, k.Logger(ctx))
if err != nil {
k.Logger(ctx).Error(fmt.Sprintf("failed to unmarshal txMsgData, packet %v", packet))
return sdkerrors.Wrap(icacallbackstypes.ErrTxMsgData, err.Error())
}

// handle timeout
if ack == nil {
if icaTxResponse.Status == icacallbackstypes.TIMEOUT {
k.Logger(ctx).Error(fmt.Sprintf("ClaimCallback timeout, ack is nil, packet %v", packet))
// after a timeout, a user should be able to retry the claim
userRedemptionRecord.ClaimIsPending = false
k.RecordsKeeper.SetUserRedemptionRecord(ctx, userRedemptionRecord)
return nil
}

txMsgData, err := icacallbacks.GetTxMsgData(ctx, *ack, k.Logger(ctx))
if err != nil {
k.Logger(ctx).Error(fmt.Sprintf("failed to unmarshal txMsgData, packet %v", packet))
return sdkerrors.Wrap(icacallbackstypes.ErrTxMsgData, err.Error())
}

k.Logger(ctx).Info("ClaimCallback executing", "packet", packet, "txMsgData", txMsgData, "args", args)
k.Logger(ctx).Info("ClaimCallback executing", "packet", packet, "txMsgData", &icaTxResponse.Data, "args", args)
// handle failed tx on host chain
if len(txMsgData.MsgResponses) == 0 {
if icaTxResponse.Status == icacallbackstypes.FAILURE {
k.Logger(ctx).Error(fmt.Sprintf("ClaimCallback failed, packet %v", packet))
// after an error, a user should be able to retry the claim
userRedemptionRecord.ClaimIsPending = false
Expand Down
20 changes: 9 additions & 11 deletions x/stakeibc/keeper/icacallbacks_delegate.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,20 @@ func DelegateCallback(k Keeper, ctx sdk.Context, packet channeltypes.Packet, ack
return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "deposit record not found %d", recordId)
}

// Check for timeout (ack nil)
// No need to reset the deposit record status since it will get revertted when the channel is restored
if ack == nil {
k.Logger(ctx).Error(utils.LogCallbackWithHostZone(chainId, ICACallbackID_Delegate,
"TIMEOUT (ack is nil), Packet: %+v", packet))
return nil
}

// Check for a failed transaction (ack error)
// Reset the deposit record status upon failure
txMsgData, err := icacallbacks.GetTxMsgData(ctx, *ack, k.Logger(ctx))
icaTxResponse, err := icacallbacks.GetTxMsgData(ctx, *ack, k.Logger(ctx))
if err != nil {
k.Logger(ctx).Error(fmt.Sprintf("failed to fetch txMsgData, packet %v", packet))
return sdkerrors.Wrap(icacallbackstypes.ErrTxMsgData, err.Error())
}
if len(txMsgData.MsgResponses) == 0 {

// No need to reset the deposit record status since it will get revertted when the channel is restored
if icaTxResponse.Status == icacallbackstypes.TIMEOUT {
k.Logger(ctx).Error(utils.LogCallbackWithHostZone(chainId, ICACallbackID_Delegate,
"TIMEOUT (ack is nil), Packet: %+v", packet))
return nil
}
if icaTxResponse.Status == icacallbackstypes.FAILURE {
k.Logger(ctx).Error(utils.LogCallbackWithHostZone(chainId, ICACallbackID_Delegate,
"ICA TX FAILED (ack is empty / ack error), Packet: %+v", packet))

Expand Down
15 changes: 8 additions & 7 deletions x/stakeibc/keeper/icacallbacks_rebalance.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,20 @@ func (k Keeper) UnmarshalRebalanceCallbackArgs(ctx sdk.Context, rebalanceCallbac

func RebalanceCallback(k Keeper, ctx sdk.Context, packet channeltypes.Packet, ack *channeltypes.Acknowledgement, args []byte) error {
k.Logger(ctx).Info("RebalanceCallback executing", "packet", packet)
if ack == nil {
// timeout
k.Logger(ctx).Error(fmt.Sprintf("RebalanceCallback timeout, ack is nil, packet %v", packet))
return nil
}

txMsgData, err := icacallbacks.GetTxMsgData(ctx, *ack, k.Logger(ctx))
icaTxResponse, err := icacallbacks.GetTxMsgData(ctx, *ack, k.Logger(ctx))
if err != nil {
k.Logger(ctx).Error(fmt.Sprintf("failed to fetch txMsgData, packet %v", packet))
return sdkerrors.Wrap(icacallbackstypes.ErrTxMsgData, err.Error())
}

if len(txMsgData.MsgResponses) == 0 {
if icaTxResponse.Status == icacallbackstypes.TIMEOUT {
// timeout
k.Logger(ctx).Error(fmt.Sprintf("RebalanceCallback timeout, ack is nil, packet %v", packet))
return nil
}

if icaTxResponse.Status == icacallbackstypes.FAILURE {
// failed transaction
k.Logger(ctx).Error(fmt.Sprintf("RebalanceCallback tx failed, ack is empty (ack error), packet %v", packet))
return nil
Expand Down
19 changes: 9 additions & 10 deletions x/stakeibc/keeper/icacallbacks_redemption.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,21 @@ func RedemptionCallback(k Keeper, ctx sdk.Context, packet channeltypes.Packet, a
k.Logger(ctx).Info(utils.LogCallbackWithHostZone(chainId, ICACallbackID_Redemption,
"Starting callback for Epoch Unbonding Records: %+v", redemptionCallback.EpochUnbondingRecordIds))

// Check for timeout (ack nil)
// Reset the unbonding record status upon failure
icaTxResponse, err := icacallbacks.GetTxMsgData(ctx, *ack, k.Logger(ctx))
if err != nil {
k.Logger(ctx).Error(fmt.Sprintf("RedemptionCallback txMsgData could not be parsed, packet %v", packet))
return sdkerrors.Wrap(icacallbackstypes.ErrTxMsgData, err.Error())
}

// No need to reset the unbonding record status since it will get revertted when the channel is restored
if ack == nil {
if icaTxResponse.Status == icacallbackstypes.TIMEOUT {
k.Logger(ctx).Error(utils.LogCallbackWithHostZone(chainId, ICACallbackID_Redemption,
"TIMEOUT (ack is nil), Packet: %+v", packet))
return nil
}

// Check for a failed transaction (ack error)
// Reset the unbonding record status upon failure
txMsgData, err := icacallbacks.GetTxMsgData(ctx, *ack, k.Logger(ctx))
if err != nil {
k.Logger(ctx).Error(fmt.Sprintf("RedemptionCallback txMsgData could not be parsed, packet %v", packet))
return sdkerrors.Wrap(icacallbackstypes.ErrTxMsgData, err.Error())
}
if len(txMsgData.MsgResponses) == 0 {
if icaTxResponse.Status == icacallbackstypes.FAILURE {
k.Logger(ctx).Error(utils.LogCallbackWithHostZone(chainId, ICACallbackID_Redemption,
"ICA TX FAILED (ack is empty / ack error), Packet: %+v", packet))

Expand Down
16 changes: 8 additions & 8 deletions x/stakeibc/keeper/icacallbacks_reinvest.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,19 @@ func (k Keeper) UnmarshalReinvestCallbackArgs(ctx sdk.Context, reinvestCallback

func ReinvestCallback(k Keeper, ctx sdk.Context, packet channeltypes.Packet, ack *channeltypes.Acknowledgement, args []byte) error {
k.Logger(ctx).Info("ReinvestCallback executing", "packet", packet)
if ack == nil {
// handle timeout
k.Logger(ctx).Error(fmt.Sprintf("ReinvestCallback timeout, ack is nil, packet %v", packet))
return nil
}

txMsgData, err := icacallbacks.GetTxMsgData(ctx, *ack, k.Logger(ctx))
icaTxResponse, err := icacallbacks.GetTxMsgData(ctx, *ack, k.Logger(ctx))
if err != nil {
k.Logger(ctx).Error(fmt.Sprintf("failed to fetch txMsgData, packet %v", packet))
return sdkerrors.Wrap(icacallbackstypes.ErrTxMsgData, err.Error())
}

if icaTxResponse.Status == icacallbackstypes.TIMEOUT {
// handle timeout
k.Logger(ctx).Error(fmt.Sprintf("ReinvestCallback timeout, ack is nil, packet %v", packet))
return nil
}

if len(txMsgData.MsgResponses) == 0 {
if icaTxResponse.Status == icacallbackstypes.FAILURE {
// handle tx failure
k.Logger(ctx).Error(fmt.Sprintf("ReinvestCallback tx failed, txMsgData is empty, ack error, packet %v", packet))
return nil
Expand Down
69 changes: 45 additions & 24 deletions x/stakeibc/keeper/icacallbacks_undelegate.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,22 +61,21 @@ func UndelegateCallback(k Keeper, ctx sdk.Context, packet channeltypes.Packet, a
k.Logger(ctx).Info(utils.LogCallbackWithHostZone(chainId, ICACallbackID_Undelegate,
"Starting callback for Epoch Unbonding Records: %+v", undelegateCallback.EpochUnbondingRecordIds))

// Check for timeout (ack nil)
// Reset the unbonding record status upon failure
icaTxResponse, err := icacallbacks.GetTxMsgData(ctx, *ack, k.Logger(ctx))
if err != nil {
k.Logger(ctx).Error(fmt.Sprintf("UndelegateCallback failed to fetch txMsgData, packet %v", packet))
return sdkerrors.Wrap(icacallbackstypes.ErrTxMsgData, err.Error())
}

// No need to reset the unbonding record status since it will get revertted when the channel is restored
if ack == nil {
if icaTxResponse.Status == icacallbackstypes.TIMEOUT {
k.Logger(ctx).Error(utils.LogCallbackWithHostZone(chainId, ICACallbackID_Undelegate,
"TIMEOUT (ack is nil), Packet: %+v", packet))
return nil
}

// Check for a failed transaction (ack error)
// Reset the unbonding record status upon failure
txMsgData, err := icacallbacks.GetTxMsgData(ctx, *ack, k.Logger(ctx))
if err != nil {
k.Logger(ctx).Error(fmt.Sprintf("UndelegateCallback failed to fetch txMsgData, packet %v", packet))
return sdkerrors.Wrap(icacallbackstypes.ErrTxMsgData, err.Error())
}
if len(txMsgData.MsgResponses) == 0 {
if icaTxResponse.Status == icacallbackstypes.FAILURE {
k.Logger(ctx).Error(utils.LogCallbackWithHostZone(chainId, ICACallbackID_Undelegate,
"ICA TX FAILED (ack is empty / ack error), Packet: %+v", packet))

Expand All @@ -102,7 +101,7 @@ func UndelegateCallback(k Keeper, ctx sdk.Context, packet channeltypes.Packet, a
}

// Get the latest transaction completion time (to determine the unbonding time)
latestCompletionTime, err := k.GetLatestCompletionTime(ctx, txMsgData)
latestCompletionTime, err := k.GetLatestCompletionTime(ctx, &icaTxResponse.Data)
if err != nil {
k.Logger(ctx).Error(fmt.Sprintf("UndelegateCallback | %s", err.Error()))
return err
Expand Down Expand Up @@ -155,22 +154,44 @@ func (k Keeper) UpdateDelegationBalances(ctx sdk.Context, zone types.HostZone, u
func (k Keeper) GetLatestCompletionTime(ctx sdk.Context, txMsgData *sdk.TxMsgData) (*time.Time, error) {
// Update the completion time using the latest completion time across each message within the transaction
latestCompletionTime := time.Time{}
for _, msgResponse := range txMsgData.MsgResponses {
var undelegateResponse stakingtypes.MsgUndelegateResponse
if msgResponse == nil {
return nil, sdkerrors.Wrap(types.ErrTxMsgDataInvalid, "msgResponseBytes or msgResponseBytes.Data is nil")
switch len(txMsgData.Data) {
case 0: // for SDK 0.46 and above
for _, msgResponse := range txMsgData.MsgResponses {
// unmarshall msgResponse and execute logic based on the response
var undelegateResponse stakingtypes.MsgUndelegateResponse
if msgResponse == nil {
return nil, sdkerrors.Wrap(types.ErrTxMsgDataInvalid, "msgResponse is nil")
}
undelegateResponsebz := msgResponse.GetValue()
err := proto.Unmarshal(undelegateResponsebz, &undelegateResponse)
if err != nil {
errMsg := fmt.Sprintf("Unable to unmarshal undelegation tx response | %s", err)
k.Logger(ctx).Error(errMsg)
return nil, sdkerrors.Wrapf(types.ErrUnmarshalFailure, errMsg)
}
if undelegateResponse.CompletionTime.After(latestCompletionTime) {
latestCompletionTime = undelegateResponse.CompletionTime
}
}
undelegateResponsebz := msgResponse.GetValue()
err := proto.Unmarshal(undelegateResponsebz, &undelegateResponse)
if err != nil {
errMsg := fmt.Sprintf("Unable to unmarshal undelegation tx response | %s", err)
k.Logger(ctx).Error(errMsg)
return nil, sdkerrors.Wrapf(types.ErrUnmarshalFailure, errMsg)
}
if undelegateResponse.CompletionTime.After(latestCompletionTime) {
latestCompletionTime = undelegateResponse.CompletionTime
default: // for SDK 0.45 and below
for _, msgResponseBytes := range txMsgData.Data {
// unmarshall msgData and execute logic based on the response
var undelegateResponse stakingtypes.MsgUndelegateResponse
if msgResponseBytes == nil || msgResponseBytes.Data == nil {
return nil, sdkerrors.Wrap(types.ErrTxMsgDataInvalid, "msgResponseBytes or msgResponseBytes.Data is nil")
}
err := proto.Unmarshal(msgResponseBytes.Data, &undelegateResponse)
if err != nil {
errMsg := fmt.Sprintf("Unable to unmarshal undelegation tx response | %s", err)
k.Logger(ctx).Error(errMsg)
return nil, sdkerrors.Wrapf(types.ErrUnmarshalFailure, errMsg)
}
if undelegateResponse.CompletionTime.After(latestCompletionTime) {
latestCompletionTime = undelegateResponse.CompletionTime
}
asalzmann marked this conversation as resolved.
Show resolved Hide resolved
}
}

if latestCompletionTime.IsZero() {
errMsg := fmt.Sprintf("Invalid completion time (%s) from txMsg", latestCompletionTime.String())
k.Logger(ctx).Error(errMsg)
Expand Down