Merge branch 'master' into master
This commit is contained in:
commit
38762621a3
|
@ -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`.
|
* `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.
|
* 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.
|
* (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
|
### State Machine Breaking
|
||||||
|
|
|
@ -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)
|
|
@ -1323,8 +1323,7 @@ account with the provided expiration time.
|
||||||
| ----- | ---- | ----- | ----------- |
|
| ----- | ---- | ----- | ----------- |
|
||||||
| `granter` | [string](#string) | | |
|
| `granter` | [string](#string) | | |
|
||||||
| `grantee` | [string](#string) | | |
|
| `grantee` | [string](#string) | | |
|
||||||
| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | |
|
| `grant` | [Grant](#cosmos.authz.v1beta1.Grant) | | |
|
||||||
| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -6183,9 +6182,9 @@ AuthorizationType defines the type of staking module authorization type
|
||||||
| Name | Number | Description |
|
| Name | Number | Description |
|
||||||
| ---- | ------ | ----------- |
|
| ---- | ------ | ----------- |
|
||||||
| AUTHORIZATION_TYPE_UNSPECIFIED | 0 | AUTHORIZATION_TYPE_UNSPECIFIED specifies an unknown authorization type |
|
| 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_DELEGATE | 1 | AUTHORIZATION_TYPE_DELEGATE defines an authorization type for MsgDelegate |
|
||||||
| AUTHORIZATION_TYPE_UNDELEGATE | 2 | AUTHORIZATION_TYPE_UNDELEGATE defines an authorization type for Msg/Undelegate |
|
| 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 Msg/BeginRedelegate |
|
| AUTHORIZATION_TYPE_REDELEGATE | 3 | AUTHORIZATION_TYPE_REDELEGATE defines an authorization type for MsgBeginRedelegate |
|
||||||
|
|
||||||
|
|
||||||
<!-- end enums -->
|
<!-- 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>
|
<a name="cosmos.staking.v1beta1.MsgBeginRedelegateResponse"></a>
|
||||||
|
|
||||||
### MsgBeginRedelegateResponse
|
### MsgBeginRedelegateResponse
|
||||||
MsgBeginRedelegateResponse defines the Msg/BeginRedelegate response type.
|
MsgBeginRedelegateResponse defines the MsgBeginRedelegate response type.
|
||||||
|
|
||||||
|
|
||||||
| Field | Type | Label | Description |
|
| 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>
|
<a name="cosmos.staking.v1beta1.MsgCreateValidatorResponse"></a>
|
||||||
|
|
||||||
### MsgCreateValidatorResponse
|
### 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>
|
<a name="cosmos.staking.v1beta1.MsgDelegateResponse"></a>
|
||||||
|
|
||||||
### MsgDelegateResponse
|
### 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>
|
<a name="cosmos.staking.v1beta1.MsgEditValidatorResponse"></a>
|
||||||
|
|
||||||
### MsgEditValidatorResponse
|
### 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>
|
<a name="cosmos.staking.v1beta1.MsgUndelegateResponse"></a>
|
||||||
|
|
||||||
### MsgUndelegateResponse
|
### MsgUndelegateResponse
|
||||||
MsgUndelegateResponse defines the Msg/Undelegate response type.
|
MsgUndelegateResponse defines the MsgUndelegate response type.
|
||||||
|
|
||||||
|
|
||||||
| Field | Type | Label | Description |
|
| Field | Type | Label | Description |
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -30,7 +30,7 @@ require (
|
||||||
github.com/jhump/protoreflect v1.8.2
|
github.com/jhump/protoreflect v1.8.2
|
||||||
github.com/magiconair/properties v1.8.5
|
github.com/magiconair/properties v1.8.5
|
||||||
github.com/mattn/go-isatty v0.0.12
|
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/pelletier/go-toml v1.8.1 // indirect
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/prometheus/client_golang v1.10.0
|
github.com/prometheus/client_golang v1.10.0
|
||||||
|
|
4
go.sum
4
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.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.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||||
github.com/openzipkin/zipkin-go v0.2.2/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.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ=
|
||||||
github.com/otiai10/copy v1.5.1/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E=
|
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 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 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI=
|
||||||
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
|
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
|
||||||
|
|
|
@ -6,6 +6,7 @@ import "gogoproto/gogo.proto";
|
||||||
import "google/protobuf/timestamp.proto";
|
import "google/protobuf/timestamp.proto";
|
||||||
import "google/protobuf/any.proto";
|
import "google/protobuf/any.proto";
|
||||||
import "cosmos/base/abci/v1beta1/abci.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 go_package = "github.com/cosmos/cosmos-sdk/x/authz";
|
||||||
option (gogoproto.goproto_getters_all) = false;
|
option (gogoproto.goproto_getters_all) = false;
|
||||||
|
@ -32,8 +33,7 @@ message MsgGrant {
|
||||||
string granter = 1;
|
string granter = 1;
|
||||||
string grantee = 2;
|
string grantee = 2;
|
||||||
|
|
||||||
google.protobuf.Any authorization = 3 [(cosmos_proto.accepts_interface) = "Authorization"];
|
cosmos.authz.v1beta1.Grant grant = 3 [(gogoproto.nullable) = false];
|
||||||
google.protobuf.Timestamp expiration = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MsgExecResponse defines the Msg/MsgExecResponse response type.
|
// MsgExecResponse defines the Msg/MsgExecResponse response type.
|
||||||
|
|
|
@ -52,7 +52,7 @@ message Supply {
|
||||||
option (gogoproto.equal) = true;
|
option (gogoproto.equal) = true;
|
||||||
option (gogoproto.goproto_getters) = false;
|
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
|
repeated cosmos.base.v1beta1.Coin total = 1
|
||||||
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
|
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
|
||||||
|
|
|
@ -32,7 +32,7 @@ func (s msgServer) CreateVestingAccount(goCtx context.Context, msg *types.MsgCre
|
||||||
ak := s.AccountKeeper
|
ak := s.AccountKeeper
|
||||||
bk := s.BankKeeper
|
bk := s.BankKeeper
|
||||||
|
|
||||||
if err := bk.SendEnabledCoins(ctx, msg.Amount...); err != nil {
|
if err := bk.IsSendEnabledCoins(ctx, msg.Amount...); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
// BankKeeper defines the expected interface contract the vesting module requires
|
// BankKeeper defines the expected interface contract the vesting module requires
|
||||||
// for creating vesting accounts with funds.
|
// for creating vesting accounts with funds.
|
||||||
type BankKeeper interface {
|
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
|
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
|
||||||
BlockedAddr(addr sdk.AccAddress) bool
|
BlockedAddr(addr sdk.AccAddress) bool
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,24 +9,23 @@ import (
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewGrant returns new AuthrizationGrant
|
// NewGrant returns new Grant
|
||||||
func NewGrant(authorization Authorization, expiration time.Time) (Grant, error) {
|
func NewGrant(a Authorization, expiration time.Time) (Grant, error) {
|
||||||
auth := Grant{
|
g := Grant{
|
||||||
Expiration: expiration,
|
Expiration: expiration,
|
||||||
}
|
}
|
||||||
msg, ok := authorization.(proto.Message)
|
msg, ok := a.(proto.Message)
|
||||||
if !ok {
|
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)
|
any, err := cdctypes.NewAnyWithValue(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Grant{}, err
|
return Grant{}, err
|
||||||
}
|
}
|
||||||
|
g.Authorization = any
|
||||||
|
|
||||||
auth.Authorization = any
|
return g, nil
|
||||||
|
|
||||||
return auth, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -34,16 +33,32 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
|
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
|
||||||
func (auth Grant) UnpackInterfaces(unpacker cdctypes.AnyUnpacker) error {
|
func (g Grant) UnpackInterfaces(unpacker cdctypes.AnyUnpacker) error {
|
||||||
var authorization Authorization
|
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.
|
// GetAuthorization returns the cached value from the Grant.Authorization if present.
|
||||||
func (auth Grant) GetAuthorization() Authorization {
|
func (g Grant) GetAuthorization() Authorization {
|
||||||
authorization, ok := auth.Authorization.GetCachedValue().(Authorization)
|
if g.Authorization == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
a, ok := g.Authorization.GetCachedValue().(Authorization)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ func NewMsgGrant(granter sdk.AccAddress, grantee sdk.AccAddress, a Authorization
|
||||||
m := &MsgGrant{
|
m := &MsgGrant{
|
||||||
Granter: granter.String(),
|
Granter: granter.String(),
|
||||||
Grantee: grantee.String(),
|
Grantee: grantee.String(),
|
||||||
Expiration: expiration,
|
Grant: Grant{Expiration: expiration},
|
||||||
}
|
}
|
||||||
err := m.SetAuthorization(a)
|
err := m.SetAuthorization(a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -57,26 +57,12 @@ func (msg MsgGrant) ValidateBasic() error {
|
||||||
if granter.Equals(grantee) {
|
if granter.Equals(grantee) {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "granter and grantee cannot be same")
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "granter and grantee cannot be same")
|
||||||
}
|
}
|
||||||
|
return msg.Grant.ValidateBasic()
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAuthorization returns the cache value from the MsgGrant.Authorization if present.
|
// GetAuthorization returns the cache value from the MsgGrant.Authorization if present.
|
||||||
func (msg *MsgGrant) GetAuthorization() Authorization {
|
func (msg *MsgGrant) GetAuthorization() Authorization {
|
||||||
a, ok := msg.Authorization.GetCachedValue().(Authorization)
|
return msg.Grant.GetAuthorization()
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return a
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAuthorization converts Authorization to any and adds it to MsgGrant.Authorization.
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
msg.Authorization = any
|
msg.Grant.Authorization = any
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,8 +94,7 @@ func (msg MsgExec) UnpackInterfaces(unpacker cdctypes.AnyUnpacker) error {
|
||||||
|
|
||||||
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
|
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
|
||||||
func (msg MsgGrant) UnpackInterfaces(unpacker cdctypes.AnyUnpacker) error {
|
func (msg MsgGrant) UnpackInterfaces(unpacker cdctypes.AnyUnpacker) error {
|
||||||
var a Authorization
|
return msg.Grant.UnpackInterfaces(unpacker)
|
||||||
return unpacker.UnpackAny(msg.Authorization, &a)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMsgRevoke creates a new MsgRevoke
|
// NewMsgRevoke creates a new MsgRevoke
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/authz"
|
"github.com/cosmos/cosmos-sdk/x/authz"
|
||||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
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)
|
||||||
|
}
|
||||||
|
|
143
x/authz/tx.pb.go
143
x/authz/tx.pb.go
|
@ -6,12 +6,11 @@ package authz
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
fmt "fmt"
|
fmt "fmt"
|
||||||
types "github.com/cosmos/cosmos-sdk/codec/types"
|
types1 "github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
types1 "github.com/cosmos/cosmos-sdk/types"
|
types "github.com/cosmos/cosmos-sdk/types"
|
||||||
_ "github.com/gogo/protobuf/gogoproto"
|
_ "github.com/gogo/protobuf/gogoproto"
|
||||||
grpc1 "github.com/gogo/protobuf/grpc"
|
grpc1 "github.com/gogo/protobuf/grpc"
|
||||||
proto "github.com/gogo/protobuf/proto"
|
proto "github.com/gogo/protobuf/proto"
|
||||||
github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
|
|
||||||
_ "github.com/regen-network/cosmos-proto"
|
_ "github.com/regen-network/cosmos-proto"
|
||||||
grpc "google.golang.org/grpc"
|
grpc "google.golang.org/grpc"
|
||||||
codes "google.golang.org/grpc/codes"
|
codes "google.golang.org/grpc/codes"
|
||||||
|
@ -20,14 +19,12 @@ import (
|
||||||
io "io"
|
io "io"
|
||||||
math "math"
|
math "math"
|
||||||
math_bits "math/bits"
|
math_bits "math/bits"
|
||||||
time "time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
var _ = proto.Marshal
|
var _ = proto.Marshal
|
||||||
var _ = fmt.Errorf
|
var _ = fmt.Errorf
|
||||||
var _ = math.Inf
|
var _ = math.Inf
|
||||||
var _ = time.Kitchen
|
|
||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
// is compatible with the proto package it is being compiled against.
|
// 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 {
|
type MsgGrant struct {
|
||||||
Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"`
|
Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"`
|
||||||
Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,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"`
|
Grant Grant `protobuf:"bytes,3,opt,name=grant,proto3" json:"grant"`
|
||||||
Expiration time.Time `protobuf:"bytes,4,opt,name=expiration,proto3,stdtime" json:"expiration"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MsgGrant) Reset() { *m = MsgGrant{} }
|
func (m *MsgGrant) Reset() { *m = MsgGrant{} }
|
||||||
|
@ -79,7 +75,7 @@ var xxx_messageInfo_MsgGrant proto.InternalMessageInfo
|
||||||
|
|
||||||
// MsgExecResponse defines the Msg/MsgExecResponse response type.
|
// MsgExecResponse defines the Msg/MsgExecResponse response type.
|
||||||
type MsgExecResponse struct {
|
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{} }
|
func (m *MsgExecResponse) Reset() { *m = MsgExecResponse{} }
|
||||||
|
@ -123,7 +119,7 @@ type MsgExec struct {
|
||||||
// Authorization Msg requests to execute. Each msg must implement Authorization interface
|
// 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))
|
// The x/authz will try to find a grant matching (msg.signers[0], grantee, MsgTypeURL(msg))
|
||||||
// triple and validate it.
|
// 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{} }
|
func (m *MsgExec) Reset() { *m = MsgExec{} }
|
||||||
|
@ -286,40 +282,39 @@ func init() {
|
||||||
func init() { proto.RegisterFile("cosmos/authz/v1beta1/tx.proto", fileDescriptor_3ceddab7d8589ad1) }
|
func init() { proto.RegisterFile("cosmos/authz/v1beta1/tx.proto", fileDescriptor_3ceddab7d8589ad1) }
|
||||||
|
|
||||||
var fileDescriptor_3ceddab7d8589ad1 = []byte{
|
var fileDescriptor_3ceddab7d8589ad1 = []byte{
|
||||||
// 523 bytes of a gzipped FileDescriptorProto
|
// 498 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x4d, 0x6f, 0xd3, 0x30,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0xcb, 0x6e, 0xd3, 0x40,
|
||||||
0x18, 0xae, 0xd7, 0xd2, 0xad, 0xef, 0x98, 0x60, 0xa1, 0x87, 0x2e, 0x62, 0x69, 0x14, 0xbe, 0x76,
|
0x14, 0xb5, 0x9b, 0x34, 0x25, 0x13, 0x24, 0xc0, 0x64, 0xe1, 0x1a, 0xea, 0x58, 0xe6, 0x95, 0x05,
|
||||||
0xa0, 0x8e, 0x56, 0x2e, 0x5c, 0x57, 0x81, 0x90, 0x80, 0x08, 0x29, 0x1a, 0x17, 0x2e, 0x55, 0xd2,
|
0x1d, 0xab, 0x61, 0x01, 0xdb, 0x46, 0x42, 0x48, 0x80, 0x85, 0x64, 0xc1, 0x86, 0x4d, 0x64, 0xa7,
|
||||||
0x19, 0x2f, 0x6a, 0x13, 0x47, 0xb1, 0x33, 0xb5, 0xfb, 0x15, 0xfb, 0x31, 0xfb, 0x11, 0xd5, 0x4e,
|
0xc3, 0xc4, 0x4a, 0xec, 0xb1, 0x7c, 0xc7, 0x25, 0xe9, 0x57, 0xf0, 0x31, 0x7c, 0x44, 0xc4, 0xaa,
|
||||||
0x93, 0xb8, 0x70, 0xe2, 0xa3, 0xfd, 0x13, 0x1c, 0x51, 0x6c, 0xa7, 0xb4, 0x40, 0x87, 0xc4, 0xa9,
|
0x4b, 0x56, 0x08, 0x92, 0x9f, 0x60, 0x89, 0x3c, 0x8f, 0x50, 0x50, 0x5a, 0x24, 0x56, 0x99, 0x3b,
|
||||||
0x7e, 0xfd, 0x3c, 0x7e, 0xfc, 0xf8, 0x79, 0xdf, 0x06, 0xf6, 0x07, 0x8c, 0xc7, 0x8c, 0xbb, 0x41,
|
0xe7, 0xe4, 0xdc, 0x73, 0xcf, 0xf5, 0xa0, 0x83, 0x31, 0x83, 0x8c, 0x41, 0x10, 0x57, 0x7c, 0x72,
|
||||||
0x2e, 0x4e, 0xcf, 0xdd, 0xb3, 0xc3, 0x90, 0x88, 0xe0, 0xd0, 0x15, 0x63, 0x9c, 0x66, 0x4c, 0x30,
|
0x16, 0x9c, 0x1e, 0x25, 0x84, 0xc7, 0x47, 0x01, 0x9f, 0xe3, 0xa2, 0x64, 0x9c, 0x59, 0x5d, 0x09,
|
||||||
0xa3, 0xa9, 0x60, 0x2c, 0x61, 0xac, 0x61, 0x73, 0x4f, 0xed, 0xf6, 0x25, 0xc7, 0xd5, 0x14, 0x59,
|
0x63, 0x01, 0x63, 0x05, 0x3b, 0xfb, 0xf2, 0x76, 0x24, 0x38, 0x81, 0xa2, 0x88, 0xc2, 0xe9, 0x52,
|
||||||
0x98, 0x4d, 0xca, 0x28, 0x53, 0xfb, 0xc5, 0x4a, 0xef, 0xb6, 0x29, 0x63, 0x74, 0x44, 0x5c, 0x59,
|
0x46, 0x99, 0xbc, 0xaf, 0x4f, 0xea, 0xb6, 0x47, 0x19, 0xa3, 0x33, 0x12, 0x88, 0x2a, 0xa9, 0x3e,
|
||||||
0x85, 0xf9, 0x47, 0x57, 0x44, 0x31, 0xe1, 0x22, 0x88, 0x53, 0x4d, 0xd8, 0xfb, 0x9d, 0x10, 0x24,
|
0x04, 0x3c, 0xcd, 0x08, 0xf0, 0x38, 0x2b, 0x14, 0x61, 0xff, 0x6f, 0x42, 0x9c, 0x2f, 0x14, 0x74,
|
||||||
0x13, 0x0d, 0x3d, 0xd0, 0x0e, 0xc3, 0x80, 0x13, 0x37, 0x08, 0x07, 0xd1, 0xc2, 0x65, 0x51, 0x28,
|
0x4f, 0x39, 0x4c, 0x62, 0x20, 0x41, 0x9c, 0x8c, 0xd3, 0x8d, 0xcb, 0xba, 0x50, 0x24, 0x6f, 0xeb,
|
||||||
0x92, 0xf3, 0x09, 0xc1, 0x96, 0xc7, 0xe9, 0xab, 0x2c, 0x48, 0x84, 0xd1, 0x82, 0x4d, 0x5a, 0x2c,
|
0x18, 0xd2, 0xb5, 0x60, 0xf8, 0x1f, 0xd1, 0xb5, 0x10, 0xe8, 0x8b, 0x32, 0xce, 0xb9, 0x65, 0xa3,
|
||||||
0x48, 0xd6, 0x42, 0x36, 0x3a, 0x68, 0xf8, 0x65, 0xf9, 0x0b, 0x21, 0xad, 0x8d, 0x65, 0x84, 0x18,
|
0x3d, 0x5a, 0x1f, 0x48, 0x69, 0x9b, 0x9e, 0xd9, 0x6f, 0x47, 0xba, 0xfc, 0x8d, 0x10, 0x7b, 0xe7,
|
||||||
0x1e, 0xec, 0x14, 0x6f, 0x64, 0x59, 0x74, 0x1e, 0x88, 0x88, 0x25, 0xad, 0xaa, 0x8d, 0x0e, 0xb6,
|
0x22, 0x42, 0xac, 0xa7, 0x68, 0x57, 0x1c, 0xed, 0x86, 0x67, 0xf6, 0x3b, 0x83, 0x3b, 0x78, 0x5b,
|
||||||
0xbb, 0x4d, 0xac, 0x8c, 0xe1, 0xd2, 0x18, 0x3e, 0x4a, 0x26, 0xbd, 0xdd, 0xab, 0xcb, 0xce, 0xce,
|
0x32, 0x58, 0xe8, 0x0f, 0x9b, 0xcb, 0x6f, 0x3d, 0x23, 0x92, 0x7c, 0xff, 0x15, 0xba, 0x11, 0x02,
|
||||||
0xd1, 0x32, 0xdd, 0x5f, 0x3d, 0x6d, 0xbc, 0x00, 0x20, 0xe3, 0x34, 0xca, 0x94, 0x56, 0x4d, 0x6a,
|
0x7d, 0x3e, 0x27, 0xe3, 0x88, 0x40, 0xc1, 0x72, 0x20, 0xd6, 0x33, 0xd4, 0x2a, 0x09, 0x54, 0x33,
|
||||||
0x99, 0x7f, 0x68, 0x1d, 0x97, 0x29, 0xf4, 0xb6, 0xa6, 0x5f, 0xda, 0x95, 0x8b, 0xaf, 0x6d, 0xe4,
|
0x2e, 0xda, 0x77, 0x06, 0x9e, 0x16, 0xab, 0x67, 0xc4, 0x62, 0x2c, 0x2d, 0x18, 0x09, 0x5e, 0xa4,
|
||||||
0x2f, 0x9d, 0x73, 0xde, 0xc0, 0x1d, 0x8f, 0xd3, 0x97, 0x63, 0x32, 0xf0, 0x09, 0x4f, 0x59, 0xc2,
|
0xf8, 0x3e, 0x43, 0x7b, 0x4a, 0xec, 0xa2, 0x55, 0xf3, 0x4f, 0xab, 0x2f, 0x51, 0x33, 0x03, 0x0a,
|
||||||
0x89, 0xf1, 0x1c, 0xea, 0x19, 0xe1, 0xf9, 0x48, 0xc8, 0xa7, 0x6d, 0x77, 0x6d, 0xac, 0xe3, 0x2f,
|
0xf6, 0x8e, 0xd7, 0xe8, 0x77, 0x06, 0x5d, 0x2c, 0xb3, 0xc5, 0x3a, 0x5b, 0x7c, 0x9c, 0x2f, 0x86,
|
||||||
0xe2, 0xc1, 0x32, 0x11, 0x1d, 0x0f, 0xf6, 0x25, 0xcf, 0xd7, 0x7c, 0x87, 0xc1, 0xa6, 0x16, 0x5b,
|
0xde, 0x97, 0xcf, 0x87, 0x77, 0xe1, 0x64, 0x8a, 0x43, 0xa0, 0x8f, 0x3d, 0x39, 0xc4, 0x71, 0xc5,
|
||||||
0x8e, 0x01, 0xad, 0xc6, 0xf0, 0x1a, 0x6a, 0x31, 0xa7, 0xbc, 0xb5, 0x61, 0x57, 0xd7, 0xbe, 0xde,
|
0x27, 0xac, 0x4c, 0xcf, 0x62, 0x9e, 0xb2, 0x3c, 0x12, 0x1a, 0xbe, 0x85, 0x6e, 0xea, 0xd8, 0xb4,
|
||||||
0xbe, 0xba, 0xec, 0xdc, 0xe7, 0x27, 0x43, 0xec, 0x71, 0xfa, 0xd4, 0x56, 0x93, 0xb1, 0x1a, 0x86,
|
0x7d, 0x3f, 0x46, 0xed, 0x10, 0x68, 0x44, 0x4e, 0xd9, 0x94, 0xfc, 0x57, 0x96, 0x1e, 0xba, 0x9e,
|
||||||
0xd4, 0x70, 0x0c, 0xb8, 0x5b, 0xb6, 0xa4, 0xb4, 0xef, 0x04, 0xd0, 0xf0, 0x38, 0xf5, 0xc9, 0x19,
|
0x01, 0x1d, 0xf1, 0x45, 0x41, 0x46, 0x55, 0x39, 0x13, 0x91, 0xb6, 0x23, 0x94, 0x01, 0x7d, 0xbb,
|
||||||
0x1b, 0x92, 0xff, 0xea, 0x93, 0x0d, 0xb7, 0x63, 0x4e, 0xfb, 0x62, 0x92, 0x92, 0x7e, 0x9e, 0x8d,
|
0x28, 0xc8, 0xbb, 0x72, 0xe6, 0xdf, 0x46, 0xb7, 0x36, 0x2d, 0x74, 0xdf, 0xc1, 0x4f, 0x13, 0x35,
|
||||||
0x64, 0x9b, 0x1a, 0x3e, 0xc4, 0x9c, 0x1e, 0x4f, 0x52, 0xf2, 0x3e, 0x1b, 0x39, 0xf7, 0x60, 0x77,
|
0x42, 0xa0, 0xd6, 0x1b, 0xb4, 0x2b, 0xf7, 0xe8, 0x6e, 0x5f, 0x82, 0x36, 0xec, 0x3c, 0xbc, 0x1a,
|
||||||
0x71, 0x45, 0x79, 0x6f, 0xf7, 0x07, 0x82, 0xaa, 0xc7, 0xa9, 0xf1, 0x0e, 0x6e, 0xa9, 0x19, 0xb1,
|
0xdf, 0xec, 0xe3, 0x35, 0x6a, 0x8a, 0x48, 0x0f, 0x2e, 0xe5, 0xd7, 0xb0, 0xf3, 0xe0, 0x4a, 0x78,
|
||||||
0xf0, 0xdf, 0x26, 0x1b, 0x97, 0x86, 0xcd, 0xc7, 0x37, 0xe3, 0x8b, 0x7e, 0xbc, 0x85, 0x9a, 0x8c,
|
0xa3, 0x16, 0xa1, 0x96, 0xca, 0xa6, 0x77, 0xe9, 0x1f, 0x24, 0xc1, 0x79, 0xf4, 0x0f, 0x82, 0xd6,
|
||||||
0x74, 0x7f, 0x2d, 0xbf, 0x80, 0xcd, 0x47, 0x37, 0xc2, 0x0b, 0x35, 0x1f, 0xea, 0x3a, 0x9b, 0xf6,
|
0x1c, 0x0e, 0x97, 0x3f, 0x5c, 0x63, 0xb9, 0x72, 0xcd, 0xf3, 0x95, 0x6b, 0x7e, 0x5f, 0xb9, 0xe6,
|
||||||
0xda, 0x03, 0x8a, 0x60, 0x3e, 0xf9, 0x07, 0xa1, 0xd4, 0xec, 0xf5, 0xa6, 0xdf, 0xad, 0xca, 0x74,
|
0xa7, 0xb5, 0x6b, 0x9c, 0xaf, 0x5d, 0xe3, 0xeb, 0xda, 0x35, 0xde, 0xdf, 0xa7, 0x29, 0x9f, 0x54,
|
||||||
0x66, 0xa1, 0xeb, 0x99, 0x85, 0xbe, 0xcd, 0x2c, 0x74, 0x31, 0xb7, 0x2a, 0xd7, 0x73, 0xab, 0xf2,
|
0x09, 0x1e, 0xb3, 0x4c, 0xbd, 0x46, 0xf5, 0x73, 0x08, 0x27, 0xd3, 0x60, 0x2e, 0xdf, 0x41, 0xd2,
|
||||||
0x79, 0x6e, 0x55, 0x3e, 0x3c, 0xa4, 0x91, 0x38, 0xcd, 0x43, 0x3c, 0x60, 0xb1, 0xfe, 0x23, 0xeb,
|
0x12, 0x1f, 0xc0, 0x93, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x4a, 0xa9, 0xb0, 0x59, 0xf3, 0x03,
|
||||||
0x9f, 0x0e, 0x3f, 0x19, 0xba, 0x63, 0xf5, 0x5d, 0x08, 0xeb, 0x72, 0x00, 0x9e, 0xfd, 0x0c, 0x00,
|
0x00, 0x00,
|
||||||
0x00, 0xff, 0xff, 0x5b, 0x69, 0x39, 0xef, 0x2e, 0x04, 0x00, 0x00,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
@ -508,17 +503,8 @@ func (m *MsgGrant) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
_ = i
|
_ = i
|
||||||
var l int
|
var l int
|
||||||
_ = l
|
_ = 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 {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -527,7 +513,6 @@ func (m *MsgGrant) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
}
|
}
|
||||||
i--
|
i--
|
||||||
dAtA[i] = 0x1a
|
dAtA[i] = 0x1a
|
||||||
}
|
|
||||||
if len(m.Grantee) > 0 {
|
if len(m.Grantee) > 0 {
|
||||||
i -= len(m.Grantee)
|
i -= len(m.Grantee)
|
||||||
copy(dAtA[i:], m.Grantee)
|
copy(dAtA[i:], m.Grantee)
|
||||||
|
@ -739,11 +724,7 @@ func (m *MsgGrant) Size() (n int) {
|
||||||
if l > 0 {
|
if l > 0 {
|
||||||
n += 1 + l + sovTx(uint64(l))
|
n += 1 + l + sovTx(uint64(l))
|
||||||
}
|
}
|
||||||
if m.Authorization != nil {
|
l = m.Grant.Size()
|
||||||
l = m.Authorization.Size()
|
|
||||||
n += 1 + l + sovTx(uint64(l))
|
|
||||||
}
|
|
||||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Expiration)
|
|
||||||
n += 1 + l + sovTx(uint64(l))
|
n += 1 + l + sovTx(uint64(l))
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
@ -920,7 +901,7 @@ func (m *MsgGrant) Unmarshal(dAtA []byte) error {
|
||||||
iNdEx = postIndex
|
iNdEx = postIndex
|
||||||
case 3:
|
case 3:
|
||||||
if wireType != 2 {
|
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
|
var msglen int
|
||||||
for shift := uint(0); ; shift += 7 {
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
@ -947,43 +928,7 @@ func (m *MsgGrant) Unmarshal(dAtA []byte) error {
|
||||||
if postIndex > l {
|
if postIndex > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
if m.Authorization == nil {
|
if err := m.Grant.Unmarshal(dAtA[iNdEx:postIndex]); err != 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 {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
iNdEx = postIndex
|
iNdEx = postIndex
|
||||||
|
@ -1067,7 +1012,7 @@ func (m *MsgExecResponse) Unmarshal(dAtA []byte) error {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
if m.Result == nil {
|
if m.Result == nil {
|
||||||
m.Result = &types1.Result{}
|
m.Result = &types.Result{}
|
||||||
}
|
}
|
||||||
if err := m.Result.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
if err := m.Result.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -1184,7 +1129,7 @@ func (m *MsgExec) Unmarshal(dAtA []byte) error {
|
||||||
if postIndex > l {
|
if postIndex > l {
|
||||||
return io.ErrUnexpectedEOF
|
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 {
|
if err := m.Msgs[len(m.Msgs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,14 +35,14 @@ with particular kinds of accounts.
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Create the keeper. Note, the `x/bank` module depends on the `x/auth` module
|
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.
|
sent to. Your application will need to define this method based your needs.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func NewApp(...) *App {
|
func NewApp(...) *App {
|
||||||
// ...
|
// ...
|
||||||
app.BankKeeper = bank.NewBaseKeeper(
|
app.BankKeeper = bank.NewBaseKeeper(
|
||||||
app.AccountKeeper, app.subspaces[bank.ModuleName], app.BlacklistedAccAddrs(),
|
app.AccountKeeper, app.subspaces[bank.ModuleName], app.BlocklistedAccAddrs(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -55,6 +55,7 @@ type BaseKeeper struct {
|
||||||
paramSpace paramtypes.Subspace
|
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) {
|
func (k BaseKeeper) GetPaginatedTotalSupply(ctx sdk.Context, pagination *query.PageRequest) (sdk.Coins, *query.PageResponse, error) {
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
supplyStore := prefix.NewStore(store, types.SupplyKey)
|
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) {
|
func (k BaseKeeper) GetDenomMetaData(ctx sdk.Context, denom string) (types.Metadata, bool) {
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
store = prefix.NewStore(store, types.DenomMetadataKey(denom))
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setSupply sets the supply for the given coin
|
||||||
func (k BaseKeeper) setSupply(ctx sdk.Context, coin sdk.Coin) {
|
func (k BaseKeeper) setSupply(ctx sdk.Context, coin sdk.Coin) {
|
||||||
intBytes, err := coin.Amount.Marshal()
|
intBytes, err := coin.Amount.Marshal()
|
||||||
if err != nil {
|
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 {
|
func (k BaseKeeper) trackDelegation(ctx sdk.Context, addr sdk.AccAddress, balance, amt sdk.Coins) error {
|
||||||
acc := k.ak.GetAccount(ctx, addr)
|
acc := k.ak.GetAccount(ctx, addr)
|
||||||
if acc == nil {
|
if acc == nil {
|
||||||
|
@ -460,6 +464,7 @@ func (k BaseKeeper) trackDelegation(ctx sdk.Context, addr sdk.AccAddress, balanc
|
||||||
return nil
|
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 {
|
func (k BaseKeeper) trackUndelegation(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error {
|
||||||
acc := k.ak.GetAccount(ctx, addr)
|
acc := k.ak.GetAccount(ctx, addr)
|
||||||
if acc == nil {
|
if acc == nil {
|
||||||
|
@ -476,6 +481,9 @@ func (k BaseKeeper) trackUndelegation(ctx sdk.Context, addr sdk.AccAddress, amt
|
||||||
return nil
|
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) {
|
func (k BaseViewKeeper) IterateTotalSupply(ctx sdk.Context, cb func(sdk.Coin) bool) {
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
supplyStore := prefix.NewStore(store, types.SupplyKey)
|
supplyStore := prefix.NewStore(store, types.SupplyKey)
|
||||||
|
|
|
@ -111,7 +111,7 @@ func (suite *IntegrationTestSuite) SetupTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *IntegrationTestSuite) TestSupply() {
|
func (suite *IntegrationTestSuite) TestSupply() {
|
||||||
_, ctx := suite.app, suite.ctx
|
ctx := suite.ctx
|
||||||
|
|
||||||
require := suite.Require()
|
require := suite.Require()
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ func (suite *IntegrationTestSuite) TestSupply() {
|
||||||
authKeeper, keeper := suite.initKeepersWithmAccPerms(make(map[string]bool))
|
authKeeper, keeper := suite.initKeepersWithmAccPerms(make(map[string]bool))
|
||||||
|
|
||||||
initialPower := int64(100)
|
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))
|
totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens))
|
||||||
|
|
||||||
// set burnerAcc balance
|
// set burnerAcc balance
|
||||||
|
@ -140,7 +140,7 @@ func (suite *IntegrationTestSuite) TestSupply() {
|
||||||
require.Equal(total.String(), "")
|
require.Equal(total.String(), "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *IntegrationTestSuite) TestSendCoinsFromModuleToAccount_Blacklist() {
|
func (suite *IntegrationTestSuite) TestSendCoinsFromModuleToAccount_Blocklist() {
|
||||||
ctx := suite.ctx
|
ctx := suite.ctx
|
||||||
|
|
||||||
// add module accounts to supply keeper
|
// add module accounts to supply keeper
|
||||||
|
@ -484,11 +484,11 @@ func (suite *IntegrationTestSuite) TestSendEnabled() {
|
||||||
barCoin := sdk.NewCoin("barcoin", sdk.OneInt())
|
barCoin := sdk.NewCoin("barcoin", sdk.OneInt())
|
||||||
|
|
||||||
// assert with default (all denom) send enabled both Bar and Bond Denom are enabled
|
// 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.IsSendEnabledCoin(ctx, barCoin))
|
||||||
suite.Require().Equal(enabled, app.BankKeeper.SendEnabledCoin(ctx, bondCoin))
|
suite.Require().Equal(enabled, app.BankKeeper.IsSendEnabledCoin(ctx, bondCoin))
|
||||||
|
|
||||||
// Both coins should be send enabled.
|
// Both coins should be send enabled.
|
||||||
err := app.BankKeeper.SendEnabledCoins(ctx, fooCoin, bondCoin)
|
err := app.BankKeeper.IsSendEnabledCoins(ctx, fooCoin, bondCoin)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
// Set default send_enabled to !enabled, add a foodenom that overrides default as enabled
|
// 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)
|
app.BankKeeper.SetParams(ctx, params)
|
||||||
|
|
||||||
// Expect our specific override to be enabled, others to be !enabled.
|
// 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.IsSendEnabledCoin(ctx, fooCoin))
|
||||||
suite.Require().Equal(!enabled, app.BankKeeper.SendEnabledCoin(ctx, barCoin))
|
suite.Require().Equal(!enabled, app.BankKeeper.IsSendEnabledCoin(ctx, barCoin))
|
||||||
suite.Require().Equal(!enabled, app.BankKeeper.SendEnabledCoin(ctx, bondCoin))
|
suite.Require().Equal(!enabled, app.BankKeeper.IsSendEnabledCoin(ctx, bondCoin))
|
||||||
|
|
||||||
// Foo coin should be send enabled.
|
// Foo coin should be send enabled.
|
||||||
err = app.BankKeeper.SendEnabledCoins(ctx, fooCoin)
|
err = app.BankKeeper.IsSendEnabledCoins(ctx, fooCoin)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
// Expect an error when one coin is not send enabled.
|
// 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)
|
suite.Require().Error(err)
|
||||||
|
|
||||||
// Expect an error when all coins are not send enabled.
|
// 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)
|
suite.Require().Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,12 +538,9 @@ func (suite *IntegrationTestSuite) TestMsgSendEvents() {
|
||||||
|
|
||||||
app.AccountKeeper.SetAccount(ctx, acc)
|
app.AccountKeeper.SetAccount(ctx, acc)
|
||||||
newCoins := sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50))
|
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))
|
suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr, addr2, newCoins))
|
||||||
|
|
||||||
events := ctx.EventManager().ABCIEvents()
|
|
||||||
suite.Require().Equal(2, len(events))
|
|
||||||
|
|
||||||
event1 := sdk.Event{
|
event1 := sdk.Event{
|
||||||
Type: types.EventTypeTransfer,
|
Type: types.EventTypeTransfer,
|
||||||
Attributes: []abci.EventAttribute{},
|
Attributes: []abci.EventAttribute{},
|
||||||
|
@ -570,17 +567,9 @@ func (suite *IntegrationTestSuite) TestMsgSendEvents() {
|
||||||
abci.EventAttribute{Key: []byte(types.AttributeKeySender), Value: []byte(addr.String())},
|
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 are shifted due to the funding account events
|
||||||
events = ctx.EventManager().ABCIEvents()
|
events := ctx.EventManager().ABCIEvents()
|
||||||
suite.Require().Equal(12, len(events))
|
suite.Require().Equal(10, len(events))
|
||||||
suite.Require().Equal(abci.Event(event1), events[8])
|
suite.Require().Equal(abci.Event(event1), events[8])
|
||||||
suite.Require().Equal(abci.Event(event2), events[9])
|
suite.Require().Equal(abci.Event(event2), events[9])
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ var _ types.MsgServer = msgServer{}
|
||||||
func (k msgServer) Send(goCtx context.Context, msg *types.MsgSend) (*types.MsgSendResponse, error) {
|
func (k msgServer) Send(goCtx context.Context, msg *types.MsgSend) (*types.MsgSendResponse, error) {
|
||||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
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
|
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
|
// NOTE: totalIn == totalOut should already have been checked
|
||||||
for _, in := range msg.Inputs {
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,8 @@ type SendKeeper interface {
|
||||||
GetParams(ctx sdk.Context) types.Params
|
GetParams(ctx sdk.Context) types.Params
|
||||||
SetParams(ctx sdk.Context, params types.Params)
|
SetParams(ctx sdk.Context, params types.Params)
|
||||||
|
|
||||||
SendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool
|
IsSendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool
|
||||||
SendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
|
IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
|
||||||
|
|
||||||
BlockedAddr(addr sdk.AccAddress) bool
|
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.
|
// SendCoins transfers amt coins from a sending account to a receiving account.
|
||||||
// An error is returned upon failure.
|
// An error is returned upon failure.
|
||||||
func (k BaseSendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error {
|
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)
|
err := k.subUnlockedCoins(ctx, fromAddr, amt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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))
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,20 +277,20 @@ func (k BaseSendKeeper) setBalance(ctx sdk.Context, addr sdk.AccAddress, balance
|
||||||
return nil
|
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
|
// any of the coins are not configured for sending. Returns nil if sending is enabled
|
||||||
// for all provided coin
|
// 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 {
|
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 sdkerrors.Wrapf(types.ErrSendDisabled, "%s transfers are currently disabled", coin.Denom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendEnabledCoin returns the current SendEnabled status of the provided coin's denom
|
// IsSendEnabledCoin returns the current SendEnabled status of the provided coin's denom
|
||||||
func (k BaseSendKeeper) SendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool {
|
func (k BaseSendKeeper) IsSendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool {
|
||||||
return k.GetParams(ctx).SendEnabledDenom(coin.Denom)
|
return k.GetParams(ctx).SendEnabledDenom(coin.Denom)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,7 +186,7 @@ func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterStoreDecoder registers a decoder for supply module's types
|
// 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.
|
// WeightedOperations returns the all the gov module operations with their respective weights.
|
||||||
func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation {
|
func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation {
|
||||||
|
|
|
@ -61,7 +61,7 @@ func SimulateMsgSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Operatio
|
||||||
simAccount, toSimAcc, coins, skip := randomSendFields(r, ctx, accs, bk, ak)
|
simAccount, toSimAcc, coins, skip := randomSendFields(r, ctx, accs, bk, ak)
|
||||||
|
|
||||||
// Check send_enabled status of each coin denom
|
// 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
|
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
|
// 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
|
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgMultiSend, err.Error()), nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,14 +12,14 @@ require.
|
||||||
Best practices dictate careful review of `bank` module code to ensure that
|
Best practices dictate careful review of `bank` module code to ensure that
|
||||||
permissions are limited in the way that you expect.
|
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
|
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
|
from directly and explicitly receiving funds through means such as `MsgSend` and
|
||||||
`MsgMultiSend` and direct API calls like `SendCoinsFromModuleToAccount`.
|
`MsgMultiSend` and direct API calls like `SendCoinsFromModuleToAccount`.
|
||||||
|
|
||||||
Typically, these addresses are module accounts. If these addresses receive funds
|
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.
|
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/).
|
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)
|
InitGenesis(sdk.Context, *types.GenesisState)
|
||||||
ExportGenesis(sdk.Context) *types.GenesisState
|
ExportGenesis(sdk.Context) *types.GenesisState
|
||||||
|
|
||||||
GetSupply(ctx sdk.Context) exported.SupplyI
|
GetSupply(ctx sdk.Context, denom string) sdk.Coin
|
||||||
SetSupply(ctx sdk.Context, supply exported.SupplyI)
|
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
|
GetDenomMetaData(ctx sdk.Context, denom string) (types.Metadata, bool)
|
||||||
SetDenomMetaData(ctx sdk.Context, denomMetaData types.Metadata)
|
SetDenomMetaData(ctx sdk.Context, denomMetaData types.Metadata)
|
||||||
IterateAllDenomMetaData(ctx sdk.Context, cb func(types.Metadata) bool)
|
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
|
DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error
|
||||||
UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr 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
|
types.QueryServer
|
||||||
}
|
}
|
||||||
|
@ -104,8 +102,8 @@ type SendKeeper interface {
|
||||||
GetParams(ctx sdk.Context) types.Params
|
GetParams(ctx sdk.Context) types.Params
|
||||||
SetParams(ctx sdk.Context, params types.Params)
|
SetParams(ctx sdk.Context, params types.Params)
|
||||||
|
|
||||||
SendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool
|
IsSendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool
|
||||||
SendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
|
IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
|
||||||
|
|
||||||
BlockedAddr(addr sdk.AccAddress) bool
|
BlockedAddr(addr sdk.AccAddress) bool
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,20 +6,21 @@ order: 3
|
||||||
|
|
||||||
## MsgSend
|
## 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
|
+++ 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
|
## MsgMultiSend
|
||||||
handleMsgSend(msg MsgSend)
|
|
||||||
inputSum = 0
|
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.
|
||||||
for input in inputs
|
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/bank/v1beta1/tx.proto#L33-L39
|
||||||
inputSum += input.Amount
|
|
||||||
outputSum = 0
|
The message will fail under the following conditions:
|
||||||
for output in outputs
|
- Any of the coins do not have sending enabled
|
||||||
outputSum += output.Amount
|
- Any of the `to` addresses are restricted
|
||||||
if inputSum != outputSum:
|
- Any of the coins are locked
|
||||||
fail with "input/output amount mismatch"
|
- The inputs and outputs do not correctly correspond to one another
|
||||||
|
|
||||||
return inputOutputCoins(msg.Inputs, msg.Outputs)
|
|
||||||
```
|
|
||||||
|
|
|
@ -426,44 +426,44 @@ func init() {
|
||||||
func init() { proto.RegisterFile("cosmos/bank/v1beta1/bank.proto", fileDescriptor_dd052eee12edf988) }
|
func init() { proto.RegisterFile("cosmos/bank/v1beta1/bank.proto", fileDescriptor_dd052eee12edf988) }
|
||||||
|
|
||||||
var fileDescriptor_dd052eee12edf988 = []byte{
|
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,
|
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,
|
0x14, 0xf6, 0x35, 0x8d, 0x49, 0x2f, 0xb0, 0x1c, 0x15, 0x72, 0x23, 0x61, 0x1b, 0x4b, 0x48, 0x29,
|
||||||
0xa2, 0x0e, 0x05, 0xb1, 0x64, 0x41, 0x4a, 0x41, 0xa8, 0x03, 0x02, 0xb9, 0x42, 0x48, 0x30, 0x44,
|
0xa2, 0x4e, 0x0a, 0x0c, 0x28, 0x0b, 0x52, 0xca, 0x0f, 0x75, 0x40, 0x20, 0x57, 0x08, 0x09, 0x86,
|
||||||
0xe7, 0xdc, 0x35, 0x58, 0xb5, 0xef, 0xac, 0xdc, 0x19, 0xd5, 0xff, 0x01, 0x13, 0x30, 0x32, 0x76,
|
0xe8, 0x9c, 0xbb, 0x06, 0xab, 0xf6, 0x9d, 0x95, 0x3b, 0x57, 0xf5, 0x7f, 0xc0, 0x04, 0x8c, 0x8c,
|
||||||
0x66, 0x62, 0xe0, 0x7f, 0xa0, 0x63, 0x05, 0x0b, 0x53, 0x40, 0xc9, 0xc2, 0xdc, 0xbf, 0x00, 0xdd,
|
0x9d, 0x59, 0xe1, 0x7f, 0xa0, 0x63, 0x05, 0x0b, 0x53, 0x40, 0xc9, 0xc2, 0xdc, 0xbf, 0x00, 0xf9,
|
||||||
0x9d, 0xf3, 0xa3, 0x52, 0x40, 0x0c, 0x0c, 0x4c, 0x79, 0xdf, 0x7b, 0xdf, 0xfb, 0xde, 0xd3, 0x77,
|
0xce, 0xf9, 0x51, 0x29, 0x20, 0x06, 0x06, 0xa6, 0xbc, 0xef, 0xbd, 0xef, 0x7d, 0xef, 0xe9, 0xbb,
|
||||||
0xcf, 0x81, 0x6e, 0x9f, 0x8b, 0x8c, 0x8b, 0x76, 0x8c, 0xd9, 0x61, 0xfb, 0xd5, 0x4e, 0x4c, 0x25,
|
0xe7, 0x40, 0xbb, 0xcf, 0x45, 0xc2, 0x45, 0x2b, 0xc4, 0xec, 0xa0, 0x75, 0xb8, 0x1d, 0x52, 0x89,
|
||||||
0xde, 0xd1, 0x20, 0xcc, 0x87, 0x5c, 0x72, 0x74, 0xd9, 0xd4, 0x43, 0x9d, 0xaa, 0xea, 0x9b, 0xeb,
|
0xb7, 0x15, 0xf0, 0xd3, 0x21, 0x97, 0x1c, 0x5d, 0xd6, 0x75, 0x5f, 0xa5, 0xca, 0x7a, 0x63, 0x7d,
|
||||||
0x03, 0x3e, 0xe0, 0xba, 0xde, 0x56, 0x91, 0xa1, 0x6e, 0x6e, 0x18, 0x6a, 0xcf, 0x14, 0xaa, 0x3e,
|
0xc0, 0x07, 0x5c, 0xd5, 0x5b, 0x45, 0xa4, 0xa9, 0x8d, 0x0d, 0x4d, 0xed, 0xe9, 0x42, 0xd9, 0xa7,
|
||||||
0x53, 0x9a, 0x4f, 0x11, 0x74, 0x36, 0xa5, 0xcf, 0x13, 0x66, 0xea, 0xc1, 0x57, 0x00, 0xed, 0x27,
|
0x4b, 0xf3, 0x29, 0x82, 0xce, 0xa6, 0xf4, 0x79, 0xc4, 0x74, 0xdd, 0xfb, 0x0a, 0xa0, 0xf9, 0x14,
|
||||||
0x78, 0x88, 0x33, 0x81, 0x0e, 0xe0, 0x45, 0x41, 0x19, 0xe9, 0x51, 0x86, 0xe3, 0x94, 0x12, 0x07,
|
0x0f, 0x71, 0x22, 0xd0, 0x3e, 0xbc, 0x28, 0x28, 0x23, 0x3d, 0xca, 0x70, 0x18, 0x53, 0x62, 0x01,
|
||||||
0xf8, 0xb5, 0x56, 0xf3, 0xb6, 0x1f, 0x2e, 0xd9, 0x23, 0xdc, 0xa7, 0x8c, 0x3c, 0x30, 0xbc, 0xee,
|
0xb7, 0xd2, 0xac, 0xdf, 0x72, 0xfd, 0x25, 0x7b, 0xf8, 0x7b, 0x94, 0x91, 0x07, 0x9a, 0xd7, 0xbd,
|
||||||
0xb5, 0xb3, 0x91, 0x77, 0xb5, 0xc4, 0x59, 0xda, 0x09, 0x16, 0xfb, 0x6f, 0xf2, 0x2c, 0x91, 0x34,
|
0x76, 0x36, 0x72, 0xae, 0xe6, 0x38, 0x89, 0x3b, 0xde, 0x62, 0xff, 0x4d, 0x9e, 0x44, 0x92, 0x26,
|
||||||
0xcb, 0x65, 0x19, 0x44, 0x4d, 0x31, 0xe7, 0xa3, 0x17, 0x70, 0x9d, 0xd0, 0x03, 0x5c, 0xa4, 0xb2,
|
0xa9, 0xcc, 0xbd, 0xa0, 0x2e, 0xe6, 0x7c, 0xf4, 0x12, 0xae, 0x13, 0xba, 0x8f, 0xb3, 0x58, 0xf6,
|
||||||
0x77, 0x6e, 0xde, 0x8a, 0x0f, 0x5a, 0x8d, 0xee, 0xd6, 0xd9, 0xc8, 0xbb, 0x6e, 0xd4, 0x96, 0xb1,
|
0xce, 0xcd, 0x5b, 0x71, 0x41, 0xb3, 0xd6, 0xdd, 0x3c, 0x1b, 0x39, 0xd7, 0xb5, 0xda, 0x32, 0xd6,
|
||||||
0x16, 0x55, 0x51, 0x45, 0x58, 0x58, 0xa6, 0xb3, 0xfa, 0xfe, 0xd8, 0xb3, 0x82, 0x87, 0xb0, 0xb9,
|
0xa2, 0x2a, 0x2a, 0x09, 0x0b, 0xcb, 0x74, 0x56, 0xdf, 0x1f, 0x3b, 0x86, 0xf7, 0x08, 0xd6, 0x17,
|
||||||
0x90, 0x44, 0xeb, 0xb0, 0x4e, 0x28, 0xe3, 0x99, 0x03, 0x7c, 0xd0, 0x5a, 0x8b, 0x0c, 0x40, 0x0e,
|
0x92, 0x68, 0x1d, 0x56, 0x09, 0x65, 0x3c, 0xb1, 0x80, 0x0b, 0x9a, 0x6b, 0x81, 0x06, 0xc8, 0x82,
|
||||||
0xbc, 0x70, 0x6e, 0x74, 0x34, 0x85, 0x9d, 0x86, 0x12, 0xf9, 0x79, 0xec, 0x81, 0xe0, 0x0d, 0x80,
|
0x17, 0xce, 0x8d, 0x0e, 0xa6, 0xb0, 0x53, 0x2b, 0x44, 0x7e, 0x1e, 0x3b, 0xc0, 0x7b, 0x03, 0x60,
|
||||||
0xf5, 0x3d, 0x96, 0x17, 0x52, 0xb1, 0x31, 0x21, 0x43, 0x2a, 0x44, 0xa5, 0x32, 0x85, 0x08, 0xc3,
|
0x75, 0x97, 0xa5, 0x99, 0x2c, 0xd8, 0x98, 0x90, 0x21, 0x15, 0xa2, 0x54, 0x99, 0x42, 0x84, 0x61,
|
||||||
0xba, 0x32, 0x54, 0x38, 0x2b, 0xda, 0xb0, 0x8d, 0xb9, 0x61, 0x82, 0xce, 0x0c, 0xdb, 0xe5, 0x09,
|
0xb5, 0x30, 0x54, 0x58, 0x2b, 0xca, 0xb0, 0x8d, 0xb9, 0x61, 0x82, 0xce, 0x0c, 0xdb, 0xe1, 0x11,
|
||||||
0xeb, 0xde, 0x3a, 0x19, 0x79, 0xd6, 0x87, 0xef, 0x5e, 0x6b, 0x90, 0xc8, 0x97, 0x45, 0x1c, 0xf6,
|
0xeb, 0xb6, 0x4f, 0x46, 0x8e, 0xf1, 0xe1, 0xbb, 0xd3, 0x1c, 0x44, 0xf2, 0x55, 0x16, 0xfa, 0x7d,
|
||||||
0x79, 0x56, 0xbd, 0x56, 0xf5, 0xb3, 0x2d, 0xc8, 0x61, 0x5b, 0x96, 0x39, 0x15, 0xba, 0x41, 0x44,
|
0x9e, 0x94, 0xaf, 0x55, 0xfe, 0x6c, 0x09, 0x72, 0xd0, 0x92, 0x79, 0x4a, 0x85, 0x6a, 0x10, 0x81,
|
||||||
0x46, 0xb9, 0xd3, 0x78, 0x6d, 0x16, 0xb2, 0x82, 0xb7, 0x00, 0xda, 0x8f, 0x0b, 0xf9, 0x1f, 0x6d,
|
0x56, 0xee, 0xd4, 0x5e, 0xeb, 0x85, 0x0c, 0xef, 0x2d, 0x80, 0xe6, 0x93, 0x4c, 0xfe, 0x47, 0x1b,
|
||||||
0xf4, 0x11, 0x40, 0x7b, 0xbf, 0xc8, 0xf3, 0xb4, 0x54, 0x73, 0x25, 0x97, 0x38, 0xad, 0x4e, 0xe7,
|
0x7d, 0x04, 0xd0, 0xdc, 0xcb, 0xd2, 0x34, 0xce, 0x8b, 0xb9, 0x92, 0x4b, 0x1c, 0x97, 0xa7, 0xf3,
|
||||||
0xdf, 0xce, 0xd5, 0xca, 0x9d, 0xdd, 0x6a, 0x2e, 0xf8, 0xf2, 0x69, 0xfb, 0xee, 0x8d, 0x3f, 0x76,
|
0x6f, 0xe7, 0x2a, 0xe5, 0xce, 0xc3, 0x72, 0x2e, 0xf8, 0xf2, 0x69, 0xeb, 0xee, 0x8d, 0x3f, 0x76,
|
||||||
0x1f, 0x99, 0x4f, 0x8b, 0x1e, 0xe5, 0x7c, 0x28, 0x29, 0x09, 0xcd, 0x92, 0x7b, 0x0e, 0x08, 0x9e,
|
0x1f, 0xe9, 0x4f, 0x2b, 0xa6, 0x03, 0xdc, 0xcf, 0x5b, 0x87, 0xed, 0x3b, 0x6d, 0x5f, 0xef, 0xb9,
|
||||||
0xc1, 0xb5, 0xfb, 0xea, 0x04, 0x9e, 0xb2, 0x44, 0xfe, 0xe6, 0x38, 0x36, 0x61, 0x43, 0x35, 0x32,
|
0x6b, 0x01, 0xef, 0x39, 0x5c, 0xbb, 0x5f, 0x5c, 0xc1, 0x33, 0x16, 0xc9, 0xdf, 0xdc, 0x47, 0x03,
|
||||||
0xca, 0xa4, 0xbe, 0x8e, 0x4b, 0xd1, 0x0c, 0x6b, 0xe3, 0xd3, 0x04, 0x0b, 0x2a, 0x9c, 0x9a, 0x5f,
|
0xd6, 0xe8, 0x51, 0xca, 0x19, 0x65, 0x52, 0x1d, 0xc8, 0xa5, 0x60, 0x86, 0x95, 0xf7, 0x71, 0x84,
|
||||||
0xd3, 0xc6, 0x1b, 0x18, 0x7c, 0x06, 0xb0, 0xf1, 0x88, 0x4a, 0x4c, 0xb0, 0xc4, 0xc8, 0x87, 0x4d,
|
0x05, 0x15, 0x56, 0xc5, 0xad, 0x28, 0xef, 0x35, 0xf4, 0x3e, 0x03, 0x58, 0x7b, 0x4c, 0x25, 0x26,
|
||||||
0x42, 0x45, 0x7f, 0x98, 0xe4, 0x32, 0xe1, 0xac, 0x92, 0x5f, 0x4c, 0xa1, 0x7b, 0x8a, 0xc1, 0x78,
|
0x58, 0x62, 0xe4, 0xc2, 0x3a, 0xa1, 0xa2, 0x3f, 0x8c, 0x52, 0x19, 0x71, 0x56, 0xca, 0x2f, 0xa6,
|
||||||
0xd6, 0x2b, 0x58, 0x22, 0xa7, 0xaf, 0xe5, 0x2e, 0xfd, 0xe0, 0x66, 0xfb, 0x46, 0x90, 0x4c, 0x43,
|
0xd0, 0xbd, 0x82, 0xc1, 0x78, 0xd2, 0xcb, 0x58, 0x24, 0xa7, 0x0f, 0x66, 0x2f, 0xfd, 0xe6, 0x66,
|
||||||
0x81, 0x10, 0x5c, 0x55, 0xde, 0x3a, 0x35, 0xad, 0xad, 0x63, 0xb5, 0x1d, 0x49, 0x44, 0x9e, 0xe2,
|
0xfb, 0x06, 0x90, 0x4c, 0x43, 0x81, 0x10, 0x5c, 0x2d, 0xec, 0xb5, 0x2a, 0x4a, 0x5b, 0xc5, 0xc5,
|
||||||
0xd2, 0x59, 0x35, 0x67, 0x51, 0x41, 0xc5, 0x66, 0x38, 0xa3, 0x4e, 0xdd, 0xb0, 0x55, 0x8c, 0xae,
|
0x76, 0x24, 0x12, 0x69, 0x8c, 0x73, 0x6b, 0x55, 0x5f, 0x46, 0x09, 0x0b, 0x36, 0xc3, 0x09, 0xb5,
|
||||||
0x40, 0x5b, 0x94, 0x59, 0xcc, 0x53, 0xc7, 0xd6, 0xd9, 0x0a, 0x75, 0x77, 0x4f, 0xc6, 0x2e, 0x38,
|
0xaa, 0x9a, 0x5d, 0xc4, 0xe8, 0x0a, 0x34, 0x45, 0x9e, 0x84, 0x3c, 0xb6, 0x4c, 0x95, 0x2d, 0x51,
|
||||||
0x1d, 0xbb, 0xe0, 0xc7, 0xd8, 0x05, 0xef, 0x26, 0xae, 0x75, 0x3a, 0x71, 0xad, 0x6f, 0x13, 0xd7,
|
0x77, 0xe7, 0x64, 0x6c, 0x83, 0xd3, 0xb1, 0x0d, 0x7e, 0x8c, 0x6d, 0xf0, 0x6e, 0x62, 0x1b, 0xa7,
|
||||||
0x7a, 0xbe, 0xf5, 0x37, 0xa6, 0xeb, 0x97, 0x8b, 0x6d, 0xfd, 0x1f, 0x73, 0xe7, 0x57, 0x00, 0x00,
|
0x13, 0xdb, 0xf8, 0x36, 0xb1, 0x8d, 0x17, 0x9b, 0x7f, 0xe3, 0xbb, 0x7a, 0xbc, 0xd0, 0x54, 0x7f,
|
||||||
0x00, 0xff, 0xff, 0xe7, 0x1c, 0xc1, 0x93, 0xeb, 0x04, 0x00, 0x00,
|
0x33, 0xb7, 0x7f, 0x05, 0x00, 0x00, 0xff, 0xff, 0xcc, 0x03, 0xbf, 0xe9, 0xee, 0x04, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *SendEnabled) Equal(that interface{}) bool {
|
func (this *SendEnabled) Equal(that interface{}) bool {
|
||||||
|
|
|
@ -21,8 +21,8 @@ const (
|
||||||
|
|
||||||
// KVStore keys
|
// KVStore keys
|
||||||
var (
|
var (
|
||||||
// BalancesPrefix is the for the account balances store. We use a byte
|
// BalancesPrefix is the prefix for the account balances store. We use a byte
|
||||||
// (instead of say `[]]byte("balances")` to save some disk space).
|
// (instead of `[]byte("balances")` to save some disk space).
|
||||||
BalancesPrefix = []byte{0x02}
|
BalancesPrefix = []byte{0x02}
|
||||||
SupplyKey = []byte{0x00}
|
SupplyKey = []byte{0x00}
|
||||||
DenomMetadataPrefix = []byte{0x1}
|
DenomMetadataPrefix = []byte{0x1}
|
||||||
|
@ -35,7 +35,7 @@ func DenomMetadataKey(denom string) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddressFromBalancesStore returns an account address from a balances prefix
|
// 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.
|
// iterator discards the actual prefix.
|
||||||
//
|
//
|
||||||
// If invalid key is passed, AddressFromBalancesStore returns ErrInvalidKey.
|
// If invalid key is passed, AddressFromBalancesStore returns ErrInvalidKey.
|
||||||
|
|
|
@ -660,7 +660,6 @@ $ %s query staking historical-info 5
|
||||||
|
|
||||||
params := &types.QueryHistoricalInfoRequest{Height: height}
|
params := &types.QueryHistoricalInfoRequest{Height: height}
|
||||||
res, err := queryClient.HistoricalInfo(cmd.Context(), params)
|
res, err := queryClient.HistoricalInfo(cmd.Context(), params)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,7 +230,7 @@ func (s *IntegrationTestSuite) TestGetCmdQueryValidator() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"happy case",
|
"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,
|
false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -415,7 +415,7 @@ func (s *IntegrationTestSuite) TestGetCmdQueryDelegations() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *IntegrationTestSuite) TestGetCmdQueryDelegationsTo() {
|
func (s *IntegrationTestSuite) TestGetCmdQueryValidatorDelegations() {
|
||||||
val := s.network.Validators[0]
|
val := s.network.Validators[0]
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
|
@ -755,7 +755,7 @@ func (s *IntegrationTestSuite) TestGetCmdQueryRedelegation() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *IntegrationTestSuite) TestGetCmdQueryRedelegationsFrom() {
|
func (s *IntegrationTestSuite) TestGetCmdQueryValidatorRedelegations() {
|
||||||
val := s.network.Validators[0]
|
val := s.network.Validators[0]
|
||||||
val2 := s.network.Validators[1]
|
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]
|
val := s.network.Validators[0]
|
||||||
|
|
||||||
details := "bio"
|
details := "bio"
|
||||||
|
@ -1041,7 +1041,7 @@ func (s *IntegrationTestSuite) TestNewCmdEditValidator() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *IntegrationTestSuite) TestNewCmdDelegate() {
|
func (s *IntegrationTestSuite) TestNewDelegateCmd() {
|
||||||
val := s.network.Validators[0]
|
val := s.network.Validators[0]
|
||||||
|
|
||||||
info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
|
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]
|
val := s.network.Validators[0]
|
||||||
val2 := s.network.Validators[1]
|
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]
|
val := s.network.Validators[0]
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
|
|
|
@ -384,6 +384,7 @@ func TestUndelegateFromUnbondingValidator(t *testing.T) {
|
||||||
selfDelegation := types.NewDelegation(addrVals[0].Bytes(), addrVals[0], issuedShares)
|
selfDelegation := types.NewDelegation(addrVals[0].Bytes(), addrVals[0], issuedShares)
|
||||||
app.StakingKeeper.SetDelegation(ctx, selfDelegation)
|
app.StakingKeeper.SetDelegation(ctx, selfDelegation)
|
||||||
|
|
||||||
|
// add bonded tokens to pool for delegations
|
||||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||||
require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
|
require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
|
||||||
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
||||||
|
@ -470,6 +471,7 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) {
|
||||||
selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
|
selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
|
||||||
app.StakingKeeper.SetDelegation(ctx, selfDelegation)
|
app.StakingKeeper.SetDelegation(ctx, selfDelegation)
|
||||||
|
|
||||||
|
// add bonded tokens to pool for delegations
|
||||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||||
require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
|
require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
|
||||||
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
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())
|
_, err = app.StakingKeeper.Undelegate(ctx, addrDels[1], addrVals[0], remainingTokens.ToDec())
|
||||||
require.NoError(t, err)
|
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])
|
validator, found = app.StakingKeeper.GetValidator(ctx, addrVals[0])
|
||||||
require.False(t, found, "%v", validator)
|
require.False(t, found, "%v", validator)
|
||||||
}
|
}
|
||||||
|
@ -556,6 +558,7 @@ func TestUnbondingAllDelegationFromValidator(t *testing.T) {
|
||||||
validator, issuedShares = validator.AddTokensFromDel(delTokens)
|
validator, issuedShares = validator.AddTokensFromDel(delTokens)
|
||||||
require.Equal(t, delTokens, issuedShares.RoundInt())
|
require.Equal(t, delTokens, issuedShares.RoundInt())
|
||||||
|
|
||||||
|
// add bonded tokens to pool for delegations
|
||||||
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
bondedPool := app.StakingKeeper.GetBondedPool(ctx)
|
||||||
require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
|
require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
|
||||||
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
|
||||||
|
|
|
@ -61,7 +61,7 @@ func (k Querier) Validators(c context.Context, req *types.QueryValidatorsRequest
|
||||||
return &types.QueryValidatorsResponse{Validators: validators, Pagination: pageRes}, nil
|
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) {
|
func (k Querier) Validator(c context.Context, req *types.QueryValidatorRequest) (*types.QueryValidatorResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
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
|
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) {
|
func (k Querier) Redelegations(c context.Context, req *types.QueryRedelegationsRequest) (*types.QueryRedelegationsResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
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
|
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) {
|
func (k Querier) DelegatorValidators(c context.Context, req *types.QueryDelegatorValidatorsRequest) (*types.QueryDelegatorValidatorsResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||||
|
|
|
@ -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
|
app, ctx, queryClient, vals := suite.app, suite.ctx, suite.queryClient, suite.vals
|
||||||
validator, found := app.StakingKeeper.GetValidator(ctx, vals[0].GetOperator())
|
validator, found := app.StakingKeeper.GetValidator(ctx, vals[0].GetOperator())
|
||||||
suite.True(found)
|
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
|
app, ctx, queryClient, addrs, vals := suite.app, suite.ctx, suite.queryClient, suite.addrs, suite.vals
|
||||||
|
|
||||||
addrAcc, addrAcc1 := addrs[0], addrs[1]
|
addrAcc, addrAcc1 := addrs[0], addrs[1]
|
||||||
|
|
|
@ -26,6 +26,7 @@ func NewMsgServerImpl(keeper Keeper) types.MsgServer {
|
||||||
|
|
||||||
var _ types.MsgServer = 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) {
|
func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateValidator) (*types.MsgCreateValidatorResponse, error) {
|
||||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||||
|
|
||||||
|
@ -119,6 +120,7 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa
|
||||||
return &types.MsgCreateValidatorResponse{}, nil
|
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) {
|
func (k msgServer) EditValidator(goCtx context.Context, msg *types.MsgEditValidator) (*types.MsgEditValidatorResponse, error) {
|
||||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||||
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
|
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
|
||||||
|
@ -181,6 +183,7 @@ func (k msgServer) EditValidator(goCtx context.Context, msg *types.MsgEditValida
|
||||||
return &types.MsgEditValidatorResponse{}, nil
|
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) {
|
func (k msgServer) Delegate(goCtx context.Context, msg *types.MsgDelegate) (*types.MsgDelegateResponse, error) {
|
||||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||||
valAddr, valErr := sdk.ValAddressFromBech32(msg.ValidatorAddress)
|
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
|
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) {
|
func (k msgServer) BeginRedelegate(goCtx context.Context, msg *types.MsgBeginRedelegate) (*types.MsgBeginRedelegateResponse, error) {
|
||||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||||
valSrcAddr, err := sdk.ValAddressFromBech32(msg.ValidatorSrcAddress)
|
valSrcAddr, err := sdk.ValAddressFromBech32(msg.ValidatorSrcAddress)
|
||||||
|
@ -302,6 +306,7 @@ func (k msgServer) BeginRedelegate(goCtx context.Context, msg *types.MsgBeginRed
|
||||||
}, nil
|
}, 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) {
|
func (k msgServer) Undelegate(goCtx context.Context, msg *types.MsgUndelegate) (*types.MsgUndelegateResponse, error) {
|
||||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||||
|
|
||||||
|
|
|
@ -21,18 +21,18 @@ const (
|
||||||
historicalEntries = "historical_entries"
|
historicalEntries = "historical_entries"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GenUnbondingTime randomized UnbondingTime
|
// genUnbondingTime returns randomized UnbondingTime
|
||||||
func GenUnbondingTime(r *rand.Rand) (ubdTime time.Duration) {
|
func genUnbondingTime(r *rand.Rand) (ubdTime time.Duration) {
|
||||||
return time.Duration(simulation.RandIntBetween(r, 60, 60*60*24*3*2)) * time.Second
|
return time.Duration(simulation.RandIntBetween(r, 60, 60*60*24*3*2)) * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenMaxValidators randomized MaxValidators
|
// genMaxValidators returns randomized MaxValidators
|
||||||
func GenMaxValidators(r *rand.Rand) (maxValidators uint32) {
|
func genMaxValidators(r *rand.Rand) (maxValidators uint32) {
|
||||||
return uint32(r.Intn(250) + 1)
|
return uint32(r.Intn(250) + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHistEntries randomized HistoricalEntries between 0-100.
|
// getHistEntries returns randomized HistoricalEntries between 0-100.
|
||||||
func GetHistEntries(r *rand.Rand) uint32 {
|
func getHistEntries(r *rand.Rand) uint32 {
|
||||||
return uint32(r.Intn(int(types.DefaultHistoricalEntries + 1)))
|
return uint32(r.Intn(int(types.DefaultHistoricalEntries + 1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,17 +47,17 @@ func RandomizedGenState(simState *module.SimulationState) {
|
||||||
|
|
||||||
simState.AppParams.GetOrGenerate(
|
simState.AppParams.GetOrGenerate(
|
||||||
simState.Cdc, unbondingTime, &unbondTime, simState.Rand,
|
simState.Cdc, unbondingTime, &unbondTime, simState.Rand,
|
||||||
func(r *rand.Rand) { unbondTime = GenUnbondingTime(r) },
|
func(r *rand.Rand) { unbondTime = genUnbondingTime(r) },
|
||||||
)
|
)
|
||||||
|
|
||||||
simState.AppParams.GetOrGenerate(
|
simState.AppParams.GetOrGenerate(
|
||||||
simState.Cdc, maxValidators, &maxVals, simState.Rand,
|
simState.Cdc, maxValidators, &maxVals, simState.Rand,
|
||||||
func(r *rand.Rand) { maxVals = GenMaxValidators(r) },
|
func(r *rand.Rand) { maxVals = genMaxValidators(r) },
|
||||||
)
|
)
|
||||||
|
|
||||||
simState.AppParams.GetOrGenerate(
|
simState.AppParams.GetOrGenerate(
|
||||||
simState.Cdc, historicalEntries, &histEntries, simState.Rand,
|
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
|
// NOTE: the slashing module need to be defined after the staking module on the
|
||||||
|
|
|
@ -68,7 +68,7 @@ func TestRandomizedGenState(t *testing.T) {
|
||||||
require.Equal(t, "1", stakingGenesis.Validators[2].MinSelfDelegation.String())
|
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) {
|
func TestRandomizedGenState1(t *testing.T) {
|
||||||
interfaceRegistry := codectypes.NewInterfaceRegistry()
|
interfaceRegistry := codectypes.NewInterfaceRegistry()
|
||||||
cdc := codec.NewProtoCodec(interfaceRegistry)
|
cdc := codec.NewProtoCodec(interfaceRegistry)
|
||||||
|
|
|
@ -6,9 +6,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/x/simulation"
|
|
||||||
|
|
||||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/simulation"
|
||||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,17 +17,17 @@ func ParamChanges(r *rand.Rand) []simtypes.ParamChange {
|
||||||
return []simtypes.ParamChange{
|
return []simtypes.ParamChange{
|
||||||
simulation.NewSimParamChange(types.ModuleName, string(types.KeyMaxValidators),
|
simulation.NewSimParamChange(types.ModuleName, string(types.KeyMaxValidators),
|
||||||
func(r *rand.Rand) string {
|
func(r *rand.Rand) string {
|
||||||
return fmt.Sprintf("%d", GenMaxValidators(r))
|
return fmt.Sprintf("%d", genMaxValidators(r))
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
simulation.NewSimParamChange(types.ModuleName, string(types.KeyUnbondingTime),
|
simulation.NewSimParamChange(types.ModuleName, string(types.KeyUnbondingTime),
|
||||||
func(r *rand.Rand) string {
|
func(r *rand.Rand) string {
|
||||||
return fmt.Sprintf("\"%d\"", GenUnbondingTime(r))
|
return fmt.Sprintf("\"%d\"", genUnbondingTime(r))
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
simulation.NewSimParamChange(types.ModuleName, string(types.KeyHistoricalEntries),
|
simulation.NewSimParamChange(types.ModuleName, string(types.KeyHistoricalEntries),
|
||||||
func(r *rand.Rand) string {
|
func(r *rand.Rand) string {
|
||||||
return fmt.Sprintf("%d", GetHistEntries(r))
|
return fmt.Sprintf("%d", getHistEntries(r))
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,10 @@ order: 1
|
||||||
|
|
||||||
# State
|
# State
|
||||||
|
|
||||||
|
## Pool
|
||||||
|
|
||||||
|
Pool is used for tracking bonded and not-bonded token supply of the bond denomination.
|
||||||
|
|
||||||
## LastTotalPower
|
## LastTotalPower
|
||||||
|
|
||||||
LastTotalPower tracks the total amounts of bonded tokens recorded during the previous end block.
|
LastTotalPower tracks the total amounts of bonded tokens recorded during the previous end block.
|
||||||
|
|
|
@ -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.
|
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.
|
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#L16-L17
|
||||||
|
|
||||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L35-L51
|
+++ 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 operator address is already registered
|
||||||
- another validator with this pubkey 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 initial `MaxChangeRate` is either negative or > `MaxRate`
|
||||||
- the description fields are too large
|
- 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
|
Additionally a self-delegation is made with the initial tokens delegation
|
||||||
tokens `Delegation`. The validator always starts as unbonded but may be bonded
|
tokens `Delegation`. The validator always starts as unbonded but may be bonded
|
||||||
in the first end-block.
|
in the first end-block.
|
||||||
|
|
||||||
## Msg/EditValidator
|
## MsgEditValidator
|
||||||
|
|
||||||
The `Description`, `CommissionRate` of a validator can be updated using the
|
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#L19-L20
|
||||||
|
|
||||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L56-L76
|
+++ 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 initial `CommissionRate` is either negative or > `MaxRate`
|
||||||
- the `CommissionRate` has already been updated within the previous 24 hours
|
- the `CommissionRate` has already been updated within the previous 24 hours
|
||||||
- the `CommissionRate` is > `MaxChangeRate`
|
- the `CommissionRate` is > `MaxChangeRate`
|
||||||
- the description fields are too large
|
- 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
|
some amount of their validator's (newly created) delegator-shares that are
|
||||||
assigned to `Delegation.Shares`.
|
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
|
+++ 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 `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 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
|
- 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)
|
![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.
|
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#L30-L32
|
||||||
|
|
||||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L112-L121
|
+++ 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
|
+++ 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 delegation doesn't exist
|
||||||
- the validator 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`
|
- existing `UnbondingDelegation` has maximum entries as defined by `params.MaxEntries`
|
||||||
- the `Amount` has a denomination different than one defined by `params.BondDenom`
|
- 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`
|
- 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
|
- 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)
|
![Unbond sequence](../../../docs/uml/svg/unbond_sequence.svg)
|
||||||
|
|
||||||
## Msg/BeginRedelegate
|
## MsgBeginRedelegate
|
||||||
|
|
||||||
The redelegation command allows delegators to instantly switch validators. Once
|
The redelegation command allows delegators to instantly switch validators. Once
|
||||||
the unbonding period has passed, the redelegation is automatically completed in
|
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
|
+++ 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
|
+++ 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 delegation doesn't exist
|
||||||
- the source or destination validators don'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`
|
- existing `Redelegation` has maximum entries as defined by `params.MaxEntries`
|
||||||
- the `Amount` `Coin` has a denomination different than one defined by `params.BondDenom`
|
- 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`
|
- 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.
|
- calculate the token worth of the shares remove that amount tokens held within the source validator.
|
||||||
|
|
|
@ -18,9 +18,9 @@ The staking module emits the following events:
|
||||||
| complete_redelegation | destination_validator | {dstValidatorAddress} |
|
| complete_redelegation | destination_validator | {dstValidatorAddress} |
|
||||||
| complete_redelegation | delegator | {delegatorAddress} |
|
| complete_redelegation | delegator | {delegatorAddress} |
|
||||||
|
|
||||||
## Service Messages
|
## Msg's
|
||||||
|
|
||||||
### Msg/CreateValidator
|
### MsgCreateValidator
|
||||||
|
|
||||||
| Type | Attribute Key | Attribute Value |
|
| Type | Attribute Key | Attribute Value |
|
||||||
| ---------------- | ------------- | ------------------ |
|
| ---------------- | ------------- | ------------------ |
|
||||||
|
@ -30,7 +30,7 @@ The staking module emits the following events:
|
||||||
| message | action | create_validator |
|
| message | action | create_validator |
|
||||||
| message | sender | {senderAddress} |
|
| message | sender | {senderAddress} |
|
||||||
|
|
||||||
### Msg/EditValidator
|
### MsgEditValidator
|
||||||
|
|
||||||
| Type | Attribute Key | Attribute Value |
|
| Type | Attribute Key | Attribute Value |
|
||||||
| -------------- | ------------------- | ------------------- |
|
| -------------- | ------------------- | ------------------- |
|
||||||
|
@ -40,7 +40,7 @@ The staking module emits the following events:
|
||||||
| message | action | edit_validator |
|
| message | action | edit_validator |
|
||||||
| message | sender | {senderAddress} |
|
| message | sender | {senderAddress} |
|
||||||
|
|
||||||
### Msg/Delegate
|
### MsgDelegate
|
||||||
|
|
||||||
| Type | Attribute Key | Attribute Value |
|
| Type | Attribute Key | Attribute Value |
|
||||||
| -------- | ------------- | ------------------ |
|
| -------- | ------------- | ------------------ |
|
||||||
|
@ -50,7 +50,7 @@ The staking module emits the following events:
|
||||||
| message | action | delegate |
|
| message | action | delegate |
|
||||||
| message | sender | {senderAddress} |
|
| message | sender | {senderAddress} |
|
||||||
|
|
||||||
### Msg/Undelegate
|
### MsgUndelegate
|
||||||
|
|
||||||
| Type | Attribute Key | Attribute Value |
|
| Type | Attribute Key | Attribute Value |
|
||||||
| ------- | ------------------- | ------------------ |
|
| ------- | ------------------- | ------------------ |
|
||||||
|
@ -63,7 +63,7 @@ The staking module emits the following events:
|
||||||
|
|
||||||
- [0] Time is formatted in the RFC3339 standard
|
- [0] Time is formatted in the RFC3339 standard
|
||||||
|
|
||||||
### Msg/BeginRedelegate
|
### MsgBeginRedelegate
|
||||||
|
|
||||||
| Type | Attribute Key | Attribute Value |
|
| Type | Attribute Key | Attribute Value |
|
||||||
| ---------- | --------------------- | --------------------- |
|
| ---------- | --------------------- | --------------------- |
|
||||||
|
|
|
@ -38,11 +38,11 @@ network.
|
||||||
- [Delegations](02_state_transitions.md#delegations)
|
- [Delegations](02_state_transitions.md#delegations)
|
||||||
- [Slashing](02_state_transitions.md#slashing)
|
- [Slashing](02_state_transitions.md#slashing)
|
||||||
3. **[Messages](03_messages.md)**
|
3. **[Messages](03_messages.md)**
|
||||||
- [Msg/CreateValidator](03_messages.md#msgcreatevalidator)
|
- [MsgCreateValidator](03_messages.md#msgcreatevalidator)
|
||||||
- [Msg/EditValidator](03_messages.md#msgeditvalidator)
|
- [MsgEditValidator](03_messages.md#msgeditvalidator)
|
||||||
- [Msg/Delegate](03_messages.md#msgdelegate)
|
- [MsgDelegate](03_messages.md#msgdelegate)
|
||||||
- [Msg/BeginUnbonding](03_messages.md#msgbeginunbonding)
|
- [MsgUndelegate](03_messages.md#msgundelegate)
|
||||||
- [Msg/BeginRedelegate](03_messages.md#msgbeginredelegate)
|
- [MsgBeginRedelegate](03_messages.md#msgbeginredelegate)
|
||||||
4. **[Begin-Block](04_begin_block.md)**
|
4. **[Begin-Block](04_begin_block.md)**
|
||||||
- [Historical Info Tracking](04_begin_block.md#historical-info-tracking)
|
- [Historical Info Tracking](04_begin_block.md#historical-info-tracking)
|
||||||
5. **[End-Block ](05_end_block.md)**
|
5. **[End-Block ](05_end_block.md)**
|
||||||
|
@ -51,5 +51,5 @@ network.
|
||||||
6. **[Hooks](06_hooks.md)**
|
6. **[Hooks](06_hooks.md)**
|
||||||
7. **[Events](07_events.md)**
|
7. **[Events](07_events.md)**
|
||||||
- [EndBlocker](07_events.md#endblocker)
|
- [EndBlocker](07_events.md#endblocker)
|
||||||
- [Handlers](07_events.md#handlers)
|
- [Msg's](07_events.md#msg's)
|
||||||
8. **[Parameters](08_params.md)**
|
8. **[Parameters](08_params.md)**
|
||||||
|
|
Loading…
Reference in New Issue