-
Notifications
You must be signed in to change notification settings - Fork 370
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
45 changed files
with
3,657 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<!-- | ||
Guiding Principles: | ||
Changelogs are for humans, not machines. | ||
There should be an entry for every single version. | ||
The same types of changes should be grouped. | ||
Versions and sections should be linkable. | ||
The latest version comes first. | ||
The release date of each version is displayed. | ||
Mention whether you follow Semantic Versioning. | ||
Usage: | ||
Change log entries are to be added to the Unreleased section under the | ||
appropriate stanza (see below). Each entry should ideally include a tag and | ||
the Github issue reference in the following format: | ||
* (<tag>) [#<issue-number>] Changelog message. | ||
Types of changes (Stanzas): | ||
"Features" for new features. | ||
"Improvements" for changes in existing functionality. | ||
"Deprecated" for soon-to-be removed features. | ||
"Bug Fixes" for any bug fixes. | ||
"API Breaking" for breaking exported APIs used by developers building on SDK. | ||
Ref: https://keepachangelog.com/en/1.0.0/ | ||
--> | ||
|
||
# Changelog | ||
|
||
## [Unreleased] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
--- | ||
sidebar_position: 1 | ||
--- | ||
|
||
# `x/params` | ||
|
||
> Note: The Params module has been deprecated in favour of each module housing its own parameters. | ||
## Abstract | ||
|
||
Package params provides a globally available parameter store. | ||
|
||
There are two main types, Keeper and Subspace. Subspace is an isolated namespace for a | ||
paramstore, where keys are prefixed by preconfigured spacename. Keeper has a | ||
permission to access all existing spaces. | ||
|
||
Subspace can be used by the individual keepers, which need a private parameter store | ||
that the other keepers cannot modify. The params Keeper can be used to add a route to `x/gov` router in order to modify any parameter in case a proposal passes. | ||
|
||
The following contents explains how to use params module for master and user modules. | ||
|
||
## Contents | ||
|
||
* [Keeper](#keeper) | ||
* [Subspace](#subspace) | ||
* [Key](#key) | ||
* [KeyTable](#keytable) | ||
* [ParamSet](#paramset) | ||
|
||
## Keeper | ||
|
||
In the app initialization stage, [subspaces](#subspace) can be allocated for other modules' keeper using `Keeper.Subspace` and are stored in `Keeper.spaces`. Then, those modules can have a reference to their specific parameter store through `Keeper.GetSubspace`. | ||
|
||
Example: | ||
|
||
```go | ||
type ExampleKeeper struct { | ||
paramSpace paramtypes.Subspace | ||
} | ||
|
||
func (k ExampleKeeper) SetParams(ctx sdk.Context, params types.Params) { | ||
k.paramSpace.SetParamSet(ctx, ¶ms) | ||
} | ||
``` | ||
|
||
## Subspace | ||
|
||
`Subspace` is a prefixed subspace of the parameter store. Each module which uses the | ||
parameter store will take a `Subspace` to isolate permission to access. | ||
|
||
### Key | ||
|
||
Parameter keys are human readable alphanumeric strings. A parameter for the key | ||
`"ExampleParameter"` is stored under `[]byte("SubspaceName" + "/" + "ExampleParameter")`, | ||
where `"SubspaceName"` is the name of the subspace. | ||
|
||
Subkeys are secondary parameter keys those are used along with a primary parameter key. | ||
Subkeys can be used for grouping or dynamic parameter key generation during runtime. | ||
|
||
### KeyTable | ||
|
||
All of the parameter keys that will be used should be registered at the compile | ||
time. `KeyTable` is essentially a `map[string]attribute`, where the `string` is a parameter key. | ||
|
||
Currently, `attribute` consists of a `reflect.Type`, which indicates the parameter | ||
type to check that provided key and value are compatible and registered, as well as a function `ValueValidatorFn` to validate values. | ||
|
||
Only primary keys have to be registered on the `KeyTable`. Subkeys inherit the | ||
attribute of the primary key. | ||
|
||
### ParamSet | ||
|
||
Modules often define parameters as a proto message. The generated struct can implement | ||
`ParamSet` interface to be used with the following methods: | ||
|
||
* `KeyTable.RegisterParamSet()`: registers all parameters in the struct | ||
* `Subspace.{Get, Set}ParamSet()`: Get to & Set from the struct | ||
|
||
The implementer should be a pointer in order to use `GetParamSet()`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package params | ||
|
||
import ( | ||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" | ||
paramsv1beta1 "cosmossdk.io/api/cosmos/params/v1beta1" | ||
) | ||
|
||
// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface. | ||
func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { | ||
return &autocliv1.ModuleOptions{ | ||
Query: &autocliv1.ServiceCommandDescriptor{ | ||
Service: paramsv1beta1.Query_ServiceDesc.ServiceName, | ||
RpcCommandOptions: []*autocliv1.RpcCommandOptions{ | ||
{ | ||
RpcMethod: "Params", | ||
Use: "subspace <subspace> <key>", | ||
Short: "Query for raw parameters by subspace and key", | ||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{ | ||
{ProtoField: "subspace"}, | ||
{ProtoField: "key"}, | ||
}, | ||
}, | ||
{ | ||
RpcMethod: "Subspaces", | ||
Use: "subspaces", | ||
Short: "Query for all registered subspaces and all keys for a subspace", | ||
}, | ||
}, | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package cli | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/spf13/cobra" | ||
|
||
govv1beta1 "cosmossdk.io/x/gov/types/v1beta1" | ||
paramscutils "cosmossdk.io/x/params/client/utils" | ||
paramproposal "cosmossdk.io/x/params/types/proposal" | ||
|
||
"github.com/cosmos/cosmos-sdk/client" | ||
"github.com/cosmos/cosmos-sdk/client/tx" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/cosmos/cosmos-sdk/version" | ||
) | ||
|
||
// NewSubmitParamChangeProposalTxCmd returns a CLI command handler for creating | ||
// a parameter change proposal governance transaction. | ||
func NewSubmitParamChangeProposalTxCmd() *cobra.Command { | ||
return &cobra.Command{ | ||
Use: "param-change <proposal-file>", | ||
Args: cobra.ExactArgs(1), | ||
Short: "Submit a parameter change proposal", | ||
Long: strings.TrimSpace( | ||
fmt.Sprintf(`Submit a parameter proposal along with an initial deposit. | ||
The proposal details must be supplied via a JSON file. For values that contains | ||
objects, only non-empty fields will be updated. | ||
IMPORTANT: Currently parameter changes are evaluated but not validated, so it is | ||
very important that any "value" change is valid (ie. correct type and within bounds) | ||
for its respective parameter, eg. "MaxValidators" should be an integer and not a decimal. | ||
Proper vetting of a parameter change proposal should prevent this from happening | ||
(no deposits should occur during the governance process), but it should be noted | ||
regardless. | ||
Example: | ||
$ %s tx gov submit-proposal param-change <path/to/proposal.json> --from=<key_or_address> | ||
Where proposal.json contains: | ||
{ | ||
"title": "Staking Param Change", | ||
"description": "Update max validators", | ||
"changes": [ | ||
{ | ||
"subspace": "staking", | ||
"key": "MaxValidators", | ||
"value": 105 | ||
} | ||
], | ||
"deposit": "1000stake" | ||
} | ||
`, | ||
version.AppName, | ||
), | ||
), | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
clientCtx, err := client.GetClientTxContext(cmd) | ||
if err != nil { | ||
return err | ||
} | ||
proposal, err := paramscutils.ParseParamChangeProposalJSON(clientCtx.LegacyAmino, args[0]) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
from, err := clientCtx.AddressCodec.BytesToString(clientCtx.GetFromAddress()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
content := paramproposal.NewParameterChangeProposal( | ||
proposal.Title, proposal.Description, proposal.Changes.ToParamChanges(), | ||
) | ||
|
||
deposit, err := sdk.ParseCoinsNormalized(proposal.Deposit) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
msg, err := govv1beta1.NewMsgSubmitProposal(content, deposit, from) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package cli | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
|
||
"cosmossdk.io/x/params/client/utils" | ||
|
||
"github.com/cosmos/cosmos-sdk/codec" | ||
"github.com/cosmos/cosmos-sdk/testutil" | ||
) | ||
|
||
func TestParseProposal(t *testing.T) { | ||
cdc := codec.NewLegacyAmino() | ||
okJSON := testutil.WriteToNewTempFile(t, ` | ||
{ | ||
"title": "Staking Param Change", | ||
"description": "Update max validators", | ||
"changes": [ | ||
{ | ||
"subspace": "staking", | ||
"key": "MaxValidators", | ||
"value": 1 | ||
} | ||
], | ||
"deposit": "1000stake" | ||
} | ||
`) | ||
proposal, err := utils.ParseParamChangeProposalJSON(cdc, okJSON.Name()) | ||
require.NoError(t, err) | ||
|
||
require.Equal(t, "Staking Param Change", proposal.Title) | ||
require.Equal(t, "Update max validators", proposal.Description) | ||
require.Equal(t, "1000stake", proposal.Deposit) | ||
require.Equal(t, utils.ParamChangesJSON{ | ||
{ | ||
Subspace: "staking", | ||
Key: "MaxValidators", | ||
Value: []byte{0x31}, | ||
}, | ||
}, proposal.Changes) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package client | ||
|
||
import ( | ||
govclient "cosmossdk.io/x/gov/client" | ||
"cosmossdk.io/x/params/client/cli" | ||
) | ||
|
||
// ProposalHandler is the param change proposal handler. | ||
var ProposalHandler = govclient.NewProposalHandler(cli.NewSubmitParamChangeProposalTxCmd) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package utils | ||
|
||
import ( | ||
"encoding/json" | ||
"os" | ||
|
||
"cosmossdk.io/x/params/types/proposal" | ||
|
||
"github.com/cosmos/cosmos-sdk/codec" | ||
) | ||
|
||
type ( | ||
// ParamChangesJSON defines a slice of ParamChangeJSON objects which can be | ||
// converted to a slice of ParamChange objects. | ||
ParamChangesJSON []ParamChangeJSON | ||
|
||
// ParamChangeJSON defines a parameter change used in JSON input. This | ||
// allows values to be specified in raw JSON instead of being string encoded. | ||
ParamChangeJSON struct { | ||
Subspace string `json:"subspace" yaml:"subspace"` | ||
Key string `json:"key" yaml:"key"` | ||
Value json.RawMessage `json:"value" yaml:"value"` | ||
} | ||
|
||
// ParamChangeProposalJSON defines a ParameterChangeProposal with a deposit used | ||
// to parse parameter change proposals from a JSON file. | ||
ParamChangeProposalJSON struct { | ||
Title string `json:"title" yaml:"title"` | ||
Description string `json:"description" yaml:"description"` | ||
Changes ParamChangesJSON `json:"changes" yaml:"changes"` | ||
Deposit string `json:"deposit" yaml:"deposit"` | ||
} | ||
) | ||
|
||
func NewParamChangeJSON(subspace, key string, value json.RawMessage) ParamChangeJSON { | ||
return ParamChangeJSON{subspace, key, value} | ||
} | ||
|
||
// ToParamChange converts a ParamChangeJSON object to ParamChange. | ||
func (pcj ParamChangeJSON) ToParamChange() proposal.ParamChange { | ||
return proposal.NewParamChange(pcj.Subspace, pcj.Key, string(pcj.Value)) | ||
} | ||
|
||
// ToParamChanges converts a slice of ParamChangeJSON objects to a slice of | ||
// ParamChange. | ||
func (pcj ParamChangesJSON) ToParamChanges() []proposal.ParamChange { | ||
res := make([]proposal.ParamChange, len(pcj)) | ||
for i, pc := range pcj { | ||
res[i] = pc.ToParamChange() | ||
} | ||
return res | ||
} | ||
|
||
// ParseParamChangeProposalJSON reads and parses a ParamChangeProposalJSON from | ||
// file. | ||
func ParseParamChangeProposalJSON(cdc *codec.LegacyAmino, proposalFile string) (ParamChangeProposalJSON, error) { | ||
proposal := ParamChangeProposalJSON{} | ||
|
||
contents, err := os.ReadFile(proposalFile) | ||
if err != nil { | ||
return proposal, err | ||
} | ||
|
||
if err := cdc.UnmarshalJSON(contents, &proposal); err != nil { | ||
return proposal, err | ||
} | ||
|
||
return proposal, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package utils | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestNewParamChangeJSON(t *testing.T) { | ||
pcj := NewParamChangeJSON("subspace", "key", json.RawMessage(`{}`)) | ||
require.Equal(t, "subspace", pcj.Subspace) | ||
require.Equal(t, "key", pcj.Key) | ||
require.Equal(t, json.RawMessage(`{}`), pcj.Value) | ||
} | ||
|
||
func TestToParamChanges(t *testing.T) { | ||
pcj1 := NewParamChangeJSON("subspace", "key1", json.RawMessage(`{}`)) | ||
pcj2 := NewParamChangeJSON("subspace", "key2", json.RawMessage(`{}`)) | ||
pcjs := ParamChangesJSON{pcj1, pcj2} | ||
|
||
paramChanges := pcjs.ToParamChanges() | ||
require.Len(t, paramChanges, 2) | ||
|
||
require.Equal(t, paramChanges[0].Subspace, pcj1.Subspace) | ||
require.Equal(t, paramChanges[0].Key, pcj1.Key) | ||
require.Equal(t, paramChanges[0].Value, string(pcj1.Value)) | ||
|
||
require.Equal(t, paramChanges[1].Subspace, pcj2.Subspace) | ||
require.Equal(t, paramChanges[1].Key, pcj2.Key) | ||
require.Equal(t, paramChanges[1].Value, string(pcj2.Value)) | ||
} |
Oops, something went wrong.