-
Notifications
You must be signed in to change notification settings - Fork 616
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
feat: allow ability to lock fee module in presence of severe bug #1031
Changes from all commits
f1b196b
1ff4fa9
b140255
5466343
fbce570
6974982
7399b52
3cc256f
b128ea0
e81e4e5
8e59f13
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -230,6 +230,16 @@ func (im IBCModule) OnAcknowledgementPacket( | |
return sdkerrors.Wrapf(err, "cannot unmarshal ICS-29 incentivized packet acknowledgement: %v", ack) | ||
} | ||
|
||
if im.keeper.IsLocked(ctx) { | ||
// if the fee keeper is locked then fee logic should be skipped | ||
// this may occur in the presence of a severe bug which leads invalid state | ||
// the fee keeper will be unlocked after manual intervention | ||
// the acknowledgement has been unmarshalled into an ics29 acknowledgement | ||
// since the counterparty is still sending incentivized acknowledgements | ||
// for fee enabled channels | ||
return im.app.OnAcknowledgementPacket(ctx, packet, ack.Result, relayer) | ||
} | ||
|
||
packetID := channeltypes.NewPacketId(packet.SourceChannel, packet.SourcePort, packet.Sequence) | ||
feesInEscrow, found := im.keeper.GetFeesInEscrow(ctx, packetID) | ||
if !found { | ||
|
@@ -253,7 +263,10 @@ func (im IBCModule) OnTimeoutPacket( | |
packet channeltypes.Packet, | ||
relayer sdk.AccAddress, | ||
) error { | ||
if !im.keeper.IsFeeEnabled(ctx, packet.SourcePort, packet.SourceChannel) { | ||
// if the fee keeper is locked then fee logic should be skipped | ||
// this may occur in the presence of a severe bug which leads invalid state | ||
// the fee keeper will be unlocked after manual intervention | ||
if !im.keeper.IsFeeEnabled(ctx, packet.SourcePort, packet.SourceChannel) || im.keeper.IsLocked(ctx) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Document why we're just passing through to underlying app in case of locked module |
||
return im.app.OnTimeoutPacket(ctx, packet, relayer) | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -124,22 +124,51 @@ func (suite *KeeperTestSuite) TestDistributeFee() { | |
reverseRelayer sdk.AccAddress | ||
forwardRelayer string | ||
refundAcc sdk.AccAddress | ||
refundAccBal sdk.Coin | ||
fee types.Fee | ||
packetID channeltypes.PacketId | ||
) | ||
|
||
validSeq := uint64(1) | ||
|
||
testCases := []struct { | ||
name string | ||
malleate func() | ||
expPass bool | ||
name string | ||
malleate func() | ||
expResult func() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I made these changes to test |
||
}{ | ||
{ | ||
"success", func() {}, true, | ||
"success", func() {}, func() { | ||
// check if the reverse relayer is paid | ||
hasBalance := suite.chainA.GetSimApp().BankKeeper.HasBalance(suite.chainA.GetContext(), reverseRelayer, fee.AckFee[0].Add(fee.AckFee[0])) | ||
suite.Require().True(hasBalance) | ||
|
||
// check if the forward relayer is paid | ||
forward, err := sdk.AccAddressFromBech32(forwardRelayer) | ||
suite.Require().NoError(err) | ||
hasBalance = suite.chainA.GetSimApp().BankKeeper.HasBalance(suite.chainA.GetContext(), forward, fee.RecvFee[0].Add(fee.RecvFee[0])) | ||
suite.Require().True(hasBalance) | ||
|
||
// check if the refund acc has been refunded the timeoutFee | ||
expectedRefundAccBal := refundAccBal.Add(fee.TimeoutFee[0].Add(fee.TimeoutFee[0])) | ||
hasBalance = suite.chainA.GetSimApp().BankKeeper.HasBalance(suite.chainA.GetContext(), refundAcc, expectedRefundAccBal) | ||
suite.Require().True(hasBalance) | ||
|
||
// check the module acc wallet is now empty | ||
hasBalance = suite.chainA.GetSimApp().BankKeeper.HasBalance(suite.chainA.GetContext(), suite.chainA.GetSimApp().IBCFeeKeeper.GetFeeModuleAddress(), sdk.Coin{Denom: sdk.DefaultBondDenom, Amount: sdk.NewInt(0)}) | ||
suite.Require().True(hasBalance) | ||
}, | ||
}, | ||
{ | ||
"invalid forward address", func() { | ||
forwardRelayer = "invalid address" | ||
}, false, | ||
}, | ||
func() { | ||
// check if the refund acc has been refunded the timeoutFee & onRecvFee | ||
expectedRefundAccBal := refundAccBal.Add(fee.TimeoutFee[0]).Add(fee.RecvFee[0]).Add(fee.TimeoutFee[0]).Add(fee.RecvFee[0]) | ||
hasBalance := suite.chainA.GetSimApp().BankKeeper.HasBalance(suite.chainA.GetContext(), refundAcc, expectedRefundAccBal) | ||
suite.Require().True(hasBalance) | ||
|
||
}, | ||
}, | ||
} | ||
|
||
|
@@ -155,8 +184,8 @@ func (suite *KeeperTestSuite) TestDistributeFee() { | |
reverseRelayer = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()) | ||
forwardRelayer = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()).String() | ||
|
||
packetID := channeltypes.NewPacketId(suite.path.EndpointA.ChannelID, suite.path.EndpointA.ChannelConfig.PortID, validSeq) | ||
fee := types.Fee{ | ||
packetID = channeltypes.NewPacketId(suite.path.EndpointA.ChannelID, suite.path.EndpointA.ChannelConfig.PortID, validSeq) | ||
fee = types.Fee{ | ||
RecvFee: defaultReceiveFee, | ||
AckFee: defaultAckFee, | ||
TimeoutFee: defaultTimeoutFee, | ||
|
@@ -174,35 +203,12 @@ func (suite *KeeperTestSuite) TestDistributeFee() { | |
tc.malleate() | ||
|
||
// refundAcc balance after escrow | ||
refundAccBal := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), refundAcc, sdk.DefaultBondDenom) | ||
refundAccBal = suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), refundAcc, sdk.DefaultBondDenom) | ||
|
||
suite.chainA.GetSimApp().IBCFeeKeeper.DistributePacketFees(suite.chainA.GetContext(), forwardRelayer, reverseRelayer, []types.PacketFee{packetFee, packetFee}) | ||
|
||
if tc.expPass { | ||
// check if the reverse relayer is paid | ||
hasBalance := suite.chainA.GetSimApp().BankKeeper.HasBalance(suite.chainA.GetContext(), reverseRelayer, fee.AckFee[0].Add(fee.AckFee[0])) | ||
suite.Require().True(hasBalance) | ||
|
||
// check if the forward relayer is paid | ||
forward, err := sdk.AccAddressFromBech32(forwardRelayer) | ||
suite.Require().NoError(err) | ||
hasBalance = suite.chainA.GetSimApp().BankKeeper.HasBalance(suite.chainA.GetContext(), forward, fee.RecvFee[0].Add(fee.RecvFee[0])) | ||
suite.Require().True(hasBalance) | ||
|
||
// check if the refund acc has been refunded the timeoutFee | ||
expectedRefundAccBal := refundAccBal.Add(fee.TimeoutFee[0].Add(fee.TimeoutFee[0])) | ||
hasBalance = suite.chainA.GetSimApp().BankKeeper.HasBalance(suite.chainA.GetContext(), refundAcc, expectedRefundAccBal) | ||
suite.Require().True(hasBalance) | ||
tc.expResult() | ||
|
||
// check the module acc wallet is now empty | ||
hasBalance = suite.chainA.GetSimApp().BankKeeper.HasBalance(suite.chainA.GetContext(), suite.chainA.GetSimApp().IBCFeeKeeper.GetFeeModuleAddress(), sdk.Coin{Denom: sdk.DefaultBondDenom, Amount: sdk.NewInt(0)}) | ||
suite.Require().True(hasBalance) | ||
} else { | ||
// check if the refund acc has been refunded the timeoutFee & onRecvFee | ||
expectedRefundAccBal := refundAccBal.Add(fee.TimeoutFee[0]).Add(fee.RecvFee[0]).Add(fee.TimeoutFee[0]).Add(fee.RecvFee[0]) | ||
hasBalance := suite.chainA.GetSimApp().BankKeeper.HasBalance(suite.chainA.GetContext(), refundAcc, expectedRefundAccBal) | ||
suite.Require().True(hasBalance) | ||
} | ||
}) | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,10 @@ func (k Keeper) RegisterCounterpartyAddress(goCtx context.Context, msg *types.Ms | |
func (k Keeper) PayPacketFee(goCtx context.Context, msg *types.MsgPayPacketFee) (*types.MsgPayPacketFeeResponse, error) { | ||
ctx := sdk.UnwrapSDKContext(goCtx) | ||
|
||
if k.IsLocked(ctx) { | ||
return nil, types.ErrFeeModuleLocked | ||
} | ||
|
||
// get the next sequence | ||
sequence, found := k.GetNextSequenceSend(ctx, msg.SourcePortId, msg.SourceChannelId) | ||
if !found { | ||
|
@@ -57,6 +61,10 @@ func (k Keeper) PayPacketFee(goCtx context.Context, msg *types.MsgPayPacketFee) | |
func (k Keeper) PayPacketFeeAsync(goCtx context.Context, msg *types.MsgPayPacketFeeAsync) (*types.MsgPayPacketFeeAsyncResponse, error) { | ||
ctx := sdk.UnwrapSDKContext(goCtx) | ||
|
||
if k.IsLocked(ctx) { | ||
return nil, types.ErrFeeModuleLocked | ||
} | ||
|
||
if err := k.EscrowPacketFee(ctx, msg.PacketId, msg.PacketFee); err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we move the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
return nil, err | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's also document why we're still unmarshalling the acknowledgement because the counterparty is still sending the incentivized ack over