Skip to content

Commit

Permalink
Merge pull request #545 from bandprotocol/tunnel-fail-produce-packet
Browse files Browse the repository at this point in the history
[Tunnel] Fix Produce packet logic
  • Loading branch information
RogerKSI authored Jan 9, 2025
2 parents 927e579 + 8d87db3 commit 90ddbc5
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 738 deletions.
445 changes: 68 additions & 377 deletions api/band/tunnel/v1beta1/tunnel.pulsar.go

Large diffs are not rendered by default.

8 changes: 1 addition & 7 deletions proto/band/tunnel/v1beta1/tunnel.proto
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,8 @@ message Packet {
repeated band.feeds.v1beta1.Price prices = 3 [(gogoproto.nullable) = false];
// receipt represents the confirmation of the packet delivery to the destination via the specified route.
google.protobuf.Any receipt = 4 [(cosmos_proto.accepts_interface) = "PacketReceiptI"];
// base_fee is the base fee of the packet
repeated cosmos.base.v1beta1.Coin base_fee = 5
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
// route_fee is the route fee of the packet
repeated cosmos.base.v1beta1.Coin route_fee = 6
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
// created_at is the timestamp when the packet is created
int64 created_at = 7;
int64 created_at = 5;
}

// Deposit defines an amount deposited by an account address to the tunnel.
Expand Down
56 changes: 11 additions & 45 deletions x/tunnel/keeper/keeper_packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,41 +53,24 @@ func (k Keeper) ProduceActiveTunnelPackets(ctx sdk.Context) error {

// create new packet. If failed to produce packet, emit an event.
for _, id := range ids {
if err := k.ProduceActiveTunnelPacket(ctx, id, pricesMap); err != nil {
cacheCtx, writeFn := ctx.CacheContext()

// Produce a packet. If produce packet successfully, update the context state.
// if not, emit an event and deactivate the tunnel.
if err := k.ProducePacket(cacheCtx, id, pricesMap); err != nil {
ctx.EventManager().EmitEvent(sdk.NewEvent(
types.EventTypeProducePacketFail,
sdk.NewAttribute(types.AttributeKeyTunnelID, fmt.Sprintf("%d", id)),
sdk.NewAttribute(types.AttributeKeyReason, err.Error()),
))
}
}

return nil
}

// ProduceActiveTunnelPacket generates a packet and sends it to the destination route for the given tunnel ID.
// If not enough fund, deactivate the tunnel.
func (k Keeper) ProduceActiveTunnelPacket(
ctx sdk.Context,
tunnelID uint64,
pricesMap map[string]feedstypes.Price,
) (err error) {
// Check if the tunnel has enough fund to create a packet and deactivate the tunnel if not
// enough fund. Error should not happen here since the tunnel is already validated.
ok, err := k.HasEnoughFundToCreatePacket(ctx, tunnelID)
if err != nil {
return err
}
if !ok {
return k.DeactivateTunnel(ctx, tunnelID)
}

// Produce a packet. If produce packet successfully, update the context state.
cacheCtx, writeFn := ctx.CacheContext()
if err := k.ProducePacket(cacheCtx, tunnelID, pricesMap); err != nil {
return err
if err := k.DeactivateTunnel(ctx, id); err != nil {
return err
}
} else {
writeFn()
}
}
writeFn()

return nil
}
Expand Down Expand Up @@ -162,9 +145,6 @@ func (k Keeper) CreatePacket(
tunnelID uint64,
prices []feedstypes.Price,
) (types.Packet, error) {
// get tunnel and prices info
params := k.GetParams(ctx)

tunnel, err := k.GetTunnel(ctx, tunnelID)
if err != nil {
return types.Packet{}, err
Expand All @@ -176,25 +156,11 @@ func (k Keeper) CreatePacket(
return types.Packet{}, sdkerrors.Wrapf(err, "failed to deduct base packet fee for tunnel %d", tunnel.ID)
}

// get the route
route, err := tunnel.GetRouteValue()
if err != nil {
return types.Packet{}, err
}

// get the route fee
routeFee, err := k.GetRouteFee(ctx, route)
if err != nil {
return types.Packet{}, err
}

tunnel.Sequence++
packet := types.NewPacket(
tunnelID,
tunnel.Sequence,
prices,
params.BasePacketFee,
routeFee,
ctx.BlockTime().Unix(),
)

Expand Down
23 changes: 6 additions & 17 deletions x/tunnel/keeper/keeper_packet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
sdkmath "cosmossdk.io/math"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

bandtsstypes "github.com/bandprotocol/chain/v3/x/bandtss/types"
feedstypes "github.com/bandprotocol/chain/v3/x/feeds/types"
Expand Down Expand Up @@ -54,8 +55,6 @@ func (s *KeeperTestSuite) TestGetSetPacket() {
func (s *KeeperTestSuite) TestCreatePacket() {
ctx, k := s.ctx, s.keeper

params := k.GetParams(ctx)

feePayer := sdk.AccAddress([]byte("fee_payer_address"))
tunnel := types.Tunnel{
ID: 1,
Expand All @@ -74,10 +73,6 @@ func (s *KeeperTestSuite) TestCreatePacket() {
{Status: feedstypes.PRICE_STATUS_AVAILABLE, SignalID: "CS:BAND-USD", Price: 5000000, Timestamp: 1733000000},
}

s.bandtssKeeper.EXPECT().GetSigningFee(gomock.Any()).Return(
sdk.NewCoins(sdk.NewCoin("uband", sdkmath.NewInt(20))), nil,
)

s.bankKeeper.EXPECT().
SendCoinsFromAccountToModule(ctx, feePayer, types.ModuleName, k.GetParams(ctx).BasePacketFee).
Return(nil)
Expand All @@ -92,8 +87,6 @@ func (s *KeeperTestSuite) TestCreatePacket() {
TunnelID: 1,
Sequence: 1,
Prices: prices,
BaseFee: params.BasePacketFee,
RouteFee: sdk.NewCoins(sdk.NewCoin("uband", sdkmath.NewInt(20))),
CreatedAt: ctx.BlockTime().Unix(),
}

Expand Down Expand Up @@ -191,14 +184,12 @@ func (s *KeeperTestSuite) TestProduceActiveTunnelPackets() {

s.bandtssKeeper.EXPECT().GetSigningFee(gomock.Any()).Return(
sdk.NewCoins(sdk.NewCoin("uband", sdkmath.NewInt(20))), nil,
).Times(2)
)

s.feedsKeeper.EXPECT().GetAllPrices(gomock.Any()).Return([]feedstypes.Price{
{Status: feedstypes.PRICE_STATUS_AVAILABLE, SignalID: "CS:BAND-USD", Price: 50000, Timestamp: 1733000000},
})

spendableCoins := types.DefaultBasePacketFee.Add(sdk.NewCoin("uband", sdkmath.NewInt(20)))
s.bankKeeper.EXPECT().SpendableCoins(gomock.Any(), feePayer).Return(spendableCoins)
s.bankKeeper.EXPECT().
SendCoinsFromAccountToModule(gomock.Any(), feePayer, types.ModuleName, types.DefaultBasePacketFee).
Return(nil)
Expand Down Expand Up @@ -259,15 +250,13 @@ func (s *KeeperTestSuite) TestProduceActiveTunnelPacketsNotEnoughMoney() {
DestinationContractAddress: "0x",
}

s.bandtssKeeper.EXPECT().GetSigningFee(gomock.Any()).Return(
sdk.NewCoins(sdk.NewCoin("uband", sdkmath.NewInt(20))), nil,
)

s.feedsKeeper.EXPECT().GetAllPrices(gomock.Any()).Return([]feedstypes.Price{
{Status: feedstypes.PRICE_STATUS_AVAILABLE, SignalID: "CS:BAND-USD", Price: 50000, Timestamp: 1733000000},
})
s.bankKeeper.EXPECT().SpendableCoins(gomock.Any(), feePayer).
Return(sdk.Coins{sdk.NewInt64Coin("uband", 1)})

s.bankKeeper.EXPECT().
SendCoinsFromAccountToModule(gomock.Any(), feePayer, types.ModuleName, types.DefaultBasePacketFee).
Return(sdkerrors.ErrInsufficientFunds)

err := tunnel.SetRoute(route)
s.Require().NoError(err)
Expand Down
7 changes: 6 additions & 1 deletion x/tunnel/keeper/keeper_packet_tss.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ func (k Keeper) SendTSSPacket(
route.Encoder,
)

tssFee, err := k.bandtssKeeper.GetSigningFee(ctx)
if err != nil {
return nil, err
}

// try signing TSS packet, if success, write the context.
signingID, err := k.bandtssKeeper.CreateTunnelSigningRequest(
ctx,
Expand All @@ -28,7 +33,7 @@ func (k Keeper) SendTSSPacket(
route.DestinationContractAddress,
content,
feePayer,
packet.RouteFee,
tssFee,
)
if err != nil {
return nil, err
Expand Down
4 changes: 2 additions & 2 deletions x/tunnel/keeper/keeper_packet_tss_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ func (s *KeeperTestSuite) TestSendTSSPacket() {
1, // tunnelID
1, // sequence
[]feedstypes.Price{}, // priceInfos[]
sdk.NewCoins(), // baseFee
sdk.NewCoins(sdk.NewCoin("uband", sdkmath.NewInt(20))), // routeFee
time.Now().Unix(),
)

s.bandtssKeeper.EXPECT().GetSigningFee(ctx).Return(sdk.NewCoins(sdk.NewCoin("uband", sdkmath.NewInt(20))), nil)

// Mock the TSS keeper and set the state for checking later
s.bandtssKeeper.EXPECT().CreateTunnelSigningRequest(
gomock.Any(),
Expand Down
43 changes: 1 addition & 42 deletions x/tunnel/keeper/keeper_tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,36 +255,7 @@ func (k Keeper) GetTotalFees(ctx sdk.Context) types.TotalFees {
return totalFee
}

// HasEnoughFundToCreatePacket checks if the fee payer has enough balance to create a packet
func (k Keeper) HasEnoughFundToCreatePacket(ctx sdk.Context, tunnelID uint64) (bool, error) {
tunnel, err := k.GetTunnel(ctx, tunnelID)
if err != nil {
return false, err
}

// get the route fee from the tunnel
route, err := tunnel.GetRouteValue()
if err != nil {
return false, err
}
routeFee, err := k.GetRouteFee(ctx, route)
if err != nil {
return false, err
}

// get the base packet fee and calculate total fee
basePacketFee := k.GetParams(ctx).BasePacketFee
totalFee := basePacketFee.Add(routeFee...)

// compare the fee payer's balance with the total fee
feePayer, err := sdk.AccAddressFromBech32(tunnel.FeePayer)
if err != nil {
return false, err
}
balances := k.bankKeeper.SpendableCoins(ctx, feePayer)
return balances.IsAllGTE(totalFee), nil
}

// GenerateTunnelAccount generates a new tunnel account for the given key
func (k Keeper) GenerateTunnelAccount(ctx sdk.Context, key string) (sdk.AccAddress, error) {
header := ctx.BlockHeader()

Expand Down Expand Up @@ -317,15 +288,3 @@ func (k Keeper) GenerateTunnelAccount(ctx sdk.Context, key string) (sdk.AccAddre

return tunnelAccAddr, nil
}

// GetRouteFee returns the fee of the given route
func (k Keeper) GetRouteFee(ctx sdk.Context, route types.RouteI) (sdk.Coins, error) {
switch route.(type) {
case *types.TSSRoute:
return k.bandtssKeeper.GetSigningFee(ctx)
case *types.IBCRoute:
return sdk.Coins{}, nil
default:
return sdk.Coins{}, types.ErrInvalidRoute
}
}
9 changes: 0 additions & 9 deletions x/tunnel/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,15 +289,6 @@ func (k msgServer) TriggerTunnel(
return nil, types.ErrInactiveTunnel.Wrapf("tunnelID %d", msg.TunnelID)
}

ok, err := k.Keeper.HasEnoughFundToCreatePacket(ctx, tunnel.ID)
if err != nil {
return nil, err
}

if !ok {
return nil, types.ErrInsufficientFund.Wrapf("tunnelID %d", msg.TunnelID)
}

signalIDs := tunnel.GetSignalIDs()
prices := k.Keeper.feedsKeeper.GetPrices(ctx, signalIDs)

Expand Down
5 changes: 1 addition & 4 deletions x/tunnel/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ func (s *KeeperTestSuite) TestMsgTriggerTunnel() {

s.bandtssKeeper.EXPECT().GetSigningFee(gomock.Any()).Return(
sdk.NewCoins(sdk.NewCoin("uband", sdkmath.NewInt(20))), nil,
).Times(2)
)

s.bandtssKeeper.EXPECT().CreateTunnelSigningRequest(
gomock.Any(),
Expand All @@ -720,9 +720,6 @@ func (s *KeeperTestSuite) TestMsgTriggerTunnel() {
SendCoinsFromAccountToModule(gomock.Any(), feePayer, types.ModuleName, types.DefaultBasePacketFee).
Return(nil)

spendableCoins := types.DefaultBasePacketFee.Add(sdk.NewCoin("uband", sdkmath.NewInt(20)))
s.bankKeeper.EXPECT().SpendableCoins(gomock.Any(), feePayer).Return(spendableCoins)

return types.NewMsgTriggerTunnel(1, sdk.AccAddress([]byte("creator_address")).String())
},
expErr: false,
Expand Down
22 changes: 8 additions & 14 deletions x/tunnel/testutil/expected_keepers_mocks.go

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

Loading

0 comments on commit 90ddbc5

Please sign in to comment.