Skip to content

Commit

Permalink
doc fix
Browse files Browse the repository at this point in the history
  • Loading branch information
stana-miric committed Nov 4, 2024
1 parent 9319c3f commit ea0b735
Show file tree
Hide file tree
Showing 5 changed files with 1 addition and 235 deletions.
219 changes: 0 additions & 219 deletions docs/docs/build/modules/04-democracy.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,225 +216,6 @@ func NewApp(...) {
}
```

## Governance

The `x/ccv/democracy/governance` module extends the `x/governance` module with the functionality to filter proposals.
The module uses `AnteHandler` to limit the types of proposals that can be executed.
As a result, consumer chains can limit the types of governance proposals that can be executed on chain to avoid inadvertent changes to the ICS protocol that could affect security properties.

### Integration

Add new `AnteHandler` to your `app`.

```go

// app/ante/forbidden_proposals.go
package ante

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"

"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
"github.com/cosmos/cosmos-sdk/x/params/types/proposal"
)

type ForbiddenProposalsDecorator struct {
isLegacyProposalWhitelisted func(govv1beta1.Content) bool
isModuleWhiteList func(string) bool
}

func NewForbiddenProposalsDecorator(
whiteListFn func(govv1beta1.Content) bool,
isModuleWhiteList func(string) bool,
) ForbiddenProposalsDecorator {
return ForbiddenProposalsDecorator{
isLegacyProposalWhitelisted: whiteListFn,
isModuleWhiteList: isModuleWhiteList,
}
}

func (decorator ForbiddenProposalsDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
currHeight := ctx.BlockHeight()

for _, msg := range tx.GetMsgs() {
// if the message is MsgSubmitProposal, check if proposal is whitelisted
submitProposalMgs, ok := msg.(*govv1.MsgSubmitProposal)
if !ok {
continue
}

messages := submitProposalMgs.GetMessages()
for _, message := range messages {
if sdkMsg, isLegacyProposal := message.GetCachedValue().(*govv1.MsgExecLegacyContent); isLegacyProposal {
// legacy gov proposal content
content, err := govv1.LegacyContentFromMessage(sdkMsg)
if err != nil {
return ctx, fmt.Errorf("tx contains invalid LegacyContent")
}
if !decorator.isLegacyProposalWhitelisted(content) {
return ctx, fmt.Errorf("tx contains unsupported proposal message types at height %d", currHeight)
}
continue
}
// not legacy gov proposal content and not whitelisted
if !decorator.isModuleWhiteList(message.TypeUrl) {
return ctx, fmt.Errorf("tx contains unsupported proposal message types at height %d", currHeight)
}
}
}

return next(ctx, tx, simulate)
}

func IsProposalWhitelisted(content v1beta1.Content) bool {
switch c := content.(type) {
case *proposal.ParameterChangeProposal:
return isLegacyParamChangeWhitelisted(c.Changes)

default:
return false
}
}

func isLegacyParamChangeWhitelisted(paramChanges []proposal.ParamChange) bool {
for _, paramChange := range paramChanges {
_, found := LegacyWhitelistedParams[legacyParamChangeKey{Subspace: paramChange.Subspace, Key: paramChange.Key}]
if !found {
return false
}
}
return true
}

type legacyParamChangeKey struct {
Subspace, Key string
}

// Legacy params can be whitelisted
var LegacyWhitelistedParams = map[legacyParamChangeKey]struct{}{
{Subspace: ibctransfertypes.ModuleName, Key: "SendEnabled"}: {},
{Subspace: ibctransfertypes.ModuleName, Key: "ReceiveEnabled"}: {},
}

// New proposal types can be whitelisted
var WhiteListModule = map[string]struct{}{
"/cosmos.gov.v1.MsgUpdateParams": {},
"/cosmos.bank.v1beta1.MsgUpdateParams": {},
"/cosmos.staking.v1beta1.MsgUpdateParams": {},
"/cosmos.distribution.v1beta1.MsgUpdateParams": {},
"/cosmos.mint.v1beta1.MsgUpdateParams": {},
}

func IsModuleWhiteList(typeUrl string) bool {
_, found := WhiteListModule[typeUrl]
return found
}
```

Add the `AnteHandler` to the list of supported antehandlers:

```diff
// app/ante_handler.go
package app

import (
...

+ democracyante "github.com/cosmos/interchain-security/v4/app/consumer-democracy/ante"
+ consumerante "github.com/cosmos/interchain-security/v4/app/consumer/ante"
+ icsconsumerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"
)

type HandlerOptions struct {
ante.HandlerOptions

IBCKeeper *ibckeeper.Keeper
+ ConsumerKeeper ibcconsumerkeeper.Keeper
}

func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
....

anteDecorators := []sdk.AnteDecorator{
...
+ consumerante.NewMsgFilterDecorator(options.ConsumerKeeper),
+ consumerante.NewDisabledModulesDecorator("/cosmos.evidence", "/cosmos.slashing"),
+ democracyante.NewForbiddenProposalsDecorator(IsProposalWhitelisted, IsModuleWhiteList),
...
}

return sdk.ChainAnteDecorators(anteDecorators...), nil
}
```

Wire the module in `app.go`.

```diff
// app/app.go
package app
import (
...
sdkgov "github.com/cosmos/cosmos-sdk/x/gov"
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"

+ ccvgov "github.com/cosmos/interchain-security/v4/x/ccv/democracy/governance"
)

var (

// use sdk governance module
ModuleBasics = module.NewBasicManager(
...
sdkgov.NewAppModuleBasic(
[]govclient.ProposalHandler{
paramsclient.ProposalHandler,
upgradeclient.LegacyProposalHandler,
upgradeclient.LegacyCancelProposalHandler,
},
),
)
)

func NewApp(...) {
// retain sdk gov router and keeper registrations
sdkgovRouter := govv1beta1.NewRouter()
sdkgovRouter.
AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler).
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(&app.UpgradeKeeper))
govConfig := govtypes.DefaultConfig()

app.GovKeeper = *govkeeper.NewKeeper(
appCodec,
keys[govtypes.StoreKey],
app.AccountKeeper,
app.BankKeeper,
app.StakingKeeper,
app.MsgServiceRouter(),
govConfig,
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)

app.GovKeeper.SetLegacyRouter(sdkgovRouter)


// register the module with module manager
// replace the x/gov module
app.MM = module.NewManager(
- sdkgov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper, IsProposalWhitelisted, app.GetSubspace(govtypes.ModuleName), IsModuleWhiteList),
+ ccvgov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper, IsProposalWhitelisted, app.GetSubspace(govtypes.ModuleName), IsModuleWhiteList),
...
)
}
```

## Distribution

The `x/ccv/democracy/distribution` module allows the consumer chain to send rewards to the provider chain while retaining the logic of the `x/distribution` module for internal reward distribution to governators and their delegators.
Expand Down
6 changes: 1 addition & 5 deletions docs/docs/consumer-development/consumer-chain-governance.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ sidebar_position: 3

# Consumer Chain Governance

Different consumer chains can do governance in different ways. However, no matter what the governance method is, there are a few settings specifically related to consensus that consumer chain governance cannot change. We'll cover what these are in the "Whitelist" section below.
Different consumer chains can do governance in different ways. However, no matter what the governance method is, there are a few settings specifically related to consensus that consumer chain governance cannot change.

## Democracy module

Expand All @@ -19,7 +19,3 @@ For an example, see the [Democracy Consumer](https://github.com/cosmos/interchai
There are several great DAO and governance frameworks written as CosmWasm contracts. These can be used as the main governance system for a consumer chain. Actions triggered by the CosmWasm governance contracts are able to affect parameters and trigger actions on the consumer chain.

For an example, see [Neutron](https://github.com/neutron-org/neutron/).

## The Whitelist

Not everything on a consumer chain can be changed by the consumer's governance. Some settings having to do with consensus etc. can only be changed by the provider chain. Consumer chains include a whitelist of parameters that are allowed to be changed by the consumer chain governance. For an example, see [Neutron's](https://github.com/neutron-org/neutron/blob/main/app/proposals_allowlisting.go) whitelist.
6 changes: 0 additions & 6 deletions docs/upgrades_reference/democracy.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,5 @@ The inner workings of `EndBlock` were refactored to allow using the cosmos-sdk g

## App wiring & tests

Whitelisted proposal list was changed because `param-change` proposals were deprecated for most modules (they cannot be submitted).

Added to whitelists:
* `/cosmos.gov.v1beta1.TextProposal`


e2e tests were refactored to send the `TextProposal` instead of a `param-change` because there are no modules that can process `param-change` so we cannot use those proposals any longer.

4 changes: 0 additions & 4 deletions docs/upgrades_reference/imports_only.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
# import change only [file list]
* app/consumer-democracy/ante_handler.go
* app/consumer-democracy/proposals_whitelisting.go
* app/consumer-democracy/proposals_whitelisting_test.go
* app/consumer/ante/disabled_modules_ante_test.go
* app/consumer/ante/msg_filter_ante_test.go
* app/consumer/ante_handler.go
* app/provider/ante_handler.go
Expand Down
1 change: 0 additions & 1 deletion scripts/test_doc/test_documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
| Function | Short Description |
|----------|-------------------|
[TestDemocracyRewardsDistribution](../../tests/integration/democracy.go#L78) | TestDemocracyRewardsDistribution checks that rewards to democracy representatives, community pool, and provider redistribution account are done correctly.<details><summary>Details</summary>* Set up a democracy consumer chain.<br>* Create a new block.<br>* Check that rewards to democracy representatives, community pool, and provider redistribution account are distributed in the right proportions.</details> |
[TestDemocracyGovernanceWhitelisting](../../tests/integration/democracy.go#L194) | TestDemocracyGovernanceWhitelisting checks that only whitelisted governance proposals can be executed on democracy consumer chains.<details><summary>Details</summary>For context, see the whitelist for proposals in app/consumer-democracy/proposals_whitelisting.go.<br>* Set up a democracy consumer chain.<br>* Submit a proposal containing changes to the auth and mint module parameters.<br>* Check that the proposal is not executed, since the change to the auth module is not whitelisted.<br>* Submit a proposal containing changes *only* to the mint module parameters.<br>* Check that the proposal is executed, since the change to the mint module is whitelisted.<br>* Submit a proposal containing changes *only* to the auth module parameters.<br>* Check that again, the proposal is not executed, since the change to the auth module is not whitelisted.</details> |
[TestDemocracyMsgUpdateParams](../../tests/integration/democracy.go#L294) | TestDemocracyMsgUpdateParams checks that the consumer parameters can be updated through a governance proposal.<details><summary>Details</summary>* Set up a democracy consumer chain.<br>* Submit a proposal containing changes to the consumer module parameters.<br>* Check that the proposal is executed, and the parameters are updated.</details> |
</details>

Expand Down

0 comments on commit ea0b735

Please sign in to comment.