Skip to content

Commit

Permalink
IBC Rate Limiting (#556)
Browse files Browse the repository at this point in the history
Co-authored-by: antstalepresh <36045227+antstalepresh@users.noreply.github.com>
Co-authored-by: antstalepresh <stalepresh121@outlook.com>
Co-authored-by: Aidan Salzmann <aidan@stridelabs.co>
Co-authored-by: riley-stride <104941670+riley-stride@users.noreply.github.com>
  • Loading branch information
5 people authored Feb 18, 2023
1 parent 59a872b commit 94e3a91
Show file tree
Hide file tree
Showing 91 changed files with 11,753 additions and 47 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ We use the following modules from [Osmosis](https://github.com/osmosis-labs/osmo
```
x/epochs
x/mint
x/ratelimit
```
We use the following module (marketed as public infra) from [Quicksilver](https://github.com/ingenuity-build/quicksilver) provided under [this License](https://github.com/ingenuity-build/quicksilver/blob/main/LICENSE):
```
Expand Down
51 changes: 45 additions & 6 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ import (
ibcclient "github.com/cosmos/ibc-go/v5/modules/core/02-client"
ibcclientclient "github.com/cosmos/ibc-go/v5/modules/core/02-client/client"
ibcclienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
ibcporttypes "github.com/cosmos/ibc-go/v5/modules/core/05-port/types"
ibchost "github.com/cosmos/ibc-go/v5/modules/core/24-host"
ibckeeper "github.com/cosmos/ibc-go/v5/modules/core/keeper"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
Expand Down Expand Up @@ -120,6 +119,10 @@ import (
icacallbacksmodule "github.com/Stride-Labs/stride/v5/x/icacallbacks"
icacallbacksmodulekeeper "github.com/Stride-Labs/stride/v5/x/icacallbacks/keeper"
icacallbacksmoduletypes "github.com/Stride-Labs/stride/v5/x/icacallbacks/types"
ratelimitmodule "github.com/Stride-Labs/stride/v5/x/ratelimit"
ratelimitclient "github.com/Stride-Labs/stride/v5/x/ratelimit/client"
ratelimitmodulekeeper "github.com/Stride-Labs/stride/v5/x/ratelimit/keeper"
ratelimitmoduletypes "github.com/Stride-Labs/stride/v5/x/ratelimit/types"
recordsmodule "github.com/Stride-Labs/stride/v5/x/records"
recordsmodulekeeper "github.com/Stride-Labs/stride/v5/x/records/keeper"
recordsmoduletypes "github.com/Stride-Labs/stride/v5/x/records/types"
Expand Down Expand Up @@ -155,6 +158,10 @@ func getGovProposalHandlers() []govclient.ProposalHandler {
ibcclientclient.UpdateClientProposalHandler,
ibcclientclient.UpgradeProposalHandler,
stakeibcclient.AddValidatorProposalHandler,
ratelimitclient.AddRateLimitProposalHandler,
ratelimitclient.UpdateRateLimitProposalHandler,
ratelimitclient.RemoveRateLimitProposalHandler,
ratelimitclient.ResetRateLimitProposalHandler,
// this line is used by starport scaffolding # stargate/app/govProposalHandler
)

Expand Down Expand Up @@ -193,6 +200,7 @@ var (
interchainquery.AppModuleBasic{},
ica.AppModuleBasic{},
recordsmodule.AppModuleBasic{},
ratelimitmodule.AppModuleBasic{},
icacallbacksmodule.AppModuleBasic{},
claim.AppModuleBasic{},
// this line is used by starport scaffolding # stargate/app/moduleBasic
Expand Down Expand Up @@ -283,6 +291,8 @@ type StrideApp struct {
RecordsKeeper recordsmodulekeeper.Keeper
ScopedIcacallbacksKeeper capabilitykeeper.ScopedKeeper
IcacallbacksKeeper icacallbacksmodulekeeper.Keeper
ScopedratelimitKeeper capabilitykeeper.ScopedKeeper
RatelimitKeeper ratelimitmodulekeeper.Keeper
ClaimKeeper claimkeeper.Keeper
// this line is used by starport scaffolding # stargate/app/keeperDeclaration

Expand Down Expand Up @@ -324,6 +334,7 @@ func NewStrideApp(
interchainquerytypes.StoreKey,
icacontrollertypes.StoreKey, icahosttypes.StoreKey,
recordsmoduletypes.StoreKey,
ratelimitmoduletypes.StoreKey,
icacallbacksmoduletypes.StoreKey,
claimtypes.StoreKey,
// this line is used by starport scaffolding # stargate/app/storeKey
Expand Down Expand Up @@ -405,11 +416,30 @@ func NewStrideApp(
appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper,
)

// Create Ratelimit Keeper
scopedratelimitKeeper := app.CapabilityKeeper.ScopeToModule(ratelimitmoduletypes.ModuleName)
app.ScopedratelimitKeeper = scopedratelimitKeeper
app.RatelimitKeeper = *ratelimitmodulekeeper.NewKeeper(
appCodec,
keys[ratelimitmoduletypes.StoreKey],
app.GetSubspace(ratelimitmoduletypes.ModuleName),
app.BankKeeper,
app.IBCKeeper.ChannelKeeper,
// TODO: Implement ICS4Wrapper in Records and pass records keeper here
app.IBCKeeper.ChannelKeeper, // ICS4Wrapper
)
ratelimitModule := ratelimitmodule.NewAppModule(appCodec, app.RatelimitKeeper)

// Create Transfer Keepers
app.TransferKeeper = ibctransferkeeper.NewKeeper(
appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName),
app.IBCKeeper.ChannelKeeper, app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper,
app.AccountKeeper, app.BankKeeper, scopedTransferKeeper,
appCodec, keys[ibctransfertypes.StoreKey],
app.GetSubspace(ibctransfertypes.ModuleName),
app.RatelimitKeeper, // ICS4Wrapper
app.IBCKeeper.ChannelKeeper,
&app.IBCKeeper.PortKeeper,
app.AccountKeeper,
app.BankKeeper,
scopedTransferKeeper,
)
transferModule := transfer.NewAppModule(app.TransferKeeper)
transferIBCModule := transfer.NewIBCModule(app.TransferKeeper)
Expand Down Expand Up @@ -508,7 +538,8 @@ func NewStrideApp(
AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)).
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)).
AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)).
AddRoute(stakeibcmoduletypes.RouterKey, stakeibcmodule.NewStakeibcProposalHandler(app.StakeibcKeeper))
AddRoute(stakeibcmoduletypes.RouterKey, stakeibcmodule.NewStakeibcProposalHandler(app.StakeibcKeeper)).
AddRoute(ratelimitmoduletypes.RouterKey, ratelimitmodule.NewRateLimitProposalHandler(app.RatelimitKeeper, app.IBCKeeper.ChannelKeeper))

app.GovKeeper = govkeeper.NewKeeper(
appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
Expand All @@ -526,6 +557,7 @@ func NewStrideApp(
app.StakeibcKeeper.Hooks(),
app.MintKeeper.Hooks(),
app.ClaimKeeper.Hooks(),
app.RatelimitKeeper.Hooks(),
),
)
epochsModule := epochsmodule.NewAppModule(appCodec, app.EpochsKeeper)
Expand Down Expand Up @@ -577,9 +609,11 @@ func NewStrideApp(
// Stack three contains
// - IBC
// - records
// - ratelimit
// - transfer
// - base app
var transferStack porttypes.IBCModule = transferIBCModule
transferStack = ratelimitmodule.NewIBCMiddleware(app.RatelimitKeeper, transferStack)
transferStack = recordsmodule.NewIBCModule(app.RecordsKeeper, transferStack)

// Create static IBC router, add transfer route, then set and seal it
Expand All @@ -591,7 +625,7 @@ func NewStrideApp(
// 4. In stakeibc's OnChanOpenInit, the stakeibc module steals the portId from the icacontroller module
// 5. Now in OnChanOpenAck and any other subsequent IBC callback, the message server will identify
// the portID owner as stakeibc and route to the same stakeibcStack, this time using the "stakeibc" route instead
ibcRouter := ibcporttypes.NewRouter()
ibcRouter := porttypes.NewRouter()
ibcRouter.
// ICAHost Stack
AddRoute(icahosttypes.SubModuleName, icaHostIBCModule).
Expand Down Expand Up @@ -642,6 +676,7 @@ func NewStrideApp(
interchainQueryModule,
icaModule,
recordsModule,
ratelimitModule,
icacallbacksModule,
// this line is used by starport scaffolding # stargate/app/appModule
)
Expand Down Expand Up @@ -675,6 +710,7 @@ func NewStrideApp(
epochsmoduletypes.ModuleName,
interchainquerytypes.ModuleName,
recordsmoduletypes.ModuleName,
ratelimitmoduletypes.ModuleName,
icacallbacksmoduletypes.ModuleName,
claimtypes.ModuleName,
// this line is used by starport scaffolding # stargate/app/beginBlockers
Expand Down Expand Up @@ -705,6 +741,7 @@ func NewStrideApp(
epochsmoduletypes.ModuleName,
interchainquerytypes.ModuleName,
recordsmoduletypes.ModuleName,
ratelimitmoduletypes.ModuleName,
icacallbacksmoduletypes.ModuleName,
claimtypes.ModuleName,
// this line is used by starport scaffolding # stargate/app/endBlockers
Expand Down Expand Up @@ -740,6 +777,7 @@ func NewStrideApp(
epochsmoduletypes.ModuleName,
interchainquerytypes.ModuleName,
recordsmoduletypes.ModuleName,
ratelimitmoduletypes.ModuleName,
icacallbacksmoduletypes.ModuleName,
claimtypes.ModuleName,
// this line is used by starport scaffolding # stargate/app/initGenesis
Expand Down Expand Up @@ -1003,6 +1041,7 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino
paramsKeeper.Subspace(icacontrollertypes.SubModuleName)
paramsKeeper.Subspace(icahosttypes.SubModuleName)
paramsKeeper.Subspace(recordsmoduletypes.ModuleName)
paramsKeeper.Subspace(ratelimitmoduletypes.ModuleName)
paramsKeeper.Subspace(icacallbacksmoduletypes.ModuleName)
// this line is used by starport scaffolding # stargate/app/paramSubspace

Expand Down
15 changes: 15 additions & 0 deletions app/apptesting/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ var (
}))
)

type SuitelessAppTestHelper struct {
App *app.StrideApp
Ctx sdk.Context
}

type AppTestHelper struct {
suite.Suite

Expand Down Expand Up @@ -69,6 +74,16 @@ func (s *AppTestHelper) Setup() {
s.IcaAddresses = make(map[string]string)
}

// Instantiates an TestHelper without the test suite
// This is for testing scenarios where we simply need the setup function to run,
// and need access to the TestHelper attributes and keepers (e.g. genesis tests)
func SetupSuitelessTestHelper() SuitelessAppTestHelper {
s := SuitelessAppTestHelper{}
s.App = app.InitStrideTestApp(true)
s.Ctx = s.App.BaseApp.NewContext(false, tmtypes.Header{Height: 1, ChainID: StrideChainID})
return s
}

// Mints coins directly to a module account
func (s *AppTestHelper) FundModuleAccount(moduleName string, amount sdk.Coin) {
err := s.App.BankKeeper.MintCoins(s.Ctx, moduleName, sdk.NewCoins(amount))
Expand Down
8 changes: 8 additions & 0 deletions app/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ func (app *StrideApp) setupUpgradeHandlers() {
Deleted: []string{authz.ModuleName},
}
}
// TODO: RATE LIMIT UPGRADE
// 1. Add ratelimit store key when module is added
// storeUpgrades = &storetypes.StoreUpgrades{
// Added: []string{ratelimittypes.StoreKey},
// }
//
// 2. Add hour epoch to store
// 3. Add rate limits for existing denoms

if storeUpgrades != nil {
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, storeUpgrades))
Expand Down
1 change: 1 addition & 0 deletions dockernet/config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ IBC_STARS_DENOM=$IBC_STARS_CHANNEL_3_DENOM

# CHAIN PARAMS
BLOCK_TIME='1s'
STRIDE_HOUR_EPOCH_DURATION="90s"
STRIDE_DAY_EPOCH_DURATION="100s"
STRIDE_EPOCH_EPOCH_DURATION="40s"
HOST_DAY_EPOCH_DURATION="60s"
Expand Down
45 changes: 45 additions & 0 deletions dockernet/config/relayer_config_juno_osmo.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Sometimes it's beneficial to test a channel that is not connected with Stride
# For this case, we can use juno <> osmo
global:
api-listen-addr: :5183
timeout: 10s
memo: ""
light-cache-size: 20
chains:
juno:
type: cosmos
value:
key: juno-osmo-rly1
chain-id: JUNO
rpc-addr: http://juno1:26657
account-prefix: juno
keyring-backend: test
gas-adjustment: 1.2
gas-prices: 0.01ujuno
debug: false
timeout: 20s
output-format: json
sign-mode: direct
osmo:
type: cosmos
value:
key: juno-osmo-rly2
chain-id: OSMO
rpc-addr: http://osmo1:26657
account-prefix: osmo
keyring-backend: test
gas-adjustment: 1.2
gas-prices: 0.01uosmo
debug: false
timeout: 20s
output-format: json
sign-mode: direct
paths:
juno-osmo:
src:
chain-id: JUNO
dst:
chain-id: OSMO
src-channel-filter:
rule: ""
channel-list: []
7 changes: 7 additions & 0 deletions dockernet/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,10 @@ services:
- ./state/relayer-host:/home/relayer/.relayer
restart: always
command: [ "bash", "start.sh", "stride-host" ]

relayer-juno-osmo:
image: stridezone:relayer
volumes:
- ./state/relayer-juno-osmo:/home/relayer/.relayer
restart: always
command: [ "bash", "start.sh", "juno-osmo" ]
13 changes: 13 additions & 0 deletions dockernet/scripts/ratelimit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Rate Limit Integration Tests
* **These tests are not intended to be run with normal CI, they were meant as a comprehensive sanity check before deploying the module and are redundant with the unit tests.**
* **WARNING**: `STRIDE_HOUR_EPOCH_DURATION` must be at least '90s' in `config.sh`
* `HOST_CHAINS` should be set to `(GAIA JUNO OSMO)` in `config.sh`
* Start dockernet
```
make start-docker
```
* Run the integration tests
```
bash dockernet/scripts/ratelimit/run_all_tests.sh
```
* Each test will print a checkmark or X depending on the status - if there are no X's, the tests passed.
Loading

0 comments on commit 94e3a91

Please sign in to comment.