Merge branch 'master' into master

This commit is contained in:
Shahan Khatchadourian 2021-05-10 11:50:18 -07:00 committed by GitHub
commit 38762621a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 629 additions and 381 deletions

View File

@ -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

View File

@ -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)

View File

@ -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 |
<!-- end enums -->
@ -7168,7 +7167,7 @@ of coins from a delegator and source validator to a destination validator.
<a name="cosmos.staking.v1beta1.MsgBeginRedelegateResponse"></a>
### 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.
<a name="cosmos.staking.v1beta1.MsgCreateValidatorResponse"></a>
### MsgCreateValidatorResponse
MsgCreateValidatorResponse defines the Msg/CreateValidator response type.
MsgCreateValidatorResponse defines the MsgCreateValidator response type.
@ -7232,7 +7231,7 @@ from a delegator to a validator.
<a name="cosmos.staking.v1beta1.MsgDelegateResponse"></a>
### 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.
<a name="cosmos.staking.v1beta1.MsgEditValidatorResponse"></a>
### MsgEditValidatorResponse
MsgEditValidatorResponse defines the Msg/EditValidator response type.
MsgEditValidatorResponse defines the MsgEditValidator response type.
@ -7288,7 +7287,7 @@ delegate and a validator.
<a name="cosmos.staking.v1beta1.MsgUndelegateResponse"></a>
### MsgUndelegateResponse
MsgUndelegateResponse defines the Msg/Undelegate response type.
MsgUndelegateResponse defines the MsgUndelegate response type.
| Field | Type | Label | Description |

2
go.mod
View File

@ -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

4
go.sum
View File

@ -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=

View File

@ -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.

View File

@ -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"];

View File

@ -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
}

View File

@ -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
}

View File

@ -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()
}

View File

@ -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
}

View File

@ -25,7 +25,7 @@ func NewMsgGrant(granter sdk.AccAddress, grantee sdk.AccAddress, a Authorization
m := &MsgGrant{
Granter: granter.String(),
Grantee: grantee.String(),
Expiration: expiration,
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

View File

@ -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)
}

View File

@ -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.
@ -40,8 +37,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
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"`
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,17 +503,8 @@ 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])
size, err := m.Grant.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
@ -527,7 +513,6 @@ func (m *MsgGrant) MarshalToSizedBuffer(dAtA []byte) (int, error) {
}
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
}

View File

@ -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(),
)
}
```

View File

@ -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)

View File

@ -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])
}

View File

@ -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
}
}

View File

@ -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)
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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/).
@ -63,10 +63,10 @@ type Keeper interface {
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
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)
@ -80,8 +80,6 @@ type Keeper interface {
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
}
@ -104,8 +102,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
}

View File

@ -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)
```

View File

@ -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 {

View File

@ -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.

View File

@ -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
}

View File

@ -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 {

View File

@ -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)

View File

@ -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")

View File

@ -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]

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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))
},
),
}

View File

@ -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.

View File

@ -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.
![Delegation sequence](../../../docs/uml/svg/delegation_sequence.svg)
## 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:
![Unbond sequence](../../../docs/uml/svg/unbond_sequence.svg)
## 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.

View File

@ -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 |
| ---------- | --------------------- | --------------------- |

View File

@ -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)**