diff --git a/CHANGELOG.md b/CHANGELOG.md
index 33f45f7e88..f0ac315e0d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -105,6 +105,7 @@ if input key is empty, or input data contains empty key.
* `sdk.Msg` now only contains `ValidateBasic` and `GetSigners` methods. The remaining methods `GetSignBytes`, `Route` and `Type` are moved to `legacytx.LegacyMsg`.
* The `RegisterCustomTypeURL` function and the `cosmos.base.v1beta1.ServiceMsg` interface have been removed from the interface registry.
* (codec) [\#9251](https://github.com/cosmos/cosmos-sdk/pull/9251) Rename `clientCtx.JSONMarshaler` to `clientCtx.JSONCodec` as per #9226.
+* (x/bank) [\#9271](https://github.com/cosmos/cosmos-sdk/pull/9271) SendEnabledCoin(s) renamed to IsSendEnabledCoin(s) to better reflect its functionality.
### State Machine Breaking
diff --git a/docs/architecture/adr-042-group-module.md b/docs/architecture/adr-042-group-module.md
new file mode 100644
index 0000000000..dcca987bcd
--- /dev/null
+++ b/docs/architecture/adr-042-group-module.md
@@ -0,0 +1,277 @@
+# ADR 042: Group Module
+
+## Changelog
+
+- 2020/04/09: Initial Draft
+
+## Status
+
+Draft
+
+## Abstract
+
+This ADR defines the `x/group` module which allows the creation and management of on-chain multi-signature accounts and enables voting for message execution based on configurable decision policies.
+
+## Context
+
+The legacy amino multi-signature mechanism of the Cosmos SDK has certain limitations:
+- Key rotation is not possible, although this can be solved with [account rekeying](adr-034-account-rekeying.md).
+- Thresholds can't be changed.
+- UX is cumbersome for non-technical users ([#5661](https://github.com/cosmos/cosmos-sdk/issues/5661)).
+- It requires `legacy_amino` sign mode ([#8141](https://github.com/cosmos/cosmos-sdk/issues/8141)).
+
+While the group module is not meant to be a total replacement for the current multi-signature accounts, it provides a solution to the limitations described above, with a more flexible key management system where keys can be added, updated or removed, as well as configurable thresholds.
+It's meant to be used with other access control modules such as [`x/feegrant`](./adr-029-fee-grant-module.md) ans [`x/authz`](adr-030-authz-module.md) to simplify key management for individuals and organizations.
+
+The proof of concept of the group module can be found in https://github.com/regen-network/regen-ledger/tree/master/proto/regen/group/v1alpha1 and https://github.com/regen-network/regen-ledger/tree/master/x/group.
+
+## Decision
+
+We propose merging the `x/group` module with its supporting [ORM/Table Store package](https://github.com/regen-network/regen-ledger/tree/master/orm) ([#7098](https://github.com/cosmos/cosmos-sdk/issues/7098)) into the Cosmos SDK and continuing development here. There will be a dedicated ADR for the ORM package.
+
+### Group
+
+A group is a composition of accounts with associated weights. It is not
+an account and doesn't have a balance. It doesn't in and of itself have any
+sort of voting or decision weight.
+Group members can create proposals and vote on them through group accounts using different decision policies.
+
+It has an `admin` account which can manage members in the group, update the group
+metadata and set a new admin.
+
+```proto
+message GroupInfo {
+
+ // group_id is the unique ID of this group.
+ uint64 group_id = 1;
+
+ // admin is the account address of the group's admin.
+ string admin = 2;
+
+ // metadata is any arbitrary metadata to attached to the group.
+ bytes metadata = 3;
+
+ // version is used to track changes to a group's membership structure that
+ // would break existing proposals. Whenever a member weight has changed,
+ // or any member is added or removed, the version is incremented and will
+ // invalidate all proposals from older versions.
+ uint64 version = 4;
+
+ // total_weight is the sum of the group members' weights.
+ string total_weight = 5;
+}
+```
+
+```proto
+message GroupMember {
+
+ // group_id is the unique ID of the group.
+ uint64 group_id = 1;
+
+ // member is the member data.
+ Member member = 2;
+}
+
+// Member represents a group member with an account address,
+// non-zero weight and metadata.
+message Member {
+
+ // address is the member's account address.
+ string address = 1;
+
+ // weight is the member's voting weight that should be greater than 0.
+ string weight = 2;
+
+ // metadata is any arbitrary metadata to attached to the member.
+ bytes metadata = 3;
+}
+```
+
+### Group Account
+
+A group account is an account associated with a group and a decision policy.
+A group account does have a balance.
+
+Group accounts are abstracted from groups because a single group may have
+multiple decision policies for different types of actions. Managing group
+membership separately from decision policies results in the least overhead
+and keeps membership consistent across different policies. The pattern that
+is recommended is to have a single master group account for a given group,
+and then to create separate group accounts with different decision policies
+and delegate the desired permissions from the master account to
+those "sub-accounts" using the [`x/authz` module](adr-030-authz-module.md).
+
+```proto
+message GroupAccountInfo {
+
+ // address is the group account address.
+ string address = 1;
+
+ // group_id is the ID of the Group the GroupAccount belongs to.
+ uint64 group_id = 2;
+
+ // admin is the account address of the group admin.
+ string admin = 3;
+
+ // metadata is any arbitrary metadata of this group account.
+ bytes metadata = 4;
+
+ // version is used to track changes to a group's GroupAccountInfo structure that
+ // invalidates active proposal from old versions.
+ uint64 version = 5;
+
+ // decision_policy specifies the group account's decision policy.
+ google.protobuf.Any decision_policy = 6 [(cosmos_proto.accepts_interface) = "DecisionPolicy"];
+}
+```
+
+Similarly to a group admin, a group account admin can update its metadata, decision policy or set a new group account admin.
+
+A group account can also be an admin or a member of a group.
+For instance, a group admin could be another group account which could "elects" the members or it could be the same group that elects itself.
+
+### Decision Policy
+
+A decision policy is the mechanism by which members of a group can vote on
+proposals.
+
+All decision policies should have a minimum and maximum voting window.
+The minimum voting window is the minimum duration that must pass in order
+for a proposal to potentially pass, and it may be set to 0. The maximum voting
+window is the maximum time that a proposal may be voted on and executed if
+it reached enough support before it is closed.
+Both of these values must be less than a chain-wide max voting window parameter.
+
+We define the `DecisionPolicy` interface that all decision policies must implement:
+
+```go
+type DecisionPolicy interface {
+ codec.ProtoMarshaler
+
+ ValidateBasic() error
+ GetTimeout() types.Duration
+ Allow(tally Tally, totalPower string, votingDuration time.Duration) (DecisionPolicyResult, error)
+ Validate(g GroupInfo) error
+}
+
+type DecisionPolicyResult struct {
+ Allow bool
+ Final bool
+}
+```
+
+#### Threshold decision policy
+
+A threshold decision policy defines a minimum support votes (_yes_), based on a tally
+of voter weights, for a proposal to pass. For
+this decision policy, abstain and veto are treated as no support (_no_).
+
+```proto
+message ThresholdDecisionPolicy {
+
+ // threshold is the minimum weighted sum of support votes for a proposal to succeed.
+ string threshold = 1;
+
+ // voting_period is the duration from submission of a proposal to the end of voting period
+ // Within this period, votes and exec messages can be submitted.
+ google.protobuf.Duration voting_period = 2 [(gogoproto.nullable) = false];
+}
+```
+
+### Proposal
+
+Any member of a group can submit a proposal for a group account to decide upon.
+A proposal consists of a set of `sdk.Msg`s that will be executed if the proposal
+passes as well as any metadata associated with the proposal. These `sdk.Msg`s get validated as part of the `Msg/CreateProposal` request validation. They should also have their signer set as the group account.
+
+Internally, a proposal also tracks:
+- its current `Status`: submitted, closed or aborted
+- its `Result`: unfinalized, accepted or rejected
+- its `VoteState` in the form of a `Tally`, which is calculated on new votes and when executing the proposal.
+
+```proto
+// Tally represents the sum of weighted votes.
+message Tally {
+ option (gogoproto.goproto_getters) = false;
+
+ // yes_count is the weighted sum of yes votes.
+ string yes_count = 1;
+
+ // no_count is the weighted sum of no votes.
+ string no_count = 2;
+
+ // abstain_count is the weighted sum of abstainers.
+ string abstain_count = 3;
+
+ // veto_count is the weighted sum of vetoes.
+ string veto_count = 4;
+}
+```
+
+### Voting
+
+Members of a group can vote on proposals. There are four choices to choose while voting - yes, no, abstain and veto. Not
+all decision policies will support them. Votes can contain some optional metadata.
+In the current implementation, the voting window begins as soon as a proposal
+is submitted.
+
+Voting internally updates the proposal `VoteState` as well as `Status` and `Result` if needed.
+
+### Executing Proposals
+
+Proposals will not be automatically executed by the chain in this current design,
+but rather a user must submit a `Msg/Exec` transaction to attempt to execute the
+proposal based on the current votes and decision policy. A future upgrade could
+automate this and have the group account (or a fee granter) pay.
+
+#### Changing Group Membership
+
+In the current implementation, updating a group or a group account after submitting a proposal will make it invalid. It will simply fail if someone calls `Msg/Exec` and will eventually be garbage collected.
+
+### Notes on current implementation
+
+This section outlines the current implementation used in the proof of concept of the group module but this could be subject to changes and iterated on.
+
+#### ORM
+
+The [ORM package](https://github.com/cosmos/cosmos-sdk/discussions/9156) defines tables, sequences and secondary indexes which are used in the group module.
+
+Groups are stored in state as part of a `groupTable`, the `group_id` being an auto-increment integer. Group members are stored in a `groupMemberTable`.
+
+Group accounts are stored in a `groupAccountTable`. The group account address is generated based on an auto-increment integer which is used to derive the group module `RootModuleKey` into a `DerivedModuleKey`, as stated in [ADR-033](adr-033-protobuf-inter-module-comm.md#modulekeys-and-moduleids). The group account is added as a new `ModuleAccount` through `x/auth`.
+
+Proposals are stored as part of the `proposalTable` using the `Proposal` type. The `proposal_id` is an auto-increment integer.
+
+Votes are stored in the `voteTable`. The primary key is based on the vote's `proposal_id` and `voter` account address.
+
+#### ADR-033 to route proposal messages
+
+Inter-module communication introduced by [ADR-033](adr-033-protobuf-inter-module-comm.md) can be used to route a proposal's messages using the `DerivedModuleKey` corresponding to the proposal's group account.
+
+## Consequences
+
+### Positive
+
+- Improved UX for multi-signature accounts allowing key rotation and custom decision policies.
+
+### Negative
+
+### Neutral
+
+- It uses ADR 033 so it will need to be implemented within the Cosmos SDK, but this doesn't imply necessarily any large refactoring of existing Cosmos SDK modules.
+- The current implementation of the group module uses the ORM package.
+
+## Further Discussions
+
+- Convergence of `/group` and `x/gov` as both support proposals and voting: https://github.com/cosmos/cosmos-sdk/discussions/9066
+- `x/group` possible future improvements:
+ - Execute proposals on submission (https://github.com/regen-network/regen-ledger/issues/288)
+ - Withdraw a proposal (https://github.com/regen-network/cosmos-modules/issues/41)
+ - Make `Tally` more flexible and support non-binary choices
+
+## References
+
+- Initial specification:
+ - https://gist.github.com/aaronc/b60628017352df5983791cad30babe56#group-module
+ - [#5236](https://github.com/cosmos/cosmos-sdk/pull/5236)
+- Proposal to add `x/group` into the SDK: [#7633](https://github.com/cosmos/cosmos-sdk/issues/7633)
diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md
index d8b85efe7b..254ce496c8 100644
--- a/docs/core/proto-docs.md
+++ b/docs/core/proto-docs.md
@@ -1323,8 +1323,7 @@ account with the provided expiration time.
| ----- | ---- | ----- | ----------- |
| `granter` | [string](#string) | | |
| `grantee` | [string](#string) | | |
-| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | |
-| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | |
+| `grant` | [Grant](#cosmos.authz.v1beta1.Grant) | | |
@@ -6183,9 +6182,9 @@ AuthorizationType defines the type of staking module authorization type
| Name | Number | Description |
| ---- | ------ | ----------- |
| AUTHORIZATION_TYPE_UNSPECIFIED | 0 | AUTHORIZATION_TYPE_UNSPECIFIED specifies an unknown authorization type |
-| AUTHORIZATION_TYPE_DELEGATE | 1 | AUTHORIZATION_TYPE_DELEGATE defines an authorization type for Msg/Delegate |
-| AUTHORIZATION_TYPE_UNDELEGATE | 2 | AUTHORIZATION_TYPE_UNDELEGATE defines an authorization type for Msg/Undelegate |
-| AUTHORIZATION_TYPE_REDELEGATE | 3 | AUTHORIZATION_TYPE_REDELEGATE defines an authorization type for Msg/BeginRedelegate |
+| AUTHORIZATION_TYPE_DELEGATE | 1 | AUTHORIZATION_TYPE_DELEGATE defines an authorization type for MsgDelegate |
+| AUTHORIZATION_TYPE_UNDELEGATE | 2 | AUTHORIZATION_TYPE_UNDELEGATE defines an authorization type for MsgUndelegate |
+| AUTHORIZATION_TYPE_REDELEGATE | 3 | AUTHORIZATION_TYPE_REDELEGATE defines an authorization type for MsgBeginRedelegate |
@@ -7168,7 +7167,7 @@ of coins from a delegator and source validator to a destination validator.
### MsgBeginRedelegateResponse
-MsgBeginRedelegateResponse defines the Msg/BeginRedelegate response type.
+MsgBeginRedelegateResponse defines the MsgBeginRedelegate response type.
| Field | Type | Label | Description |
@@ -7204,7 +7203,7 @@ MsgCreateValidator defines a SDK message for creating a new validator.
### MsgCreateValidatorResponse
-MsgCreateValidatorResponse defines the Msg/CreateValidator response type.
+MsgCreateValidatorResponse defines the MsgCreateValidator response type.
@@ -7232,7 +7231,7 @@ from a delegator to a validator.
### MsgDelegateResponse
-MsgDelegateResponse defines the Msg/Delegate response type.
+MsgDelegateResponse defines the MsgDelegate response type.
@@ -7260,7 +7259,7 @@ MsgEditValidator defines a SDK message for editing an existing validator.
### MsgEditValidatorResponse
-MsgEditValidatorResponse defines the Msg/EditValidator response type.
+MsgEditValidatorResponse defines the MsgEditValidator response type.
@@ -7288,7 +7287,7 @@ delegate and a validator.
### MsgUndelegateResponse
-MsgUndelegateResponse defines the Msg/Undelegate response type.
+MsgUndelegateResponse defines the MsgUndelegate response type.
| Field | Type | Label | Description |
diff --git a/go.mod b/go.mod
index 4ee3d42a96..bc23379ef6 100644
--- a/go.mod
+++ b/go.mod
@@ -30,7 +30,7 @@ require (
github.com/jhump/protoreflect v1.8.2
github.com/magiconair/properties v1.8.5
github.com/mattn/go-isatty v0.0.12
- github.com/otiai10/copy v1.5.1
+ github.com/otiai10/copy v1.6.0
github.com/pelletier/go-toml v1.8.1 // indirect
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.10.0
diff --git a/go.sum b/go.sum
index 6bad6bbff0..e76a4a0baa 100644
--- a/go.sum
+++ b/go.sum
@@ -512,8 +512,8 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
-github.com/otiai10/copy v1.5.1 h1:a/cs2E1/1V0az8K5nblbl+ymEa4E11AfaOLMar8V34w=
-github.com/otiai10/copy v1.5.1/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E=
+github.com/otiai10/copy v1.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ=
+github.com/otiai10/copy v1.6.0/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI=
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
diff --git a/proto/cosmos/authz/v1beta1/tx.proto b/proto/cosmos/authz/v1beta1/tx.proto
index 8a2aaf76a7..472b81a0e4 100644
--- a/proto/cosmos/authz/v1beta1/tx.proto
+++ b/proto/cosmos/authz/v1beta1/tx.proto
@@ -6,6 +6,7 @@ import "gogoproto/gogo.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/any.proto";
import "cosmos/base/abci/v1beta1/abci.proto";
+import "cosmos/authz/v1beta1/authz.proto";
option go_package = "github.com/cosmos/cosmos-sdk/x/authz";
option (gogoproto.goproto_getters_all) = false;
@@ -32,8 +33,7 @@ message MsgGrant {
string granter = 1;
string grantee = 2;
- google.protobuf.Any authorization = 3 [(cosmos_proto.accepts_interface) = "Authorization"];
- google.protobuf.Timestamp expiration = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
+ cosmos.authz.v1beta1.Grant grant = 3 [(gogoproto.nullable) = false];
}
// MsgExecResponse defines the Msg/MsgExecResponse response type.
diff --git a/proto/cosmos/bank/v1beta1/bank.proto b/proto/cosmos/bank/v1beta1/bank.proto
index 1a4cc289ea..eb843b2cb6 100644
--- a/proto/cosmos/bank/v1beta1/bank.proto
+++ b/proto/cosmos/bank/v1beta1/bank.proto
@@ -52,7 +52,7 @@ message Supply {
option (gogoproto.equal) = true;
option (gogoproto.goproto_getters) = false;
- option (cosmos_proto.implements_interface) = "*github.com/cosmos/cosmos-sdk/x/bank/exported.SupplyI";
+ option (cosmos_proto.implements_interface) = "*github.com/cosmos/cosmos-sdk/x/bank/legacy/v040.SupplyI";
repeated cosmos.base.v1beta1.Coin total = 1
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
diff --git a/x/auth/vesting/msg_server.go b/x/auth/vesting/msg_server.go
index dadd65dbcf..795fc2c605 100644
--- a/x/auth/vesting/msg_server.go
+++ b/x/auth/vesting/msg_server.go
@@ -32,7 +32,7 @@ func (s msgServer) CreateVestingAccount(goCtx context.Context, msg *types.MsgCre
ak := s.AccountKeeper
bk := s.BankKeeper
- if err := bk.SendEnabledCoins(ctx, msg.Amount...); err != nil {
+ if err := bk.IsSendEnabledCoins(ctx, msg.Amount...); err != nil {
return nil, err
}
diff --git a/x/auth/vesting/types/expected_keepers.go b/x/auth/vesting/types/expected_keepers.go
index 8212f6e375..5705eea30b 100644
--- a/x/auth/vesting/types/expected_keepers.go
+++ b/x/auth/vesting/types/expected_keepers.go
@@ -7,7 +7,7 @@ import (
// BankKeeper defines the expected interface contract the vesting module requires
// for creating vesting accounts with funds.
type BankKeeper interface {
- SendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
+ IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
BlockedAddr(addr sdk.AccAddress) bool
}
diff --git a/x/authz/authorization_grant.go b/x/authz/authorization_grant.go
index 8a5995c5d0..f5ebf8797b 100644
--- a/x/authz/authorization_grant.go
+++ b/x/authz/authorization_grant.go
@@ -9,24 +9,23 @@ import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
-// NewGrant returns new AuthrizationGrant
-func NewGrant(authorization Authorization, expiration time.Time) (Grant, error) {
- auth := Grant{
+// NewGrant returns new Grant
+func NewGrant(a Authorization, expiration time.Time) (Grant, error) {
+ g := Grant{
Expiration: expiration,
}
- msg, ok := authorization.(proto.Message)
+ msg, ok := a.(proto.Message)
if !ok {
- return Grant{}, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", authorization)
+ return Grant{}, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", a)
}
any, err := cdctypes.NewAnyWithValue(msg)
if err != nil {
return Grant{}, err
}
+ g.Authorization = any
- auth.Authorization = any
-
- return auth, nil
+ return g, nil
}
var (
@@ -34,16 +33,32 @@ var (
)
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
-func (auth Grant) UnpackInterfaces(unpacker cdctypes.AnyUnpacker) error {
+func (g Grant) UnpackInterfaces(unpacker cdctypes.AnyUnpacker) error {
var authorization Authorization
- return unpacker.UnpackAny(auth.Authorization, &authorization)
+ return unpacker.UnpackAny(g.Authorization, &authorization)
}
// GetAuthorization returns the cached value from the Grant.Authorization if present.
-func (auth Grant) GetAuthorization() Authorization {
- authorization, ok := auth.Authorization.GetCachedValue().(Authorization)
+func (g Grant) GetAuthorization() Authorization {
+ if g.Authorization == nil {
+ return nil
+ }
+ a, ok := g.Authorization.GetCachedValue().(Authorization)
if !ok {
return nil
}
- return authorization
+ return a
+}
+
+func (g Grant) ValidateBasic() error {
+ if g.Expiration.Unix() < time.Now().Unix() {
+ return sdkerrors.Wrap(ErrInvalidExpirationTime, "Time can't be in the past")
+ }
+
+ av := g.Authorization.GetCachedValue()
+ a, ok := av.(Authorization)
+ if !ok {
+ return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expected %T, got %T", (Authorization)(nil), av)
+ }
+ return a.ValidateBasic()
}
diff --git a/x/authz/keeper/msg_server.go b/x/authz/keeper/msg_server.go
index 0ade948821..0d96599087 100644
--- a/x/authz/keeper/msg_server.go
+++ b/x/authz/keeper/msg_server.go
@@ -31,7 +31,7 @@ func (k Keeper) Grant(goCtx context.Context, msg *authz.MsgGrant) (*authz.MsgGra
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "%s doesn't exist.", t)
}
- err = k.SaveGrant(ctx, grantee, granter, authorization, msg.Expiration)
+ err = k.SaveGrant(ctx, grantee, granter, authorization, msg.Grant.Expiration)
if err != nil {
return nil, err
}
diff --git a/x/authz/msgs.go b/x/authz/msgs.go
index a747d2c7a5..dd6bc8b19d 100644
--- a/x/authz/msgs.go
+++ b/x/authz/msgs.go
@@ -23,9 +23,9 @@ var (
//nolint:interfacer
func NewMsgGrant(granter sdk.AccAddress, grantee sdk.AccAddress, a Authorization, expiration time.Time) (*MsgGrant, error) {
m := &MsgGrant{
- Granter: granter.String(),
- Grantee: grantee.String(),
- Expiration: expiration,
+ Granter: granter.String(),
+ Grantee: grantee.String(),
+ Grant: Grant{Expiration: expiration},
}
err := m.SetAuthorization(a)
if err != nil {
@@ -57,26 +57,12 @@ func (msg MsgGrant) ValidateBasic() error {
if granter.Equals(grantee) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "granter and grantee cannot be same")
}
-
- if msg.Expiration.Unix() < time.Now().Unix() {
- return sdkerrors.Wrap(ErrInvalidExpirationTime, "Time can't be in the past")
- }
-
- av := msg.Authorization.GetCachedValue()
- a, ok := av.(Authorization)
- if !ok {
- return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expected %T, got %T", (Authorization)(nil), av)
- }
- return a.ValidateBasic()
+ return msg.Grant.ValidateBasic()
}
// GetAuthorization returns the cache value from the MsgGrant.Authorization if present.
func (msg *MsgGrant) GetAuthorization() Authorization {
- a, ok := msg.Authorization.GetCachedValue().(Authorization)
- if !ok {
- return nil
- }
- return a
+ return msg.Grant.GetAuthorization()
}
// SetAuthorization converts Authorization to any and adds it to MsgGrant.Authorization.
@@ -89,7 +75,7 @@ func (msg *MsgGrant) SetAuthorization(a Authorization) error {
if err != nil {
return err
}
- msg.Authorization = any
+ msg.Grant.Authorization = any
return nil
}
@@ -108,8 +94,7 @@ func (msg MsgExec) UnpackInterfaces(unpacker cdctypes.AnyUnpacker) error {
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (msg MsgGrant) UnpackInterfaces(unpacker cdctypes.AnyUnpacker) error {
- var a Authorization
- return unpacker.UnpackAny(msg.Authorization, &a)
+ return msg.Grant.UnpackInterfaces(unpacker)
}
// NewMsgRevoke creates a new MsgRevoke
diff --git a/x/authz/msgs_test.go b/x/authz/msgs_test.go
index 0d9ad12c44..7a41c1befb 100644
--- a/x/authz/msgs_test.go
+++ b/x/authz/msgs_test.go
@@ -6,6 +6,7 @@ import (
"github.com/stretchr/testify/require"
+ cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/authz"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
@@ -97,3 +98,20 @@ func TestMsgGrantAuthorization(t *testing.T) {
}
}
}
+
+func TestMsgGrantGetAuthorization(t *testing.T) {
+ require := require.New(t)
+
+ m := authz.MsgGrant{}
+ require.Nil(m.GetAuthorization())
+
+ g := authz.GenericAuthorization{Msg: "some_type"}
+ var err error
+ m.Grant.Authorization, err = cdctypes.NewAnyWithValue(&g)
+ require.NoError(err)
+ require.Equal(m.GetAuthorization(), &g)
+
+ g = authz.GenericAuthorization{Msg: "some_type2"}
+ m.SetAuthorization(&g)
+ require.Equal(m.GetAuthorization(), &g)
+}
diff --git a/x/authz/tx.pb.go b/x/authz/tx.pb.go
index 7042d70173..69e9fd72c7 100644
--- a/x/authz/tx.pb.go
+++ b/x/authz/tx.pb.go
@@ -6,12 +6,11 @@ package authz
import (
context "context"
fmt "fmt"
- types "github.com/cosmos/cosmos-sdk/codec/types"
- types1 "github.com/cosmos/cosmos-sdk/types"
+ types1 "github.com/cosmos/cosmos-sdk/codec/types"
+ types "github.com/cosmos/cosmos-sdk/types"
_ "github.com/gogo/protobuf/gogoproto"
grpc1 "github.com/gogo/protobuf/grpc"
proto "github.com/gogo/protobuf/proto"
- github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
_ "github.com/regen-network/cosmos-proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
@@ -20,14 +19,12 @@ import (
io "io"
math "math"
math_bits "math/bits"
- time "time"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
-var _ = time.Kitchen
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
@@ -38,10 +35,9 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// MsgGrant grants the provided authorization to the grantee on the granter's
// account with the provided expiration time.
type MsgGrant struct {
- Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"`
- Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"`
- Authorization *types.Any `protobuf:"bytes,3,opt,name=authorization,proto3" json:"authorization,omitempty"`
- Expiration time.Time `protobuf:"bytes,4,opt,name=expiration,proto3,stdtime" json:"expiration"`
+ Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"`
+ Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"`
+ Grant Grant `protobuf:"bytes,3,opt,name=grant,proto3" json:"grant"`
}
func (m *MsgGrant) Reset() { *m = MsgGrant{} }
@@ -79,7 +75,7 @@ var xxx_messageInfo_MsgGrant proto.InternalMessageInfo
// MsgExecResponse defines the Msg/MsgExecResponse response type.
type MsgExecResponse struct {
- Result *types1.Result `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"`
+ Result *types.Result `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"`
}
func (m *MsgExecResponse) Reset() { *m = MsgExecResponse{} }
@@ -123,7 +119,7 @@ type MsgExec struct {
// Authorization Msg requests to execute. Each msg must implement Authorization interface
// The x/authz will try to find a grant matching (msg.signers[0], grantee, MsgTypeURL(msg))
// triple and validate it.
- Msgs []*types.Any `protobuf:"bytes,2,rep,name=msgs,proto3" json:"msgs,omitempty"`
+ Msgs []*types1.Any `protobuf:"bytes,2,rep,name=msgs,proto3" json:"msgs,omitempty"`
}
func (m *MsgExec) Reset() { *m = MsgExec{} }
@@ -286,40 +282,39 @@ func init() {
func init() { proto.RegisterFile("cosmos/authz/v1beta1/tx.proto", fileDescriptor_3ceddab7d8589ad1) }
var fileDescriptor_3ceddab7d8589ad1 = []byte{
- // 523 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x4d, 0x6f, 0xd3, 0x30,
- 0x18, 0xae, 0xd7, 0xd2, 0xad, 0xef, 0x98, 0x60, 0xa1, 0x87, 0x2e, 0x62, 0x69, 0x14, 0xbe, 0x76,
- 0xa0, 0x8e, 0x56, 0x2e, 0x5c, 0x57, 0x81, 0x90, 0x80, 0x08, 0x29, 0x1a, 0x17, 0x2e, 0x55, 0xd2,
- 0x19, 0x2f, 0x6a, 0x13, 0x47, 0xb1, 0x33, 0xb5, 0xfb, 0x15, 0xfb, 0x31, 0xfb, 0x11, 0xd5, 0x4e,
- 0x93, 0xb8, 0x70, 0xe2, 0xa3, 0xfd, 0x13, 0x1c, 0x51, 0x6c, 0xa7, 0xb4, 0x40, 0x87, 0xc4, 0xa9,
- 0x7e, 0xfd, 0x3c, 0x7e, 0xfc, 0xf8, 0x79, 0xdf, 0x06, 0xf6, 0x07, 0x8c, 0xc7, 0x8c, 0xbb, 0x41,
- 0x2e, 0x4e, 0xcf, 0xdd, 0xb3, 0xc3, 0x90, 0x88, 0xe0, 0xd0, 0x15, 0x63, 0x9c, 0x66, 0x4c, 0x30,
- 0xa3, 0xa9, 0x60, 0x2c, 0x61, 0xac, 0x61, 0x73, 0x4f, 0xed, 0xf6, 0x25, 0xc7, 0xd5, 0x14, 0x59,
- 0x98, 0x4d, 0xca, 0x28, 0x53, 0xfb, 0xc5, 0x4a, 0xef, 0xb6, 0x29, 0x63, 0x74, 0x44, 0x5c, 0x59,
- 0x85, 0xf9, 0x47, 0x57, 0x44, 0x31, 0xe1, 0x22, 0x88, 0x53, 0x4d, 0xd8, 0xfb, 0x9d, 0x10, 0x24,
- 0x13, 0x0d, 0x3d, 0xd0, 0x0e, 0xc3, 0x80, 0x13, 0x37, 0x08, 0x07, 0xd1, 0xc2, 0x65, 0x51, 0x28,
- 0x92, 0xf3, 0x09, 0xc1, 0x96, 0xc7, 0xe9, 0xab, 0x2c, 0x48, 0x84, 0xd1, 0x82, 0x4d, 0x5a, 0x2c,
- 0x48, 0xd6, 0x42, 0x36, 0x3a, 0x68, 0xf8, 0x65, 0xf9, 0x0b, 0x21, 0xad, 0x8d, 0x65, 0x84, 0x18,
- 0x1e, 0xec, 0x14, 0x6f, 0x64, 0x59, 0x74, 0x1e, 0x88, 0x88, 0x25, 0xad, 0xaa, 0x8d, 0x0e, 0xb6,
- 0xbb, 0x4d, 0xac, 0x8c, 0xe1, 0xd2, 0x18, 0x3e, 0x4a, 0x26, 0xbd, 0xdd, 0xab, 0xcb, 0xce, 0xce,
- 0xd1, 0x32, 0xdd, 0x5f, 0x3d, 0x6d, 0xbc, 0x00, 0x20, 0xe3, 0x34, 0xca, 0x94, 0x56, 0x4d, 0x6a,
- 0x99, 0x7f, 0x68, 0x1d, 0x97, 0x29, 0xf4, 0xb6, 0xa6, 0x5f, 0xda, 0x95, 0x8b, 0xaf, 0x6d, 0xe4,
- 0x2f, 0x9d, 0x73, 0xde, 0xc0, 0x1d, 0x8f, 0xd3, 0x97, 0x63, 0x32, 0xf0, 0x09, 0x4f, 0x59, 0xc2,
- 0x89, 0xf1, 0x1c, 0xea, 0x19, 0xe1, 0xf9, 0x48, 0xc8, 0xa7, 0x6d, 0x77, 0x6d, 0xac, 0xe3, 0x2f,
- 0xe2, 0xc1, 0x32, 0x11, 0x1d, 0x0f, 0xf6, 0x25, 0xcf, 0xd7, 0x7c, 0x87, 0xc1, 0xa6, 0x16, 0x5b,
- 0x8e, 0x01, 0xad, 0xc6, 0xf0, 0x1a, 0x6a, 0x31, 0xa7, 0xbc, 0xb5, 0x61, 0x57, 0xd7, 0xbe, 0xde,
- 0xbe, 0xba, 0xec, 0xdc, 0xe7, 0x27, 0x43, 0xec, 0x71, 0xfa, 0xd4, 0x56, 0x93, 0xb1, 0x1a, 0x86,
- 0xd4, 0x70, 0x0c, 0xb8, 0x5b, 0xb6, 0xa4, 0xb4, 0xef, 0x04, 0xd0, 0xf0, 0x38, 0xf5, 0xc9, 0x19,
- 0x1b, 0x92, 0xff, 0xea, 0x93, 0x0d, 0xb7, 0x63, 0x4e, 0xfb, 0x62, 0x92, 0x92, 0x7e, 0x9e, 0x8d,
- 0x64, 0x9b, 0x1a, 0x3e, 0xc4, 0x9c, 0x1e, 0x4f, 0x52, 0xf2, 0x3e, 0x1b, 0x39, 0xf7, 0x60, 0x77,
- 0x71, 0x45, 0x79, 0x6f, 0xf7, 0x07, 0x82, 0xaa, 0xc7, 0xa9, 0xf1, 0x0e, 0x6e, 0xa9, 0x19, 0xb1,
- 0xf0, 0xdf, 0x26, 0x1b, 0x97, 0x86, 0xcd, 0xc7, 0x37, 0xe3, 0x8b, 0x7e, 0xbc, 0x85, 0x9a, 0x8c,
- 0x74, 0x7f, 0x2d, 0xbf, 0x80, 0xcd, 0x47, 0x37, 0xc2, 0x0b, 0x35, 0x1f, 0xea, 0x3a, 0x9b, 0xf6,
- 0xda, 0x03, 0x8a, 0x60, 0x3e, 0xf9, 0x07, 0xa1, 0xd4, 0xec, 0xf5, 0xa6, 0xdf, 0xad, 0xca, 0x74,
- 0x66, 0xa1, 0xeb, 0x99, 0x85, 0xbe, 0xcd, 0x2c, 0x74, 0x31, 0xb7, 0x2a, 0xd7, 0x73, 0xab, 0xf2,
- 0x79, 0x6e, 0x55, 0x3e, 0x3c, 0xa4, 0x91, 0x38, 0xcd, 0x43, 0x3c, 0x60, 0xb1, 0xfe, 0x23, 0xeb,
- 0x9f, 0x0e, 0x3f, 0x19, 0xba, 0x63, 0xf5, 0x5d, 0x08, 0xeb, 0x72, 0x00, 0x9e, 0xfd, 0x0c, 0x00,
- 0x00, 0xff, 0xff, 0x5b, 0x69, 0x39, 0xef, 0x2e, 0x04, 0x00, 0x00,
+ // 498 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0xcb, 0x6e, 0xd3, 0x40,
+ 0x14, 0xb5, 0x9b, 0x34, 0x25, 0x13, 0x24, 0xc0, 0x64, 0xe1, 0x1a, 0xea, 0x58, 0xe6, 0x95, 0x05,
+ 0x1d, 0xab, 0x61, 0x01, 0xdb, 0x46, 0x42, 0x48, 0x80, 0x85, 0x64, 0xc1, 0x86, 0x4d, 0x64, 0xa7,
+ 0xc3, 0xc4, 0x4a, 0xec, 0xb1, 0x7c, 0xc7, 0x25, 0xe9, 0x57, 0xf0, 0x31, 0x7c, 0x44, 0xc4, 0xaa,
+ 0x4b, 0x56, 0x08, 0x92, 0x9f, 0x60, 0x89, 0x3c, 0x8f, 0x50, 0x50, 0x5a, 0x24, 0x56, 0x99, 0x3b,
+ 0xe7, 0xe4, 0xdc, 0x73, 0xcf, 0xf5, 0xa0, 0x83, 0x31, 0x83, 0x8c, 0x41, 0x10, 0x57, 0x7c, 0x72,
+ 0x16, 0x9c, 0x1e, 0x25, 0x84, 0xc7, 0x47, 0x01, 0x9f, 0xe3, 0xa2, 0x64, 0x9c, 0x59, 0x5d, 0x09,
+ 0x63, 0x01, 0x63, 0x05, 0x3b, 0xfb, 0xf2, 0x76, 0x24, 0x38, 0x81, 0xa2, 0x88, 0xc2, 0xe9, 0x52,
+ 0x46, 0x99, 0xbc, 0xaf, 0x4f, 0xea, 0xb6, 0x47, 0x19, 0xa3, 0x33, 0x12, 0x88, 0x2a, 0xa9, 0x3e,
+ 0x04, 0x3c, 0xcd, 0x08, 0xf0, 0x38, 0x2b, 0x14, 0x61, 0xff, 0x6f, 0x42, 0x9c, 0x2f, 0x14, 0x74,
+ 0x4f, 0x39, 0x4c, 0x62, 0x20, 0x41, 0x9c, 0x8c, 0xd3, 0x8d, 0xcb, 0xba, 0x50, 0x24, 0x6f, 0xeb,
+ 0x18, 0xd2, 0xb5, 0x60, 0xf8, 0x1f, 0xd1, 0xb5, 0x10, 0xe8, 0x8b, 0x32, 0xce, 0xb9, 0x65, 0xa3,
+ 0x3d, 0x5a, 0x1f, 0x48, 0x69, 0x9b, 0x9e, 0xd9, 0x6f, 0x47, 0xba, 0xfc, 0x8d, 0x10, 0x7b, 0xe7,
+ 0x22, 0x42, 0xac, 0xa7, 0x68, 0x57, 0x1c, 0xed, 0x86, 0x67, 0xf6, 0x3b, 0x83, 0x3b, 0x78, 0x5b,
+ 0x32, 0x58, 0xe8, 0x0f, 0x9b, 0xcb, 0x6f, 0x3d, 0x23, 0x92, 0x7c, 0xff, 0x15, 0xba, 0x11, 0x02,
+ 0x7d, 0x3e, 0x27, 0xe3, 0x88, 0x40, 0xc1, 0x72, 0x20, 0xd6, 0x33, 0xd4, 0x2a, 0x09, 0x54, 0x33,
+ 0x2e, 0xda, 0x77, 0x06, 0x9e, 0x16, 0xab, 0x67, 0xc4, 0x62, 0x2c, 0x2d, 0x18, 0x09, 0x5e, 0xa4,
+ 0xf8, 0x3e, 0x43, 0x7b, 0x4a, 0xec, 0xa2, 0x55, 0xf3, 0x4f, 0xab, 0x2f, 0x51, 0x33, 0x03, 0x0a,
+ 0xf6, 0x8e, 0xd7, 0xe8, 0x77, 0x06, 0x5d, 0x2c, 0xb3, 0xc5, 0x3a, 0x5b, 0x7c, 0x9c, 0x2f, 0x86,
+ 0xde, 0x97, 0xcf, 0x87, 0x77, 0xe1, 0x64, 0x8a, 0x43, 0xa0, 0x8f, 0x3d, 0x39, 0xc4, 0x71, 0xc5,
+ 0x27, 0xac, 0x4c, 0xcf, 0x62, 0x9e, 0xb2, 0x3c, 0x12, 0x1a, 0xbe, 0x85, 0x6e, 0xea, 0xd8, 0xb4,
+ 0x7d, 0x3f, 0x46, 0xed, 0x10, 0x68, 0x44, 0x4e, 0xd9, 0x94, 0xfc, 0x57, 0x96, 0x1e, 0xba, 0x9e,
+ 0x01, 0x1d, 0xf1, 0x45, 0x41, 0x46, 0x55, 0x39, 0x13, 0x91, 0xb6, 0x23, 0x94, 0x01, 0x7d, 0xbb,
+ 0x28, 0xc8, 0xbb, 0x72, 0xe6, 0xdf, 0x46, 0xb7, 0x36, 0x2d, 0x74, 0xdf, 0xc1, 0x4f, 0x13, 0x35,
+ 0x42, 0xa0, 0xd6, 0x1b, 0xb4, 0x2b, 0xf7, 0xe8, 0x6e, 0x5f, 0x82, 0x36, 0xec, 0x3c, 0xbc, 0x1a,
+ 0xdf, 0xec, 0xe3, 0x35, 0x6a, 0x8a, 0x48, 0x0f, 0x2e, 0xe5, 0xd7, 0xb0, 0xf3, 0xe0, 0x4a, 0x78,
+ 0xa3, 0x16, 0xa1, 0x96, 0xca, 0xa6, 0x77, 0xe9, 0x1f, 0x24, 0xc1, 0x79, 0xf4, 0x0f, 0x82, 0xd6,
+ 0x1c, 0x0e, 0x97, 0x3f, 0x5c, 0x63, 0xb9, 0x72, 0xcd, 0xf3, 0x95, 0x6b, 0x7e, 0x5f, 0xb9, 0xe6,
+ 0xa7, 0xb5, 0x6b, 0x9c, 0xaf, 0x5d, 0xe3, 0xeb, 0xda, 0x35, 0xde, 0xdf, 0xa7, 0x29, 0x9f, 0x54,
+ 0x09, 0x1e, 0xb3, 0x4c, 0xbd, 0x46, 0xf5, 0x73, 0x08, 0x27, 0xd3, 0x60, 0x2e, 0xdf, 0x41, 0xd2,
+ 0x12, 0x1f, 0xc0, 0x93, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x4a, 0xa9, 0xb0, 0x59, 0xf3, 0x03,
+ 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -508,26 +503,16 @@ func (m *MsgGrant) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
- n1, err1 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Expiration, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Expiration):])
- if err1 != nil {
- return 0, err1
- }
- i -= n1
- i = encodeVarintTx(dAtA, i, uint64(n1))
- i--
- dAtA[i] = 0x22
- if m.Authorization != nil {
- {
- size, err := m.Authorization.MarshalToSizedBuffer(dAtA[:i])
- if err != nil {
- return 0, err
- }
- i -= size
- i = encodeVarintTx(dAtA, i, uint64(size))
+ {
+ size, err := m.Grant.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
}
- i--
- dAtA[i] = 0x1a
+ i -= size
+ i = encodeVarintTx(dAtA, i, uint64(size))
}
+ i--
+ dAtA[i] = 0x1a
if len(m.Grantee) > 0 {
i -= len(m.Grantee)
copy(dAtA[i:], m.Grantee)
@@ -739,11 +724,7 @@ func (m *MsgGrant) Size() (n int) {
if l > 0 {
n += 1 + l + sovTx(uint64(l))
}
- if m.Authorization != nil {
- l = m.Authorization.Size()
- n += 1 + l + sovTx(uint64(l))
- }
- l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Expiration)
+ l = m.Grant.Size()
n += 1 + l + sovTx(uint64(l))
return n
}
@@ -920,7 +901,7 @@ func (m *MsgGrant) Unmarshal(dAtA []byte) error {
iNdEx = postIndex
case 3:
if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Authorization", wireType)
+ return fmt.Errorf("proto: wrong wireType = %d for field Grant", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
@@ -947,43 +928,7 @@ func (m *MsgGrant) Unmarshal(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
- if m.Authorization == nil {
- m.Authorization = &types.Any{}
- }
- if err := m.Authorization.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
- iNdEx = postIndex
- case 4:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Expiration", wireType)
- }
- var msglen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowTx
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- msglen |= int(b&0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if msglen < 0 {
- return ErrInvalidLengthTx
- }
- postIndex := iNdEx + msglen
- if postIndex < 0 {
- return ErrInvalidLengthTx
- }
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Expiration, dAtA[iNdEx:postIndex]); err != nil {
+ if err := m.Grant.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
@@ -1067,7 +1012,7 @@ func (m *MsgExecResponse) Unmarshal(dAtA []byte) error {
return io.ErrUnexpectedEOF
}
if m.Result == nil {
- m.Result = &types1.Result{}
+ m.Result = &types.Result{}
}
if err := m.Result.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
@@ -1184,7 +1129,7 @@ func (m *MsgExec) Unmarshal(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
- m.Msgs = append(m.Msgs, &types.Any{})
+ m.Msgs = append(m.Msgs, &types1.Any{})
if err := m.Msgs[len(m.Msgs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
diff --git a/x/bank/atlas/atlas-v0.39.1.md b/x/bank/atlas/atlas-v0.39.1.md
index affca5b9e2..cc7a75d951 100644
--- a/x/bank/atlas/atlas-v0.39.1.md
+++ b/x/bank/atlas/atlas-v0.39.1.md
@@ -35,14 +35,14 @@ with particular kinds of accounts.
```
4. Create the keeper. Note, the `x/bank` module depends on the `x/auth` module
- and a list of blacklisted account addresses which funds are not allowed to be
+ and a list of blocklisted account addresses which funds are not allowed to be
sent to. Your application will need to define this method based your needs.
```go
func NewApp(...) *App {
// ...
app.BankKeeper = bank.NewBaseKeeper(
- app.AccountKeeper, app.subspaces[bank.ModuleName], app.BlacklistedAccAddrs(),
+ app.AccountKeeper, app.subspaces[bank.ModuleName], app.BlocklistedAccAddrs(),
)
}
```
diff --git a/x/bank/keeper/keeper.go b/x/bank/keeper/keeper.go
index c02b11a17e..cc8ded2401 100644
--- a/x/bank/keeper/keeper.go
+++ b/x/bank/keeper/keeper.go
@@ -55,6 +55,7 @@ type BaseKeeper struct {
paramSpace paramtypes.Subspace
}
+// GetPaginatedTotalSupply queries for the supply, ignoring 0 coins, with a given pagination
func (k BaseKeeper) GetPaginatedTotalSupply(ctx sdk.Context, pagination *query.PageRequest) (sdk.Coins, *query.PageResponse, error) {
store := ctx.KVStore(k.storeKey)
supplyStore := prefix.NewStore(store, types.SupplyKey)
@@ -213,7 +214,8 @@ func (k BaseKeeper) GetSupply(ctx sdk.Context, denom string) sdk.Coin {
}
}
-// GetDenomMetaData retrieves the denomination metadata
+// GetDenomMetaData retrieves the denomination metadata. returns the metadata and true if the denom exists,
+// false otherwise.
func (k BaseKeeper) GetDenomMetaData(ctx sdk.Context, denom string) (types.Metadata, bool) {
store := ctx.KVStore(k.storeKey)
store = prefix.NewStore(store, types.DenomMetadataKey(denom))
@@ -427,6 +429,7 @@ func (k BaseKeeper) BurnCoins(ctx sdk.Context, moduleName string, amounts sdk.Co
return nil
}
+// setSupply sets the supply for the given coin
func (k BaseKeeper) setSupply(ctx sdk.Context, coin sdk.Coin) {
intBytes, err := coin.Amount.Marshal()
if err != nil {
@@ -444,6 +447,7 @@ func (k BaseKeeper) setSupply(ctx sdk.Context, coin sdk.Coin) {
}
}
+// trackDelegation tracks the delegation of the given account if it is a vesting account
func (k BaseKeeper) trackDelegation(ctx sdk.Context, addr sdk.AccAddress, balance, amt sdk.Coins) error {
acc := k.ak.GetAccount(ctx, addr)
if acc == nil {
@@ -460,6 +464,7 @@ func (k BaseKeeper) trackDelegation(ctx sdk.Context, addr sdk.AccAddress, balanc
return nil
}
+// trackUndelegation trakcs undelegation of the given account if it is a vesting account
func (k BaseKeeper) trackUndelegation(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error {
acc := k.ak.GetAccount(ctx, addr)
if acc == nil {
@@ -476,6 +481,9 @@ func (k BaseKeeper) trackUndelegation(ctx sdk.Context, addr sdk.AccAddress, amt
return nil
}
+// IterateTotalSupply iterates over the total supply calling the given cb (callback) function
+// with the balance of each coin.
+// The iteration stops if the callback returns true.
func (k BaseViewKeeper) IterateTotalSupply(ctx sdk.Context, cb func(sdk.Coin) bool) {
store := ctx.KVStore(k.storeKey)
supplyStore := prefix.NewStore(store, types.SupplyKey)
diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go
index e20ce3e21f..e9f35b6a11 100644
--- a/x/bank/keeper/keeper_test.go
+++ b/x/bank/keeper/keeper_test.go
@@ -111,7 +111,7 @@ func (suite *IntegrationTestSuite) SetupTest() {
}
func (suite *IntegrationTestSuite) TestSupply() {
- _, ctx := suite.app, suite.ctx
+ ctx := suite.ctx
require := suite.Require()
@@ -119,7 +119,7 @@ func (suite *IntegrationTestSuite) TestSupply() {
authKeeper, keeper := suite.initKeepersWithmAccPerms(make(map[string]bool))
initialPower := int64(100)
- initTokens := suite.app.StakingKeeper.TokensFromConsensusPower(suite.ctx, initialPower)
+ initTokens := suite.app.StakingKeeper.TokensFromConsensusPower(ctx, initialPower)
totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens))
// set burnerAcc balance
@@ -140,7 +140,7 @@ func (suite *IntegrationTestSuite) TestSupply() {
require.Equal(total.String(), "")
}
-func (suite *IntegrationTestSuite) TestSendCoinsFromModuleToAccount_Blacklist() {
+func (suite *IntegrationTestSuite) TestSendCoinsFromModuleToAccount_Blocklist() {
ctx := suite.ctx
// add module accounts to supply keeper
@@ -484,11 +484,11 @@ func (suite *IntegrationTestSuite) TestSendEnabled() {
barCoin := sdk.NewCoin("barcoin", sdk.OneInt())
// assert with default (all denom) send enabled both Bar and Bond Denom are enabled
- suite.Require().Equal(enabled, app.BankKeeper.SendEnabledCoin(ctx, barCoin))
- suite.Require().Equal(enabled, app.BankKeeper.SendEnabledCoin(ctx, bondCoin))
+ suite.Require().Equal(enabled, app.BankKeeper.IsSendEnabledCoin(ctx, barCoin))
+ suite.Require().Equal(enabled, app.BankKeeper.IsSendEnabledCoin(ctx, bondCoin))
// Both coins should be send enabled.
- err := app.BankKeeper.SendEnabledCoins(ctx, fooCoin, bondCoin)
+ err := app.BankKeeper.IsSendEnabledCoins(ctx, fooCoin, bondCoin)
suite.Require().NoError(err)
// Set default send_enabled to !enabled, add a foodenom that overrides default as enabled
@@ -497,20 +497,20 @@ func (suite *IntegrationTestSuite) TestSendEnabled() {
app.BankKeeper.SetParams(ctx, params)
// Expect our specific override to be enabled, others to be !enabled.
- suite.Require().Equal(enabled, app.BankKeeper.SendEnabledCoin(ctx, fooCoin))
- suite.Require().Equal(!enabled, app.BankKeeper.SendEnabledCoin(ctx, barCoin))
- suite.Require().Equal(!enabled, app.BankKeeper.SendEnabledCoin(ctx, bondCoin))
+ suite.Require().Equal(enabled, app.BankKeeper.IsSendEnabledCoin(ctx, fooCoin))
+ suite.Require().Equal(!enabled, app.BankKeeper.IsSendEnabledCoin(ctx, barCoin))
+ suite.Require().Equal(!enabled, app.BankKeeper.IsSendEnabledCoin(ctx, bondCoin))
// Foo coin should be send enabled.
- err = app.BankKeeper.SendEnabledCoins(ctx, fooCoin)
+ err = app.BankKeeper.IsSendEnabledCoins(ctx, fooCoin)
suite.Require().NoError(err)
// Expect an error when one coin is not send enabled.
- err = app.BankKeeper.SendEnabledCoins(ctx, fooCoin, bondCoin)
+ err = app.BankKeeper.IsSendEnabledCoins(ctx, fooCoin, bondCoin)
suite.Require().Error(err)
// Expect an error when all coins are not send enabled.
- err = app.BankKeeper.SendEnabledCoins(ctx, bondCoin, barCoin)
+ err = app.BankKeeper.IsSendEnabledCoins(ctx, bondCoin, barCoin)
suite.Require().Error(err)
}
@@ -538,12 +538,9 @@ func (suite *IntegrationTestSuite) TestMsgSendEvents() {
app.AccountKeeper.SetAccount(ctx, acc)
newCoins := sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50))
+ suite.Require().NoError(simapp.FundAccount(app, ctx, addr, newCoins))
- suite.Require().Error(app.BankKeeper.SendCoins(ctx, addr, addr2, newCoins))
-
- events := ctx.EventManager().ABCIEvents()
- suite.Require().Equal(2, len(events))
-
+ suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr, addr2, newCoins))
event1 := sdk.Event{
Type: types.EventTypeTransfer,
Attributes: []abci.EventAttribute{},
@@ -570,17 +567,9 @@ func (suite *IntegrationTestSuite) TestMsgSendEvents() {
abci.EventAttribute{Key: []byte(types.AttributeKeySender), Value: []byte(addr.String())},
)
- suite.Require().Equal(abci.Event(event1), events[0])
- suite.Require().Equal(abci.Event(event2), events[1])
-
- suite.Require().NoError(simapp.FundAccount(app, ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50))))
- newCoins = sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50))
-
- suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr, addr2, newCoins))
-
// events are shifted due to the funding account events
- events = ctx.EventManager().ABCIEvents()
- suite.Require().Equal(12, len(events))
+ events := ctx.EventManager().ABCIEvents()
+ suite.Require().Equal(10, len(events))
suite.Require().Equal(abci.Event(event1), events[8])
suite.Require().Equal(abci.Event(event2), events[9])
}
diff --git a/x/bank/keeper/msg_server.go b/x/bank/keeper/msg_server.go
index b318db2cc4..5d940b459e 100644
--- a/x/bank/keeper/msg_server.go
+++ b/x/bank/keeper/msg_server.go
@@ -26,7 +26,7 @@ var _ types.MsgServer = msgServer{}
func (k msgServer) Send(goCtx context.Context, msg *types.MsgSend) (*types.MsgSendResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
- if err := k.SendEnabledCoins(ctx, msg.Amount...); err != nil {
+ if err := k.IsSendEnabledCoins(ctx, msg.Amount...); err != nil {
return nil, err
}
@@ -75,7 +75,7 @@ func (k msgServer) MultiSend(goCtx context.Context, msg *types.MsgMultiSend) (*t
// NOTE: totalIn == totalOut should already have been checked
for _, in := range msg.Inputs {
- if err := k.SendEnabledCoins(ctx, in.Coins...); err != nil {
+ if err := k.IsSendEnabledCoins(ctx, in.Coins...); err != nil {
return nil, err
}
}
diff --git a/x/bank/keeper/send.go b/x/bank/keeper/send.go
index 8fd7e602a4..675eb67735 100644
--- a/x/bank/keeper/send.go
+++ b/x/bank/keeper/send.go
@@ -20,8 +20,8 @@ type SendKeeper interface {
GetParams(ctx sdk.Context) types.Params
SetParams(ctx sdk.Context, params types.Params)
- SendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool
- SendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
+ IsSendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool
+ IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
BlockedAddr(addr sdk.AccAddress) bool
}
@@ -131,19 +131,6 @@ func (k BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.Input,
// SendCoins transfers amt coins from a sending account to a receiving account.
// An error is returned upon failure.
func (k BaseSendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error {
- ctx.EventManager().EmitEvents(sdk.Events{
- sdk.NewEvent(
- types.EventTypeTransfer,
- sdk.NewAttribute(types.AttributeKeyRecipient, toAddr.String()),
- sdk.NewAttribute(types.AttributeKeySender, fromAddr.String()),
- sdk.NewAttribute(sdk.AttributeKeyAmount, amt.String()),
- ),
- sdk.NewEvent(
- sdk.EventTypeMessage,
- sdk.NewAttribute(types.AttributeKeySender, fromAddr.String()),
- ),
- })
-
err := k.subUnlockedCoins(ctx, fromAddr, amt)
if err != nil {
return err
@@ -164,6 +151,19 @@ func (k BaseSendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAd
k.ak.SetAccount(ctx, k.ak.NewAccountWithAddress(ctx, toAddr))
}
+ ctx.EventManager().EmitEvents(sdk.Events{
+ sdk.NewEvent(
+ types.EventTypeTransfer,
+ sdk.NewAttribute(types.AttributeKeyRecipient, toAddr.String()),
+ sdk.NewAttribute(types.AttributeKeySender, fromAddr.String()),
+ sdk.NewAttribute(sdk.AttributeKeyAmount, amt.String()),
+ ),
+ sdk.NewEvent(
+ sdk.EventTypeMessage,
+ sdk.NewAttribute(types.AttributeKeySender, fromAddr.String()),
+ ),
+ })
+
return nil
}
@@ -277,20 +277,20 @@ func (k BaseSendKeeper) setBalance(ctx sdk.Context, addr sdk.AccAddress, balance
return nil
}
-// SendEnabledCoins checks the coins provide and returns an ErrSendDisabled if
+// IsSendEnabledCoins checks the coins provide and returns an ErrSendDisabled if
// any of the coins are not configured for sending. Returns nil if sending is enabled
// for all provided coin
-func (k BaseSendKeeper) SendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error {
+func (k BaseSendKeeper) IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error {
for _, coin := range coins {
- if !k.SendEnabledCoin(ctx, coin) {
+ if !k.IsSendEnabledCoin(ctx, coin) {
return sdkerrors.Wrapf(types.ErrSendDisabled, "%s transfers are currently disabled", coin.Denom)
}
}
return nil
}
-// SendEnabledCoin returns the current SendEnabled status of the provided coin's denom
-func (k BaseSendKeeper) SendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool {
+// IsSendEnabledCoin returns the current SendEnabled status of the provided coin's denom
+func (k BaseSendKeeper) IsSendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool {
return k.GetParams(ctx).SendEnabledDenom(coin.Denom)
}
diff --git a/x/bank/module.go b/x/bank/module.go
index ea97a9efa3..c43251acc2 100644
--- a/x/bank/module.go
+++ b/x/bank/module.go
@@ -186,7 +186,7 @@ func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange {
}
// RegisterStoreDecoder registers a decoder for supply module's types
-func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {}
+func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {}
// WeightedOperations returns the all the gov module operations with their respective weights.
func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation {
diff --git a/x/bank/simulation/operations.go b/x/bank/simulation/operations.go
index 16e1b77500..8c3aef80f8 100644
--- a/x/bank/simulation/operations.go
+++ b/x/bank/simulation/operations.go
@@ -61,7 +61,7 @@ func SimulateMsgSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Operatio
simAccount, toSimAcc, coins, skip := randomSendFields(r, ctx, accs, bk, ak)
// Check send_enabled status of each coin denom
- if err := bk.SendEnabledCoins(ctx, coins...); err != nil {
+ if err := bk.IsSendEnabledCoins(ctx, coins...); err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSend, err.Error()), nil, nil
}
@@ -173,7 +173,7 @@ func SimulateMsgMultiSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Ope
}
// Check send_enabled status of each sent coin denom
- if err := bk.SendEnabledCoins(ctx, totalSentCoins...); err != nil {
+ if err := bk.IsSendEnabledCoins(ctx, totalSentCoins...); err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgMultiSend, err.Error()), nil, nil
}
diff --git a/x/bank/spec/02_keepers.md b/x/bank/spec/02_keepers.md
index 8db69c34d0..ea5b9ed692 100644
--- a/x/bank/spec/02_keepers.md
+++ b/x/bank/spec/02_keepers.md
@@ -12,14 +12,14 @@ require.
Best practices dictate careful review of `bank` module code to ensure that
permissions are limited in the way that you expect.
-## Blacklisting Addresses
+## Blocklisting Addresses
The `x/bank` module accepts a map of addresses that are considered blocklisted
from directly and explicitly receiving funds through means such as `MsgSend` and
`MsgMultiSend` and direct API calls like `SendCoinsFromModuleToAccount`.
Typically, these addresses are module accounts. If these addresses receive funds
-outside of the expected rules of the state machine, invariants are likely to be
+outside the expected rules of the state machine, invariants are likely to be
broken and could result in a halted network.
By providing the `x/bank` module with a blocklisted set of addresses, an error occurs for the operation if a user or client attempts to directly or indirectly send funds to a blocklisted account, for example, by using [IBC](http://docs.cosmos.network/master/ibc/).
@@ -58,32 +58,30 @@ The base keeper provides full-permission access: the ability to arbitrary modify
// Keeper defines a module interface that facilitates the transfer of coins
// between accounts.
type Keeper interface {
- SendKeeper
-
- InitGenesis(sdk.Context, *types.GenesisState)
- ExportGenesis(sdk.Context) *types.GenesisState
-
- GetSupply(ctx sdk.Context) exported.SupplyI
- SetSupply(ctx sdk.Context, supply exported.SupplyI)
-
- GetDenomMetaData(ctx sdk.Context, denom string) types.Metadata
- SetDenomMetaData(ctx sdk.Context, denomMetaData types.Metadata)
- IterateAllDenomMetaData(ctx sdk.Context, cb func(types.Metadata) bool)
-
- SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
- SendCoinsFromModuleToModule(ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins) error
- SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
- DelegateCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
- UndelegateCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
- MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
- BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
-
- DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error
- UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) error
- MarshalSupply(supplyI exported.SupplyI) ([]byte, error)
- UnmarshalSupply(bz []byte) (exported.SupplyI, error)
-
- types.QueryServer
+ SendKeeper
+
+ InitGenesis(sdk.Context, *types.GenesisState)
+ ExportGenesis(sdk.Context) *types.GenesisState
+
+ GetSupply(ctx sdk.Context, denom string) sdk.Coin
+ GetPaginatedTotalSupply(ctx sdk.Context, pagination *query.PageRequest) (sdk.Coins, *query.PageResponse, error)
+ IterateTotalSupply(ctx sdk.Context, cb func(sdk.Coin) bool)
+ GetDenomMetaData(ctx sdk.Context, denom string) (types.Metadata, bool)
+ SetDenomMetaData(ctx sdk.Context, denomMetaData types.Metadata)
+ IterateAllDenomMetaData(ctx sdk.Context, cb func(types.Metadata) bool)
+
+ SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
+ SendCoinsFromModuleToModule(ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins) error
+ SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
+ DelegateCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
+ UndelegateCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
+ MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
+ BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
+
+ DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error
+ UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) error
+
+ types.QueryServer
}
```
@@ -96,18 +94,18 @@ accounts. The send keeper does not alter the total supply (mint or burn coins).
// SendKeeper defines a module interface that facilitates the transfer of coins
// between accounts without the possibility of creating coins.
type SendKeeper interface {
- ViewKeeper
-
- InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error
- SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
-
- GetParams(ctx sdk.Context) types.Params
- SetParams(ctx sdk.Context, params types.Params)
-
- SendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool
- SendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
-
- BlockedAddr(addr sdk.AccAddress) bool
+ ViewKeeper
+
+ InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error
+ SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
+
+ GetParams(ctx sdk.Context) types.Params
+ SetParams(ctx sdk.Context, params types.Params)
+
+ IsSendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool
+ IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
+
+ BlockedAddr(addr sdk.AccAddress) bool
}
```
@@ -119,16 +117,16 @@ The view keeper provides read-only access to account balances. The view keeper d
// ViewKeeper defines a module interface that facilitates read only access to
// account balances.
type ViewKeeper interface {
- ValidateBalance(ctx sdk.Context, addr sdk.AccAddress) error
- HasBalance(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coin) bool
-
- GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
- GetAccountsBalances(ctx sdk.Context) []types.Balance
- GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
- LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
- SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
-
- IterateAccountBalances(ctx sdk.Context, addr sdk.AccAddress, cb func(coin sdk.Coin) (stop bool))
- IterateAllBalances(ctx sdk.Context, cb func(address sdk.AccAddress, coin sdk.Coin) (stop bool))
+ ValidateBalance(ctx sdk.Context, addr sdk.AccAddress) error
+ HasBalance(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coin) bool
+
+ GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
+ GetAccountsBalances(ctx sdk.Context) []types.Balance
+ GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
+ LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
+ SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
+
+ IterateAccountBalances(ctx sdk.Context, addr sdk.AccAddress, cb func(coin sdk.Coin) (stop bool))
+ IterateAllBalances(ctx sdk.Context, cb func(address sdk.AccAddress, coin sdk.Coin) (stop bool))
}
```
diff --git a/x/bank/spec/03_messages.md b/x/bank/spec/03_messages.md
index 07c42f5f78..0ef6ce72ef 100644
--- a/x/bank/spec/03_messages.md
+++ b/x/bank/spec/03_messages.md
@@ -6,20 +6,21 @@ order: 3
## MsgSend
+Send coins from one address to another.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/bank/v1beta1/tx.proto#L19-L28
-`handleMsgSend` just runs `inputOutputCoins`.
+The message will fail under the following conditions:
+- The coins do not have sending enabled
+- The `to` address is restricted
-```go
-handleMsgSend(msg MsgSend)
- inputSum = 0
- for input in inputs
- inputSum += input.Amount
- outputSum = 0
- for output in outputs
- outputSum += output.Amount
- if inputSum != outputSum:
- fail with "input/output amount mismatch"
+## MsgMultiSend
+
+Send coins from and to a series of different address. If any of the receiving addresses do not correspond to an existing account, a new account is created.
++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/bank/v1beta1/tx.proto#L33-L39
+
+The message will fail under the following conditions:
+- Any of the coins do not have sending enabled
+- Any of the `to` addresses are restricted
+- Any of the coins are locked
+- The inputs and outputs do not correctly correspond to one another
- return inputOutputCoins(msg.Inputs, msg.Outputs)
-```
diff --git a/x/bank/types/bank.pb.go b/x/bank/types/bank.pb.go
index 0511d1e961..f190a457b2 100644
--- a/x/bank/types/bank.pb.go
+++ b/x/bank/types/bank.pb.go
@@ -426,44 +426,44 @@ func init() {
func init() { proto.RegisterFile("cosmos/bank/v1beta1/bank.proto", fileDescriptor_dd052eee12edf988) }
var fileDescriptor_dd052eee12edf988 = []byte{
- // 587 bytes of a gzipped FileDescriptorProto
+ // 592 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0xbf, 0x6f, 0xd3, 0x40,
- 0x14, 0xf6, 0x35, 0x8d, 0x49, 0x2f, 0xb0, 0x1c, 0x15, 0x72, 0x2b, 0x61, 0x1b, 0x4b, 0x48, 0x29,
- 0xa2, 0x0e, 0x05, 0xb1, 0x64, 0x41, 0x4a, 0x41, 0xa8, 0x03, 0x02, 0xb9, 0x42, 0x48, 0x30, 0x44,
- 0xe7, 0xdc, 0x35, 0x58, 0xb5, 0xef, 0xac, 0xdc, 0x19, 0xd5, 0xff, 0x01, 0x13, 0x30, 0x32, 0x76,
- 0x66, 0x62, 0xe0, 0x7f, 0xa0, 0x63, 0x05, 0x0b, 0x53, 0x40, 0xc9, 0xc2, 0xdc, 0xbf, 0x00, 0xdd,
- 0x9d, 0xf3, 0xa3, 0x52, 0x40, 0x0c, 0x0c, 0x4c, 0x79, 0xdf, 0x7b, 0xdf, 0xfb, 0xde, 0xd3, 0x77,
- 0xcf, 0x81, 0x6e, 0x9f, 0x8b, 0x8c, 0x8b, 0x76, 0x8c, 0xd9, 0x61, 0xfb, 0xd5, 0x4e, 0x4c, 0x25,
- 0xde, 0xd1, 0x20, 0xcc, 0x87, 0x5c, 0x72, 0x74, 0xd9, 0xd4, 0x43, 0x9d, 0xaa, 0xea, 0x9b, 0xeb,
- 0x03, 0x3e, 0xe0, 0xba, 0xde, 0x56, 0x91, 0xa1, 0x6e, 0x6e, 0x18, 0x6a, 0xcf, 0x14, 0xaa, 0x3e,
- 0x53, 0x9a, 0x4f, 0x11, 0x74, 0x36, 0xa5, 0xcf, 0x13, 0x66, 0xea, 0xc1, 0x57, 0x00, 0xed, 0x27,
- 0x78, 0x88, 0x33, 0x81, 0x0e, 0xe0, 0x45, 0x41, 0x19, 0xe9, 0x51, 0x86, 0xe3, 0x94, 0x12, 0x07,
- 0xf8, 0xb5, 0x56, 0xf3, 0xb6, 0x1f, 0x2e, 0xd9, 0x23, 0xdc, 0xa7, 0x8c, 0x3c, 0x30, 0xbc, 0xee,
- 0xb5, 0xb3, 0x91, 0x77, 0xb5, 0xc4, 0x59, 0xda, 0x09, 0x16, 0xfb, 0x6f, 0xf2, 0x2c, 0x91, 0x34,
- 0xcb, 0x65, 0x19, 0x44, 0x4d, 0x31, 0xe7, 0xa3, 0x17, 0x70, 0x9d, 0xd0, 0x03, 0x5c, 0xa4, 0xb2,
- 0x77, 0x6e, 0xde, 0x8a, 0x0f, 0x5a, 0x8d, 0xee, 0xd6, 0xd9, 0xc8, 0xbb, 0x6e, 0xd4, 0x96, 0xb1,
- 0x16, 0x55, 0x51, 0x45, 0x58, 0x58, 0xa6, 0xb3, 0xfa, 0xfe, 0xd8, 0xb3, 0x82, 0x87, 0xb0, 0xb9,
- 0x90, 0x44, 0xeb, 0xb0, 0x4e, 0x28, 0xe3, 0x99, 0x03, 0x7c, 0xd0, 0x5a, 0x8b, 0x0c, 0x40, 0x0e,
- 0xbc, 0x70, 0x6e, 0x74, 0x34, 0x85, 0x9d, 0x86, 0x12, 0xf9, 0x79, 0xec, 0x81, 0xe0, 0x0d, 0x80,
- 0xf5, 0x3d, 0x96, 0x17, 0x52, 0xb1, 0x31, 0x21, 0x43, 0x2a, 0x44, 0xa5, 0x32, 0x85, 0x08, 0xc3,
- 0xba, 0x32, 0x54, 0x38, 0x2b, 0xda, 0xb0, 0x8d, 0xb9, 0x61, 0x82, 0xce, 0x0c, 0xdb, 0xe5, 0x09,
- 0xeb, 0xde, 0x3a, 0x19, 0x79, 0xd6, 0x87, 0xef, 0x5e, 0x6b, 0x90, 0xc8, 0x97, 0x45, 0x1c, 0xf6,
- 0x79, 0x56, 0xbd, 0x56, 0xf5, 0xb3, 0x2d, 0xc8, 0x61, 0x5b, 0x96, 0x39, 0x15, 0xba, 0x41, 0x44,
- 0x46, 0xb9, 0xd3, 0x78, 0x6d, 0x16, 0xb2, 0x82, 0xb7, 0x00, 0xda, 0x8f, 0x0b, 0xf9, 0x1f, 0x6d,
- 0xf4, 0x11, 0x40, 0x7b, 0xbf, 0xc8, 0xf3, 0xb4, 0x54, 0x73, 0x25, 0x97, 0x38, 0xad, 0x4e, 0xe7,
- 0xdf, 0xce, 0xd5, 0xca, 0x9d, 0xdd, 0x6a, 0x2e, 0xf8, 0xf2, 0x69, 0xfb, 0xee, 0x8d, 0x3f, 0x76,
- 0x1f, 0x99, 0x4f, 0x8b, 0x1e, 0xe5, 0x7c, 0x28, 0x29, 0x09, 0xcd, 0x92, 0x7b, 0x0e, 0x08, 0x9e,
- 0xc1, 0xb5, 0xfb, 0xea, 0x04, 0x9e, 0xb2, 0x44, 0xfe, 0xe6, 0x38, 0x36, 0x61, 0x43, 0x35, 0x32,
- 0xca, 0xa4, 0xbe, 0x8e, 0x4b, 0xd1, 0x0c, 0x6b, 0xe3, 0xd3, 0x04, 0x0b, 0x2a, 0x9c, 0x9a, 0x5f,
- 0xd3, 0xc6, 0x1b, 0x18, 0x7c, 0x06, 0xb0, 0xf1, 0x88, 0x4a, 0x4c, 0xb0, 0xc4, 0xc8, 0x87, 0x4d,
- 0x42, 0x45, 0x7f, 0x98, 0xe4, 0x32, 0xe1, 0xac, 0x92, 0x5f, 0x4c, 0xa1, 0x7b, 0x8a, 0xc1, 0x78,
- 0xd6, 0x2b, 0x58, 0x22, 0xa7, 0xaf, 0xe5, 0x2e, 0xfd, 0xe0, 0x66, 0xfb, 0x46, 0x90, 0x4c, 0x43,
- 0x81, 0x10, 0x5c, 0x55, 0xde, 0x3a, 0x35, 0xad, 0xad, 0x63, 0xb5, 0x1d, 0x49, 0x44, 0x9e, 0xe2,
- 0xd2, 0x59, 0x35, 0x67, 0x51, 0x41, 0xc5, 0x66, 0x38, 0xa3, 0x4e, 0xdd, 0xb0, 0x55, 0x8c, 0xae,
- 0x40, 0x5b, 0x94, 0x59, 0xcc, 0x53, 0xc7, 0xd6, 0xd9, 0x0a, 0x75, 0x77, 0x4f, 0xc6, 0x2e, 0x38,
- 0x1d, 0xbb, 0xe0, 0xc7, 0xd8, 0x05, 0xef, 0x26, 0xae, 0x75, 0x3a, 0x71, 0xad, 0x6f, 0x13, 0xd7,
- 0x7a, 0xbe, 0xf5, 0x37, 0xa6, 0xeb, 0x97, 0x8b, 0x6d, 0xfd, 0x1f, 0x73, 0xe7, 0x57, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0xe7, 0x1c, 0xc1, 0x93, 0xeb, 0x04, 0x00, 0x00,
+ 0x14, 0xf6, 0x35, 0x8d, 0x49, 0x2f, 0xb0, 0x1c, 0x15, 0x72, 0x23, 0x61, 0x1b, 0x4b, 0x48, 0x29,
+ 0xa2, 0x4e, 0x0a, 0x0c, 0x28, 0x0b, 0x52, 0xca, 0x0f, 0x75, 0x40, 0x20, 0x57, 0x08, 0x09, 0x86,
+ 0xe8, 0x9c, 0xbb, 0x06, 0xab, 0xf6, 0x9d, 0x95, 0x3b, 0x57, 0xf5, 0x7f, 0xc0, 0x04, 0x8c, 0x8c,
+ 0x9d, 0x59, 0xe1, 0x7f, 0xa0, 0x63, 0x05, 0x0b, 0x53, 0x40, 0xc9, 0xc2, 0xdc, 0xbf, 0x00, 0xf9,
+ 0xce, 0xf9, 0x51, 0x29, 0x20, 0x06, 0x06, 0xa6, 0xbc, 0xef, 0xbd, 0xef, 0x7d, 0xef, 0xe9, 0xbb,
+ 0xe7, 0x40, 0xbb, 0xcf, 0x45, 0xc2, 0x45, 0x2b, 0xc4, 0xec, 0xa0, 0x75, 0xb8, 0x1d, 0x52, 0x89,
+ 0xb7, 0x15, 0xf0, 0xd3, 0x21, 0x97, 0x1c, 0x5d, 0xd6, 0x75, 0x5f, 0xa5, 0xca, 0x7a, 0x63, 0x7d,
+ 0xc0, 0x07, 0x5c, 0xd5, 0x5b, 0x45, 0xa4, 0xa9, 0x8d, 0x0d, 0x4d, 0xed, 0xe9, 0x42, 0xd9, 0xa7,
+ 0x4b, 0xf3, 0x29, 0x82, 0xce, 0xa6, 0xf4, 0x79, 0xc4, 0x74, 0xdd, 0xfb, 0x0a, 0xa0, 0xf9, 0x14,
+ 0x0f, 0x71, 0x22, 0xd0, 0x3e, 0xbc, 0x28, 0x28, 0x23, 0x3d, 0xca, 0x70, 0x18, 0x53, 0x62, 0x01,
+ 0xb7, 0xd2, 0xac, 0xdf, 0x72, 0xfd, 0x25, 0x7b, 0xf8, 0x7b, 0x94, 0x91, 0x07, 0x9a, 0xd7, 0xbd,
+ 0x76, 0x36, 0x72, 0xae, 0xe6, 0x38, 0x89, 0x3b, 0xde, 0x62, 0xff, 0x4d, 0x9e, 0x44, 0x92, 0x26,
+ 0xa9, 0xcc, 0xbd, 0xa0, 0x2e, 0xe6, 0x7c, 0xf4, 0x12, 0xae, 0x13, 0xba, 0x8f, 0xb3, 0x58, 0xf6,
+ 0xce, 0xcd, 0x5b, 0x71, 0x41, 0xb3, 0xd6, 0xdd, 0x3c, 0x1b, 0x39, 0xd7, 0xb5, 0xda, 0x32, 0xd6,
+ 0xa2, 0x2a, 0x2a, 0x09, 0x0b, 0xcb, 0x74, 0x56, 0xdf, 0x1f, 0x3b, 0x86, 0xf7, 0x08, 0xd6, 0x17,
+ 0x92, 0x68, 0x1d, 0x56, 0x09, 0x65, 0x3c, 0xb1, 0x80, 0x0b, 0x9a, 0x6b, 0x81, 0x06, 0xc8, 0x82,
+ 0x17, 0xce, 0x8d, 0x0e, 0xa6, 0xb0, 0x53, 0x2b, 0x44, 0x7e, 0x1e, 0x3b, 0xc0, 0x7b, 0x03, 0x60,
+ 0x75, 0x97, 0xa5, 0x99, 0x2c, 0xd8, 0x98, 0x90, 0x21, 0x15, 0xa2, 0x54, 0x99, 0x42, 0x84, 0x61,
+ 0xb5, 0x30, 0x54, 0x58, 0x2b, 0xca, 0xb0, 0x8d, 0xb9, 0x61, 0x82, 0xce, 0x0c, 0xdb, 0xe1, 0x11,
+ 0xeb, 0xb6, 0x4f, 0x46, 0x8e, 0xf1, 0xe1, 0xbb, 0xd3, 0x1c, 0x44, 0xf2, 0x55, 0x16, 0xfa, 0x7d,
+ 0x9e, 0x94, 0xaf, 0x55, 0xfe, 0x6c, 0x09, 0x72, 0xd0, 0x92, 0x79, 0x4a, 0x85, 0x6a, 0x10, 0x81,
+ 0x56, 0xee, 0xd4, 0x5e, 0xeb, 0x85, 0x0c, 0xef, 0x2d, 0x80, 0xe6, 0x93, 0x4c, 0xfe, 0x47, 0x1b,
+ 0x7d, 0x04, 0xd0, 0xdc, 0xcb, 0xd2, 0x34, 0xce, 0x8b, 0xb9, 0x92, 0x4b, 0x1c, 0x97, 0xa7, 0xf3,
+ 0x6f, 0xe7, 0x2a, 0xe5, 0xce, 0xc3, 0x72, 0x2e, 0xf8, 0xf2, 0x69, 0xeb, 0xee, 0x8d, 0x3f, 0x76,
+ 0x1f, 0xe9, 0x4f, 0x2b, 0xa6, 0x03, 0xdc, 0xcf, 0x5b, 0x87, 0xed, 0x3b, 0x6d, 0x5f, 0xef, 0xb9,
+ 0x6b, 0x01, 0xef, 0x39, 0x5c, 0xbb, 0x5f, 0x5c, 0xc1, 0x33, 0x16, 0xc9, 0xdf, 0xdc, 0x47, 0x03,
+ 0xd6, 0xe8, 0x51, 0xca, 0x19, 0x65, 0x52, 0x1d, 0xc8, 0xa5, 0x60, 0x86, 0x95, 0xf7, 0x71, 0x84,
+ 0x05, 0x15, 0x56, 0xc5, 0xad, 0x28, 0xef, 0x35, 0xf4, 0x3e, 0x03, 0x58, 0x7b, 0x4c, 0x25, 0x26,
+ 0x58, 0x62, 0xe4, 0xc2, 0x3a, 0xa1, 0xa2, 0x3f, 0x8c, 0x52, 0x19, 0x71, 0x56, 0xca, 0x2f, 0xa6,
+ 0xd0, 0xbd, 0x82, 0xc1, 0x78, 0xd2, 0xcb, 0x58, 0x24, 0xa7, 0x0f, 0x66, 0x2f, 0xfd, 0xe6, 0x66,
+ 0xfb, 0x06, 0x90, 0x4c, 0x43, 0x81, 0x10, 0x5c, 0x2d, 0xec, 0xb5, 0x2a, 0x4a, 0x5b, 0xc5, 0xc5,
+ 0x76, 0x24, 0x12, 0x69, 0x8c, 0x73, 0x6b, 0x55, 0x5f, 0x46, 0x09, 0x0b, 0x36, 0xc3, 0x09, 0xb5,
+ 0xaa, 0x9a, 0x5d, 0xc4, 0xe8, 0x0a, 0x34, 0x45, 0x9e, 0x84, 0x3c, 0xb6, 0x4c, 0x95, 0x2d, 0x51,
+ 0x77, 0xe7, 0x64, 0x6c, 0x83, 0xd3, 0xb1, 0x0d, 0x7e, 0x8c, 0x6d, 0xf0, 0x6e, 0x62, 0x1b, 0xa7,
+ 0x13, 0xdb, 0xf8, 0x36, 0xb1, 0x8d, 0x17, 0x9b, 0x7f, 0xe3, 0xbb, 0x7a, 0xbc, 0xd0, 0x54, 0x7f,
+ 0x33, 0xb7, 0x7f, 0x05, 0x00, 0x00, 0xff, 0xff, 0xcc, 0x03, 0xbf, 0xe9, 0xee, 0x04, 0x00, 0x00,
}
func (this *SendEnabled) Equal(that interface{}) bool {
diff --git a/x/bank/types/key.go b/x/bank/types/key.go
index a50d04a0a7..5d7f52baa5 100644
--- a/x/bank/types/key.go
+++ b/x/bank/types/key.go
@@ -21,8 +21,8 @@ const (
// KVStore keys
var (
- // BalancesPrefix is the for the account balances store. We use a byte
- // (instead of say `[]]byte("balances")` to save some disk space).
+ // BalancesPrefix is the prefix for the account balances store. We use a byte
+ // (instead of `[]byte("balances")` to save some disk space).
BalancesPrefix = []byte{0x02}
SupplyKey = []byte{0x00}
DenomMetadataPrefix = []byte{0x1}
@@ -35,7 +35,7 @@ func DenomMetadataKey(denom string) []byte {
}
// AddressFromBalancesStore returns an account address from a balances prefix
-// store. The key must not contain the perfix BalancesPrefix as the prefix store
+// store. The key must not contain the prefix BalancesPrefix as the prefix store
// iterator discards the actual prefix.
//
// If invalid key is passed, AddressFromBalancesStore returns ErrInvalidKey.
diff --git a/x/staking/client/cli/query.go b/x/staking/client/cli/query.go
index 7bf3ae41cc..0982296161 100644
--- a/x/staking/client/cli/query.go
+++ b/x/staking/client/cli/query.go
@@ -660,7 +660,6 @@ $ %s query staking historical-info 5
params := &types.QueryHistoricalInfoRequest{Height: height}
res, err := queryClient.HistoricalInfo(cmd.Context(), params)
-
if err != nil {
return err
}
diff --git a/x/staking/client/testutil/suite.go b/x/staking/client/testutil/suite.go
index a6e385b405..d75978cb6f 100644
--- a/x/staking/client/testutil/suite.go
+++ b/x/staking/client/testutil/suite.go
@@ -230,7 +230,7 @@ func (s *IntegrationTestSuite) TestGetCmdQueryValidator() {
},
{
"happy case",
- []string{fmt.Sprintf("%s", val.ValAddress), fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
+ []string{val.ValAddress.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
false,
},
}
@@ -415,7 +415,7 @@ func (s *IntegrationTestSuite) TestGetCmdQueryDelegations() {
}
}
-func (s *IntegrationTestSuite) TestGetCmdQueryDelegationsTo() {
+func (s *IntegrationTestSuite) TestGetCmdQueryValidatorDelegations() {
val := s.network.Validators[0]
testCases := []struct {
@@ -755,7 +755,7 @@ func (s *IntegrationTestSuite) TestGetCmdQueryRedelegation() {
}
}
-func (s *IntegrationTestSuite) TestGetCmdQueryRedelegationsFrom() {
+func (s *IntegrationTestSuite) TestGetCmdQueryValidatorRedelegations() {
val := s.network.Validators[0]
val2 := s.network.Validators[1]
@@ -925,7 +925,7 @@ not_bonded_tokens: "0"`, cli.DefaultTokens.Mul(sdk.NewInt(2)).String()),
}
}
-func (s *IntegrationTestSuite) TestNewCmdEditValidator() {
+func (s *IntegrationTestSuite) TestNewEditValidatorCmd() {
val := s.network.Validators[0]
details := "bio"
@@ -1041,7 +1041,7 @@ func (s *IntegrationTestSuite) TestNewCmdEditValidator() {
}
}
-func (s *IntegrationTestSuite) TestNewCmdDelegate() {
+func (s *IntegrationTestSuite) TestNewDelegateCmd() {
val := s.network.Validators[0]
info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
@@ -1123,7 +1123,7 @@ func (s *IntegrationTestSuite) TestNewCmdDelegate() {
}
}
-func (s *IntegrationTestSuite) TestNewCmdRedelegate() {
+func (s *IntegrationTestSuite) TestNewRedelegateCmd() {
val := s.network.Validators[0]
val2 := s.network.Validators[1]
@@ -1209,7 +1209,7 @@ func (s *IntegrationTestSuite) TestNewCmdRedelegate() {
}
}
-func (s *IntegrationTestSuite) TestNewCmdUnbond() {
+func (s *IntegrationTestSuite) TestNewUnbondCmd() {
val := s.network.Validators[0]
testCases := []struct {
diff --git a/x/staking/keeper/delegation_test.go b/x/staking/keeper/delegation_test.go
index de7a9ba0e6..49083d2376 100644
--- a/x/staking/keeper/delegation_test.go
+++ b/x/staking/keeper/delegation_test.go
@@ -384,6 +384,7 @@ func TestUndelegateFromUnbondingValidator(t *testing.T) {
selfDelegation := types.NewDelegation(addrVals[0].Bytes(), addrVals[0], issuedShares)
app.StakingKeeper.SetDelegation(ctx, selfDelegation)
+ // add bonded tokens to pool for delegations
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
@@ -470,6 +471,7 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) {
selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
app.StakingKeeper.SetDelegation(ctx, selfDelegation)
+ // add bonded tokens to pool for delegations
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
@@ -518,7 +520,7 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) {
_, err = app.StakingKeeper.Undelegate(ctx, addrDels[1], addrVals[0], remainingTokens.ToDec())
require.NoError(t, err)
- // now validator should now be deleted from state
+ // now validator should be deleted from state
validator, found = app.StakingKeeper.GetValidator(ctx, addrVals[0])
require.False(t, found, "%v", validator)
}
@@ -556,6 +558,7 @@ func TestUnbondingAllDelegationFromValidator(t *testing.T) {
validator, issuedShares = validator.AddTokensFromDel(delTokens)
require.Equal(t, delTokens, issuedShares.RoundInt())
+ // add bonded tokens to pool for delegations
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
diff --git a/x/staking/keeper/grpc_query.go b/x/staking/keeper/grpc_query.go
index 49d9b92ce2..4852848255 100644
--- a/x/staking/keeper/grpc_query.go
+++ b/x/staking/keeper/grpc_query.go
@@ -61,7 +61,7 @@ func (k Querier) Validators(c context.Context, req *types.QueryValidatorsRequest
return &types.QueryValidatorsResponse{Validators: validators, Pagination: pageRes}, nil
}
-// Validator queries validator info for given validator addr
+// Validator queries validator info for given validator address
func (k Querier) Validator(c context.Context, req *types.QueryValidatorRequest) (*types.QueryValidatorResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
@@ -380,6 +380,7 @@ func (k Querier) HistoricalInfo(c context.Context, req *types.QueryHistoricalInf
return &types.QueryHistoricalInfoResponse{Hist: &hi}, nil
}
+// Redelegations queries redelegations of given address
func (k Querier) Redelegations(c context.Context, req *types.QueryRedelegationsRequest) (*types.QueryRedelegationsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
@@ -410,6 +411,7 @@ func (k Querier) Redelegations(c context.Context, req *types.QueryRedelegationsR
return &types.QueryRedelegationsResponse{RedelegationResponses: redelResponses, Pagination: pageRes}, nil
}
+// DelegatorValidators queries all validators info for given delegator address
func (k Querier) DelegatorValidators(c context.Context, req *types.QueryDelegatorValidatorsRequest) (*types.QueryDelegatorValidatorsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
diff --git a/x/staking/keeper/grpc_query_test.go b/x/staking/keeper/grpc_query_test.go
index c82f71552e..dc47dc34c1 100644
--- a/x/staking/keeper/grpc_query_test.go
+++ b/x/staking/keeper/grpc_query_test.go
@@ -84,7 +84,7 @@ func (suite *KeeperTestSuite) TestGRPCQueryValidators() {
}
}
-func (suite *KeeperTestSuite) TestGRPCValidator() {
+func (suite *KeeperTestSuite) TestGRPCQueryValidator() {
app, ctx, queryClient, vals := suite.app, suite.ctx, suite.queryClient, suite.vals
validator, found := app.StakingKeeper.GetValidator(ctx, vals[0].GetOperator())
suite.True(found)
@@ -586,7 +586,7 @@ func (suite *KeeperTestSuite) TestGRPCQueryHistoricalInfo() {
}
}
-func (suite *KeeperTestSuite) TestGRPCQueryRedelegation() {
+func (suite *KeeperTestSuite) TestGRPCQueryRedelegations() {
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
addrAcc, addrAcc1 := addrs[0], addrs[1]
diff --git a/x/staking/keeper/msg_server.go b/x/staking/keeper/msg_server.go
index 37e5edb042..25031c9638 100644
--- a/x/staking/keeper/msg_server.go
+++ b/x/staking/keeper/msg_server.go
@@ -26,6 +26,7 @@ func NewMsgServerImpl(keeper Keeper) types.MsgServer {
var _ types.MsgServer = msgServer{}
+// CreateValidator defines a method for creating a new validator
func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateValidator) (*types.MsgCreateValidatorResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
@@ -119,6 +120,7 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa
return &types.MsgCreateValidatorResponse{}, nil
}
+// EditValidator defines a method for editing an existing validator
func (k msgServer) EditValidator(goCtx context.Context, msg *types.MsgEditValidator) (*types.MsgEditValidatorResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
@@ -181,6 +183,7 @@ func (k msgServer) EditValidator(goCtx context.Context, msg *types.MsgEditValida
return &types.MsgEditValidatorResponse{}, nil
}
+// Delegate defines a method for performing a delegation of coins from a delegator to a validator
func (k msgServer) Delegate(goCtx context.Context, msg *types.MsgDelegate) (*types.MsgDelegateResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
valAddr, valErr := sdk.ValAddressFromBech32(msg.ValidatorAddress)
@@ -237,6 +240,7 @@ func (k msgServer) Delegate(goCtx context.Context, msg *types.MsgDelegate) (*typ
return &types.MsgDelegateResponse{}, nil
}
+// BeginRedelegate defines a method for performing a redelegation of coins from a delegator and source validator to a destination validator
func (k msgServer) BeginRedelegate(goCtx context.Context, msg *types.MsgBeginRedelegate) (*types.MsgBeginRedelegateResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
valSrcAddr, err := sdk.ValAddressFromBech32(msg.ValidatorSrcAddress)
@@ -302,6 +306,7 @@ func (k msgServer) BeginRedelegate(goCtx context.Context, msg *types.MsgBeginRed
}, nil
}
+// Undelegate defines a method for performing an undelegation from a delegate and a validator
func (k msgServer) Undelegate(goCtx context.Context, msg *types.MsgUndelegate) (*types.MsgUndelegateResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
diff --git a/x/staking/simulation/genesis.go b/x/staking/simulation/genesis.go
index bf01b90bfe..2f1caf2692 100644
--- a/x/staking/simulation/genesis.go
+++ b/x/staking/simulation/genesis.go
@@ -21,18 +21,18 @@ const (
historicalEntries = "historical_entries"
)
-// GenUnbondingTime randomized UnbondingTime
-func GenUnbondingTime(r *rand.Rand) (ubdTime time.Duration) {
+// genUnbondingTime returns randomized UnbondingTime
+func genUnbondingTime(r *rand.Rand) (ubdTime time.Duration) {
return time.Duration(simulation.RandIntBetween(r, 60, 60*60*24*3*2)) * time.Second
}
-// GenMaxValidators randomized MaxValidators
-func GenMaxValidators(r *rand.Rand) (maxValidators uint32) {
+// genMaxValidators returns randomized MaxValidators
+func genMaxValidators(r *rand.Rand) (maxValidators uint32) {
return uint32(r.Intn(250) + 1)
}
-// GetHistEntries randomized HistoricalEntries between 0-100.
-func GetHistEntries(r *rand.Rand) uint32 {
+// getHistEntries returns randomized HistoricalEntries between 0-100.
+func getHistEntries(r *rand.Rand) uint32 {
return uint32(r.Intn(int(types.DefaultHistoricalEntries + 1)))
}
@@ -47,17 +47,17 @@ func RandomizedGenState(simState *module.SimulationState) {
simState.AppParams.GetOrGenerate(
simState.Cdc, unbondingTime, &unbondTime, simState.Rand,
- func(r *rand.Rand) { unbondTime = GenUnbondingTime(r) },
+ func(r *rand.Rand) { unbondTime = genUnbondingTime(r) },
)
simState.AppParams.GetOrGenerate(
simState.Cdc, maxValidators, &maxVals, simState.Rand,
- func(r *rand.Rand) { maxVals = GenMaxValidators(r) },
+ func(r *rand.Rand) { maxVals = genMaxValidators(r) },
)
simState.AppParams.GetOrGenerate(
simState.Cdc, historicalEntries, &histEntries, simState.Rand,
- func(r *rand.Rand) { histEntries = GetHistEntries(r) },
+ func(r *rand.Rand) { histEntries = getHistEntries(r) },
)
// NOTE: the slashing module need to be defined after the staking module on the
diff --git a/x/staking/simulation/genesis_test.go b/x/staking/simulation/genesis_test.go
index a307ce9ad7..f7b31b29e1 100644
--- a/x/staking/simulation/genesis_test.go
+++ b/x/staking/simulation/genesis_test.go
@@ -68,7 +68,7 @@ func TestRandomizedGenState(t *testing.T) {
require.Equal(t, "1", stakingGenesis.Validators[2].MinSelfDelegation.String())
}
-// TestRandomizedGenState tests abnormal scenarios of applying RandomizedGenState.
+// TestRandomizedGenState1 tests abnormal scenarios of applying RandomizedGenState.
func TestRandomizedGenState1(t *testing.T) {
interfaceRegistry := codectypes.NewInterfaceRegistry()
cdc := codec.NewProtoCodec(interfaceRegistry)
diff --git a/x/staking/simulation/params.go b/x/staking/simulation/params.go
index ffbbe4fe47..30789d3467 100644
--- a/x/staking/simulation/params.go
+++ b/x/staking/simulation/params.go
@@ -6,9 +6,8 @@ import (
"fmt"
"math/rand"
- "github.com/cosmos/cosmos-sdk/x/simulation"
-
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
+ "github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
@@ -18,17 +17,17 @@ func ParamChanges(r *rand.Rand) []simtypes.ParamChange {
return []simtypes.ParamChange{
simulation.NewSimParamChange(types.ModuleName, string(types.KeyMaxValidators),
func(r *rand.Rand) string {
- return fmt.Sprintf("%d", GenMaxValidators(r))
+ return fmt.Sprintf("%d", genMaxValidators(r))
},
),
simulation.NewSimParamChange(types.ModuleName, string(types.KeyUnbondingTime),
func(r *rand.Rand) string {
- return fmt.Sprintf("\"%d\"", GenUnbondingTime(r))
+ return fmt.Sprintf("\"%d\"", genUnbondingTime(r))
},
),
simulation.NewSimParamChange(types.ModuleName, string(types.KeyHistoricalEntries),
func(r *rand.Rand) string {
- return fmt.Sprintf("%d", GetHistEntries(r))
+ return fmt.Sprintf("%d", getHistEntries(r))
},
),
}
diff --git a/x/staking/spec/01_state.md b/x/staking/spec/01_state.md
index 7238994118..9dacbb22fd 100644
--- a/x/staking/spec/01_state.md
+++ b/x/staking/spec/01_state.md
@@ -4,6 +4,10 @@ order: 1
# State
+## Pool
+
+Pool is used for tracking bonded and not-bonded token supply of the bond denomination.
+
## LastTotalPower
LastTotalPower tracks the total amounts of bonded tokens recorded during the previous end block.
diff --git a/x/staking/spec/03_messages.md b/x/staking/spec/03_messages.md
index 8b5fa28d66..4dd654227d 100644
--- a/x/staking/spec/03_messages.md
+++ b/x/staking/spec/03_messages.md
@@ -6,16 +6,16 @@ order: 3
In this section we describe the processing of the staking messages and the corresponding updates to the state. All created/modified state objects specified by each message are defined within the [state](./02_state_transitions.md) section.
-## Msg/CreateValidator
+## MsgCreateValidator
-A validator is created using the `Msg/CreateValidator` service message.
+A validator is created using the `MsgCreateValidator` message.
The validator must be created with an initial delegation from the operator.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L16-L17
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L35-L51
-This service message is expected to fail if:
+This message is expected to fail if:
- another validator with this operator address is already registered
- another validator with this pubkey is already registered
@@ -26,32 +26,32 @@ This service message is expected to fail if:
- the initial `MaxChangeRate` is either negative or > `MaxRate`
- the description fields are too large
-This service message creates and stores the `Validator` object at appropriate indexes.
+This message creates and stores the `Validator` object at appropriate indexes.
Additionally a self-delegation is made with the initial tokens delegation
tokens `Delegation`. The validator always starts as unbonded but may be bonded
in the first end-block.
-## Msg/EditValidator
+## MsgEditValidator
The `Description`, `CommissionRate` of a validator can be updated using the
-`Msg/EditCandidacy` service message.
+`MsgEditValidator` message.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L19-L20
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L56-L76
-This service message is expected to fail if:
+This message is expected to fail if:
- the initial `CommissionRate` is either negative or > `MaxRate`
- the `CommissionRate` has already been updated within the previous 24 hours
- the `CommissionRate` is > `MaxChangeRate`
- the description fields are too large
-This service message stores the updated `Validator` object.
+This message stores the updated `Validator` object.
-## Msg/Delegate
+## MsgDelegate
-Within this service message the delegator provides coins, and in return receives
+Within this message the delegator provides coins, and in return receives
some amount of their validator's (newly created) delegator-shares that are
assigned to `Delegation.Shares`.
@@ -59,9 +59,9 @@ assigned to `Delegation.Shares`.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L81-L90
-This service message is expected to fail if:
+This message is expected to fail if:
-- the validator is does not exist
+- the validator does not exist
- the `Amount` `Coin` has a denomination different than one defined by `params.BondDenom`
- the exchange rate is invalid, meaning the validator has no tokens (due to slashing) but there are outstanding shares
- the amount delegated is less than the minimum allowed delegation
@@ -82,20 +82,20 @@ will not be added to the power index until it is unjailed.

-## Msg/Undelegate
+## MsgUndelegate
-The `Msg/Undelegate` service message allows delegators to undelegate their tokens from
+The `MsgUndelegate` message allows delegators to undelegate their tokens from
validator.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L30-L32
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L112-L121
-This service message returns a response containing the completion time of the undelegation:
+This message returns a response containing the completion time of the undelegation:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L123-L126
-This service message is expected to fail if:
+This message is expected to fail if:
- the delegation doesn't exist
- the validator doesn't exist
@@ -103,7 +103,7 @@ This service message is expected to fail if:
- existing `UnbondingDelegation` has maximum entries as defined by `params.MaxEntries`
- the `Amount` has a denomination different than one defined by `params.BondDenom`
-When this service message is processed the following actions occur:
+When this message is processed the following actions occur:
- validator's `DelegatorShares` and the delegation's `Shares` are both reduced by the message `SharesAmount`
- calculate the token worth of the shares remove that amount tokens held within the validator
@@ -116,7 +116,7 @@ When this service message is processed the following actions occur:

-## Msg/BeginRedelegate
+## MsgBeginRedelegate
The redelegation command allows delegators to instantly switch validators. Once
the unbonding period has passed, the redelegation is automatically completed in
@@ -126,11 +126,11 @@ the EndBlocker.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L95-L105
-This service message returns a response containing the completion time of the redelegation:
+This message returns a response containing the completion time of the redelegation:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L107-L110
-This service message is expected to fail if:
+This message is expected to fail if:
- the delegation doesn't exist
- the source or destination validators don't exist
@@ -139,7 +139,7 @@ This service message is expected to fail if:
- existing `Redelegation` has maximum entries as defined by `params.MaxEntries`
- the `Amount` `Coin` has a denomination different than one defined by `params.BondDenom`
-When this service message is processed the following actions occur:
+When this message is processed the following actions occur:
- the source validator's `DelegatorShares` and the delegations `Shares` are both reduced by the message `SharesAmount`
- calculate the token worth of the shares remove that amount tokens held within the source validator.
diff --git a/x/staking/spec/07_events.md b/x/staking/spec/07_events.md
index 660319b3c1..f219fa2ca4 100644
--- a/x/staking/spec/07_events.md
+++ b/x/staking/spec/07_events.md
@@ -18,9 +18,9 @@ The staking module emits the following events:
| complete_redelegation | destination_validator | {dstValidatorAddress} |
| complete_redelegation | delegator | {delegatorAddress} |
-## Service Messages
+## Msg's
-### Msg/CreateValidator
+### MsgCreateValidator
| Type | Attribute Key | Attribute Value |
| ---------------- | ------------- | ------------------ |
@@ -30,7 +30,7 @@ The staking module emits the following events:
| message | action | create_validator |
| message | sender | {senderAddress} |
-### Msg/EditValidator
+### MsgEditValidator
| Type | Attribute Key | Attribute Value |
| -------------- | ------------------- | ------------------- |
@@ -40,7 +40,7 @@ The staking module emits the following events:
| message | action | edit_validator |
| message | sender | {senderAddress} |
-### Msg/Delegate
+### MsgDelegate
| Type | Attribute Key | Attribute Value |
| -------- | ------------- | ------------------ |
@@ -50,7 +50,7 @@ The staking module emits the following events:
| message | action | delegate |
| message | sender | {senderAddress} |
-### Msg/Undelegate
+### MsgUndelegate
| Type | Attribute Key | Attribute Value |
| ------- | ------------------- | ------------------ |
@@ -63,7 +63,7 @@ The staking module emits the following events:
- [0] Time is formatted in the RFC3339 standard
-### Msg/BeginRedelegate
+### MsgBeginRedelegate
| Type | Attribute Key | Attribute Value |
| ---------- | --------------------- | --------------------- |
diff --git a/x/staking/spec/README.md b/x/staking/spec/README.md
index a2cb7cf3a8..8eb42de8aa 100644
--- a/x/staking/spec/README.md
+++ b/x/staking/spec/README.md
@@ -38,11 +38,11 @@ network.
- [Delegations](02_state_transitions.md#delegations)
- [Slashing](02_state_transitions.md#slashing)
3. **[Messages](03_messages.md)**
- - [Msg/CreateValidator](03_messages.md#msgcreatevalidator)
- - [Msg/EditValidator](03_messages.md#msgeditvalidator)
- - [Msg/Delegate](03_messages.md#msgdelegate)
- - [Msg/BeginUnbonding](03_messages.md#msgbeginunbonding)
- - [Msg/BeginRedelegate](03_messages.md#msgbeginredelegate)
+ - [MsgCreateValidator](03_messages.md#msgcreatevalidator)
+ - [MsgEditValidator](03_messages.md#msgeditvalidator)
+ - [MsgDelegate](03_messages.md#msgdelegate)
+ - [MsgUndelegate](03_messages.md#msgundelegate)
+ - [MsgBeginRedelegate](03_messages.md#msgbeginredelegate)
4. **[Begin-Block](04_begin_block.md)**
- [Historical Info Tracking](04_begin_block.md#historical-info-tracking)
5. **[End-Block ](05_end_block.md)**
@@ -51,5 +51,5 @@ network.
6. **[Hooks](06_hooks.md)**
7. **[Events](07_events.md)**
- [EndBlocker](07_events.md#endblocker)
- - [Handlers](07_events.md#handlers)
+ - [Msg's](07_events.md#msg's)
8. **[Parameters](08_params.md)**