Merge branch 'master' into powerreduction_param
This commit is contained in:
commit
10b2b08ece
|
@ -20,12 +20,10 @@ linters:
|
|||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- interfacer
|
||||
- maligned
|
||||
- misspell
|
||||
- nakedret
|
||||
- prealloc
|
||||
- scopelint
|
||||
- exportloopref
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- stylecheck
|
||||
|
|
30
CHANGELOG.md
30
CHANGELOG.md
|
@ -53,7 +53,6 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||
* updated the keyring display structure (it uses protobuf JSON serialization) - the output is more verbose.
|
||||
* Renamed `MarshalAny` and `UnmarshalAny` to `MarshalInterface` and `UnmarshalInterface` respectively. These functions must take an interface as parameter (not a concrete type nor `Any` object). Underneath they use `Any` wrapping for correct protobuf serialization.
|
||||
* CLI: removed `--text` flag from `show-node-id` command; the text format for public keys is not used any more - instead we use ProtoJSON.
|
||||
* [\#9026](https://github.com/cosmos/cosmos-sdk/pull/9026) The `tx sign` and `tx sign-batch` CLI commands use SIGN_MODE_DIRECT by default for local pubkeys. For multisigs and ledger keys, the default LEGACY_AMINO_JSON is kept.
|
||||
|
||||
### API Breaking Changes
|
||||
|
||||
|
@ -106,13 +105,34 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||
|
||||
### Bug Fixes
|
||||
|
||||
* (gRPC) [\#9015](https://github.com/cosmos/cosmos-sdk/pull/9015) Fix invalid status code when accessing gRPC endpoints.
|
||||
* (gRPC) [\#8945](https://github.com/cosmos/cosmos-sdk/pull/8945) gRPC reflection now works correctly.
|
||||
* (keyring) [#\8635](https://github.com/cosmos/cosmos-sdk/issues/8635) Remove hardcoded default passphrase value on `NewMnemonic`
|
||||
* (x/bank) [\#8434](https://github.com/cosmos/cosmos-sdk/pull/8434) Fix legacy REST API `GET /bank/total` and `GET /bank/total/{denom}` in swagger
|
||||
* (x/slashing) [\#8427](https://github.com/cosmos/cosmos-sdk/pull/8427) Fix query signing infos command
|
||||
* (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value
|
||||
* [\#9026](https://github.com/cosmos/cosmos-sdk/pull/9026) Fix bug of `gentx` command not working with ledger keys.
|
||||
|
||||
### Deprecated
|
||||
|
||||
* (grpc) [\#8926](https://github.com/cosmos/cosmos-sdk/pull/8926) The `tx` field in `SimulateRequest` has been deprecated, prefer to pass `tx_bytes` instead.
|
||||
|
||||
## [v0.42.4](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.42.4) - 2021-04-08
|
||||
|
||||
### Client Breaking Changes
|
||||
|
||||
* [\#9026](https://github.com/cosmos/cosmos-sdk/pull/9026) By default, the `tx sign` and `tx sign-batch` CLI commands use SIGN_MODE_DIRECT to sign transactions for local pubkeys. For multisigs and ledger keys, the default LEGACY_AMINO_JSON is used.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (gRPC) [\#9015](https://github.com/cosmos/cosmos-sdk/pull/9015) Fix invalid status code when accessing gRPC endpoints.
|
||||
* [\#9026](https://github.com/cosmos/cosmos-sdk/pull/9026) Fixed the bug that caused the `gentx` command to fail for Ledger keys.
|
||||
|
||||
### Improvements
|
||||
|
||||
* [\#9081](https://github.com/cosmos/cosmos-sdk/pull/9081) Upgrade Tendermint to v0.34.9 that includes a security issue fix for Tendermint light clients.
|
||||
|
||||
## [v0.42.3](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.42.3) - 2021-03-24
|
||||
|
||||
This release fixes a security vulnerability identified in x/bank.
|
||||
|
||||
## [v0.42.2](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.42.2) - 2021-03-19
|
||||
|
||||
|
@ -131,10 +151,6 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||
|
||||
This release fixes security vulnerability identified in the simapp.
|
||||
|
||||
### Deprecated
|
||||
|
||||
* (grpc) [\#8926](https://github.com/cosmos/cosmos-sdk/pull/8926) The `tx` field in `SimulateRequest` has been deprecated, prefer to pass `tx_bytes` instead.
|
||||
|
||||
## [v0.42.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.42.0) - 2021-03-08
|
||||
|
||||
**IMPORTANT**: This release contains an important security fix for all non Cosmos Hub chains running Stargate version of the Cosmos SDK (>0.40). Non-hub chains should not be using any version of the SDK in the v0.40.x or v0.41.x release series. See [#8461](https://github.com/cosmos/cosmos-sdk/pull/8461) for more details.
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-getter"
|
||||
"github.com/otiai10/copy"
|
||||
)
|
||||
|
||||
// DoUpgrade will be called after the log message has been parsed and the process has terminated.
|
||||
|
@ -62,10 +63,19 @@ func DownloadBinary(cfg *Config, info *UpgradeInfo) error {
|
|||
if err != nil {
|
||||
dirPath := cfg.UpgradeDir(info.Name)
|
||||
err = getter.Get(dirPath, url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = EnsureBinary(binPath)
|
||||
// copy binary to binPath from dirPath if zipped directory don't contain bin directory to wrap the binary
|
||||
if err != nil {
|
||||
err = copy.Copy(filepath.Join(dirPath, cfg.Name), binPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if it is successful, let's ensure the binary is executable
|
||||
return MarkExecutable(binPath)
|
||||
}
|
||||
|
|
|
@ -307,6 +307,7 @@
|
|||
- [Msg](#cosmos.evidence.v1beta1.Msg)
|
||||
|
||||
- [cosmos/feegrant/v1beta1/feegrant.proto](#cosmos/feegrant/v1beta1/feegrant.proto)
|
||||
- [AllowedMsgFeeAllowance](#cosmos.feegrant.v1beta1.AllowedMsgFeeAllowance)
|
||||
- [BasicFeeAllowance](#cosmos.feegrant.v1beta1.BasicFeeAllowance)
|
||||
- [Duration](#cosmos.feegrant.v1beta1.Duration)
|
||||
- [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt)
|
||||
|
@ -4543,6 +4544,22 @@ Msg defines the evidence Msg service.
|
|||
|
||||
|
||||
|
||||
<a name="cosmos.feegrant.v1beta1.AllowedMsgFeeAllowance"></a>
|
||||
|
||||
### AllowedMsgFeeAllowance
|
||||
AllowedMsgFeeAllowance creates allowance only for specified message types.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | allowance can be any of basic and filtered fee allowance. |
|
||||
| `allowed_messages` | [string](#string) | repeated | allowed_messages are the messages for which the grantee has the access. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="cosmos.feegrant.v1beta1.BasicFeeAllowance"></a>
|
||||
|
||||
### BasicFeeAllowance
|
||||
|
|
4
go.mod
4
go.mod
|
@ -30,7 +30,7 @@ require (
|
|||
github.com/jhump/protoreflect v1.8.2
|
||||
github.com/magiconair/properties v1.8.5
|
||||
github.com/mattn/go-isatty v0.0.12
|
||||
github.com/otiai10/copy v1.5.0
|
||||
github.com/otiai10/copy v1.5.1
|
||||
github.com/pelletier/go-toml v1.8.1 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.10.0
|
||||
|
@ -49,7 +49,7 @@ require (
|
|||
github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2.0.20210304154332-87d6ca4410df
|
||||
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15
|
||||
github.com/tendermint/go-amino v0.16.0
|
||||
github.com/tendermint/tendermint v0.34.8
|
||||
github.com/tendermint/tendermint v0.34.9
|
||||
github.com/tendermint/tm-db v0.6.4
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
||||
google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f
|
||||
|
|
10
go.sum
10
go.sum
|
@ -284,6 +284,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
|||
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64=
|
||||
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us=
|
||||
github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
|
@ -507,8 +509,8 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS
|
|||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/otiai10/copy v1.5.0 h1:SoXDGnlTUZoqB/wSuj/Y5L6T5i6iN4YRAcMCd+JnLNU=
|
||||
github.com/otiai10/copy v1.5.0/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E=
|
||||
github.com/otiai10/copy v1.5.1 h1:a/cs2E1/1V0az8K5nblbl+ymEa4E11AfaOLMar8V34w=
|
||||
github.com/otiai10/copy v1.5.1/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E=
|
||||
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
|
||||
github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI=
|
||||
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
|
||||
|
@ -678,8 +680,8 @@ github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoM
|
|||
github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4=
|
||||
github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg=
|
||||
github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ=
|
||||
github.com/tendermint/tendermint v0.34.8 h1:PMWgUx47FrNTsfhxCWzoiIlVAC1SE9+WBlnsF9oQW0I=
|
||||
github.com/tendermint/tendermint v0.34.8/go.mod h1:JVuu3V1ZexOaZG8VJMRl8lnfrGw6hEB2TVnoUwKRbss=
|
||||
github.com/tendermint/tendermint v0.34.9 h1:9P2MXDEPOcPW0NBcHQ/HDSfvczZm+q5nUUw7AZ6f1Vc=
|
||||
github.com/tendermint/tendermint v0.34.9/go.mod h1:kl4Z1JwGx1I+u1SXIzMDy7Z3T8LiMeCAOnzNn6AIMT4=
|
||||
github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI=
|
||||
github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8=
|
||||
github.com/tendermint/tm-db v0.6.4 h1:3N2jlnYQkXNQclQwd/eKV/NzlqPlfK21cpRRIx80XXQ=
|
||||
|
|
|
@ -52,6 +52,18 @@ message PeriodicFeeAllowance {
|
|||
ExpiresAt period_reset = 5 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
// AllowedMsgFeeAllowance creates allowance only for specified message types.
|
||||
message AllowedMsgFeeAllowance {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
option (cosmos_proto.implements_interface) = "FeeAllowanceI";
|
||||
|
||||
// allowance can be any of basic and filtered fee allowance.
|
||||
google.protobuf.Any allowance = 1 [(cosmos_proto.accepts_interface) = "FeeAllowanceI"];
|
||||
|
||||
// allowed_messages are the messages for which the grantee has the access.
|
||||
repeated string allowed_messages = 2;
|
||||
}
|
||||
|
||||
// Duration is a span of a clock time or number of blocks.
|
||||
// This is designed to be added to an ExpiresAt struct.
|
||||
message Duration {
|
||||
|
|
|
@ -4,9 +4,10 @@ import (
|
|||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNewStoreKVPairWriteListener(t *testing.T) {
|
||||
|
|
|
@ -3,11 +3,12 @@ package testdata
|
|||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// KeyTestPubAddr generates a new secp256k1 keypair.
|
||||
|
|
|
@ -3,6 +3,7 @@ package msgservice
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"google.golang.org/grpc"
|
||||
|
@ -42,3 +43,9 @@ func RegisterMsgServiceDesc(registry codectypes.InterfaceRegistry, sd *grpc.Serv
|
|||
func noopInterceptor(_ context.Context, _ interface{}, _ *grpc.UnaryServerInfo, _ grpc.UnaryHandler) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// IsServiceMsg checks if a type URL corresponds to a service method name,
|
||||
// i.e. /cosmos.bank.Msg/Send vs /cosmos.bank.MsgSend
|
||||
func IsServiceMsg(typeURL string) bool {
|
||||
return strings.Count(typeURL, "/") >= 2
|
||||
}
|
||||
|
|
|
@ -7,8 +7,9 @@ import (
|
|||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/store/types"
|
||||
db "github.com/tendermint/tm-db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/store/types"
|
||||
)
|
||||
|
||||
// DefaultLimit is the default `limit` for queries
|
||||
|
|
|
@ -2,12 +2,12 @@ package tx
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/types/msgservice"
|
||||
)
|
||||
|
||||
// MaxGasWanted defines the max gas allowed.
|
||||
|
@ -27,7 +27,7 @@ func (t *Tx) GetMsgs() []sdk.Msg {
|
|||
res := make([]sdk.Msg, len(anys))
|
||||
for i, any := range anys {
|
||||
var msg sdk.Msg
|
||||
if isServiceMsg(any.TypeUrl) {
|
||||
if msgservice.IsServiceMsg(any.TypeUrl) {
|
||||
req := any.GetCachedValue()
|
||||
if req == nil {
|
||||
panic("Any cached value is nil. Transaction messages must be correctly packed Any values.")
|
||||
|
@ -183,7 +183,7 @@ func (m *TxBody) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
|
|||
for _, any := range m.Messages {
|
||||
// If the any's typeUrl contains 2 slashes, then we unpack the any into
|
||||
// a ServiceMsg struct as per ADR-031.
|
||||
if isServiceMsg(any.TypeUrl) {
|
||||
if msgservice.IsServiceMsg(any.TypeUrl) {
|
||||
var req sdk.MsgRequest
|
||||
err := unpacker.UnpackAny(any, &req)
|
||||
if err != nil {
|
||||
|
@ -222,9 +222,3 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
|
|||
registry.RegisterInterface("cosmos.tx.v1beta1.Tx", (*sdk.Tx)(nil))
|
||||
registry.RegisterImplementations((*sdk.Tx)(nil), &Tx{})
|
||||
}
|
||||
|
||||
// isServiceMsg checks if a type URL corresponds to a service method name,
|
||||
// i.e. /cosmos.bank.Msg/Send vs /cosmos.bank.MsgSend
|
||||
func isServiceMsg(typeURL string) bool {
|
||||
return strings.Count(typeURL, "/") >= 2
|
||||
}
|
||||
|
|
|
@ -16,5 +16,5 @@ type AccountKeeper interface {
|
|||
|
||||
// FeegrantKeeper defines the expected feegrant keeper.
|
||||
type FeegrantKeeper interface {
|
||||
UseGrantedFees(ctx sdk.Context, granter, grantee sdk.AccAddress, fee sdk.Coins) error
|
||||
UseGrantedFees(ctx sdk.Context, granter, grantee sdk.AccAddress, fee sdk.Coins, msgs []sdk.Msg) error
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ func (dfd DeductFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bo
|
|||
if dfd.feegrantKeeper == nil {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "fee grants are not enabled")
|
||||
} else if !feeGranter.Equals(feePayer) {
|
||||
err := dfd.feegrantKeeper.UseGrantedFees(ctx, feeGranter, feePayer, fee)
|
||||
err := dfd.feegrantKeeper.UseGrantedFees(ctx, feeGranter, feePayer, fee, tx.GetMsgs())
|
||||
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrapf(err, "%s not allowed to pay fees from %s", feeGranter, feePayer)
|
||||
|
|
|
@ -206,7 +206,7 @@ func (ak AccountKeeper) GetModuleAccount(ctx sdk.Context, moduleName string) typ
|
|||
}
|
||||
|
||||
// SetModuleAccount sets the module account to the auth account store
|
||||
func (ak AccountKeeper) SetModuleAccount(ctx sdk.Context, macc types.ModuleAccountI) { //nolint:interfacer
|
||||
func (ak AccountKeeper) SetModuleAccount(ctx sdk.Context, macc types.ModuleAccountI) {
|
||||
ak.SetAccount(ctx, macc)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
"github.com/gogo/protobuf/grpc"
|
||||
|
||||
v043 "github.com/cosmos/cosmos-sdk/x/auth/legacy/v043"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// Migrator is a struct for handling in-place store migrations.
|
||||
type Migrator struct {
|
||||
keeper AccountKeeper
|
||||
queryServer grpc.Server
|
||||
}
|
||||
|
||||
// NewMigrator returns a new Migrator.
|
||||
func NewMigrator(keeper AccountKeeper, queryServer grpc.Server) Migrator {
|
||||
return Migrator{keeper: keeper, queryServer: queryServer}
|
||||
}
|
||||
|
||||
// Migrate1to2 migrates from version 1 to 2.
|
||||
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
|
||||
var iterErr error
|
||||
|
||||
m.keeper.IterateAccounts(ctx, func(account types.AccountI) (stop bool) {
|
||||
wb, err := v043.MigrateAccount(ctx, account, m.queryServer)
|
||||
if err != nil {
|
||||
iterErr = err
|
||||
return true
|
||||
}
|
||||
|
||||
if wb == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
m.keeper.SetAccount(ctx, wb)
|
||||
return false
|
||||
})
|
||||
|
||||
return iterErr
|
||||
}
|
|
@ -0,0 +1,269 @@
|
|||
package v043
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogo/protobuf/grpc"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/vesting/exported"
|
||||
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
const (
|
||||
delegatorDelegationPath = "/cosmos.staking.v1beta1.Query/DelegatorDelegations"
|
||||
stakingParamsPath = "/cosmos.staking.v1beta1.Query/Params"
|
||||
delegatorUnbondingDelegationsPath = "/cosmos.staking.v1beta1.Query/DelegatorUnbondingDelegations"
|
||||
balancesPath = "/cosmos.bank.v1beta1.Query/AllBalances"
|
||||
)
|
||||
|
||||
func migrateVestingAccounts(ctx sdk.Context, account types.AccountI, queryServer grpc.Server) (types.AccountI, error) {
|
||||
bondDenom, err := getBondDenom(ctx, queryServer)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
asVesting, ok := account.(exported.VestingAccount)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
addr := account.GetAddress().String()
|
||||
balance, err := getBalance(
|
||||
ctx,
|
||||
addr,
|
||||
queryServer,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
delegations, err := getDelegatorDelegationsSum(
|
||||
ctx,
|
||||
addr,
|
||||
queryServer,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
unbondingDelegations, err := getDelegatorUnbondingDelegationsSum(
|
||||
ctx,
|
||||
addr,
|
||||
bondDenom,
|
||||
queryServer,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
delegations = delegations.Add(unbondingDelegations...)
|
||||
|
||||
asVesting, ok = resetVestingDelegatedBalances(asVesting)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// balance before any delegation includes balance of delegation
|
||||
for _, coin := range delegations {
|
||||
balance = balance.Add(coin)
|
||||
}
|
||||
|
||||
asVesting.TrackDelegation(ctx.BlockTime(), balance, delegations)
|
||||
|
||||
return asVesting.(types.AccountI), nil
|
||||
}
|
||||
|
||||
func resetVestingDelegatedBalances(evacct exported.VestingAccount) (exported.VestingAccount, bool) {
|
||||
// reset `DelegatedVesting` and `DelegatedFree` to zero
|
||||
df := sdk.NewCoins()
|
||||
dv := sdk.NewCoins()
|
||||
|
||||
switch vacct := evacct.(type) {
|
||||
case *vestingtypes.ContinuousVestingAccount:
|
||||
vacct.DelegatedVesting = dv
|
||||
vacct.DelegatedFree = df
|
||||
return vacct, true
|
||||
case *vestingtypes.DelayedVestingAccount:
|
||||
vacct.DelegatedVesting = dv
|
||||
vacct.DelegatedFree = df
|
||||
return vacct, true
|
||||
case *vestingtypes.PeriodicVestingAccount:
|
||||
vacct.DelegatedVesting = dv
|
||||
vacct.DelegatedFree = df
|
||||
return vacct, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
func getDelegatorDelegationsSum(ctx sdk.Context, address string, queryServer grpc.Server) (sdk.Coins, error) {
|
||||
querier, ok := queryServer.(*baseapp.GRPCQueryRouter)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected type: %T wanted *baseapp.GRPCQueryRouter", queryServer)
|
||||
}
|
||||
|
||||
queryFn := querier.Route(delegatorDelegationPath)
|
||||
|
||||
q := &stakingtypes.QueryDelegatorDelegationsRequest{
|
||||
DelegatorAddr: address,
|
||||
}
|
||||
|
||||
b, err := proto.Marshal(q)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot marshal staking type query request, %w", err)
|
||||
}
|
||||
req := abci.RequestQuery{
|
||||
Data: b,
|
||||
Path: delegatorDelegationPath,
|
||||
}
|
||||
resp, err := queryFn(ctx, req)
|
||||
if err != nil {
|
||||
e, ok := status.FromError(err)
|
||||
if ok && e.Code() == codes.NotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("staking query error, %w", err)
|
||||
}
|
||||
|
||||
balance := new(stakingtypes.QueryDelegatorDelegationsResponse)
|
||||
if err := proto.Unmarshal(resp.Value, balance); err != nil {
|
||||
return nil, fmt.Errorf("unable to unmarshal delegator query delegations: %w", err)
|
||||
}
|
||||
|
||||
res := sdk.NewCoins()
|
||||
for _, i := range balance.DelegationResponses {
|
||||
res = res.Add(i.Balance)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func getDelegatorUnbondingDelegationsSum(ctx sdk.Context, address, bondDenom string, queryServer grpc.Server) (sdk.Coins, error) {
|
||||
querier, ok := queryServer.(*baseapp.GRPCQueryRouter)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected type: %T wanted *baseapp.GRPCQueryRouter", queryServer)
|
||||
}
|
||||
|
||||
queryFn := querier.Route(delegatorUnbondingDelegationsPath)
|
||||
|
||||
q := &stakingtypes.QueryDelegatorUnbondingDelegationsRequest{
|
||||
DelegatorAddr: address,
|
||||
}
|
||||
|
||||
b, err := proto.Marshal(q)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot marshal staking type query request, %w", err)
|
||||
}
|
||||
req := abci.RequestQuery{
|
||||
Data: b,
|
||||
Path: delegatorUnbondingDelegationsPath,
|
||||
}
|
||||
resp, err := queryFn(ctx, req)
|
||||
if err != nil && !errors.Is(err, sdkerrors.ErrNotFound) {
|
||||
e, ok := status.FromError(err)
|
||||
if ok && e.Code() == codes.NotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("staking query error, %w", err)
|
||||
}
|
||||
|
||||
balance := new(stakingtypes.QueryDelegatorUnbondingDelegationsResponse)
|
||||
if err := proto.Unmarshal(resp.Value, balance); err != nil {
|
||||
return nil, fmt.Errorf("unable to unmarshal delegator query delegations: %w", err)
|
||||
}
|
||||
|
||||
res := sdk.NewCoins()
|
||||
for _, i := range balance.UnbondingResponses {
|
||||
for _, r := range i.Entries {
|
||||
res = res.Add(sdk.NewCoin(bondDenom, r.Balance))
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func getBalance(ctx sdk.Context, address string, queryServer grpc.Server) (sdk.Coins, error) {
|
||||
querier, ok := queryServer.(*baseapp.GRPCQueryRouter)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected type: %T wanted *baseapp.GRPCQueryRouter", queryServer)
|
||||
}
|
||||
|
||||
queryFn := querier.Route(balancesPath)
|
||||
|
||||
q := &banktypes.QueryAllBalancesRequest{
|
||||
Address: address,
|
||||
Pagination: nil,
|
||||
}
|
||||
b, err := proto.Marshal(q)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot marshal bank type query request, %w", err)
|
||||
}
|
||||
|
||||
req := abci.RequestQuery{
|
||||
Data: b,
|
||||
Path: balancesPath,
|
||||
}
|
||||
resp, err := queryFn(ctx, req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bank query error, %w", err)
|
||||
}
|
||||
balance := new(banktypes.QueryAllBalancesResponse)
|
||||
if err := proto.Unmarshal(resp.Value, balance); err != nil {
|
||||
return nil, fmt.Errorf("unable to unmarshal bank balance response: %w", err)
|
||||
}
|
||||
return balance.Balances, nil
|
||||
}
|
||||
|
||||
func getBondDenom(ctx sdk.Context, queryServer grpc.Server) (string, error) {
|
||||
querier, ok := queryServer.(*baseapp.GRPCQueryRouter)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("unexpected type: %T wanted *baseapp.GRPCQueryRouter", queryServer)
|
||||
}
|
||||
|
||||
queryFn := querier.Route(stakingParamsPath)
|
||||
|
||||
q := &stakingtypes.QueryParamsRequest{}
|
||||
|
||||
b, err := proto.Marshal(q)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot marshal staking params query request, %w", err)
|
||||
}
|
||||
req := abci.RequestQuery{
|
||||
Data: b,
|
||||
Path: stakingParamsPath,
|
||||
}
|
||||
|
||||
resp, err := queryFn(ctx, req)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("staking query error, %w", err)
|
||||
}
|
||||
|
||||
params := new(stakingtypes.QueryParamsResponse)
|
||||
if err := proto.Unmarshal(resp.Value, params); err != nil {
|
||||
return "", fmt.Errorf("unable to unmarshal delegator query delegations: %w", err)
|
||||
}
|
||||
|
||||
return params.Params.BondDenom, nil
|
||||
}
|
||||
|
||||
// MigrateAccount migrates vesting account to make the DelegatedVesting and DelegatedFree fields correctly
|
||||
// track delegations.
|
||||
// References: https://github.com/cosmos/cosmos-sdk/issues/8601, https://github.com/cosmos/cosmos-sdk/issues/8812
|
||||
func MigrateAccount(ctx sdk.Context, account types.AccountI, queryServer grpc.Server) (types.AccountI, error) {
|
||||
return migrateVestingAccounts(ctx, account, queryServer)
|
||||
}
|
|
@ -0,0 +1,687 @@
|
|||
package v043_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/vesting/exported"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
func TestMigrateVestingAccounts(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
prepareFunc func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress)
|
||||
garbageFunc func(ctx sdk.Context, vesting exported.VestingAccount, app *simapp.SimApp) error
|
||||
tokenAmount int64
|
||||
expVested int64
|
||||
expFree int64
|
||||
blockTime int64
|
||||
}{
|
||||
{
|
||||
"delayed vesting has vested, multiple delegations less than the total account balance",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(200)))
|
||||
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().Unix())
|
||||
|
||||
ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
300,
|
||||
0,
|
||||
300,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"delayed vesting has vested, single delegations which exceed the vested amount",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(200)))
|
||||
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().Unix())
|
||||
|
||||
ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
300,
|
||||
0,
|
||||
300,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"delayed vesting has vested, multiple delegations which exceed the vested amount",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(200)))
|
||||
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().Unix())
|
||||
|
||||
ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
300,
|
||||
0,
|
||||
300,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"delayed vesting has not vested, single delegations which exceed the vested amount",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(200)))
|
||||
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(1, 0, 0).Unix())
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
300,
|
||||
200,
|
||||
100,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"delayed vesting has not vested, multiple delegations which exceed the vested amount",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(200)))
|
||||
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(1, 0, 0).Unix())
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
300,
|
||||
200,
|
||||
100,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"not end time",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
|
||||
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(1, 0, 0).Unix())
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
300,
|
||||
300,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"delayed vesting has not vested, single delegation greater than the total account balance",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
|
||||
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(1, 0, 0).Unix())
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
300,
|
||||
300,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"delayed vesting has vested, single delegation greater than the total account balance",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
|
||||
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().Unix())
|
||||
|
||||
ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
300,
|
||||
0,
|
||||
300,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"continuous vesting, start time after blocktime",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
|
||||
startTime := ctx.BlockTime().AddDate(1, 0, 0).Unix()
|
||||
endTime := ctx.BlockTime().AddDate(2, 0, 0).Unix()
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
|
||||
delayedAccount := types.NewContinuousVestingAccount(baseAccount, vestedCoins, startTime, endTime)
|
||||
|
||||
ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
300,
|
||||
300,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"continuous vesting, start time passed but not ended",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
|
||||
startTime := ctx.BlockTime().AddDate(-1, 0, 0).Unix()
|
||||
endTime := ctx.BlockTime().AddDate(2, 0, 0).Unix()
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
|
||||
delayedAccount := types.NewContinuousVestingAccount(baseAccount, vestedCoins, startTime, endTime)
|
||||
|
||||
ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
300,
|
||||
200,
|
||||
100,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"continuous vesting, start time and endtime passed",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
|
||||
startTime := ctx.BlockTime().AddDate(-2, 0, 0).Unix()
|
||||
endTime := ctx.BlockTime().AddDate(-1, 0, 0).Unix()
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
|
||||
delayedAccount := types.NewContinuousVestingAccount(baseAccount, vestedCoins, startTime, endTime)
|
||||
|
||||
ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
300,
|
||||
0,
|
||||
300,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"periodic vesting account, yet to be vested, some rewards delegated",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(100)))
|
||||
|
||||
start := ctx.BlockTime().Unix() + int64(time.Hour/time.Second)
|
||||
|
||||
periods := []types.Period{
|
||||
{
|
||||
Length: int64((24 * time.Hour) / time.Second),
|
||||
Amount: vestedCoins,
|
||||
},
|
||||
}
|
||||
|
||||
account := types.NewPeriodicVestingAccount(baseAccount, vestedCoins, start, periods)
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, account)
|
||||
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(150), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
300,
|
||||
100,
|
||||
50,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"periodic vesting account, nothing has vested yet",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
/*
|
||||
Test case:
|
||||
- periodic vesting account starts at time 1601042400
|
||||
- account balance and original vesting: 3666666670000
|
||||
- nothing has vested, we put the block time slightly after start time
|
||||
- expected vested: original vesting amount
|
||||
- expected free: zero
|
||||
- we're delegating the full original vesting
|
||||
*/
|
||||
startTime := int64(1601042400)
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(3666666670000)))
|
||||
periods := []types.Period{
|
||||
{
|
||||
Length: 31536000,
|
||||
Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(1833333335000))),
|
||||
},
|
||||
{
|
||||
Length: 15638400,
|
||||
Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
|
||||
},
|
||||
{
|
||||
Length: 15897600,
|
||||
Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
|
||||
},
|
||||
}
|
||||
|
||||
delayedAccount := types.NewPeriodicVestingAccount(baseAccount, vestedCoins, startTime, periods)
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
// delegation of the original vesting
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(3666666670000), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
3666666670000,
|
||||
3666666670000,
|
||||
0,
|
||||
1601042400 + 1,
|
||||
},
|
||||
{
|
||||
"periodic vesting account, all has vested",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
/*
|
||||
Test case:
|
||||
- periodic vesting account starts at time 1601042400
|
||||
- account balance and original vesting: 3666666670000
|
||||
- all has vested, so we set the block time at initial time + sum of all periods times + 1 => 1601042400 + 31536000 + 15897600 + 15897600 + 1
|
||||
- expected vested: zero
|
||||
- expected free: original vesting amount
|
||||
- we're delegating the full original vesting
|
||||
*/
|
||||
startTime := int64(1601042400)
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(3666666670000)))
|
||||
periods := []types.Period{
|
||||
{
|
||||
Length: 31536000,
|
||||
Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(1833333335000))),
|
||||
},
|
||||
{
|
||||
Length: 15638400,
|
||||
Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
|
||||
},
|
||||
{
|
||||
Length: 15897600,
|
||||
Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
|
||||
},
|
||||
}
|
||||
|
||||
delayedAccount := types.NewPeriodicVestingAccount(baseAccount, vestedCoins, startTime, periods)
|
||||
|
||||
ctx = ctx.WithBlockTime(time.Unix(1601042400+31536000+15897600+15897600+1, 0))
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
// delegation of the original vesting
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(3666666670000), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
3666666670000,
|
||||
0,
|
||||
3666666670000,
|
||||
1601042400 + 31536000 + 15897600 + 15897600 + 1,
|
||||
},
|
||||
{
|
||||
"periodic vesting account, first period has vested",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
/*
|
||||
Test case:
|
||||
- periodic vesting account starts at time 1601042400
|
||||
- account balance and original vesting: 3666666670000
|
||||
- first period have vested, so we set the block time at initial time + time of the first periods + 1 => 1601042400 + 31536000 + 1
|
||||
- expected vested: original vesting - first period amount
|
||||
- expected free: first period amount
|
||||
- we're delegating the full original vesting
|
||||
*/
|
||||
startTime := int64(1601042400)
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(3666666670000)))
|
||||
periods := []types.Period{
|
||||
{
|
||||
Length: 31536000,
|
||||
Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(1833333335000))),
|
||||
},
|
||||
{
|
||||
Length: 15638400,
|
||||
Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
|
||||
},
|
||||
{
|
||||
Length: 15897600,
|
||||
Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
|
||||
},
|
||||
}
|
||||
|
||||
delayedAccount := types.NewPeriodicVestingAccount(baseAccount, vestedCoins, startTime, periods)
|
||||
|
||||
ctx = ctx.WithBlockTime(time.Unix(1601042400+31536000+1, 0))
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
// delegation of the original vesting
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(3666666670000), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
3666666670000,
|
||||
3666666670000 - 1833333335000,
|
||||
1833333335000,
|
||||
1601042400 + 31536000 + 1,
|
||||
},
|
||||
{
|
||||
"periodic vesting account, first 2 period has vested",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
/*
|
||||
Test case:
|
||||
- periodic vesting account starts at time 1601042400
|
||||
- account balance and original vesting: 3666666670000
|
||||
- first 2 periods have vested, so we set the block time at initial time + time of the two periods + 1 => 1601042400 + 31536000 + 15638400 + 1
|
||||
- expected vested: original vesting - (sum of the first two periods amounts)
|
||||
- expected free: sum of the first two periods
|
||||
- we're delegating the full original vesting
|
||||
*/
|
||||
startTime := int64(1601042400)
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(3666666670000)))
|
||||
periods := []types.Period{
|
||||
{
|
||||
Length: 31536000,
|
||||
Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(1833333335000))),
|
||||
},
|
||||
{
|
||||
Length: 15638400,
|
||||
Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
|
||||
},
|
||||
{
|
||||
Length: 15897600,
|
||||
Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
|
||||
},
|
||||
}
|
||||
|
||||
delayedAccount := types.NewPeriodicVestingAccount(baseAccount, vestedCoins, startTime, periods)
|
||||
|
||||
ctx = ctx.WithBlockTime(time.Unix(1601042400+31536000+15638400+1, 0))
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
// delegation of the original vesting
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(3666666670000), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
3666666670000,
|
||||
3666666670000 - 1833333335000 - 916666667500,
|
||||
1833333335000 + 916666667500,
|
||||
1601042400 + 31536000 + 15638400 + 1,
|
||||
},
|
||||
{
|
||||
"vesting account has unbonding delegations in place",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
|
||||
|
||||
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(10, 0, 0).Unix())
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
|
||||
// delegation of the original vesting
|
||||
_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
|
||||
|
||||
valAddr, err := sdk.ValAddressFromBech32(validator.OperatorAddress)
|
||||
require.NoError(t, err)
|
||||
|
||||
// un-delegation of the original vesting
|
||||
_, err = app.StakingKeeper.Undelegate(ctx, delegatorAddr, valAddr, sdk.NewDecFromInt(sdk.NewInt(300)))
|
||||
require.NoError(t, err)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
450,
|
||||
300,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"vesting account has never delegated anything",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
|
||||
|
||||
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(10, 0, 0).Unix())
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
},
|
||||
cleartTrackingFields,
|
||||
450,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"vesting account has no delegation but dirty DelegatedFree and DelegatedVesting fields",
|
||||
func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
|
||||
baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
|
||||
vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
|
||||
|
||||
delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(10, 0, 0).Unix())
|
||||
|
||||
app.AccountKeeper.SetAccount(ctx, delayedAccount)
|
||||
},
|
||||
dirtyTrackingFields,
|
||||
450,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
app := simapp.Setup(false)
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{
|
||||
Time: time.Now(),
|
||||
})
|
||||
|
||||
addrs := simapp.AddTestAddrs(app, ctx, 1, sdk.NewInt(tc.tokenAmount))
|
||||
delegatorAddr := addrs[0]
|
||||
|
||||
_, valAddr := createValidator(t, ctx, app, tc.tokenAmount*2)
|
||||
validator, found := app.StakingKeeper.GetValidator(ctx, valAddr)
|
||||
require.True(t, found)
|
||||
|
||||
tc.prepareFunc(app, ctx, validator, delegatorAddr)
|
||||
|
||||
if tc.blockTime != 0 {
|
||||
ctx = ctx.WithBlockTime(time.Unix(tc.blockTime, 0))
|
||||
}
|
||||
|
||||
// We introduce the bug
|
||||
savedAccount := app.AccountKeeper.GetAccount(ctx, delegatorAddr)
|
||||
vestingAccount, ok := savedAccount.(exported.VestingAccount)
|
||||
require.True(t, ok)
|
||||
require.NoError(t, tc.garbageFunc(ctx, vestingAccount, app))
|
||||
|
||||
m := authkeeper.NewMigrator(app.AccountKeeper, app.GRPCQueryRouter())
|
||||
require.NoError(t, m.Migrate1to2(ctx))
|
||||
|
||||
var expVested sdk.Coins
|
||||
var expFree sdk.Coins
|
||||
|
||||
if tc.expVested != 0 {
|
||||
expVested = sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(tc.expVested)))
|
||||
}
|
||||
|
||||
if tc.expFree != 0 {
|
||||
expFree = sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(tc.expFree)))
|
||||
}
|
||||
|
||||
trackingCorrected(
|
||||
ctx,
|
||||
t,
|
||||
app.AccountKeeper,
|
||||
savedAccount.GetAddress(),
|
||||
expVested,
|
||||
expFree,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func trackingCorrected(ctx sdk.Context, t *testing.T, ak authkeeper.AccountKeeper, addr sdk.AccAddress, expDelVesting sdk.Coins, expDelFree sdk.Coins) {
|
||||
t.Helper()
|
||||
baseAccount := ak.GetAccount(ctx, addr)
|
||||
vDA, ok := baseAccount.(exported.VestingAccount)
|
||||
require.True(t, ok)
|
||||
|
||||
vestedOk := expDelVesting.IsEqual(vDA.GetDelegatedVesting())
|
||||
freeOk := expDelFree.IsEqual(vDA.GetDelegatedFree())
|
||||
require.True(t, vestedOk, vDA.GetDelegatedVesting().String())
|
||||
require.True(t, freeOk, vDA.GetDelegatedFree().String())
|
||||
}
|
||||
|
||||
func cleartTrackingFields(ctx sdk.Context, vesting exported.VestingAccount, app *simapp.SimApp) error {
|
||||
switch t := vesting.(type) {
|
||||
case *types.DelayedVestingAccount:
|
||||
t.DelegatedFree = nil
|
||||
t.DelegatedVesting = nil
|
||||
app.AccountKeeper.SetAccount(ctx, t)
|
||||
case *types.ContinuousVestingAccount:
|
||||
t.DelegatedFree = nil
|
||||
t.DelegatedVesting = nil
|
||||
app.AccountKeeper.SetAccount(ctx, t)
|
||||
case *types.PeriodicVestingAccount:
|
||||
t.DelegatedFree = nil
|
||||
t.DelegatedVesting = nil
|
||||
app.AccountKeeper.SetAccount(ctx, t)
|
||||
default:
|
||||
return fmt.Errorf("expected vesting account, found %t", t)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func dirtyTrackingFields(ctx sdk.Context, vesting exported.VestingAccount, app *simapp.SimApp) error {
|
||||
dirt := sdk.NewCoins(sdk.NewInt64Coin("stake", 42))
|
||||
|
||||
switch t := vesting.(type) {
|
||||
case *types.DelayedVestingAccount:
|
||||
t.DelegatedFree = dirt
|
||||
t.DelegatedVesting = dirt
|
||||
app.AccountKeeper.SetAccount(ctx, t)
|
||||
case *types.ContinuousVestingAccount:
|
||||
t.DelegatedFree = dirt
|
||||
t.DelegatedVesting = dirt
|
||||
app.AccountKeeper.SetAccount(ctx, t)
|
||||
case *types.PeriodicVestingAccount:
|
||||
t.DelegatedFree = dirt
|
||||
t.DelegatedVesting = dirt
|
||||
app.AccountKeeper.SetAccount(ctx, t)
|
||||
default:
|
||||
return fmt.Errorf("expected vesting account, found %t", t)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createValidator(t *testing.T, ctx sdk.Context, app *simapp.SimApp, powers int64) (sdk.AccAddress, sdk.ValAddress) {
|
||||
valTokens := sdk.TokensFromConsensusPower(powers)
|
||||
addrs := simapp.AddTestAddrsIncremental(app, ctx, 1, valTokens)
|
||||
valAddrs := simapp.ConvertAddrsToValAddrs(addrs)
|
||||
pks := simapp.CreateTestPubKeys(1)
|
||||
cdc := simapp.MakeTestEncodingConfig().Marshaler
|
||||
|
||||
app.StakingKeeper = stakingkeeper.NewKeeper(
|
||||
cdc,
|
||||
app.GetKey(stakingtypes.StoreKey),
|
||||
app.AccountKeeper,
|
||||
app.BankKeeper,
|
||||
app.GetSubspace(stakingtypes.ModuleName),
|
||||
)
|
||||
|
||||
val1, err := stakingtypes.NewValidator(valAddrs[0], pks[0], stakingtypes.Description{})
|
||||
require.NoError(t, err)
|
||||
|
||||
app.StakingKeeper.SetValidator(ctx, val1)
|
||||
require.NoError(t, app.StakingKeeper.SetValidatorByConsAddr(ctx, val1))
|
||||
app.StakingKeeper.SetNewValidatorByPowerIndex(ctx, val1)
|
||||
|
||||
_, err = app.StakingKeeper.Delegate(ctx, addrs[0], valTokens, stakingtypes.Unbonded, val1, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
_ = staking.EndBlocker(ctx, app.StakingKeeper)
|
||||
|
||||
return addrs[0], valAddrs[0]
|
||||
}
|
|
@ -129,6 +129,11 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd
|
|||
// module-specific GRPC queries.
|
||||
func (am AppModule) RegisterServices(cfg module.Configurator) {
|
||||
types.RegisterQueryServer(cfg.QueryServer(), am.accountKeeper)
|
||||
m := keeper.NewMigrator(am.accountKeeper, cfg.QueryServer())
|
||||
err := cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// InitGenesis performs genesis initialization for the auth module. It returns
|
||||
|
@ -148,7 +153,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
|
|||
}
|
||||
|
||||
// ConsensusVersion implements AppModule/ConsensusVersion.
|
||||
func (AppModule) ConsensusVersion() uint64 { return 1 }
|
||||
func (AppModule) ConsensusVersion() uint64 { return 2 }
|
||||
|
||||
// BeginBlock returns the begin blocker for the auth module.
|
||||
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"strings"
|
||||
|
||||
gogogrpc "github.com/gogo/protobuf/grpc"
|
||||
"github.com/golang/protobuf/proto" //nolint:staticcheck
|
||||
"github.com/golang/protobuf/proto" // nolint: staticcheck
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
|
|
@ -8,6 +8,8 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
clienttx "github.com/cosmos/cosmos-sdk/client/tx"
|
||||
|
@ -28,7 +30,6 @@ import (
|
|||
authtest "github.com/cosmos/cosmos-sdk/x/auth/client/testutil"
|
||||
bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/testutil"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type IntegrationTestSuite struct {
|
||||
|
|
|
@ -156,8 +156,8 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() {
|
|||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
|
||||
},
|
||||
&sdk.TxResponse{}, 29,
|
||||
false,
|
||||
nil, 0,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"failed with error both validators not allowed",
|
||||
|
|
|
@ -3,8 +3,6 @@ package exported
|
|||
import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
|
@ -17,5 +15,9 @@ type Authorization interface {
|
|||
|
||||
// Accept determines whether this grant permits the provided sdk.ServiceMsg to be performed, and if
|
||||
// so provides an upgraded authorization instance.
|
||||
Accept(msg sdk.ServiceMsg, block tmproto.Header) (updated Authorization, delete bool, err error)
|
||||
Accept(ctx sdk.Context, msg sdk.ServiceMsg) (updated Authorization, delete bool, err error)
|
||||
|
||||
// ValidateBasic does a simple validation check that
|
||||
// doesn't require access to any other information.
|
||||
ValidateBasic() error
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ func (k Keeper) DispatchActions(ctx sdk.Context, grantee sdk.AccAddress, service
|
|||
if authorization == nil {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "authorization not found")
|
||||
}
|
||||
updated, del, err := authorization.Accept(serviceMsg, ctx.BlockHeader())
|
||||
updated, del, err := authorization.Accept(ctx, serviceMsg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -96,8 +96,12 @@ func SimulateMsgGrantAuthorization(ak types.AccountKeeper, bk types.BankKeeper,
|
|||
}
|
||||
|
||||
blockTime := ctx.BlockTime()
|
||||
spendLimit := spendableCoins.Sub(fees)
|
||||
if spendLimit == nil {
|
||||
return simtypes.NoOpMsg(types.ModuleName, TypeMsgGrantAuthorization, "spend limit is nil"), nil, nil
|
||||
}
|
||||
msg, err := types.NewMsgGrantAuthorization(granter.Address, grantee.Address,
|
||||
banktype.NewSendAuthorization(spendableCoins.Sub(fees)), blockTime.AddDate(1, 0, 0))
|
||||
banktype.NewSendAuthorization(spendLimit), blockTime.AddDate(1, 0, 0))
|
||||
|
||||
if err != nil {
|
||||
return simtypes.NoOpMsg(types.ModuleName, TypeMsgGrantAuthorization, err.Error()), nil, err
|
||||
|
@ -249,7 +253,7 @@ func SimulateMsgExecuteAuthorized(ak types.AccountKeeper, bk types.BankKeeper, k
|
|||
|
||||
msg := types.NewMsgExecAuthorized(grantee.Address, []sdk.ServiceMsg{execMsg})
|
||||
sendGrant := targetGrant.Authorization.GetCachedValue().(*banktype.SendAuthorization)
|
||||
_, _, err = sendGrant.Accept(execMsg, ctx.BlockHeader())
|
||||
_, _, err = sendGrant.Accept(ctx, execMsg)
|
||||
if err != nil {
|
||||
return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, err.Error()), nil, nil
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/types/msgservice"
|
||||
"github.com/cosmos/cosmos-sdk/x/authz/exported"
|
||||
)
|
||||
|
||||
|
@ -19,11 +19,19 @@ func NewGenericAuthorization(methodName string) *GenericAuthorization {
|
|||
}
|
||||
|
||||
// MethodName implements Authorization.MethodName.
|
||||
func (cap GenericAuthorization) MethodName() string {
|
||||
return cap.MessageName
|
||||
func (authorization GenericAuthorization) MethodName() string {
|
||||
return authorization.MessageName
|
||||
}
|
||||
|
||||
// Accept implements Authorization.Accept.
|
||||
func (cap GenericAuthorization) Accept(msg sdk.ServiceMsg, block tmproto.Header) (updated exported.Authorization, delete bool, err error) {
|
||||
return &cap, false, nil
|
||||
func (authorization GenericAuthorization) Accept(ctx sdk.Context, msg sdk.ServiceMsg) (updated exported.Authorization, delete bool, err error) {
|
||||
return &authorization, false, nil
|
||||
}
|
||||
|
||||
// ValidateBasic implements Authorization.ValidateBasic.
|
||||
func (authorization GenericAuthorization) ValidateBasic() error {
|
||||
if !msgservice.IsServiceMsg(authorization.MessageName) {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, " %s is not a valid service msg", authorization.MessageName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package types_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/authz/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGenericAuthorization(t *testing.T) {
|
||||
t.Log("verify ValidateBasic returns error for non-service msg")
|
||||
authorization := types.NewGenericAuthorization(banktypes.TypeMsgSend)
|
||||
require.Error(t, authorization.ValidateBasic())
|
||||
|
||||
t.Log("verify ValidateBasic returns nil for service msg")
|
||||
authorization = types.NewGenericAuthorization(banktypes.SendAuthorization{}.MethodName())
|
||||
require.NoError(t, authorization.ValidateBasic())
|
||||
require.Equal(t, banktypes.SendAuthorization{}.MethodName(), authorization.MessageName)
|
||||
}
|
|
@ -63,7 +63,11 @@ func (msg MsgGrantAuthorizationRequest) ValidateBasic() error {
|
|||
return sdkerrors.Wrap(ErrInvalidExpirationTime, "Time can't be in the past")
|
||||
}
|
||||
|
||||
return nil
|
||||
authorization, ok := msg.Authorization.GetCachedValue().(exported.Authorization)
|
||||
if !ok {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expected %T, got %T", (exported.Authorization)(nil), msg.Authorization.GetCachedValue())
|
||||
}
|
||||
return authorization.ValidateBasic()
|
||||
}
|
||||
|
||||
// GetGrantAuthorization returns the cache value from the MsgGrantAuthorization.Authorization if present.
|
||||
|
|
|
@ -446,6 +446,7 @@ func (k BaseKeeper) trackDelegation(ctx sdk.Context, addr sdk.AccAddress, balanc
|
|||
if ok {
|
||||
// TODO: return error on account.TrackDelegation
|
||||
vacc.TrackDelegation(ctx.BlockHeader().Time, balance, amt)
|
||||
k.ak.SetAccount(ctx, acc)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -461,6 +462,7 @@ func (k BaseKeeper) trackUndelegation(ctx sdk.Context, addr sdk.AccAddress, amt
|
|||
if ok {
|
||||
// TODO: return error on account.TrackUndelegation
|
||||
vacc.TrackUndelegation(amt)
|
||||
k.ak.SetAccount(ctx, acc)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package keeper_test
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/types/query"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types/query"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/vesting/exported"
|
||||
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
@ -905,6 +907,12 @@ func (suite *IntegrationTestSuite) TestDelegateCoins() {
|
|||
// require the ability for a vesting account to delegate
|
||||
suite.Require().NoError(app.BankKeeper.DelegateCoins(ctx, addr1, addrModule, delCoins))
|
||||
suite.Require().Equal(delCoins, app.BankKeeper.GetAllBalances(ctx, addr1))
|
||||
|
||||
// require that delegated vesting amount is equal to what was delegated with DelegateCoins
|
||||
acc = app.AccountKeeper.GetAccount(ctx, addr1)
|
||||
vestingAcc, ok := acc.(exported.VestingAccount)
|
||||
suite.Require().True(ok)
|
||||
suite.Require().Equal(delCoins, vestingAcc.GetDelegatedVesting())
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) TestDelegateCoins_Invalid() {
|
||||
|
@ -979,6 +987,12 @@ func (suite *IntegrationTestSuite) TestUndelegateCoins() {
|
|||
|
||||
suite.Require().Equal(origCoins, app.BankKeeper.GetAllBalances(ctx, addr1))
|
||||
suite.Require().True(app.BankKeeper.GetAllBalances(ctx, addrModule).Empty())
|
||||
|
||||
// require that delegated vesting amount is completely empty, since they were completely undelegated
|
||||
acc = app.AccountKeeper.GetAccount(ctx, addr1)
|
||||
vestingAcc, ok := acc.(exported.VestingAccount)
|
||||
suite.Require().True(ok)
|
||||
suite.Require().Empty(vestingAcc.GetDelegatedVesting())
|
||||
}
|
||||
|
||||
func (suite *IntegrationTestSuite) TestUndelegateCoins_Invalid() {
|
||||
|
|
|
@ -3,8 +3,6 @@ package types
|
|||
import (
|
||||
"reflect"
|
||||
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
authz "github.com/cosmos/cosmos-sdk/x/authz/exported"
|
||||
|
@ -27,7 +25,7 @@ func (authorization SendAuthorization) MethodName() string {
|
|||
}
|
||||
|
||||
// Accept implements Authorization.Accept.
|
||||
func (authorization SendAuthorization) Accept(msg sdk.ServiceMsg, block tmproto.Header) (updated authz.Authorization, delete bool, err error) {
|
||||
func (authorization SendAuthorization) Accept(ctx sdk.Context, msg sdk.ServiceMsg) (updated authz.Authorization, delete bool, err error) {
|
||||
if reflect.TypeOf(msg.Request) == reflect.TypeOf(&MsgSend{}) {
|
||||
msg, ok := msg.Request.(*MsgSend)
|
||||
if ok {
|
||||
|
@ -44,3 +42,14 @@ func (authorization SendAuthorization) Accept(msg sdk.ServiceMsg, block tmproto.
|
|||
}
|
||||
return nil, false, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "type mismatch")
|
||||
}
|
||||
|
||||
// ValidateBasic implements Authorization.ValidateBasic.
|
||||
func (authorization SendAuthorization) ValidateBasic() error {
|
||||
if authorization.SpendLimit == nil {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "spend limit cannot be nil")
|
||||
}
|
||||
if !authorization.SpendLimit.IsAllPositive() {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "spend limit cannot be negitive")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package types_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
)
|
||||
|
||||
var (
|
||||
coins1000 = sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1000)))
|
||||
coins500 = sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(500)))
|
||||
fromAddr = sdk.AccAddress("_____from _____")
|
||||
toAddr = sdk.AccAddress("_______to________")
|
||||
)
|
||||
|
||||
func TestSendAuthorization(t *testing.T) {
|
||||
app := simapp.Setup(false)
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
authorization := types.NewSendAuthorization(coins1000)
|
||||
|
||||
t.Log("verify authorization returns valid method name")
|
||||
require.Equal(t, authorization.MethodName(), "/cosmos.bank.v1beta1.Msg/Send")
|
||||
require.NoError(t, authorization.ValidateBasic())
|
||||
send := types.NewMsgSend(fromAddr, toAddr, coins1000)
|
||||
srvMsg := sdk.ServiceMsg{
|
||||
MethodName: "/cosmos.bank.v1beta1.Msg/Send",
|
||||
Request: send,
|
||||
}
|
||||
require.NoError(t, authorization.ValidateBasic())
|
||||
|
||||
t.Log("verify updated authorization returns nil")
|
||||
updated, del, err := authorization.Accept(ctx, srvMsg)
|
||||
require.NoError(t, err)
|
||||
require.True(t, del)
|
||||
require.Nil(t, updated)
|
||||
|
||||
authorization = types.NewSendAuthorization(coins1000)
|
||||
require.Equal(t, authorization.MethodName(), "/cosmos.bank.v1beta1.Msg/Send")
|
||||
require.NoError(t, authorization.ValidateBasic())
|
||||
send = types.NewMsgSend(fromAddr, toAddr, coins500)
|
||||
srvMsg = sdk.ServiceMsg{
|
||||
MethodName: "/cosmos.bank.v1beta1.Msg/Send",
|
||||
Request: send,
|
||||
}
|
||||
require.NoError(t, authorization.ValidateBasic())
|
||||
updated, del, err = authorization.Accept(ctx, srvMsg)
|
||||
|
||||
t.Log("verify updated authorization returns remaining spent limit")
|
||||
require.NoError(t, err)
|
||||
require.False(t, del)
|
||||
require.NotNil(t, updated)
|
||||
sendAuth := types.NewSendAuthorization(coins500)
|
||||
require.Equal(t, sendAuth.String(), updated.String())
|
||||
|
||||
t.Log("expect updated authorization nil after spending remaining amount")
|
||||
updated, del, err = updated.Accept(ctx, srvMsg)
|
||||
require.NoError(t, err)
|
||||
require.True(t, del)
|
||||
require.Nil(t, updated)
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
//nolint
|
||||
package types
|
||||
|
||||
import (
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/network"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
@ -40,7 +41,7 @@ func (s *IntegrationTestSuite) SetupSuite() {
|
|||
}
|
||||
|
||||
cfg := network.DefaultConfig()
|
||||
cfg.NumValidators = 2
|
||||
cfg.NumValidators = 3
|
||||
|
||||
s.cfg = cfg
|
||||
s.network = network.New(s.T(), cfg)
|
||||
|
@ -137,7 +138,7 @@ func (s *IntegrationTestSuite) TestCmdGetFeeGrant() {
|
|||
grantee.String(),
|
||||
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
|
||||
},
|
||||
"no fee allowance found",
|
||||
"no allowance",
|
||||
true, nil, nil,
|
||||
},
|
||||
{
|
||||
|
@ -169,9 +170,13 @@ func (s *IntegrationTestSuite) TestCmdGetFeeGrant() {
|
|||
s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
|
||||
s.Require().Equal(tc.respType.Grantee, tc.respType.Grantee)
|
||||
s.Require().Equal(tc.respType.Granter, tc.respType.Granter)
|
||||
grant, err := tc.respType.GetFeeGrant()
|
||||
s.Require().NoError(err)
|
||||
grant1, err1 := tc.resp.GetFeeGrant()
|
||||
s.Require().NoError(err1)
|
||||
s.Require().Equal(
|
||||
tc.respType.GetFeeGrant().(*types.BasicFeeAllowance).SpendLimit,
|
||||
tc.resp.GetFeeGrant().(*types.BasicFeeAllowance).SpendLimit,
|
||||
grant.(*types.BasicFeeAllowance).SpendLimit,
|
||||
grant1.(*types.BasicFeeAllowance).SpendLimit,
|
||||
)
|
||||
}
|
||||
})
|
||||
|
@ -617,6 +622,181 @@ func (s *IntegrationTestSuite) TestTxWithFeeGrant() {
|
|||
s.Require().Equal(uint32(0), resp.Code)
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestFilteredFeeAllowance() {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
granter := val.Address
|
||||
info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee1", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
|
||||
s.Require().NoError(err)
|
||||
grantee := sdk.AccAddress(info.GetPubKey().Address())
|
||||
|
||||
clientCtx := val.ClientCtx
|
||||
|
||||
commonFlags := []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
}
|
||||
spendLimit := sdk.NewCoin("stake", sdk.NewInt(1000))
|
||||
|
||||
allowMsgs := "/cosmos.gov.v1beta1.Msg/SubmitProposal"
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
expectErr bool
|
||||
respType proto.Message
|
||||
expectedCode uint32
|
||||
}{
|
||||
{
|
||||
"wrong granter",
|
||||
append(
|
||||
[]string{
|
||||
"wrong granter",
|
||||
"cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl",
|
||||
fmt.Sprintf("--%s=%s", cli.FlagAllowedMsgs, allowMsgs),
|
||||
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, spendLimit.String()),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
||||
},
|
||||
commonFlags...,
|
||||
),
|
||||
true, &sdk.TxResponse{}, 0,
|
||||
},
|
||||
{
|
||||
"wrong grantee",
|
||||
append(
|
||||
[]string{
|
||||
granter.String(),
|
||||
"wrong grantee",
|
||||
fmt.Sprintf("--%s=%s", cli.FlagAllowedMsgs, allowMsgs),
|
||||
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, spendLimit.String()),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
||||
},
|
||||
commonFlags...,
|
||||
),
|
||||
true, &sdk.TxResponse{}, 0,
|
||||
},
|
||||
{
|
||||
"valid filter fee grant",
|
||||
append(
|
||||
[]string{
|
||||
granter.String(),
|
||||
grantee.String(),
|
||||
fmt.Sprintf("--%s=%s", cli.FlagAllowedMsgs, allowMsgs),
|
||||
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, spendLimit.String()),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, granter),
|
||||
},
|
||||
commonFlags...,
|
||||
),
|
||||
false, &sdk.TxResponse{}, 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
|
||||
s.Run(tc.name, func() {
|
||||
cmd := cli.NewCmdFeeGrant()
|
||||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
|
||||
|
||||
if tc.expectErr {
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
|
||||
|
||||
txResp := tc.respType.(*sdk.TxResponse)
|
||||
s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
args := []string{
|
||||
granter.String(),
|
||||
grantee.String(),
|
||||
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
|
||||
}
|
||||
|
||||
// get filtered fee allowance and check info
|
||||
cmd := cli.GetCmdQueryFeeGrant()
|
||||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
||||
s.Require().NoError(err)
|
||||
|
||||
resp := &types.FeeAllowanceGrant{}
|
||||
|
||||
s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), resp), out.String())
|
||||
s.Require().Equal(resp.Grantee, resp.Grantee)
|
||||
s.Require().Equal(resp.Granter, resp.Granter)
|
||||
|
||||
grant, err := resp.GetFeeGrant()
|
||||
s.Require().NoError(err)
|
||||
|
||||
filteredFeeGrant, err := grant.(*types.AllowedMsgFeeAllowance).GetAllowance()
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal(
|
||||
filteredFeeGrant.(*types.BasicFeeAllowance).SpendLimit.String(),
|
||||
spendLimit.String(),
|
||||
)
|
||||
|
||||
// exec filtered fee allowance
|
||||
cases := []struct {
|
||||
name string
|
||||
malleate func() (testutil.BufferWriter, error)
|
||||
expectErr bool
|
||||
respType proto.Message
|
||||
expectedCode uint32
|
||||
}{
|
||||
{
|
||||
"valid tx",
|
||||
func() (testutil.BufferWriter, error) {
|
||||
return govtestutil.MsgSubmitProposal(val.ClientCtx, grantee.String(),
|
||||
"Text Proposal", "No desc", govtypes.ProposalTypeText,
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFeeAccount, granter.String()),
|
||||
)
|
||||
},
|
||||
false,
|
||||
&sdk.TxResponse{},
|
||||
0,
|
||||
},
|
||||
{
|
||||
"should fail with unauthorized msgs",
|
||||
func() (testutil.BufferWriter, error) {
|
||||
args := append(
|
||||
[]string{
|
||||
grantee.String(),
|
||||
"cosmos14cm33pvnrv2497tyt8sp9yavhmw83nwej3m0e8",
|
||||
fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFeeAccount, granter),
|
||||
},
|
||||
commonFlags...,
|
||||
)
|
||||
cmd := cli.NewCmdFeeGrant()
|
||||
return clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
||||
},
|
||||
false, &sdk.TxResponse{}, 7,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
|
||||
s.Run(tc.name, func() {
|
||||
out, err := tc.malleate()
|
||||
|
||||
if tc.expectErr {
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
|
||||
|
||||
txResp := tc.respType.(*sdk.TxResponse)
|
||||
s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntegrationTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(IntegrationTestSuite))
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ const (
|
|||
FlagPeriod = "period"
|
||||
FlagPeriodLimit = "period-limit"
|
||||
FlagSpendLimit = "spend-limit"
|
||||
FlagAllowedMsgs = "allowed-messages"
|
||||
)
|
||||
|
||||
// GetTxCmd returns the transaction commands for this module
|
||||
|
@ -55,8 +56,10 @@ func NewCmdFeeGrant() *cobra.Command {
|
|||
|
||||
Examples:
|
||||
%s tx %s grant cosmos1skjw... cosmos1skjw... --spend-limit 100stake --expiration 36000 or
|
||||
%s tx %s grant cosmos1skjw... cosmos1skjw... --spend-limit 100stake --period 3600 --period-limit 10stake --expiration 36000
|
||||
`, version.AppName, types.ModuleName, version.AppName, types.ModuleName,
|
||||
%s tx %s grant cosmos1skjw... cosmos1skjw... --spend-limit 100stake --period 3600 --period-limit 10stake --expiration 36000 or
|
||||
%s tx %s grant cosmos1skjw... cosmos1skjw... --spend-limit 100stake --expiration 36000
|
||||
--allowed-messages "/cosmos.gov.v1beta1.Msg/SubmitProposal,/cosmos.gov.v1beta1.Msg/Vote"
|
||||
`, version.AppName, types.ModuleName, version.AppName, types.ModuleName, version.AppName, types.ModuleName,
|
||||
),
|
||||
),
|
||||
Args: cobra.ExactArgs(2),
|
||||
|
@ -143,6 +146,18 @@ Examples:
|
|||
}
|
||||
}
|
||||
|
||||
allowedMsgs, err := cmd.Flags().GetStringSlice(FlagAllowedMsgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(allowedMsgs) > 0 {
|
||||
grant, err = types.NewAllowedMsgFeeAllowance(grant, allowedMsgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
msg, err := types.NewMsgGrantFeeAllowance(grant, granter, grantee)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -160,10 +175,11 @@ Examples:
|
|||
}
|
||||
|
||||
flags.AddTxFlagsToCmd(cmd)
|
||||
cmd.Flags().StringSlice(FlagAllowedMsgs, []string{}, "Set of allowed messages for fee allowance")
|
||||
cmd.Flags().Int64(FlagExpiration, 0, "The second unit of time duration which the grant is active for the user")
|
||||
cmd.Flags().String(FlagSpendLimit, "", "Spend limit specifies the max limit can be used, if not mentioned there is no limit")
|
||||
cmd.Flags().Int64(FlagPeriod, 0, "period specifies the time duration in which period_spend_limit coins can be spent before that allowance is reset")
|
||||
cmd.Flags().String(FlagPeriodLimit, "", "// period limit specifies the maximum number of coins that can be spent in the period")
|
||||
cmd.Flags().String(FlagPeriodLimit, "", "period limit specifies the maximum number of coins that can be spent in the period")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ func (s *IntegrationTestSuite) TestQueryFeeAllowance() {
|
|||
"fail: no grants",
|
||||
fmt.Sprintf("%s/cosmos/feegrant/v1beta1/fee_allowance/%s/%s", baseURL, val.Address.String(), s.grantee.String()),
|
||||
true,
|
||||
"no fee allowance found",
|
||||
"no allowance",
|
||||
func() {},
|
||||
func(types.QueryFeeAllowanceResponse) {},
|
||||
},
|
||||
|
|
|
@ -12,7 +12,11 @@ type GenesisState []types.FeeAllowanceGrant
|
|||
// ValidateBasic ensures all grants in the genesis state are valid
|
||||
func (g GenesisState) ValidateBasic() error {
|
||||
for _, f := range g {
|
||||
err := f.GetFeeGrant().ValidateBasic()
|
||||
grant, err := f.GetFeeGrant()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = grant.ValidateBasic()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -32,7 +36,12 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, data *types.GenesisState) {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
err = k.GrantFeeAllowance(ctx, granter, grantee, f.GetFeeGrant())
|
||||
grant, err := f.GetFeeGrant()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = k.GrantFeeAllowance(ctx, granter, grantee, grant)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -34,9 +34,9 @@ func (q Keeper) FeeAllowance(c context.Context, req *types.QueryFeeAllowanceRequ
|
|||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
feeAllowance := q.GetFeeAllowance(ctx, granterAddr, granteeAddr)
|
||||
if feeAllowance == nil {
|
||||
return nil, status.Errorf(codes.NotFound, "no fee allowance found")
|
||||
feeAllowance, err := q.GetFeeAllowance(ctx, granterAddr, granteeAddr)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
msg, ok := feeAllowance.(proto.Message)
|
||||
|
|
|
@ -95,10 +95,10 @@ func (k Keeper) RevokeFeeAllowance(ctx sdk.Context, granter, grantee sdk.AccAddr
|
|||
// GetFeeAllowance returns the allowance between the granter and grantee.
|
||||
// If there is none, it returns nil, nil.
|
||||
// Returns an error on parsing issues
|
||||
func (k Keeper) GetFeeAllowance(ctx sdk.Context, granter, grantee sdk.AccAddress) types.FeeAllowanceI {
|
||||
func (k Keeper) GetFeeAllowance(ctx sdk.Context, granter, grantee sdk.AccAddress) (types.FeeAllowanceI, error) {
|
||||
grant, found := k.GetFeeGrant(ctx, granter, grantee)
|
||||
if !found {
|
||||
return nil
|
||||
return nil, sdkerrors.Wrapf(types.ErrNoAllowance, "grant missing")
|
||||
}
|
||||
|
||||
return grant.GetFeeGrant()
|
||||
|
@ -161,13 +161,18 @@ func (k Keeper) IterateAllFeeAllowances(ctx sdk.Context, cb func(types.FeeAllowa
|
|||
}
|
||||
|
||||
// UseGrantedFees will try to pay the given fee from the granter's account as requested by the grantee
|
||||
func (k Keeper) UseGrantedFees(ctx sdk.Context, granter, grantee sdk.AccAddress, fee sdk.Coins) error {
|
||||
grant, found := k.GetFeeGrant(ctx, granter, grantee)
|
||||
if !found || grant.GetFeeGrant() == nil {
|
||||
func (k Keeper) UseGrantedFees(ctx sdk.Context, granter, grantee sdk.AccAddress, fee sdk.Coins, msgs []sdk.Msg) error {
|
||||
f, found := k.GetFeeGrant(ctx, granter, grantee)
|
||||
if !found {
|
||||
return sdkerrors.Wrapf(types.ErrNoAllowance, "grant missing")
|
||||
}
|
||||
|
||||
remove, err := grant.GetFeeGrant().Accept(fee, ctx.BlockTime(), ctx.BlockHeight())
|
||||
grant, err := f.GetFeeGrant()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
remove, err := grant.Accept(ctx, fee, msgs)
|
||||
if err == nil {
|
||||
ctx.EventManager().EmitEvent(
|
||||
sdk.NewEvent(
|
||||
|
@ -189,5 +194,5 @@ func (k Keeper) UseGrantedFees(ctx sdk.Context, granter, grantee sdk.AccAddress,
|
|||
}
|
||||
|
||||
// if we accepted, store the updated state of the allowance
|
||||
return k.GrantFeeAllowance(ctx, granter, grantee, grant.GetFeeGrant())
|
||||
return k.GrantFeeAllowance(ctx, granter, grantee, grant)
|
||||
}
|
||||
|
|
|
@ -109,7 +109,8 @@ func (suite *KeeperTestSuite) TestKeeperCrud() {
|
|||
for name, tc := range cases {
|
||||
tc := tc
|
||||
suite.Run(name, func() {
|
||||
allow := k.GetFeeAllowance(ctx, tc.granter, tc.grantee)
|
||||
allow, _ := k.GetFeeAllowance(ctx, tc.granter, tc.grantee)
|
||||
|
||||
if tc.allowance == nil {
|
||||
suite.Nil(allow)
|
||||
return
|
||||
|
@ -242,14 +243,14 @@ func (suite *KeeperTestSuite) TestUseGrantedFee() {
|
|||
err = k.GrantFeeAllowance(ctx, suite.addrs[0], suite.addrs[3], expired)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
err = k.UseGrantedFees(ctx, tc.granter, tc.grantee, tc.fee)
|
||||
err = k.UseGrantedFees(ctx, tc.granter, tc.grantee, tc.fee, []sdk.Msg{})
|
||||
if tc.allowed {
|
||||
suite.NoError(err)
|
||||
} else {
|
||||
suite.Error(err)
|
||||
}
|
||||
|
||||
loaded := k.GetFeeAllowance(ctx, tc.granter, tc.grantee)
|
||||
loaded, _ := k.GetFeeAllowance(ctx, tc.granter, tc.grantee)
|
||||
|
||||
suite.Equal(tc.final, loaded)
|
||||
})
|
||||
|
|
|
@ -37,12 +37,16 @@ func (k msgServer) GrantFeeAllowance(goCtx context.Context, msg *types.MsgGrantF
|
|||
}
|
||||
|
||||
// Checking for duplicate entry
|
||||
f := k.Keeper.GetFeeAllowance(ctx, granter, grantee)
|
||||
if f != nil {
|
||||
if f, _ := k.Keeper.GetFeeAllowance(ctx, granter, grantee); f != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "fee allowance already exists")
|
||||
}
|
||||
|
||||
err = k.Keeper.GrantFeeAllowance(ctx, granter, grantee, msg.GetFeeAllowanceI())
|
||||
allowance, err := msg.GetFeeAllowanceI()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = k.Keeper.GrantFeeAllowance(ctx, granter, grantee, allowance)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -71,8 +71,7 @@ func SimulateMsgGrantFeeAllowance(ak types.AccountKeeper, bk types.BankKeeper, k
|
|||
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, "grantee and granter cannot be same"), nil, nil
|
||||
}
|
||||
|
||||
f := k.GetFeeAllowance(ctx, granter.Address, grantee.Address)
|
||||
if f != nil {
|
||||
if f, _ := k.GetFeeAllowance(ctx, granter.Address, grantee.Address); f != nil {
|
||||
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, "fee allowance exists"), nil, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,10 @@ var _ FeeAllowanceI = (*BasicFeeAllowance)(nil)
|
|||
//
|
||||
// If remove is true (regardless of the error), the FeeAllowance will be deleted from storage
|
||||
// (eg. when it is used up). (See call to RevokeFeeAllowance in Keeper.UseGrantedFees)
|
||||
func (a *BasicFeeAllowance) Accept(fee sdk.Coins, blockTime time.Time, blockHeight int64) (bool, error) {
|
||||
func (a *BasicFeeAllowance) Accept(ctx sdk.Context, fee sdk.Coins, _ []sdk.Msg) (bool, error) {
|
||||
blockTime := ctx.BlockTime()
|
||||
blockHeight := ctx.BlockHeight()
|
||||
|
||||
if a.Expiration.IsExpired(&blockTime, blockHeight) {
|
||||
return true, sdkerrors.Wrap(ErrFeeLimitExpired, "basic allowance")
|
||||
}
|
||||
|
|
|
@ -2,16 +2,19 @@ package types_test
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/feegrant/types"
|
||||
)
|
||||
|
||||
func TestBasicFeeValidAllow(t *testing.T) {
|
||||
app := simapp.Setup(false)
|
||||
|
||||
eth := sdk.NewCoins(sdk.NewInt64Coin("eth", 10))
|
||||
atom := sdk.NewCoins(sdk.NewInt64Coin("atom", 555))
|
||||
smallAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 43))
|
||||
|
@ -22,7 +25,6 @@ func TestBasicFeeValidAllow(t *testing.T) {
|
|||
allow *types.BasicFeeAllowance
|
||||
// all other checks are ignored if valid=false
|
||||
fee sdk.Coins
|
||||
blockTime time.Time
|
||||
blockHeight int64
|
||||
valid bool
|
||||
accept bool
|
||||
|
@ -124,8 +126,10 @@ func TestBasicFeeValidAllow(t *testing.T) {
|
|||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{}).WithBlockHeight(tc.blockHeight)
|
||||
|
||||
// now try to deduct
|
||||
remove, err := tc.allow.Accept(tc.fee, tc.blockTime, tc.blockHeight)
|
||||
remove, err := tc.allow.Accept(ctx, tc.fee, []sdk.Msg{})
|
||||
if !tc.accept {
|
||||
require.Error(t, err)
|
||||
return
|
||||
|
|
|
@ -18,6 +18,7 @@ func RegisterInterfaces(registry types.InterfaceRegistry) {
|
|||
(*FeeAllowanceI)(nil),
|
||||
&BasicFeeAllowance{},
|
||||
&PeriodicFeeAllowance{},
|
||||
&AllowedMsgFeeAllowance{},
|
||||
)
|
||||
|
||||
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
|
||||
|
|
|
@ -18,4 +18,8 @@ var (
|
|||
ErrInvalidDuration = sdkerrors.Register(DefaultCodespace, 4, "invalid duration")
|
||||
// ErrNoAllowance error if there is no allowance for that pair
|
||||
ErrNoAllowance = sdkerrors.Register(DefaultCodespace, 5, "no allowance")
|
||||
// ErrNoMessages error if there is no message
|
||||
ErrNoMessages = sdkerrors.Register(DefaultCodespace, 6, "allowed messages are empty")
|
||||
// ErrMessageNotAllowed error if message is not allowed
|
||||
ErrMessageNotAllowed = sdkerrors.Register(DefaultCodespace, 7, "message not allowed")
|
||||
)
|
||||
|
|
|
@ -177,6 +177,47 @@ func (m *PeriodicFeeAllowance) GetPeriodReset() ExpiresAt {
|
|||
return ExpiresAt{}
|
||||
}
|
||||
|
||||
// AllowedMsgFeeAllowance creates allowance only for specified message types.
|
||||
type AllowedMsgFeeAllowance struct {
|
||||
// allowance can be any of basic and filtered fee allowance.
|
||||
Allowance *types1.Any `protobuf:"bytes,1,opt,name=allowance,proto3" json:"allowance,omitempty"`
|
||||
// allowed_messages are the messages for which the grantee has the access.
|
||||
AllowedMessages []string `protobuf:"bytes,2,rep,name=allowed_messages,json=allowedMessages,proto3" json:"allowed_messages,omitempty"`
|
||||
}
|
||||
|
||||
func (m *AllowedMsgFeeAllowance) Reset() { *m = AllowedMsgFeeAllowance{} }
|
||||
func (m *AllowedMsgFeeAllowance) String() string { return proto.CompactTextString(m) }
|
||||
func (*AllowedMsgFeeAllowance) ProtoMessage() {}
|
||||
func (*AllowedMsgFeeAllowance) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_7279582900c30aea, []int{2}
|
||||
}
|
||||
func (m *AllowedMsgFeeAllowance) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *AllowedMsgFeeAllowance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_AllowedMsgFeeAllowance.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *AllowedMsgFeeAllowance) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_AllowedMsgFeeAllowance.Merge(m, src)
|
||||
}
|
||||
func (m *AllowedMsgFeeAllowance) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *AllowedMsgFeeAllowance) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_AllowedMsgFeeAllowance.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_AllowedMsgFeeAllowance proto.InternalMessageInfo
|
||||
|
||||
// Duration is a span of a clock time or number of blocks.
|
||||
// This is designed to be added to an ExpiresAt struct.
|
||||
type Duration struct {
|
||||
|
@ -192,7 +233,7 @@ func (m *Duration) Reset() { *m = Duration{} }
|
|||
func (m *Duration) String() string { return proto.CompactTextString(m) }
|
||||
func (*Duration) ProtoMessage() {}
|
||||
func (*Duration) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_7279582900c30aea, []int{2}
|
||||
return fileDescriptor_7279582900c30aea, []int{3}
|
||||
}
|
||||
func (m *Duration) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
@ -281,7 +322,7 @@ func (m *ExpiresAt) Reset() { *m = ExpiresAt{} }
|
|||
func (m *ExpiresAt) String() string { return proto.CompactTextString(m) }
|
||||
func (*ExpiresAt) ProtoMessage() {}
|
||||
func (*ExpiresAt) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_7279582900c30aea, []int{3}
|
||||
return fileDescriptor_7279582900c30aea, []int{4}
|
||||
}
|
||||
func (m *ExpiresAt) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
@ -366,7 +407,7 @@ func (m *FeeAllowanceGrant) Reset() { *m = FeeAllowanceGrant{} }
|
|||
func (m *FeeAllowanceGrant) String() string { return proto.CompactTextString(m) }
|
||||
func (*FeeAllowanceGrant) ProtoMessage() {}
|
||||
func (*FeeAllowanceGrant) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_7279582900c30aea, []int{4}
|
||||
return fileDescriptor_7279582900c30aea, []int{5}
|
||||
}
|
||||
func (m *FeeAllowanceGrant) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
@ -419,6 +460,7 @@ func (m *FeeAllowanceGrant) GetAllowance() *types1.Any {
|
|||
func init() {
|
||||
proto.RegisterType((*BasicFeeAllowance)(nil), "cosmos.feegrant.v1beta1.BasicFeeAllowance")
|
||||
proto.RegisterType((*PeriodicFeeAllowance)(nil), "cosmos.feegrant.v1beta1.PeriodicFeeAllowance")
|
||||
proto.RegisterType((*AllowedMsgFeeAllowance)(nil), "cosmos.feegrant.v1beta1.AllowedMsgFeeAllowance")
|
||||
proto.RegisterType((*Duration)(nil), "cosmos.feegrant.v1beta1.Duration")
|
||||
proto.RegisterType((*ExpiresAt)(nil), "cosmos.feegrant.v1beta1.ExpiresAt")
|
||||
proto.RegisterType((*FeeAllowanceGrant)(nil), "cosmos.feegrant.v1beta1.FeeAllowanceGrant")
|
||||
|
@ -429,45 +471,48 @@ func init() {
|
|||
}
|
||||
|
||||
var fileDescriptor_7279582900c30aea = []byte{
|
||||
// 599 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0x4f, 0x6e, 0xd3, 0x40,
|
||||
0x14, 0xc6, 0x6d, 0x9c, 0x96, 0x76, 0x02, 0x88, 0x8c, 0x22, 0xe1, 0x64, 0xe1, 0x94, 0x2c, 0x50,
|
||||
0x84, 0x14, 0x9b, 0x16, 0x89, 0x05, 0x12, 0x42, 0x71, 0x69, 0x1b, 0x04, 0x0b, 0x64, 0x58, 0xb1,
|
||||
0x89, 0x6c, 0x67, 0xea, 0x0c, 0xb5, 0x3d, 0x96, 0x67, 0x02, 0xcd, 0x25, 0x50, 0x97, 0x9c, 0x81,
|
||||
0x35, 0x87, 0xa8, 0x58, 0x55, 0xac, 0x58, 0xb5, 0x28, 0x39, 0x01, 0x37, 0x40, 0xf3, 0xc7, 0x4e,
|
||||
0x94, 0x10, 0x24, 0xa4, 0xae, 0xe2, 0x99, 0x79, 0xef, 0xfb, 0xbd, 0xf7, 0xbd, 0x99, 0x80, 0x07,
|
||||
0x21, 0xa1, 0x09, 0xa1, 0xce, 0x31, 0x42, 0x51, 0xee, 0xa7, 0xcc, 0xf9, 0xb8, 0x1b, 0x20, 0xe6,
|
||||
0xef, 0x96, 0x1b, 0x76, 0x96, 0x13, 0x46, 0xe0, 0x3d, 0x19, 0x67, 0x97, 0xdb, 0x2a, 0xae, 0x59,
|
||||
0x8f, 0x48, 0x44, 0x44, 0x8c, 0xc3, 0xbf, 0x64, 0x78, 0xb3, 0x11, 0x11, 0x12, 0xc5, 0xc8, 0x11,
|
||||
0xab, 0x60, 0x7c, 0xec, 0xf8, 0xe9, 0xa4, 0x38, 0x92, 0x4a, 0x03, 0x99, 0xa3, 0x64, 0xe5, 0x91,
|
||||
0xa5, 0x8a, 0x09, 0x7c, 0x8a, 0xca, 0x42, 0x42, 0x82, 0x53, 0x75, 0xde, 0x5a, 0x56, 0x65, 0x38,
|
||||
0x41, 0x94, 0xf9, 0x49, 0x56, 0x08, 0x2c, 0x07, 0x0c, 0xc7, 0xb9, 0xcf, 0x30, 0x51, 0x02, 0xed,
|
||||
0x4b, 0x1d, 0xd4, 0x5c, 0x9f, 0xe2, 0xf0, 0x10, 0xa1, 0x5e, 0x1c, 0x93, 0x4f, 0x7e, 0x1a, 0x22,
|
||||
0x18, 0x83, 0x2a, 0xcd, 0x50, 0x3a, 0x1c, 0xc4, 0x38, 0xc1, 0xcc, 0xd4, 0x77, 0x8c, 0x4e, 0x75,
|
||||
0xaf, 0x61, 0xab, 0xd2, 0x78, 0x31, 0x45, 0xb7, 0xf6, 0x3e, 0xc1, 0xa9, 0xfb, 0xe8, 0xfc, 0xb2,
|
||||
0xa5, 0x7d, 0xbd, 0x6a, 0x75, 0x22, 0xcc, 0x46, 0xe3, 0xc0, 0x0e, 0x49, 0xa2, 0xfa, 0x50, 0x3f,
|
||||
0x5d, 0x3a, 0x3c, 0x71, 0xd8, 0x24, 0x43, 0x54, 0x24, 0x50, 0x0f, 0x08, 0xfd, 0xd7, 0x5c, 0x1e,
|
||||
0xf6, 0x01, 0x40, 0xa7, 0x19, 0x96, 0x75, 0x99, 0x37, 0x76, 0xf4, 0x4e, 0x75, 0xaf, 0x6d, 0xaf,
|
||||
0xb1, 0xd7, 0x3e, 0xe0, 0xa1, 0x88, 0xf6, 0x98, 0x5b, 0xe1, 0x54, 0x6f, 0x21, 0xf7, 0x69, 0xed,
|
||||
0xc7, 0xb7, 0xee, 0xed, 0xc5, 0x4e, 0x5e, 0xb6, 0x7f, 0x1b, 0xa0, 0xfe, 0x06, 0xe5, 0x98, 0x0c,
|
||||
0x97, 0x7a, 0x3c, 0x04, 0x1b, 0x01, 0x6f, 0xdc, 0xd4, 0x05, 0xf0, 0xe1, 0x5a, 0xe0, 0x8a, 0x3d,
|
||||
0x0a, 0x2c, 0xd3, 0xe1, 0x73, 0xb0, 0x99, 0x09, 0x7d, 0x55, 0xf9, 0xfd, 0xb5, 0x42, 0x2f, 0x94,
|
||||
0xf5, 0x2a, 0x5f, 0xa5, 0xc1, 0x09, 0x80, 0xf2, 0x6b, 0xb0, 0xe8, 0xb9, 0x71, 0xfd, 0x9e, 0xdf,
|
||||
0x95, 0x98, 0xb7, 0x73, 0xe7, 0xc7, 0x40, 0xed, 0x0d, 0x42, 0x3f, 0x95, 0x78, 0xb3, 0x72, 0xfd,
|
||||
0xe0, 0x3b, 0x12, 0xb2, 0xef, 0xa7, 0x82, 0x0d, 0x5f, 0x81, 0x5b, 0x0a, 0x9b, 0x23, 0x8a, 0x98,
|
||||
0xb9, 0xf1, 0x9f, 0x23, 0xaf, 0xca, 0x6c, 0x8f, 0x27, 0xff, 0x6d, 0xe6, 0x1f, 0xc0, 0x56, 0xe1,
|
||||
0x35, 0x7c, 0x06, 0xb6, 0x8a, 0x2b, 0xaf, 0x26, 0xdd, 0xb0, 0xe5, 0x9b, 0xb0, 0x8b, 0x37, 0xb1,
|
||||
0x30, 0x98, 0x2f, 0x57, 0x2d, 0xbd, 0xaf, 0x79, 0x65, 0x0a, 0x34, 0xc1, 0x66, 0x10, 0x93, 0xf0,
|
||||
0x84, 0x8a, 0xe9, 0x56, 0xfa, 0x9a, 0xa7, 0xd6, 0xee, 0x06, 0x30, 0xe8, 0x38, 0x69, 0x0f, 0xc1,
|
||||
0x76, 0x59, 0x1e, 0x7c, 0x02, 0x2a, 0xfc, 0x01, 0x2a, 0x50, 0x73, 0x05, 0xf4, 0xae, 0x78, 0x9d,
|
||||
0x6e, 0xe5, 0x4c, 0x92, 0x44, 0x3c, 0xa7, 0x8c, 0x10, 0x8e, 0x46, 0x4c, 0x50, 0x0c, 0x4e, 0x91,
|
||||
0xeb, 0x82, 0xf2, 0x59, 0x07, 0xb5, 0xc5, 0x1e, 0x8f, 0xb8, 0x3f, 0xd0, 0x04, 0x37, 0x85, 0x51,
|
||||
0x28, 0x17, 0xc4, 0x6d, 0xaf, 0x58, 0xce, 0x4f, 0x90, 0x50, 0x2c, 0x4f, 0x10, 0x3c, 0x00, 0xdb,
|
||||
0x7e, 0xa1, 0x62, 0x1a, 0xa2, 0xce, 0xfa, 0x4a, 0x9d, 0xbd, 0x74, 0xe2, 0xd6, 0xbe, 0x2f, 0xfb,
|
||||
0xea, 0xcd, 0x33, 0xdd, 0xa3, 0xf3, 0xa9, 0xa5, 0x5f, 0x4c, 0x2d, 0xfd, 0xd7, 0xd4, 0xd2, 0xcf,
|
||||
0x66, 0x96, 0x76, 0x31, 0xb3, 0xb4, 0x9f, 0x33, 0x4b, 0x7b, 0xdf, 0xfd, 0xe7, 0xb5, 0x38, 0x9d,
|
||||
0xff, 0xaf, 0x8a, 0x1b, 0x12, 0x6c, 0x0a, 0xe8, 0xe3, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x74,
|
||||
0x27, 0xe6, 0x00, 0x77, 0x05, 0x00, 0x00,
|
||||
// 650 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0x4d, 0x6f, 0xd3, 0x30,
|
||||
0x18, 0xc7, 0x93, 0xa5, 0x1b, 0xab, 0xcb, 0xcb, 0x6a, 0x0d, 0xc8, 0x76, 0x48, 0x47, 0x0f, 0xa8,
|
||||
0x20, 0x2d, 0x61, 0x43, 0xe2, 0x30, 0x09, 0xa1, 0x65, 0xec, 0x05, 0xc1, 0x24, 0x14, 0x38, 0x71,
|
||||
0xa9, 0x9c, 0xc4, 0x4b, 0xc3, 0x92, 0x38, 0x8a, 0x5d, 0x58, 0xbf, 0x01, 0x27, 0xb4, 0x23, 0x47,
|
||||
0xb8, 0x72, 0xe6, 0x43, 0x4c, 0x9c, 0x26, 0x4e, 0x9c, 0x36, 0xd4, 0x7e, 0x02, 0xbe, 0x01, 0x8a,
|
||||
0xed, 0xa4, 0xa5, 0xa5, 0x48, 0xa0, 0x9d, 0x92, 0xc7, 0x7e, 0x9e, 0xff, 0xef, 0x79, 0xb1, 0x0d,
|
||||
0x6e, 0x7b, 0x84, 0xc6, 0x84, 0x5a, 0x07, 0x18, 0x07, 0x19, 0x4a, 0x98, 0xf5, 0x66, 0xcd, 0xc5,
|
||||
0x0c, 0xad, 0x95, 0x0b, 0x66, 0x9a, 0x11, 0x46, 0xe0, 0x4d, 0xe1, 0x67, 0x96, 0xcb, 0xd2, 0x6f,
|
||||
0x79, 0x31, 0x20, 0x01, 0xe1, 0x3e, 0x56, 0xfe, 0x27, 0xdc, 0x97, 0x97, 0x02, 0x42, 0x82, 0x08,
|
||||
0x5b, 0xdc, 0x72, 0xbb, 0x07, 0x16, 0x4a, 0x7a, 0xc5, 0x96, 0x50, 0x6a, 0x8b, 0x18, 0x29, 0x2b,
|
||||
0xb6, 0x0c, 0x99, 0x8c, 0x8b, 0x28, 0x2e, 0x13, 0xf1, 0x48, 0x98, 0xc8, 0xfd, 0xc6, 0xb8, 0x2a,
|
||||
0x0b, 0x63, 0x4c, 0x19, 0x8a, 0xd3, 0x42, 0x60, 0xdc, 0xc1, 0xef, 0x66, 0x88, 0x85, 0x44, 0x0a,
|
||||
0x34, 0xcf, 0x54, 0x50, 0xb7, 0x11, 0x0d, 0xbd, 0x1d, 0x8c, 0x37, 0xa3, 0x88, 0xbc, 0x45, 0x89,
|
||||
0x87, 0x61, 0x04, 0x6a, 0x34, 0xc5, 0x89, 0xdf, 0x8e, 0xc2, 0x38, 0x64, 0xba, 0xba, 0xa2, 0xb5,
|
||||
0x6a, 0xeb, 0x4b, 0xa6, 0x4c, 0x2d, 0x4f, 0xa6, 0xa8, 0xd6, 0xdc, 0x22, 0x61, 0x62, 0xdf, 0x3b,
|
||||
0x39, 0x6b, 0x28, 0x9f, 0xcf, 0x1b, 0xad, 0x20, 0x64, 0x9d, 0xae, 0x6b, 0x7a, 0x24, 0x96, 0x75,
|
||||
0xc8, 0xcf, 0x2a, 0xf5, 0x0f, 0x2d, 0xd6, 0x4b, 0x31, 0xe5, 0x01, 0xd4, 0x01, 0x5c, 0xff, 0x59,
|
||||
0x2e, 0x0f, 0xf7, 0x00, 0xc0, 0x47, 0x69, 0x28, 0xf2, 0xd2, 0x67, 0x56, 0xd4, 0x56, 0x6d, 0xbd,
|
||||
0x69, 0x4e, 0x69, 0xaf, 0xb9, 0x9d, 0xbb, 0x62, 0xba, 0xc9, 0xec, 0x4a, 0x4e, 0x75, 0x46, 0x62,
|
||||
0x37, 0xea, 0xdf, 0xbe, 0xac, 0x5e, 0x19, 0xad, 0xe4, 0x49, 0xf3, 0xa7, 0x06, 0x16, 0x9f, 0xe3,
|
||||
0x2c, 0x24, 0xfe, 0x58, 0x8d, 0x3b, 0x60, 0xd6, 0xcd, 0x0b, 0xd7, 0x55, 0x0e, 0xbc, 0x3b, 0x15,
|
||||
0x38, 0xd1, 0x1e, 0x09, 0x16, 0xe1, 0xf0, 0x11, 0x98, 0x4b, 0xb9, 0xbe, 0xcc, 0xfc, 0xd6, 0x54,
|
||||
0xa1, 0xc7, 0xb2, 0xf5, 0x32, 0x5e, 0x86, 0xc1, 0x1e, 0x80, 0xe2, 0xaf, 0x3d, 0xda, 0x73, 0xed,
|
||||
0xe2, 0x7b, 0xbe, 0x20, 0x30, 0x2f, 0x86, 0x9d, 0xef, 0x02, 0xb9, 0xd6, 0xf6, 0x50, 0x22, 0xf0,
|
||||
0x7a, 0xe5, 0xe2, 0xc1, 0x57, 0x05, 0x64, 0x0b, 0x25, 0x9c, 0x0d, 0x9f, 0x82, 0xcb, 0x12, 0x9b,
|
||||
0x61, 0x8a, 0x99, 0x3e, 0xfb, 0x8f, 0x23, 0xaf, 0x89, 0x68, 0x27, 0x0f, 0xfe, 0xd3, 0xcc, 0x3f,
|
||||
0xa9, 0xe0, 0x06, 0x37, 0xb1, 0xbf, 0x4f, 0x83, 0xdf, 0xa6, 0xbe, 0x0d, 0xaa, 0xa8, 0x30, 0xe4,
|
||||
0xe4, 0x17, 0x4d, 0x71, 0x47, 0xcc, 0xe2, 0x8e, 0x98, 0x9b, 0x49, 0xcf, 0xae, 0x7f, 0x1d, 0x97,
|
||||
0x75, 0x86, 0x91, 0xf0, 0x0e, 0x58, 0x40, 0x02, 0xd0, 0x8e, 0x31, 0xa5, 0x28, 0xc0, 0x54, 0x9f,
|
||||
0x59, 0xd1, 0x5a, 0x55, 0xe7, 0x9a, 0x5c, 0xdf, 0x97, 0xcb, 0x1b, 0xd7, 0xdf, 0x7d, 0x6c, 0x28,
|
||||
0x93, 0x39, 0xbe, 0x06, 0xf3, 0xc5, 0x79, 0x80, 0x0f, 0xc1, 0x7c, 0x71, 0x2d, 0x65, 0x4e, 0x4b,
|
||||
0x13, 0x39, 0x0d, 0x0f, 0xcf, 0x87, 0xf3, 0x86, 0xba, 0xa7, 0x38, 0x65, 0x08, 0xd4, 0xc1, 0x9c,
|
||||
0x1b, 0x11, 0xef, 0x90, 0xf2, 0x13, 0x58, 0xd9, 0x53, 0x1c, 0x69, 0xdb, 0xb3, 0x40, 0xa3, 0xdd,
|
||||
0xb8, 0xe9, 0x83, 0x6a, 0xd9, 0x42, 0xf8, 0x00, 0x54, 0xf2, 0x47, 0x42, 0x82, 0x96, 0x27, 0x40,
|
||||
0x2f, 0x8b, 0x17, 0xc4, 0xae, 0x1c, 0x0b, 0x12, 0xf7, 0xcf, 0x29, 0x1d, 0x1c, 0x06, 0x1d, 0xc6,
|
||||
0x29, 0x5a, 0x4e, 0x11, 0x76, 0x41, 0x79, 0xaf, 0x82, 0xfa, 0x68, 0x8d, 0xbb, 0xf9, 0x0c, 0xa1,
|
||||
0x0e, 0x2e, 0xf1, 0x61, 0xe2, 0x8c, 0x13, 0xab, 0x4e, 0x61, 0x0e, 0x77, 0x30, 0x57, 0x2c, 0x77,
|
||||
0xc6, 0x86, 0xa4, 0xfd, 0xef, 0x90, 0xec, 0xdd, 0x93, 0xbe, 0xa1, 0x9e, 0xf6, 0x0d, 0xf5, 0x47,
|
||||
0xdf, 0x50, 0x8f, 0x07, 0x86, 0x72, 0x3a, 0x30, 0x94, 0xef, 0x03, 0x43, 0x79, 0xb5, 0xfa, 0xd7,
|
||||
0xa3, 0x7b, 0x34, 0x7c, 0xfb, 0xf9, 0x29, 0x76, 0xe7, 0x38, 0xf4, 0xfe, 0xaf, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xfc, 0x05, 0xa9, 0xc7, 0x1b, 0x06, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *BasicFeeAllowance) Marshal() (dAtA []byte, err error) {
|
||||
|
@ -598,6 +643,50 @@ func (m *PeriodicFeeAllowance) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *AllowedMsgFeeAllowance) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *AllowedMsgFeeAllowance) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *AllowedMsgFeeAllowance) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.AllowedMessages) > 0 {
|
||||
for iNdEx := len(m.AllowedMessages) - 1; iNdEx >= 0; iNdEx-- {
|
||||
i -= len(m.AllowedMessages[iNdEx])
|
||||
copy(dAtA[i:], m.AllowedMessages[iNdEx])
|
||||
i = encodeVarintFeegrant(dAtA, i, uint64(len(m.AllowedMessages[iNdEx])))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
}
|
||||
if m.Allowance != nil {
|
||||
{
|
||||
size, err := m.Allowance.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintFeegrant(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *Duration) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
|
@ -638,12 +727,12 @@ func (m *Duration_Duration) MarshalTo(dAtA []byte) (int, error) {
|
|||
func (m *Duration_Duration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
if m.Duration != nil {
|
||||
n5, err5 := github_com_gogo_protobuf_types.StdDurationMarshalTo(*m.Duration, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(*m.Duration):])
|
||||
if err5 != nil {
|
||||
return 0, err5
|
||||
n6, err6 := github_com_gogo_protobuf_types.StdDurationMarshalTo(*m.Duration, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(*m.Duration):])
|
||||
if err6 != nil {
|
||||
return 0, err6
|
||||
}
|
||||
i -= n5
|
||||
i = encodeVarintFeegrant(dAtA, i, uint64(n5))
|
||||
i -= n6
|
||||
i = encodeVarintFeegrant(dAtA, i, uint64(n6))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
|
@ -701,12 +790,12 @@ func (m *ExpiresAt_Time) MarshalTo(dAtA []byte) (int, error) {
|
|||
func (m *ExpiresAt_Time) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
if m.Time != nil {
|
||||
n6, err6 := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(*m.Time):])
|
||||
if err6 != nil {
|
||||
return 0, err6
|
||||
n7, err7 := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(*m.Time):])
|
||||
if err7 != nil {
|
||||
return 0, err7
|
||||
}
|
||||
i -= n6
|
||||
i = encodeVarintFeegrant(dAtA, i, uint64(n6))
|
||||
i -= n7
|
||||
i = encodeVarintFeegrant(dAtA, i, uint64(n7))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
|
@ -828,6 +917,25 @@ func (m *PeriodicFeeAllowance) Size() (n int) {
|
|||
return n
|
||||
}
|
||||
|
||||
func (m *AllowedMsgFeeAllowance) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.Allowance != nil {
|
||||
l = m.Allowance.Size()
|
||||
n += 1 + l + sovFeegrant(uint64(l))
|
||||
}
|
||||
if len(m.AllowedMessages) > 0 {
|
||||
for _, s := range m.AllowedMessages {
|
||||
l = len(s)
|
||||
n += 1 + l + sovFeegrant(uint64(l))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *Duration) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
|
@ -1255,6 +1363,124 @@ func (m *PeriodicFeeAllowance) Unmarshal(dAtA []byte) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
func (m *AllowedMsgFeeAllowance) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowFeegrant
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: AllowedMsgFeeAllowance: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: AllowedMsgFeeAllowance: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Allowance", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowFeegrant
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthFeegrant
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthFeegrant
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Allowance == nil {
|
||||
m.Allowance = &types1.Any{}
|
||||
}
|
||||
if err := m.Allowance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AllowedMessages", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowFeegrant
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthFeegrant
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthFeegrant
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.AllowedMessages = append(m.AllowedMessages, string(dAtA[iNdEx:postIndex]))
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipFeegrant(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthFeegrant
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *Duration) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
|
|
|
@ -19,7 +19,7 @@ type FeeAllowanceI interface {
|
|||
//
|
||||
// If remove is true (regardless of the error), the FeeAllowance will be deleted from storage
|
||||
// (eg. when it is used up). (See call to RevokeFeeAllowance in Keeper.UseGrantedFees)
|
||||
Accept(fee sdk.Coins, blockTime time.Time, blockHeight int64) (remove bool, err error)
|
||||
Accept(ctx sdk.Context, fee sdk.Coins, msgs []sdk.Msg) (remove bool, err error)
|
||||
|
||||
// If we export fee allowances the timing info will be quite off (eg. go from height 100000 to 0)
|
||||
// This callback allows the fee-allowance to change it's state and return a copy that is adjusted
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
)
|
||||
|
||||
// TODO: Revisit this once we have propoer gas fee framework.
|
||||
// Tracking issues https://github.com/cosmos/cosmos-sdk/issues/9054, https://github.com/cosmos/cosmos-sdk/discussions/9072
|
||||
const (
|
||||
gasCostPerIteration = uint64(10)
|
||||
)
|
||||
|
||||
var _ FeeAllowanceI = (*AllowedMsgFeeAllowance)(nil)
|
||||
var _ types.UnpackInterfacesMessage = (*AllowedMsgFeeAllowance)(nil)
|
||||
|
||||
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
|
||||
func (a *AllowedMsgFeeAllowance) UnpackInterfaces(unpacker types.AnyUnpacker) error {
|
||||
var allowance FeeAllowanceI
|
||||
return unpacker.UnpackAny(a.Allowance, &allowance)
|
||||
}
|
||||
|
||||
// NewAllowedMsgFeeAllowance creates new filtered fee allowance.
|
||||
func NewAllowedMsgFeeAllowance(allowance FeeAllowanceI, allowedMsgs []string) (*AllowedMsgFeeAllowance, error) {
|
||||
msg, ok := allowance.(proto.Message)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", msg)
|
||||
}
|
||||
any, err := types.NewAnyWithValue(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &AllowedMsgFeeAllowance{
|
||||
Allowance: any,
|
||||
AllowedMessages: allowedMsgs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetAllowance returns allowed fee allowance.
|
||||
func (a *AllowedMsgFeeAllowance) GetAllowance() (FeeAllowanceI, error) {
|
||||
allowance, ok := a.Allowance.GetCachedValue().(FeeAllowanceI)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrap(ErrNoAllowance, "failed to get allowance")
|
||||
}
|
||||
|
||||
return allowance, nil
|
||||
}
|
||||
|
||||
// Accept method checks for the filtered messages has valid expiry
|
||||
func (a *AllowedMsgFeeAllowance) Accept(ctx sdk.Context, fee sdk.Coins, msgs []sdk.Msg) (bool, error) {
|
||||
if !a.allMsgTypesAllowed(ctx, msgs) {
|
||||
return false, sdkerrors.Wrap(ErrMessageNotAllowed, "message does not exist in allowed messages")
|
||||
}
|
||||
|
||||
allowance, err := a.GetAllowance()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return allowance.Accept(ctx, fee, msgs)
|
||||
}
|
||||
|
||||
func (a *AllowedMsgFeeAllowance) allowedMsgsToMap(ctx sdk.Context) map[string]bool {
|
||||
msgsMap := make(map[string]bool, len(a.AllowedMessages))
|
||||
for _, msg := range a.AllowedMessages {
|
||||
ctx.GasMeter().ConsumeGas(gasCostPerIteration, "check msg")
|
||||
msgsMap[msg] = true
|
||||
}
|
||||
|
||||
return msgsMap
|
||||
}
|
||||
|
||||
func (a *AllowedMsgFeeAllowance) allMsgTypesAllowed(ctx sdk.Context, msgs []sdk.Msg) bool {
|
||||
msgsMap := a.allowedMsgsToMap(ctx)
|
||||
|
||||
for _, msg := range msgs {
|
||||
ctx.GasMeter().ConsumeGas(gasCostPerIteration, "check msg")
|
||||
if !msgsMap[msg.Type()] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// PrepareForExport will adjust the expiration based on export time. In particular,
|
||||
// it will subtract the dumpHeight from any height-based expiration to ensure that
|
||||
// the elapsed number of blocks this allowance is valid for is fixed.
|
||||
func (a *AllowedMsgFeeAllowance) PrepareForExport(dumpTime time.Time, dumpHeight int64) FeeAllowanceI {
|
||||
allowance, err := a.GetAllowance()
|
||||
if err != nil {
|
||||
panic("failed to get allowance")
|
||||
}
|
||||
|
||||
f, err := NewAllowedMsgFeeAllowance(allowance.PrepareForExport(dumpTime, dumpHeight), a.AllowedMessages)
|
||||
if err != nil {
|
||||
panic("failed to export filtered fee allowance")
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
// ValidateBasic implements FeeAllowance and enforces basic sanity checks
|
||||
func (a *AllowedMsgFeeAllowance) ValidateBasic() error {
|
||||
if a.Allowance == nil {
|
||||
return sdkerrors.Wrap(ErrNoAllowance, "allowance should not be empty")
|
||||
}
|
||||
if len(a.AllowedMessages) == 0 {
|
||||
return sdkerrors.Wrap(ErrNoMessages, "allowed messages shouldn't be empty")
|
||||
}
|
||||
|
||||
allowance, err := a.GetAllowance()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return allowance.ValidateBasic()
|
||||
}
|
|
@ -14,7 +14,11 @@ func NewGenesisState(entries []FeeAllowanceGrant) *GenesisState {
|
|||
// ValidateGenesis ensures all grants in the genesis state are valid
|
||||
func ValidateGenesis(data GenesisState) error {
|
||||
for _, f := range data.FeeAllowances {
|
||||
err := f.GetFeeGrant().ValidateBasic()
|
||||
grant, err := f.GetFeeGrant()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = grant.ValidateBasic()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -47,17 +47,22 @@ func (a FeeAllowanceGrant) ValidateBasic() error {
|
|||
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "cannot self-grant fee authorization")
|
||||
}
|
||||
|
||||
return a.GetFeeGrant().ValidateBasic()
|
||||
f, err := a.GetFeeGrant()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return f.ValidateBasic()
|
||||
}
|
||||
|
||||
// GetFeeGrant unpacks allowance
|
||||
func (a FeeAllowanceGrant) GetFeeGrant() FeeAllowanceI {
|
||||
func (a FeeAllowanceGrant) GetFeeGrant() (FeeAllowanceI, error) {
|
||||
allowance, ok := a.Allowance.GetCachedValue().(FeeAllowanceI)
|
||||
if !ok {
|
||||
return nil
|
||||
return nil, sdkerrors.Wrap(ErrNoAllowance, "failed to get allowance")
|
||||
}
|
||||
|
||||
return allowance
|
||||
return allowance, nil
|
||||
}
|
||||
|
||||
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
|
||||
|
@ -69,7 +74,12 @@ func (a FeeAllowanceGrant) UnpackInterfaces(unpacker types.AnyUnpacker) error {
|
|||
// PrepareForExport will make all needed changes to the allowance to prepare to be
|
||||
// re-imported at height 0, and return a copy of this grant.
|
||||
func (a FeeAllowanceGrant) PrepareForExport(dumpTime time.Time, dumpHeight int64) FeeAllowanceGrant {
|
||||
feegrant := a.GetFeeGrant().PrepareForExport(dumpTime, dumpHeight)
|
||||
f, err := a.GetFeeGrant()
|
||||
if err != nil {
|
||||
return FeeAllowanceGrant{}
|
||||
}
|
||||
|
||||
feegrant := f.PrepareForExport(dumpTime, dumpHeight)
|
||||
if feegrant == nil {
|
||||
return FeeAllowanceGrant{}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,12 @@ func (msg MsgGrantFeeAllowance) ValidateBasic() error {
|
|||
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "cannot self-grant fee authorization")
|
||||
}
|
||||
|
||||
return msg.GetFeeAllowanceI().ValidateBasic()
|
||||
allowance, err := msg.GetFeeAllowanceI()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return allowance.ValidateBasic()
|
||||
}
|
||||
|
||||
func (msg MsgGrantFeeAllowance) GetSigners() []sdk.AccAddress {
|
||||
|
@ -62,13 +67,13 @@ func (msg MsgGrantFeeAllowance) GetSigners() []sdk.AccAddress {
|
|||
}
|
||||
|
||||
// GetFeeAllowanceI returns unpacked FeeAllowance
|
||||
func (msg MsgGrantFeeAllowance) GetFeeAllowanceI() FeeAllowanceI {
|
||||
func (msg MsgGrantFeeAllowance) GetFeeAllowanceI() (FeeAllowanceI, error) {
|
||||
allowance, ok := msg.Allowance.GetCachedValue().(FeeAllowanceI)
|
||||
if !ok {
|
||||
return nil
|
||||
return nil, sdkerrors.Wrap(ErrNoAllowance, "failed to get allowance")
|
||||
}
|
||||
|
||||
return allowance
|
||||
return allowance, nil
|
||||
}
|
||||
|
||||
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
|
||||
|
|
|
@ -19,7 +19,10 @@ var _ FeeAllowanceI = (*PeriodicFeeAllowance)(nil)
|
|||
//
|
||||
// If remove is true (regardless of the error), the FeeAllowance will be deleted from storage
|
||||
// (eg. when it is used up). (See call to RevokeFeeAllowance in Keeper.UseGrantedFees)
|
||||
func (a *PeriodicFeeAllowance) Accept(fee sdk.Coins, blockTime time.Time, blockHeight int64) (bool, error) {
|
||||
func (a *PeriodicFeeAllowance) Accept(ctx sdk.Context, fee sdk.Coins, _ []sdk.Msg) (bool, error) {
|
||||
blockTime := ctx.BlockTime()
|
||||
blockHeight := ctx.BlockHeight()
|
||||
|
||||
if a.Basic.Expiration.IsExpired(&blockTime, blockHeight) {
|
||||
return true, sdkerrors.Wrap(ErrFeeLimitExpired, "absolute limit")
|
||||
}
|
||||
|
|
|
@ -2,16 +2,18 @@ package types_test
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/feegrant/types"
|
||||
)
|
||||
|
||||
func TestPeriodicFeeValidAllow(t *testing.T) {
|
||||
app := simapp.Setup(false)
|
||||
atom := sdk.NewCoins(sdk.NewInt64Coin("atom", 555))
|
||||
smallAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 43))
|
||||
leftAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 512))
|
||||
|
@ -22,7 +24,6 @@ func TestPeriodicFeeValidAllow(t *testing.T) {
|
|||
allow types.PeriodicFeeAllowance
|
||||
// all other checks are ignored if valid=false
|
||||
fee sdk.Coins
|
||||
blockTime time.Time
|
||||
blockHeight int64
|
||||
valid bool
|
||||
accept bool
|
||||
|
@ -187,8 +188,9 @@ func TestPeriodicFeeValidAllow(t *testing.T) {
|
|||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{}).WithBlockHeight(tc.blockHeight)
|
||||
// now try to deduct
|
||||
remove, err := tc.allow.Accept(tc.fee, tc.blockTime, tc.blockHeight)
|
||||
remove, err := tc.allow.Accept(ctx, tc.fee, []sdk.Msg{})
|
||||
if !tc.accept {
|
||||
require.Error(t, err)
|
||||
return
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
authz "github.com/cosmos/cosmos-sdk/x/authz/exported"
|
||||
)
|
||||
|
||||
// TODO: Revisit this once we have propoer gas fee framework.
|
||||
// Tracking issues https://github.com/cosmos/cosmos-sdk/issues/9054, https://github.com/cosmos/cosmos-sdk/discussions/9072
|
||||
const gasCostPerIteration = uint64(10)
|
||||
|
||||
var (
|
||||
_ authz.Authorization = &StakeAuthorization{}
|
||||
TypeDelegate = "/cosmos.staking.v1beta1.Msg/Delegate"
|
||||
TypeUndelegate = "/cosmos.staking.v1beta1.Msg/Undelegate"
|
||||
TypeBeginRedelegate = "/cosmos.staking.v1beta1.Msg/BeginRedelegate"
|
||||
_ authz.Authorization = &StakeAuthorization{}
|
||||
|
||||
TypeDelegate = "/cosmos.staking.v1beta1.Msg/Delegate"
|
||||
TypeUndelegate = "/cosmos.staking.v1beta1.Msg/Undelegate"
|
||||
TypeBeginRedelegate = "/cosmos.staking.v1beta1.Msg/BeginRedelegate"
|
||||
)
|
||||
|
||||
// NewStakeAuthorization creates a new StakeAuthorization object.
|
||||
|
@ -46,8 +49,19 @@ func (authorization StakeAuthorization) MethodName() string {
|
|||
return authzType
|
||||
}
|
||||
|
||||
func (authorization StakeAuthorization) ValidateBasic() error {
|
||||
if authorization.MaxTokens != nil && authorization.MaxTokens.IsNegative() {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "negative coin amount: %v", authorization.MaxTokens)
|
||||
}
|
||||
if authorization.AuthorizationType == AuthorizationType_AUTHORIZATION_TYPE_UNSPECIFIED {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "unknown authorization type")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Accept implements Authorization.Accept.
|
||||
func (authorization StakeAuthorization) Accept(msg sdk.ServiceMsg, block tmproto.Header) (updated authz.Authorization, delete bool, err error) {
|
||||
func (authorization StakeAuthorization) Accept(ctx sdk.Context, msg sdk.ServiceMsg) (updated authz.Authorization, delete bool, err error) {
|
||||
var validatorAddress string
|
||||
var amount sdk.Coin
|
||||
|
||||
|
@ -68,13 +82,16 @@ func (authorization StakeAuthorization) Accept(msg sdk.ServiceMsg, block tmproto
|
|||
isValidatorExists := false
|
||||
allowedList := authorization.GetAllowList().GetAddress()
|
||||
for _, validator := range allowedList {
|
||||
ctx.GasMeter().ConsumeGas(gasCostPerIteration, "stake authorization")
|
||||
if validator == validatorAddress {
|
||||
isValidatorExists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
denyList := authorization.GetDenyList().GetAddress()
|
||||
for _, validator := range denyList {
|
||||
ctx.GasMeter().ConsumeGas(gasCostPerIteration, "stake authorization")
|
||||
if validator == validatorAddress {
|
||||
return nil, false, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, " cannot delegate/undelegate to %s validator", validator)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
@ -21,13 +22,21 @@ var (
|
|||
)
|
||||
|
||||
func TestAuthzAuthorizations(t *testing.T) {
|
||||
app := simapp.Setup(false)
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
// verify ValidateBasic returns error for the AUTHORIZATION_TYPE_UNSPECIFIED authorization type
|
||||
delAuth, err := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{val1, val2}, []sdk.ValAddress{}, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNSPECIFIED, &coin100)
|
||||
require.NoError(t, err)
|
||||
require.Error(t, delAuth.ValidateBasic())
|
||||
|
||||
// verify MethodName
|
||||
delAuth, _ := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{val1, val2}, []sdk.ValAddress{}, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, &coin100)
|
||||
delAuth, err = stakingtypes.NewStakeAuthorization([]sdk.ValAddress{val1, val2}, []sdk.ValAddress{}, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, &coin100)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, delAuth.MethodName(), stakingtypes.TypeDelegate)
|
||||
|
||||
// error both allow & deny list
|
||||
_, err := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{val1, val2}, []sdk.ValAddress{val1}, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, &coin100)
|
||||
_, err = stakingtypes.NewStakeAuthorization([]sdk.ValAddress{val1, val2}, []sdk.ValAddress{val1}, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, &coin100)
|
||||
require.Error(t, err)
|
||||
|
||||
// verify MethodName
|
||||
|
@ -243,7 +252,7 @@ func TestAuthzAuthorizations(t *testing.T) {
|
|||
t.Run(tc.msg, func(t *testing.T) {
|
||||
delAuth, err := stakingtypes.NewStakeAuthorization(tc.allowed, tc.denied, tc.msgType, tc.limit)
|
||||
require.NoError(t, err)
|
||||
updated, del, err := delAuth.Accept(tc.srvMsg, tmproto.Header{})
|
||||
updated, del, err := delAuth.Accept(ctx, tc.srvMsg)
|
||||
if tc.expectErr {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, tc.isDelete, del)
|
||||
|
|
|
@ -8,6 +8,9 @@ import (
|
|||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmos "github.com/tendermint/tendermint/libs/os"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/store/prefix"
|
||||
store "github.com/cosmos/cosmos-sdk/store/types"
|
||||
|
@ -16,8 +19,6 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
xp "github.com/cosmos/cosmos-sdk/x/upgrade/exported"
|
||||
"github.com/cosmos/cosmos-sdk/x/upgrade/types"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmos "github.com/tendermint/tendermint/libs/os"
|
||||
)
|
||||
|
||||
// UpgradeInfoFileName file to store upgrade information
|
||||
|
|
|
@ -195,7 +195,7 @@ func (s *KeeperTestSuite) TestSetUpgradedClient() {
|
|||
}
|
||||
|
||||
// Test that the protocol version successfully increments after an
|
||||
// upgrade and is succesfully set on BaseApp's appVersion.
|
||||
// upgrade and is successfully set on BaseApp's appVersion.
|
||||
func (s *KeeperTestSuite) TestIncrementProtocolVersion() {
|
||||
oldProtocolVersion := s.app.BaseApp.AppVersion()
|
||||
s.app.UpgradeKeeper.SetUpgradeHandler("dummy", func(_ sdk.Context, _ types.Plan, vm module.VersionMap) (module.VersionMap, error) { return vm, nil })
|
||||
|
|
Loading…
Reference in New Issue