Skip to content

Commit fe9c8e7

Browse files
committed
optimize ibc error handling for bridge
1 parent 30ce20e commit fe9c8e7

8 files changed

Lines changed: 176 additions & 283 deletions

File tree

api/side/btcbridge/params.pulsar.go

Lines changed: 33 additions & 108 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

proto/side/btcbridge/params.proto

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,8 @@ message TSSParams {
166166

167167
// IBCParams defines the params related to IBC
168168
message IBCParams {
169-
// Id of the IBC port used to transfer sBTC
170-
string port_id = 1;
171169
// Timeout height offset relative to the current client height
172-
uint64 timeout_height_offset = 2;
170+
uint64 timeout_height_offset = 1;
173171
// Timeout duration relative to the current time
174-
google.protobuf.Duration timeout_duration = 3 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true];
172+
google.protobuf.Duration timeout_duration = 2 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true];
175173
}

x/btcbridge/keeper/hooks.go

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,28 @@ func (k Keeper) AfterDeposit(ctx sdk.Context, addr string, amount sdk.Coin, tx *
2020
// perform IBC transfer if enabled
2121
script := types.GetIBCTransferScript(tx)
2222
if len(script) != 0 {
23-
var sequence uint64
24-
var errMsg string
25-
23+
// parse channel id and recipient
2624
channelId, recipient, err := types.ParseIBCTransferScript(script)
27-
if err == nil {
28-
sequence, err = k.IBCTransfer(ctx, addr, recipient, amount, channelId)
29-
}
30-
3125
if err != nil {
32-
errMsg = err.Error()
26+
// no error
27+
return nil
3328
}
3429

35-
ctx.EventManager().EmitEvent(
36-
sdk.NewEvent(
37-
types.EventTypeIBCTransfer,
38-
sdk.NewAttribute(types.AttributeKeyPacketSequence, fmt.Sprintf("%d", sequence)),
39-
sdk.NewAttribute(types.AttributeKeyErrorMsg, errMsg),
40-
),
30+
// transfer
31+
sequence, err := k.IBCTransfer(ctx, addr, recipient, amount, channelId)
32+
33+
// emit event
34+
event := sdk.NewEvent(
35+
types.EventTypeIBCTransfer,
36+
sdk.NewAttribute(types.AttributeKeyChannelId, channelId),
4137
)
38+
if err == nil {
39+
event = event.AppendAttributes(sdk.NewAttribute(types.AttributeKeyPacketSequence, fmt.Sprintf("%d", sequence)))
40+
} else {
41+
event = event.AppendAttributes(sdk.NewAttribute(types.AttributeKeyErrorMsg, err.Error()))
42+
}
43+
44+
ctx.EventManager().EmitEvent(event)
4245
}
4346

4447
return nil

x/btcbridge/keeper/ibc.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ import (
1919

2020
// IBCTransfer performs the IBC transfer by the given params
2121
func (k Keeper) IBCTransfer(ctx sdk.Context, sender string, recipient string, token sdk.Coin, channelId string) (uint64, error) {
22-
clientHeight, err := k.GetClientHeight(ctx, k.IBCPortId(ctx), channelId)
22+
portId := k.ibctransferKeeper.GetPort(ctx)
23+
24+
clientHeight, err := k.GetClientHeight(ctx, portId, channelId)
2325
if err != nil {
2426
return 0, err
2527
}
2628

2729
msg := &transfertypes.MsgTransfer{
28-
SourcePort: k.IBCPortId(ctx),
30+
SourcePort: portId,
2931
SourceChannel: channelId,
3032
Token: token,
3133
Sender: sender,
@@ -35,8 +37,20 @@ func (k Keeper) IBCTransfer(ctx sdk.Context, sender string, recipient string, to
3537
Memo: types.DefaultMemo,
3638
}
3739

40+
// total escrow before transfer
41+
totalEscrowBefore := k.ibctransferKeeper.GetTotalEscrowForDenom(ctx, token.Denom)
42+
3843
resp, err := k.ibctransferKeeper.Transfer(ctx, msg)
3944
if err != nil {
45+
// total escrow after transfer
46+
totalEscrowAfter := k.ibctransferKeeper.GetTotalEscrowForDenom(ctx, token.Denom)
47+
if totalEscrowBefore.IsLT(totalEscrowAfter) {
48+
// unescrow token
49+
if err := k.UnescrowToken(ctx, portId, channelId, sender, token); err != nil {
50+
panic(err)
51+
}
52+
}
53+
4054
return 0, err
4155
}
4256

@@ -141,6 +155,21 @@ func (k Keeper) GetClientHeight(ctx sdk.Context, sourcePort string, sourceChanne
141155
return clientState.GetLatestHeight(), nil
142156
}
143157

158+
// UnescrowToken unescrows the given token from the IBC transfer module
159+
// NOTE: This method is called only if the IBC transfer failed while the token is escrowed
160+
func (k Keeper) UnescrowToken(ctx sdk.Context, portId string, channelId string, recipient string, token sdk.Coin) error {
161+
escrowAddress := transfertypes.GetEscrowAddress(portId, channelId)
162+
if err := k.bankKeeper.SendCoins(ctx, escrowAddress, sdk.MustAccAddressFromBech32(recipient), sdk.NewCoins(token)); err != nil {
163+
return errorsmod.Wrap(err, "failed to unescrow token")
164+
}
165+
166+
currentTotalEscrow := k.ibctransferKeeper.GetTotalEscrowForDenom(ctx, token.Denom)
167+
newTotalEscrow := currentTotalEscrow.Sub(token)
168+
k.ibctransferKeeper.SetTotalEscrowForDenom(ctx, newTotalEscrow)
169+
170+
return nil
171+
}
172+
144173
// IBCSendPacketCallback implements IBC callbacks
145174
func (k Keeper) IBCSendPacketCallback(
146175
ctx sdk.Context,

x/btcbridge/keeper/params.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,6 @@ func (k Keeper) AddressRateLimitQuota(ctx sdk.Context) int64 {
104104
return k.GetParams(ctx).RateLimitParams.AddressRateLimitParams.Quota
105105
}
106106

107-
// IBCPortId gets the IBC port id
108-
func (k Keeper) IBCPortId(ctx sdk.Context) string {
109-
return k.GetParams(ctx).IbcParams.PortId
110-
}
111-
112107
// IBCTimeoutHeightOffset gets the IBC timeout height offset
113108
func (k Keeper) IBCTimeoutHeightOffset(ctx sdk.Context) uint64 {
114109
return k.GetParams(ctx).IbcParams.TimeoutHeightOffset

x/btcbridge/types/expected_keepers.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,5 +88,10 @@ type IBCChannelKeeper interface {
8888

8989
// IBCTransferKeeper defines the expected IBC transfer interfaces
9090
type IBCTransferKeeper interface {
91+
GetPort(ctx sdk.Context) string
92+
93+
GetTotalEscrowForDenom(ctx sdk.Context, denom string) sdk.Coin
94+
SetTotalEscrowForDenom(ctx sdk.Context, coin sdk.Coin)
95+
9196
Transfer(goCtx context.Context, msg *ibctransfertypes.MsgTransfer) (*ibctransfertypes.MsgTransferResponse, error)
9297
}

0 commit comments

Comments
 (0)