-
Notifications
You must be signed in to change notification settings - Fork 602
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
IBC Rate Limit - integration and tests #2410
Conversation
…ithout GenesisSupplyOffsets
Created #2941 to add the testing helpers needed by this branch. That one should be a quick merge and make this PR smaller |
…-integration-and-tests
Hi, i was looking at the osmosis rate limiter code and have some questions. Maybe this PR is not the best to ask but will do anyway and please redirect. On osmosis/x/ibc-rate-limit/ibc_module.go Lines 117 to 121 in 4fed7db
GetFundsFromPacket gets the denom as specified by the sender. On receive side (in the code above) shouldn't there be un-prefexing or prefexing performed depending on wether the receiving chain was the one originally sending the packet or not? Similar thing is done in the transfer module https://github.com/cosmos/ibc-go/blob/f693f6c11053192f369b5908c9186bd494c3a33d/modules/apps/transfer/keeper/relay.go#L165
The way it is the channel value is computed for a denom of the counterparty/ sender chain. Or maybe I am missing something important here. |
coins = transfertypes.GetTransferCoin( | ||
suite.path.EndpointB.ChannelConfig.PortID, | ||
suite.path.EndpointB.ChannelID, | ||
sdk.DefaultBondDenom, | ||
sdk.NewInt(1), | ||
) | ||
coins = sdk.NewCoin(sdk.DefaultBondDenom, amount) |
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.
why the overwrite and not:
coins = transfertypes.GetTransferCoin( | |
suite.path.EndpointB.ChannelConfig.PortID, | |
suite.path.EndpointB.ChannelID, | |
sdk.DefaultBondDenom, | |
sdk.NewInt(1), | |
) | |
coins = sdk.NewCoin(sdk.DefaultBondDenom, amount) | |
coins = transfertypes.GetTransferCoin( | |
suite.path.EndpointB.ChannelConfig.PortID, | |
suite.path.EndpointB.ChannelID, | |
sdk.DefaultBondDenom, | |
amount, | |
) |
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.
This got overlooked. Thanks for the catch!
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.
This probably also means that you're other comment is also right. I'll review this and report back
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.
The correct code here is coins = sdk.NewCoin(sdk.DefaultBondDenom, amount)
because that message is sent from chainB to chainA. What you said about getting the funds still applies though: I was not wrapping the token before getting the value and this was only working because both chains in my tests were the same chain.
I've fixed that in my latest commit (032f33b)
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.
The correct code here is
coins = sdk.NewCoin(sdk.DefaultBondDenom, amount)
because that message is sent from chainB to chainA.
I am not sure I understand TestRecvTransferWithRateLimiting()
(which calls this with forward = false
). The tokens sent back to A should be prefixed (something like "ibc/transfer/channel-0/stake"...can't remember the details). Will look at the test latest tomorrow (running out of time today).
What you said about getting the funds still applies though: I was not wrapping the token before getting the value and this was only working because both chains in my tests were the same chain.
I've fixed that in my latest commit (032f33b)
Looks good!
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.
Yeah, this is testing native B tokens being sent to a. But maybe I should also add a test for native A tokens being sent "back" from B to A
Modified this implementation to use the escrowed amount as the channel value for native tokens. This introduces a bootstrapping problem: channels need to have tokens on escrow before we initialize their quotas (otherwise the quota will always be lower than the sent amount). This can be seen in the tests. I don't think this is a problem for our use case as we will only use rate limiting for existing channels, but it may become important if someone wants all channels to have rate limiting, or to auto-initialize rate-limiting for channels on creation |
Right. Another possibility is to set some threshold for which the ratelimiter activates/ deactivates. |
func (i *ICS4Wrapper) CalculateChannelValue(ctx sdk.Context, denom string, packet exported.PacketI) sdk.Int { | ||
// If the source is the counterparty chain, this should be | ||
if strings.HasPrefix(denom, "ibc/") { | ||
return i.bankKeeper.GetSupplyWithOffset(ctx, denom).Amount | ||
} | ||
|
||
escrowAddress := transfertypes.GetEscrowAddress(packet.GetSourcePort(), packet.GetSourceChannel()) | ||
return i.bankKeeper.GetBalance(ctx, escrowAddress, denom).Amount |
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.
At first look this doesn't seem correct. If we have something like:
A B C
ch0 --- ch1 ch2 --- ch3
And a
is chain A token. In the following cases:
- B sends to C a packet with denom
ch1/a
overch2
. denom here isch1/a
. - B receives (back) from C a packet with denom
ch3/ch1/a
overch2
. denom here isch1/a
(unprefixed)
Here I think we get the ch1/a
supply instead of the balance of escrow_address(ch2)
for denom ch1/a
.
Maybe something along these lines:
func (i *ICS4Wrapper) CalculateChannelValue(ctx sdk.Context, denom string, packet exported.PacketI) sdk.Int { | |
// If the source is the counterparty chain, this should be | |
if strings.HasPrefix(denom, "ibc/") { | |
return i.bankKeeper.GetSupplyWithOffset(ctx, denom).Amount | |
} | |
escrowAddress := transfertypes.GetEscrowAddress(packet.GetSourcePort(), packet.GetSourceChannel()) | |
return i.bankKeeper.GetBalance(ctx, escrowAddress, denom).Amount | |
func (i *ICS4Wrapper) CalculateChannelValue(ctx sdk.Context, denom string, packet exported.PacketI, send bool) sdk.Int { | |
prefix_for_source:= transfertypes.GetDenomPrefix(packet.GetSourcePort(), packet.GetSourceChannel()) | |
if send { // send packet | |
if !strings.HasPrefix(denom, prefix_for_source) { | |
// Sender chain is the source | |
escrowAddress := transfertypes.GetEscrowAddress(packet.GetSourcePort(), packet.GetSourceChannel()) | |
return i.bankKeeper.GetBalance(ctx, escrowAddress, denom).Amount | |
} else { | |
return i.bankKeeper.GetSupplyWithOffset(ctx, denom).Amount | |
} | |
} else { // receive packet | |
if strings.HasPrefix(denom, prefix_for_source) { | |
// Receiver chain is the source | |
escrowAddress := transfertypes.GetEscrowAddress(packet.GetDestPort(), packet.GetDestChannel()) | |
return i.bankKeeper.GetBalance(ctx, escrowAddress, denom).Amount | |
} else { | |
return i.bankKeeper.GetSupplyWithOffset(ctx, denom).Amount | |
} | |
} |
It would be great to have tests to cover scenarios like above.
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.
The current behaviour (what you described above) is what I was trying to achieve, where escrow value is only used for native tokens (osmo/ion/tokenfactory tokens). ch0/a, as an ibc token, should be rate limited based on the current amount of ch0/a on osmosis.
I'm open to changing it to what you suggest, but I think the volume of some token/channel combinations may be too low and make the limit to be hit too often
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.
The current behaviour (what you described above) is what I was trying to achieve, where escrow value is only used for native tokens (osmo/ion/tokenfactory tokens). ch0/a, as an ibc token, should be rate limited based on the current amount of ch0/a on osmosis.
I see, thanks for the clarification.
I'm open to changing it to what you suggest, but I think the volume of some token/channel combinations may be too low and make the limit to be hit too often
But in this case ratelimiting should not be configured on those channels as they have a low value.
Are there osmosis uscases like the ones I mention above (the multi hop/channel transfers)?
Closes: #2305
What is the purpose of the change
Integrates IBC rate limiting with the chain.
Brief Changelog
Testing and Verifying
This change added tests and can be verified as follows:
x/ibc-rate-limit
Documentation and Release Note
This PR depends on @2408 and @2409. It also requires a change to the osmosis fork of the cosmos-sdk (#2307)
Unreleased
section inCHANGELOG.md
? (no)x/<module>/spec/
) / Osmosis docs repo / not documented)