diff --git a/CHANGELOG.md b/CHANGELOG.md index f53cda4880fc..1c9f9b1f3b68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -203,6 +203,9 @@ invalid or incomplete requests. ### State Machine Breaking * (x/bank) [\#6283](https://github.com/cosmos/cosmos-sdk/pull/6283) Create account if recipient does not exist on handing `MsgMultiSend`. +* (x/bank) [\#6518](https://github.com/cosmos/cosmos-sdk/pull/6518) Support for global and per-denomination send enabled flags. + * Existing send_enabled global flag has been moved into a Params structure as `default_send_enabled`. + * An array of: `{denom: string, enabled: bool}` is added to bank Params to support per-denomination override of global default value. * (x/staking) [\#6061](https://github.com/cosmos/cosmos-sdk/pull/6061) Allow a validator to immediately unjail when no signing info is present due to falling below their minimum self-delegation and never having been bonded. The validator may immediately unjail once they've met their minimum self-delegation. * (x/supply) [\#6010](https://github.com/cosmos/cosmos-sdk/pull/6010) Removed the `x/supply` module by merging the existing types and APIs into the `x/bank` module. diff --git a/proto/cosmos/bank/bank.proto b/proto/cosmos/bank/bank.proto index f695cb99d671..f54e0d6705b5 100644 --- a/proto/cosmos/bank/bank.proto +++ b/proto/cosmos/bank/bank.proto @@ -7,6 +7,25 @@ import "cosmos/cosmos.proto"; option go_package = "github.com/cosmos/cosmos-sdk/x/bank/types"; +// Params defines the set of bank parameters. +message Params { + option (gogoproto.goproto_stringer) = false; + repeated SendEnabled send_enabled = 1[ + (gogoproto.moretags) = "yaml:\"send_enabled,omitempty\"" + ]; + bool default_send_enabled = 2[ + (gogoproto.moretags) = "yaml:\"default_send_enabled,omitempty\"" + ]; +} + +// Send enabled configuration properties for each denomination +message SendEnabled { + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = false; + string denom = 1; + bool enabled = 2; +} + // MsgSend - high level transaction of the coin module message MsgSend { option (gogoproto.equal) = true; diff --git a/simapp/test_helpers.go b/simapp/test_helpers.go index 5e5dc5d041c7..6ba55f418a93 100644 --- a/simapp/test_helpers.go +++ b/simapp/test_helpers.go @@ -118,7 +118,7 @@ func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs } // update total supply - bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().SendEnabled, balances, totalSupply) + bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply) genesisState[banktypes.ModuleName] = app.Codec().MustMarshalJSON(bankGenesis) stateBytes, err := codec.MarshalJSONIndent(app.Codec(), genesisState) @@ -157,7 +157,7 @@ func SetupWithGenesisAccounts(genAccs []authtypes.GenesisAccount, balances ...ba totalSupply = totalSupply.Add(b.Coins...) } - bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().SendEnabled, balances, totalSupply) + bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply) genesisState[banktypes.ModuleName] = app.Codec().MustMarshalJSON(bankGenesis) stateBytes, err := codec.MarshalJSONIndent(app.Codec(), genesisState) diff --git a/x/bank/genesis.go b/x/bank/genesis.go index 89e3e9525eb4..45c30b536ae6 100644 --- a/x/bank/genesis.go +++ b/x/bank/genesis.go @@ -10,7 +10,7 @@ import ( // InitGenesis initializes the bank module's state from a given genesis state. func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, genState types.GenesisState) { - keeper.SetSendEnabled(ctx, genState.SendEnabled) + keeper.SetParams(ctx, genState.Params) var totalSupply sdk.Coins @@ -57,11 +57,14 @@ func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) types.GenesisState { }) } - return types.NewGenesisState(keeper.GetSendEnabled(ctx), balances, keeper.GetSupply(ctx).GetTotal()) + return types.NewGenesisState(keeper.GetParams(ctx), balances, keeper.GetSupply(ctx).GetTotal()) } // ValidateGenesis performs basic validation of supply genesis data returning an // error for any failed validation criteria. func ValidateGenesis(data types.GenesisState) error { + if err := data.Params.Validate(); err != nil { + return err + } return types.NewSupply(data.Supply).ValidateBasic() } diff --git a/x/bank/handler.go b/x/bank/handler.go index a11ac6d4e9d5..0dc8daa1fcc9 100644 --- a/x/bank/handler.go +++ b/x/bank/handler.go @@ -30,8 +30,8 @@ func NewHandler(k keeper.Keeper) sdk.Handler { // Handle MsgSend. func handleMsgSend(ctx sdk.Context, k keeper.Keeper, msg *types.MsgSend) (*sdk.Result, error) { - if !k.GetSendEnabled(ctx) { - return nil, types.ErrSendDisabled + if err := k.SendEnabledCoins(ctx, msg.Amount...); err != nil { + return nil, err } if k.BlockedAddr(msg.ToAddress) { @@ -66,8 +66,10 @@ func handleMsgSend(ctx sdk.Context, k keeper.Keeper, msg *types.MsgSend) (*sdk.R // Handle MsgMultiSend. func handleMsgMultiSend(ctx sdk.Context, k keeper.Keeper, msg *types.MsgMultiSend) (*sdk.Result, error) { // NOTE: totalIn == totalOut should already have been checked - if !k.GetSendEnabled(ctx) { - return nil, types.ErrSendDisabled + for _, in := range msg.Inputs { + if err := k.SendEnabledCoins(ctx, in.Coins...); err != nil { + return nil, err + } } for _, out := range msg.Outputs { diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index 0f5b0de0a750..2607166e8c81 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -69,7 +69,7 @@ func (suite *IntegrationTestSuite) SetupTest() { ctx := app.BaseApp.NewContext(false, abci.Header{}) app.AccountKeeper.SetParams(ctx, authtypes.DefaultParams()) - app.BankKeeper.SetSendEnabled(ctx, true) + app.BankKeeper.SetParams(ctx, types.DefaultParams()) suite.app = app suite.ctx = ctx @@ -454,9 +454,45 @@ func (suite *IntegrationTestSuite) TestBalance() { func (suite *IntegrationTestSuite) TestSendEnabled() { app, ctx := suite.app, suite.ctx - enabled := false - app.BankKeeper.SetSendEnabled(ctx, enabled) - suite.Require().Equal(enabled, app.BankKeeper.GetSendEnabled(ctx)) + enabled := true + params := types.DefaultParams() + suite.Require().Equal(enabled, params.DefaultSendEnabled) + + app.BankKeeper.SetParams(ctx, params) + + bondCoin := sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt()) + fooCoin := sdk.NewCoin("foocoin", sdk.OneInt()) + barCoin := sdk.NewCoin("barcoin", sdk.OneInt()) + + // assert with default (all denom) send enabled both Bar and Bond Denom are enabled + suite.Require().Equal(enabled, app.BankKeeper.SendEnabledCoin(ctx, barCoin)) + suite.Require().Equal(enabled, app.BankKeeper.SendEnabledCoin(ctx, bondCoin)) + + // Both coins should be send enabled. + err := app.BankKeeper.SendEnabledCoins(ctx, fooCoin, bondCoin) + suite.Require().NoError(err) + + // Set default send_enabled to !enabled, add a foodenom that overrides default as enabled + params.DefaultSendEnabled = !enabled + params = params.SetSendEnabledParam(fooCoin.Denom, enabled) + app.BankKeeper.SetParams(ctx, params) + + // Expect our specific override to be enabled, others to be !enabled. + suite.Require().Equal(enabled, app.BankKeeper.SendEnabledCoin(ctx, fooCoin)) + suite.Require().Equal(!enabled, app.BankKeeper.SendEnabledCoin(ctx, barCoin)) + suite.Require().Equal(!enabled, app.BankKeeper.SendEnabledCoin(ctx, bondCoin)) + + // Foo coin should be send enabled. + err = app.BankKeeper.SendEnabledCoins(ctx, fooCoin) + suite.Require().NoError(err) + + // Expect an error when one coin is not send enabled. + err = app.BankKeeper.SendEnabledCoins(ctx, fooCoin, bondCoin) + suite.Require().Error(err) + + // Expect an error when all coins are not send enabled. + err = app.BankKeeper.SendEnabledCoins(ctx, bondCoin, barCoin) + suite.Require().Error(err) } func (suite *IntegrationTestSuite) TestHasBalance() { @@ -531,7 +567,7 @@ func (suite *IntegrationTestSuite) TestMsgSendEvents() { func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { app, ctx := suite.app, suite.ctx - app.BankKeeper.SetSendEnabled(ctx, true) + app.BankKeeper.SetParams(ctx, types.DefaultParams()) addr := sdk.AccAddress([]byte("addr1")) addr2 := sdk.AccAddress([]byte("addr2")) diff --git a/x/bank/keeper/send.go b/x/bank/keeper/send.go index 4296891d9a8a..88d1018f2048 100644 --- a/x/bank/keeper/send.go +++ b/x/bank/keeper/send.go @@ -24,8 +24,11 @@ type SendKeeper interface { SetBalance(ctx sdk.Context, addr sdk.AccAddress, balance sdk.Coin) error SetBalances(ctx sdk.Context, addr sdk.AccAddress, balances sdk.Coins) error - GetSendEnabled(ctx sdk.Context) bool - SetSendEnabled(ctx sdk.Context, enabled bool) + GetParams(ctx sdk.Context) types.Params + SetParams(ctx sdk.Context, params types.Params) + + SendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool + SendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error BlockedAddr(addr sdk.AccAddress) bool } @@ -60,6 +63,17 @@ func NewBaseSendKeeper( } } +// GetParams returns the total set of bank parameters. +func (k BaseSendKeeper) GetParams(ctx sdk.Context) (params types.Params) { + k.paramSpace.GetParamSet(ctx, ¶ms) + return params +} + +// SetParams sets the total set of bank parameters. +func (k BaseSendKeeper) SetParams(ctx sdk.Context, params types.Params) { + k.paramSpace.SetParamSet(ctx, ¶ms) +} + // InputOutputCoins performs multi-send functionality. It accepts a series of // inputs that correspond to a series of outputs. It returns an error if the // inputs and outputs don't lineup or if any single transfer of tokens fails. @@ -256,16 +270,21 @@ func (k BaseSendKeeper) SetBalance(ctx sdk.Context, addr sdk.AccAddress, balance return nil } -// GetSendEnabled returns the current SendEnabled -func (k BaseSendKeeper) GetSendEnabled(ctx sdk.Context) bool { - var enabled bool - k.paramSpace.Get(ctx, types.ParamStoreKeySendEnabled, &enabled) - return enabled +// SendEnabledCoins checks the coins provide and returns an ErrSendDisabled if +// any of the coins are not configured for sending. Returns nil if sending is enabled +// for all provided coin +func (k BaseSendKeeper) SendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error { + for _, coin := range coins { + if !k.SendEnabledCoin(ctx, coin) { + return sdkerrors.Wrapf(types.ErrSendDisabled, "%s transfers are currently disabled", coin.Denom) + } + } + return nil } -// SetSendEnabled sets the send enabled -func (k BaseSendKeeper) SetSendEnabled(ctx sdk.Context, enabled bool) { - k.paramSpace.Set(ctx, types.ParamStoreKeySendEnabled, &enabled) +// SendEnabledCoin returns the current SendEnabled status of the provided coin's denom +func (k BaseSendKeeper) SendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool { + return k.GetParams(ctx).SendEnabledDenom(coin.Denom) } // BlockedAddr checks if a given address is restricted from diff --git a/x/bank/simulation/genesis.go b/x/bank/simulation/genesis.go index 06e2831a36b4..4d3d9dfe63b5 100644 --- a/x/bank/simulation/genesis.go +++ b/x/bank/simulation/genesis.go @@ -3,21 +3,36 @@ package simulation // DONTCOVER import ( + "fmt" "math/rand" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/bank/types" ) -// Simulation parameter constants -const ( - SendEnabled = "send_enabled" -) +// RandomGenesisDefaultSendParam computes randomized allow all send transfers param for the bank module +func RandomGenesisDefaultSendParam(r *rand.Rand) bool { + // 90% chance of transfers being enable or P(a) = 0.9 for success + return r.Int63n(101) <= 90 +} -// GenSendEnabled randomized SendEnabled -func GenSendEnabled(r *rand.Rand) bool { - return r.Int63n(101) <= 95 // 95% chance of transfers being enabled +// RandomGenesisSendParams randomized Parameters for the bank module +func RandomGenesisSendParams(r *rand.Rand) types.SendEnabledParams { + params := types.DefaultParams() + // 90% chance of transfers being DefaultSendEnabled=true or P(a) = 0.9 for success + // 50% of the time add an additional denom specific record (P(b) = 0.475 = 0.5 * 0.95) + if r.Int63n(101) <= 50 { + // set send enabled 95% of the time + bondEnabled := r.Int63n(101) <= 95 + params = params.SetSendEnabledParam( + sdk.DefaultBondDenom, + bondEnabled) + } + + // overall probability of enabled for bond denom is 94.75% (P(a)+P(b) - P(a)*P(b)) + return params.SendEnabled } // RandomGenesisAccounts returns a slice of account balances. Each account has @@ -37,16 +52,31 @@ func RandomGenesisBalances(simState *module.SimulationState) []types.Balance { // RandomizedGenState generates a random GenesisState for bank func RandomizedGenState(simState *module.SimulationState) { - var sendEnabled bool + var sendEnabledParams types.SendEnabledParams simState.AppParams.GetOrGenerate( - simState.Cdc, SendEnabled, &sendEnabled, simState.Rand, - func(r *rand.Rand) { sendEnabled = GenSendEnabled(r) }, + simState.Cdc, string(types.KeySendEnabled), &sendEnabledParams, simState.Rand, + func(r *rand.Rand) { sendEnabledParams = RandomGenesisSendParams(r) }, + ) + + var defaultSendEnabledParam bool + simState.AppParams.GetOrGenerate( + simState.Cdc, string(types.KeyDefaultSendEnabled), &defaultSendEnabledParam, simState.Rand, + func(r *rand.Rand) { defaultSendEnabledParam = RandomGenesisDefaultSendParam(r) }, ) numAccs := int64(len(simState.Accounts)) totalSupply := sdk.NewInt(simState.InitialStake * (numAccs + simState.NumBonded)) supply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, totalSupply)) - bankGenesis := types.NewGenesisState(sendEnabled, RandomGenesisBalances(simState), supply) + bankGenesis := types.GenesisState{ + Params: types.Params{ + SendEnabled: sendEnabledParams, + DefaultSendEnabled: defaultSendEnabledParam, + }, + Balances: RandomGenesisBalances(simState), + Supply: supply, + } + + fmt.Printf("Selected randomly generated bank parameters:\n%s\n", codec.MustMarshalJSONIndent(simState.Cdc, bankGenesis.Params)) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(bankGenesis) } diff --git a/x/bank/simulation/operations.go b/x/bank/simulation/operations.go index 8023a376f675..103a55d0aa6f 100644 --- a/x/bank/simulation/operations.go +++ b/x/bank/simulation/operations.go @@ -59,13 +59,13 @@ func SimulateMsgSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Operatio r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + simAccount, toSimAcc, coins, skip := randomSendFields(r, ctx, accs, bk, ak) - if !bk.GetSendEnabled(ctx) { - return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSend, "transfers are not enabled"), nil, nil + // Check send_enabled status of each coin denom + if err := bk.SendEnabledCoins(ctx, coins...); err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSend, err.Error()), nil, nil } - simAccount, toSimAcc, coins, skip := randomSendFields(r, ctx, accs, bk, ak) - if skip { return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSend, "skip all transfers"), nil, nil } @@ -130,10 +130,6 @@ func SimulateMsgMultiSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Ope accs []simtypes.Account, chainID string, ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - if !bk.GetSendEnabled(ctx) { - return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgMultiSend, "transfers are not enabled"), nil, nil - } - // random number of inputs/outputs between [1, 3] inputs := make([]types.Input, r.Intn(3)+1) outputs := make([]types.Output, r.Intn(3)+1) @@ -169,6 +165,11 @@ func SimulateMsgMultiSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Ope totalSentCoins = totalSentCoins.Add(coins...) } + // Check send_enabled status of each sent coin denom + if err := bk.SendEnabledCoins(ctx, totalSentCoins...); err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgMultiSend, err.Error()), nil, nil + } + for o := range outputs { outAddr, _ := simtypes.RandomAcc(r, accs) diff --git a/x/bank/simulation/params.go b/x/bank/simulation/params.go index 1117197279ab..a2699659f6da 100644 --- a/x/bank/simulation/params.go +++ b/x/bank/simulation/params.go @@ -12,15 +12,18 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank/types" ) -const keySendEnabled = "sendenabled" - // ParamChanges defines the parameters that can be modified by param change proposals // on the simulation func ParamChanges(r *rand.Rand) []simtypes.ParamChange { return []simtypes.ParamChange{ - simulation.NewSimParamChange(types.ModuleName, keySendEnabled, + simulation.NewSimParamChange(types.ModuleName, string(types.KeySendEnabled), + func(r *rand.Rand) string { + return fmt.Sprintf("%s", types.ModuleCdc.MustMarshalJSON(RandomGenesisSendParams(r))) + }, + ), + simulation.NewSimParamChange(types.ModuleName, string(types.KeyDefaultSendEnabled), func(r *rand.Rand) string { - return fmt.Sprintf("%v", GenSendEnabled(r)) + return fmt.Sprintf("%v", RandomGenesisDefaultSendParam(r)) }, ), } diff --git a/x/bank/spec/05_params.md b/x/bank/spec/05_params.md index fe59bed244ec..c4e89a420029 100644 --- a/x/bank/spec/05_params.md +++ b/x/bank/spec/05_params.md @@ -6,7 +6,20 @@ order: 5 The bank module contains the following parameters: -| Key | Type | Example | -|-------------|------|---------| -| sendenabled | bool | true | +| Key | Type | Example | +|--------------------|---------------|------------------------------------| +| SendEnabled | []SendEnabled | [{denom: "stake", enabled: true }] | +| DefaultSendEnabled | bool | true | + +## SendEnabled + +The send enabled parameter is an array of SendEnabled entries mapping coin +denominations to their send_enabled status. Entries in this list take +precedence over the `DefaultSendEnabled` setting. + +## DefaultSendEnabled + +The default send enabled value controls send transfer capability for all +coin denominations unless specifically included in the array of `SendEnabled` +parameters. \ No newline at end of file diff --git a/x/bank/types/bank.pb.go b/x/bank/types/bank.pb.go index 760a52ffc5a7..becb17f8c4f3 100644 --- a/x/bank/types/bank.pb.go +++ b/x/bank/types/bank.pb.go @@ -27,6 +27,110 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// Params defines the set of bank parameters. +type Params struct { + SendEnabled []*SendEnabled `protobuf:"bytes,1,rep,name=send_enabled,json=sendEnabled,proto3" json:"send_enabled,omitempty" yaml:"send_enabled,omitempty"` + DefaultSendEnabled bool `protobuf:"varint,2,opt,name=default_send_enabled,json=defaultSendEnabled,proto3" json:"default_send_enabled,omitempty" yaml:"default_send_enabled,omitempty"` +} + +func (m *Params) Reset() { *m = Params{} } +func (*Params) ProtoMessage() {} +func (*Params) Descriptor() ([]byte, []int) { + return fileDescriptor_717c78e54d4b5794, []int{0} +} +func (m *Params) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Params.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 *Params) XXX_Merge(src proto.Message) { + xxx_messageInfo_Params.Merge(m, src) +} +func (m *Params) XXX_Size() int { + return m.Size() +} +func (m *Params) XXX_DiscardUnknown() { + xxx_messageInfo_Params.DiscardUnknown(m) +} + +var xxx_messageInfo_Params proto.InternalMessageInfo + +func (m *Params) GetSendEnabled() []*SendEnabled { + if m != nil { + return m.SendEnabled + } + return nil +} + +func (m *Params) GetDefaultSendEnabled() bool { + if m != nil { + return m.DefaultSendEnabled + } + return false +} + +// Send enabled configuration properties for each denomination +type SendEnabled struct { + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` + Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"` +} + +func (m *SendEnabled) Reset() { *m = SendEnabled{} } +func (*SendEnabled) ProtoMessage() {} +func (*SendEnabled) Descriptor() ([]byte, []int) { + return fileDescriptor_717c78e54d4b5794, []int{1} +} +func (m *SendEnabled) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SendEnabled) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SendEnabled.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 *SendEnabled) XXX_Merge(src proto.Message) { + xxx_messageInfo_SendEnabled.Merge(m, src) +} +func (m *SendEnabled) XXX_Size() int { + return m.Size() +} +func (m *SendEnabled) XXX_DiscardUnknown() { + xxx_messageInfo_SendEnabled.DiscardUnknown(m) +} + +var xxx_messageInfo_SendEnabled proto.InternalMessageInfo + +func (m *SendEnabled) GetDenom() string { + if m != nil { + return m.Denom + } + return "" +} + +func (m *SendEnabled) GetEnabled() bool { + if m != nil { + return m.Enabled + } + return false +} + // MsgSend - high level transaction of the coin module type MsgSend struct { FromAddress github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,1,opt,name=from_address,json=fromAddress,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"from_address,omitempty" yaml:"from_address"` @@ -38,7 +142,7 @@ func (m *MsgSend) Reset() { *m = MsgSend{} } func (m *MsgSend) String() string { return proto.CompactTextString(m) } func (*MsgSend) ProtoMessage() {} func (*MsgSend) Descriptor() ([]byte, []int) { - return fileDescriptor_717c78e54d4b5794, []int{0} + return fileDescriptor_717c78e54d4b5794, []int{2} } func (m *MsgSend) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -98,7 +202,7 @@ func (m *Input) Reset() { *m = Input{} } func (m *Input) String() string { return proto.CompactTextString(m) } func (*Input) ProtoMessage() {} func (*Input) Descriptor() ([]byte, []int) { - return fileDescriptor_717c78e54d4b5794, []int{1} + return fileDescriptor_717c78e54d4b5794, []int{3} } func (m *Input) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -151,7 +255,7 @@ func (m *Output) Reset() { *m = Output{} } func (m *Output) String() string { return proto.CompactTextString(m) } func (*Output) ProtoMessage() {} func (*Output) Descriptor() ([]byte, []int) { - return fileDescriptor_717c78e54d4b5794, []int{2} + return fileDescriptor_717c78e54d4b5794, []int{4} } func (m *Output) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -204,7 +308,7 @@ func (m *MsgMultiSend) Reset() { *m = MsgMultiSend{} } func (m *MsgMultiSend) String() string { return proto.CompactTextString(m) } func (*MsgMultiSend) ProtoMessage() {} func (*MsgMultiSend) Descriptor() ([]byte, []int) { - return fileDescriptor_717c78e54d4b5794, []int{3} + return fileDescriptor_717c78e54d4b5794, []int{5} } func (m *MsgMultiSend) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -256,7 +360,7 @@ type Supply struct { func (m *Supply) Reset() { *m = Supply{} } func (*Supply) ProtoMessage() {} func (*Supply) Descriptor() ([]byte, []int) { - return fileDescriptor_717c78e54d4b5794, []int{4} + return fileDescriptor_717c78e54d4b5794, []int{6} } func (m *Supply) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -286,6 +390,8 @@ func (m *Supply) XXX_DiscardUnknown() { var xxx_messageInfo_Supply proto.InternalMessageInfo func init() { + proto.RegisterType((*Params)(nil), "cosmos.bank.Params") + proto.RegisterType((*SendEnabled)(nil), "cosmos.bank.SendEnabled") proto.RegisterType((*MsgSend)(nil), "cosmos.bank.MsgSend") proto.RegisterType((*Input)(nil), "cosmos.bank.Input") proto.RegisterType((*Output)(nil), "cosmos.bank.Output") @@ -296,38 +402,73 @@ func init() { func init() { proto.RegisterFile("cosmos/bank/bank.proto", fileDescriptor_717c78e54d4b5794) } var fileDescriptor_717c78e54d4b5794 = []byte{ - // 457 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4b, 0xce, 0x2f, 0xce, - 0xcd, 0x2f, 0xd6, 0x4f, 0x4a, 0xcc, 0xcb, 0x06, 0x13, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, - 0xdc, 0x10, 0x71, 0x3d, 0x90, 0x90, 0x94, 0x48, 0x7a, 0x7e, 0x7a, 0x3e, 0x58, 0x5c, 0x1f, 0xc4, - 0x82, 0x28, 0x91, 0x92, 0x84, 0x28, 0x89, 0x87, 0x48, 0x40, 0xd5, 0x43, 0xa4, 0x84, 0xa1, 0xa6, - 0x22, 0x0b, 0x2a, 0xed, 0x66, 0xe2, 0x62, 0xf7, 0x2d, 0x4e, 0x0f, 0x4e, 0xcd, 0x4b, 0x11, 0xca, - 0xe6, 0xe2, 0x49, 0x2b, 0xca, 0xcf, 0x8d, 0x4f, 0x4c, 0x49, 0x29, 0x4a, 0x2d, 0x2e, 0x96, 0x60, - 0x54, 0x60, 0xd4, 0xe0, 0x71, 0xf2, 0xf8, 0x74, 0x4f, 0x5e, 0xb8, 0x32, 0x31, 0x37, 0xc7, 0x4a, - 0x09, 0x59, 0x56, 0xe9, 0xd7, 0x3d, 0x79, 0xdd, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, - 0xfc, 0x5c, 0x7d, 0x14, 0xc3, 0x75, 0x8b, 0x53, 0xb2, 0xf5, 0x4b, 0x2a, 0x0b, 0x52, 0x8b, 0xf5, - 0x1c, 0x93, 0x93, 0x1d, 0x21, 0x3a, 0x82, 0xb8, 0x41, 0xfa, 0xa1, 0x1c, 0xa1, 0x54, 0x2e, 0xae, - 0x92, 0x7c, 0xb8, 0x55, 0x4c, 0x60, 0xab, 0xdc, 0x3e, 0xdd, 0x93, 0x17, 0x84, 0x58, 0x85, 0x90, - 0x23, 0xc3, 0x22, 0xce, 0x92, 0x7c, 0x98, 0x35, 0x61, 0x5c, 0x6c, 0x89, 0xb9, 0xf9, 0xa5, 0x79, - 0x25, 0x12, 0xcc, 0x0a, 0xcc, 0x1a, 0xdc, 0x46, 0x3c, 0x7a, 0x50, 0xef, 0x3b, 0xe7, 0x67, 0xe6, - 0x39, 0x19, 0x9c, 0xb8, 0x27, 0xcf, 0xb0, 0xea, 0xbe, 0xbc, 0x06, 0x11, 0xe6, 0x83, 0x34, 0x14, - 0x07, 0x41, 0x4d, 0xb3, 0x62, 0x79, 0xb1, 0x40, 0x9e, 0x51, 0x69, 0x03, 0x23, 0x17, 0xab, 0x67, - 0x5e, 0x41, 0x69, 0x89, 0x90, 0x37, 0x17, 0x3b, 0x6a, 0xb0, 0x19, 0x92, 0xee, 0x6c, 0x98, 0x09, - 0x42, 0x21, 0x5c, 0xac, 0xc9, 0x20, 0xdb, 0x24, 0x98, 0xa8, 0xe2, 0x66, 0x88, 0x61, 0x50, 0x27, - 0x6f, 0x64, 0xe4, 0x62, 0xf3, 0x2f, 0x2d, 0x19, 0x52, 0x6e, 0xae, 0xe6, 0xe2, 0xf1, 0x2d, 0x4e, - 0xf7, 0x2d, 0xcd, 0x29, 0xc9, 0x04, 0x27, 0x54, 0x03, 0x2e, 0xb6, 0x4c, 0x50, 0xa8, 0x83, 0xdc, - 0x0d, 0xb2, 0x4c, 0x48, 0x0f, 0x29, 0x63, 0xe8, 0x81, 0x23, 0xc4, 0x89, 0x05, 0x64, 0x65, 0x10, - 0x54, 0x9d, 0x90, 0x31, 0x17, 0x7b, 0x3e, 0xd8, 0xd3, 0x30, 0xf7, 0x09, 0xa3, 0x68, 0x81, 0x04, - 0x08, 0x54, 0x0f, 0x4c, 0x25, 0xd4, 0xf2, 0xa5, 0x8c, 0x5c, 0x6c, 0xc1, 0xa5, 0x05, 0x05, 0x39, - 0x95, 0x20, 0x3f, 0x96, 0xe4, 0x97, 0x24, 0xe6, 0x40, 0xad, 0xa5, 0xd8, 0x8f, 0x60, 0xc3, 0xac, - 0x5c, 0x3b, 0x16, 0xc8, 0x33, 0xcc, 0x58, 0x20, 0xcf, 0x00, 0xb2, 0xee, 0xd2, 0x16, 0x5d, 0x53, - 0x2d, 0xbc, 0x26, 0x54, 0x40, 0x8a, 0x85, 0xd4, 0x8a, 0x82, 0xfc, 0xa2, 0x92, 0xd4, 0x14, 0x3d, - 0x88, 0xdb, 0x3c, 0x9d, 0x9c, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, - 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x4a, - 0x93, 0x18, 0xf3, 0xc0, 0x0e, 0x4b, 0x62, 0x03, 0x97, 0x0a, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xa5, 0xa6, 0xc2, 0x41, 0x82, 0x04, 0x00, 0x00, + // 583 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x54, 0x3d, 0x6f, 0xd3, 0x4e, + 0x18, 0xf7, 0xa5, 0xad, 0xd3, 0x5e, 0xb2, 0xfc, 0x2f, 0xd1, 0x5f, 0xa6, 0x12, 0x76, 0xb0, 0x84, + 0x94, 0x22, 0xe2, 0x14, 0x2a, 0x96, 0x6c, 0x75, 0x55, 0xa0, 0x42, 0x11, 0xc8, 0x45, 0x0c, 0x20, + 0x11, 0x39, 0xf1, 0x35, 0x44, 0xb1, 0x7d, 0x56, 0xee, 0x2c, 0x35, 0xe2, 0x0b, 0x30, 0x32, 0x32, + 0x66, 0x61, 0x61, 0x02, 0x89, 0x8d, 0x2f, 0x50, 0x89, 0xa5, 0x62, 0x62, 0x32, 0x28, 0x59, 0x98, + 0x33, 0x32, 0x21, 0xdf, 0x9d, 0xa9, 0x2d, 0x21, 0x54, 0x5e, 0x16, 0x96, 0x28, 0xf7, 0x3c, 0xbf, + 0xb7, 0x7b, 0xce, 0x77, 0xf0, 0xff, 0x01, 0xa1, 0x01, 0xa1, 0xed, 0xbe, 0x1b, 0x8e, 0xf9, 0x8f, + 0x15, 0x4d, 0x08, 0x23, 0xa8, 0x22, 0xea, 0x56, 0x5a, 0xda, 0xac, 0x0f, 0xc9, 0x90, 0xf0, 0x7a, + 0x3b, 0xfd, 0x27, 0x20, 0x9b, 0x17, 0x04, 0xa4, 0x27, 0x1a, 0x12, 0x2f, 0x5a, 0x35, 0xa9, 0x9a, + 0x2f, 0x9a, 0xef, 0x01, 0x54, 0xef, 0xb9, 0x13, 0x37, 0xa0, 0xe8, 0x31, 0xac, 0x52, 0x1c, 0x7a, + 0x3d, 0x1c, 0xba, 0x7d, 0x1f, 0x7b, 0x1a, 0x68, 0xac, 0x34, 0x2b, 0xd7, 0x35, 0x2b, 0x67, 0x6a, + 0x1d, 0xe2, 0xd0, 0xdb, 0x17, 0x7d, 0xfb, 0xd2, 0x32, 0x31, 0x2e, 0x4e, 0xdd, 0xc0, 0xef, 0x98, + 0x79, 0xde, 0x55, 0x12, 0x8c, 0x18, 0x0e, 0x22, 0x36, 0x35, 0x9d, 0x0a, 0x3d, 0xc3, 0xa3, 0x47, + 0xb0, 0xee, 0xe1, 0x23, 0x37, 0xf6, 0x59, 0xaf, 0xe0, 0x53, 0x6a, 0x80, 0xe6, 0xba, 0xbd, 0xb5, + 0x4c, 0x8c, 0xcb, 0x42, 0xed, 0x47, 0xa8, 0xbc, 0x2a, 0x92, 0x80, 0x5c, 0x98, 0xce, 0xea, 0x8b, + 0x99, 0xa1, 0x98, 0xb7, 0x60, 0x25, 0x57, 0x44, 0x75, 0xb8, 0xe6, 0xe1, 0x90, 0x04, 0x1a, 0x68, + 0x80, 0xe6, 0x86, 0x23, 0x16, 0x48, 0x83, 0xe5, 0x82, 0xb5, 0x93, 0x2d, 0x3b, 0xeb, 0xa9, 0xc8, + 0x97, 0x99, 0x01, 0xcc, 0x77, 0x25, 0x58, 0xee, 0xd2, 0x61, 0x2a, 0x86, 0xc6, 0xb0, 0x7a, 0x34, + 0x21, 0x41, 0xcf, 0xf5, 0xbc, 0x09, 0xa6, 0x94, 0x8b, 0x55, 0xed, 0xdb, 0xcb, 0xc4, 0xa8, 0x89, + 0xbc, 0xf9, 0xae, 0xf9, 0x35, 0x31, 0x5a, 0xc3, 0x11, 0x7b, 0x12, 0xf7, 0xad, 0x01, 0x09, 0xda, + 0x85, 0x99, 0xb7, 0xa8, 0x37, 0x6e, 0xb3, 0x69, 0x84, 0xa9, 0xb5, 0x3b, 0x18, 0xec, 0x0a, 0x86, + 0x53, 0x49, 0xf9, 0x72, 0x81, 0x30, 0x84, 0x8c, 0x7c, 0xb7, 0x2a, 0x71, 0xab, 0x9b, 0xcb, 0xc4, + 0xf8, 0x4f, 0x58, 0x9d, 0xf5, 0x7e, 0xc3, 0x68, 0x83, 0x91, 0xcc, 0xe6, 0x01, 0x54, 0xdd, 0x80, + 0xc4, 0x21, 0xd3, 0x56, 0xf8, 0x29, 0x57, 0xb3, 0x53, 0xde, 0x23, 0xa3, 0xd0, 0xde, 0x3e, 0x49, + 0x0c, 0xe5, 0xd5, 0x27, 0xa3, 0x79, 0x0e, 0xfd, 0x94, 0x40, 0x1d, 0xa9, 0xd6, 0x59, 0xe5, 0xd3, + 0x7b, 0x0d, 0xe0, 0xda, 0x41, 0x18, 0xc5, 0x0c, 0xdd, 0x81, 0xe5, 0xe2, 0xd8, 0xae, 0xfd, 0x7a, + 0xec, 0x4c, 0x01, 0xdd, 0x87, 0x6b, 0x83, 0xd4, 0x4d, 0x2b, 0xfd, 0x95, 0xcc, 0x42, 0x4c, 0x46, + 0x7e, 0x03, 0xa0, 0x7a, 0x37, 0x66, 0xff, 0x54, 0xe6, 0xa7, 0xb0, 0xda, 0xa5, 0xc3, 0x6e, 0xec, + 0xb3, 0x11, 0xff, 0x50, 0xb7, 0xa1, 0x3a, 0x4a, 0xa7, 0x4e, 0xe5, 0xd5, 0x45, 0x85, 0xab, 0xcb, + 0x0f, 0xc4, 0x5e, 0x4d, 0x2d, 0x1d, 0x89, 0x43, 0x3b, 0xb0, 0x4c, 0xf8, 0xa6, 0xb3, 0x7c, 0xb5, + 0x02, 0x45, 0x0c, 0x44, 0x72, 0x32, 0xa4, 0x34, 0x7f, 0x09, 0xa0, 0x7a, 0x18, 0x47, 0x91, 0x3f, + 0x4d, 0xf7, 0xc8, 0x08, 0x73, 0x7d, 0x69, 0xfb, 0xc7, 0x7b, 0xe4, 0x62, 0x9d, 0xfd, 0x67, 0x33, + 0x43, 0xc9, 0x2e, 0xe4, 0x87, 0xb7, 0xad, 0x1b, 0x57, 0x7e, 0xaa, 0x70, 0x2c, 0x5e, 0x4b, 0x7c, + 0x1c, 0x91, 0x09, 0xc3, 0x9e, 0x25, 0xb2, 0x1d, 0xd8, 0x7b, 0x27, 0x73, 0x1d, 0x9c, 0xce, 0x75, + 0xf0, 0x79, 0xae, 0x83, 0xe7, 0x0b, 0x5d, 0x39, 0x5d, 0xe8, 0xca, 0xc7, 0x85, 0xae, 0x3c, 0xdc, + 0x3a, 0x8f, 0x1e, 0x0f, 0xd6, 0x57, 0xf9, 0x63, 0xb9, 0xf3, 0x2d, 0x00, 0x00, 0xff, 0xff, 0xba, + 0x32, 0x90, 0x68, 0x99, 0x05, 0x00, 0x00, } +func (this *SendEnabled) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*SendEnabled) + if !ok { + that2, ok := that.(SendEnabled) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Denom != that1.Denom { + return false + } + if this.Enabled != that1.Enabled { + return false + } + return true +} func (this *MsgSend) Equal(that interface{}) bool { if that == nil { return this == nil @@ -493,6 +634,93 @@ func (this *Supply) Equal(that interface{}) bool { } return true } +func (m *Params) 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 *Params) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.DefaultSendEnabled { + i-- + if m.DefaultSendEnabled { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + if len(m.SendEnabled) > 0 { + for iNdEx := len(m.SendEnabled) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.SendEnabled[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBank(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *SendEnabled) 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 *SendEnabled) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SendEnabled) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Enabled { + i-- + if m.Enabled { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintBank(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *MsgSend) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -731,6 +959,40 @@ func encodeVarintBank(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.SendEnabled) > 0 { + for _, e := range m.SendEnabled { + l = e.Size() + n += 1 + l + sovBank(uint64(l)) + } + } + if m.DefaultSendEnabled { + n += 2 + } + return n +} + +func (m *SendEnabled) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovBank(uint64(l)) + } + if m.Enabled { + n += 2 + } + return n +} + func (m *MsgSend) Size() (n int) { if m == nil { return 0 @@ -834,6 +1096,218 @@ func sovBank(x uint64) (n int) { func sozBank(x uint64) (n int) { return sovBank(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } +func (m *Params) 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 ErrIntOverflowBank + } + 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: Params: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SendEnabled", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBank + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBank + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBank + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SendEnabled = append(m.SendEnabled, &SendEnabled{}) + if err := m.SendEnabled[len(m.SendEnabled)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DefaultSendEnabled", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBank + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.DefaultSendEnabled = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipBank(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthBank + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthBank + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SendEnabled) 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 ErrIntOverflowBank + } + 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: SendEnabled: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SendEnabled: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBank + } + 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 ErrInvalidLengthBank + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBank + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Enabled", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBank + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Enabled = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipBank(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthBank + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthBank + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *MsgSend) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/bank/types/genesis.go b/x/bank/types/genesis.go index a184dd1b6805..77b6cb6c5865 100644 --- a/x/bank/types/genesis.go +++ b/x/bank/types/genesis.go @@ -14,9 +14,9 @@ var _ exported.GenesisBalance = (*Balance)(nil) // GenesisState defines the bank module's genesis state. type GenesisState struct { - SendEnabled bool `json:"send_enabled" yaml:"send_enabled"` - Balances []Balance `json:"balances" yaml:"balances"` - Supply sdk.Coins `json:"supply" yaml:"supply"` + Params Params `json:"params" yaml:"params"` + Balances []Balance `json:"balances" yaml:"balances"` + Supply sdk.Coins `json:"supply" yaml:"supply"` } // Balance defines an account address and balance pair used in the bank module's @@ -50,17 +50,17 @@ func SanitizeGenesisBalances(balances []Balance) []Balance { } // NewGenesisState creates a new genesis state. -func NewGenesisState(sendEnabled bool, balances []Balance, supply sdk.Coins) GenesisState { +func NewGenesisState(params Params, balances []Balance, supply sdk.Coins) GenesisState { return GenesisState{ - SendEnabled: sendEnabled, - Balances: balances, - Supply: supply, + Params: params, + Balances: balances, + Supply: supply, } } // DefaultGenesisState returns a default bank module genesis state. func DefaultGenesisState() GenesisState { - return NewGenesisState(true, []Balance{}, DefaultSupply().GetTotal()) + return NewGenesisState(DefaultParams(), []Balance{}, DefaultSupply().GetTotal()) } // GetGenesisStateFromAppState returns x/bank GenesisState given raw application diff --git a/x/bank/types/params.go b/x/bank/types/params.go index e7fda4ee286c..2d0398ef7cab 100644 --- a/x/bank/types/params.go +++ b/x/bank/types/params.go @@ -3,7 +3,9 @@ package types import ( "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + yaml "gopkg.in/yaml.v2" ) const ( @@ -11,21 +13,129 @@ const ( DefaultSendEnabled = true ) -// ParamStoreKeySendEnabled is store's key for SendEnabled -var ParamStoreKeySendEnabled = []byte("sendenabled") +var ( + // KeySendEnabled is store's key for SendEnabled Params + KeySendEnabled = []byte("SendEnabled") + // KeyDefaultSendEnabled is store's key for the DefaultSendEnabled option + KeyDefaultSendEnabled = []byte("DefaultSendEnabled") +) -// ParamKeyTable type declaration for parameters +// ParamKeyTable for bank module. func ParamKeyTable() paramtypes.KeyTable { - return paramtypes.NewKeyTable( - paramtypes.NewParamSetPair(ParamStoreKeySendEnabled, false, validateSendEnabled), - ) + return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) +} + +// NewParams creates a new parameter configuration for the bank module +func NewParams(defaultSendEnabled bool, sendEnabledParams SendEnabledParams) Params { + return Params{ + SendEnabled: sendEnabledParams, + DefaultSendEnabled: defaultSendEnabled, + } +} + +// DefaultParams is the default parameter configuration for the bank module +func DefaultParams() Params { + return Params{ + SendEnabled: SendEnabledParams{}, + // The default send enabled value allows send transfers for all coin denoms + DefaultSendEnabled: true, + } +} + +// Validate all bank module parameters +func (p Params) Validate() error { + if err := validateSendEnabledParams(p.SendEnabled); err != nil { + return err + } + return validateIsBool(p.DefaultSendEnabled) +} + +// String implements the Stringer interface. +func (p Params) String() string { + out, _ := yaml.Marshal(p) + return string(out) +} + +// SendEnabledDenom returns true if the given denom is enabled for sending +func (p Params) SendEnabledDenom(denom string) bool { + for _, pse := range p.SendEnabled { + if pse.Denom == denom { + return pse.Enabled + } + } + return p.DefaultSendEnabled +} + +// SetSendEnabledParam returns an updated set of Parameters with the given denom +// send enabled flag set. +func (p Params) SetSendEnabledParam(denom string, sendEnabled bool) Params { + var sendParams SendEnabledParams + for _, p := range p.SendEnabled { + if p.Denom != denom { + sendParams = append(sendParams, NewSendEnabled(p.Denom, p.Enabled)) + } + } + sendParams = append(sendParams, NewSendEnabled(denom, sendEnabled)) + return NewParams(p.DefaultSendEnabled, sendParams) +} + +// ParamSetPairs implements params.ParamSet +func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { + return paramtypes.ParamSetPairs{ + paramtypes.NewParamSetPair(KeySendEnabled, &p.SendEnabled, validateSendEnabledParams), + paramtypes.NewParamSetPair(KeyDefaultSendEnabled, &p.DefaultSendEnabled, validateIsBool), + } +} + +// SendEnabledParams is a collection of parameters indicating if a coin denom is enabled for sending +type SendEnabledParams []*SendEnabled + +func validateSendEnabledParams(i interface{}) error { + params, ok := i.([]*SendEnabled) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + // ensure each denom is only registered one time. + registered := make(map[string]bool) + for _, p := range params { + if _, exists := registered[p.Denom]; exists { + return fmt.Errorf("duplicate send enabled parameter found: '%s'", p.Denom) + } + if err := validateSendEnabled(*p); err != nil { + return err + } + registered[p.Denom] = true + } + return nil +} + +// NewSendEnabled creates a new SendEnabled object +// The denom may be left empty to control the global default setting of send_enabled +func NewSendEnabled(denom string, sendEnabled bool) *SendEnabled { + return &SendEnabled{ + Denom: denom, + Enabled: sendEnabled, + } +} + +// String implements stringer insterface +func (se SendEnabled) String() string { + out, _ := yaml.Marshal(se) + return string(out) } func validateSendEnabled(i interface{}) error { - _, ok := i.(bool) + param, ok := i.(SendEnabled) if !ok { return fmt.Errorf("invalid parameter type: %T", i) } + return sdk.ValidateDenom(param.Denom) +} +func validateIsBool(i interface{}) error { + _, ok := i.(bool) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } return nil } diff --git a/x/bank/types/params_test.go b/x/bank/types/params_test.go new file mode 100644 index 000000000000..502c83984c71 --- /dev/null +++ b/x/bank/types/params_test.go @@ -0,0 +1,124 @@ +package types + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func Test_validateSendEnabledParam(t *testing.T) { + type args struct { + i interface{} + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"invalid type", args{sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt())}, true}, + + {"invalid empty denom send enabled", args{*NewSendEnabled("", true)}, true}, + {"invalid empty denom send disabled", args{*NewSendEnabled("", false)}, true}, + + {"valid denom send enabled", args{*NewSendEnabled(sdk.DefaultBondDenom, true)}, false}, + {"valid denom send disabled", args{*NewSendEnabled(sdk.DefaultBondDenom, false)}, false}, + + {"invalid denom send enabled", args{*NewSendEnabled("FOO", true)}, true}, + {"invalid denom send disabled", args{*NewSendEnabled("FOO", false)}, true}, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.wantErr, validateSendEnabled(tt.args.i) != nil) + }) + } +} + +func Test_sendParamEqual(t *testing.T) { + paramsA := NewSendEnabled(sdk.DefaultBondDenom, true) + paramsB := NewSendEnabled(sdk.DefaultBondDenom, true) + paramsC := NewSendEnabled("foodenom", false) + + ok := paramsA.Equal(paramsB) + require.True(t, ok) + + ok = paramsA.Equal(paramsC) + require.False(t, ok) +} + +func Test_sendParamString(t *testing.T) { + paramString := "denom: foo\nenabled: false\n" + param := NewSendEnabled("foo", false) + + require.Equal(t, paramString, param.String()) +} + +func Test_validateParams(t *testing.T) { + params := DefaultParams() + + // default params have no error + require.NoError(t, params.Validate()) + + // default case is all denoms are enabled for sending + require.True(t, params.SendEnabledDenom(sdk.DefaultBondDenom)) + require.True(t, params.SendEnabledDenom("foodenom")) + + params.DefaultSendEnabled = false + params = params.SetSendEnabledParam("foodenom", true) + + require.NoError(t, validateSendEnabledParams(params.SendEnabled)) + require.True(t, params.SendEnabledDenom("foodenom")) + require.False(t, params.SendEnabledDenom(sdk.DefaultBondDenom)) + + params.DefaultSendEnabled = true + params = params.SetSendEnabledParam("foodenom", false) + + require.NoError(t, validateSendEnabledParams(params.SendEnabled)) + require.False(t, params.SendEnabledDenom("foodenom")) + require.True(t, params.SendEnabledDenom(sdk.DefaultBondDenom)) + + params = params.SetSendEnabledParam("foodenom", true) + require.True(t, params.SendEnabledDenom("foodenom")) + + params = params.SetSendEnabledParam("foodenom", false) + require.False(t, params.SendEnabledDenom("foodenom")) + + require.True(t, params.SendEnabledDenom("foodenom2")) + params = params.SetSendEnabledParam("foodenom2", false) + require.True(t, params.SendEnabledDenom("")) + require.True(t, params.SendEnabledDenom(sdk.DefaultBondDenom)) + require.False(t, params.SendEnabledDenom("foodenom2")) + + paramYaml := `send_enabled: +- denom: foodenom + enabled: false +- denom: foodenom2 + enabled: false +default_send_enabled: true +` + require.Equal(t, paramYaml, params.String()) + + // Ensure proper format of yaml output when false + params.DefaultSendEnabled = false + paramYaml = `send_enabled: +- denom: foodenom + enabled: false +- denom: foodenom2 + enabled: false +` + require.Equal(t, paramYaml, params.String()) + + params = NewParams(true, SendEnabledParams{ + NewSendEnabled("foodenom", false), + NewSendEnabled("foodenom", true), // this is not allowed + }) + + // fails due to duplicate entries. + require.Error(t, params.Validate()) + + // fails due to invalid type + require.Error(t, validateSendEnabledParams(NewSendEnabled("foodenom", true))) + + require.Error(t, validateSendEnabledParams(SendEnabledParams{NewSendEnabled("INVALIDDENOM", true)})) +} diff --git a/x/slashing/keeper/grpc_query_test.go b/x/slashing/keeper/grpc_query_test.go index bfa002f074de..7f1d5cd4edf1 100644 --- a/x/slashing/keeper/grpc_query_test.go +++ b/x/slashing/keeper/grpc_query_test.go @@ -13,6 +13,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/slashing/keeper" "github.com/cosmos/cosmos-sdk/x/slashing/types" ) @@ -31,7 +32,7 @@ func (suite *SlashingTestSuite) SetupTest() { ctx := app.BaseApp.NewContext(false, abci.Header{}) app.AccountKeeper.SetParams(ctx, authtypes.DefaultParams()) - app.BankKeeper.SetSendEnabled(ctx, true) + app.BankKeeper.SetParams(ctx, banktypes.DefaultParams()) app.SlashingKeeper.SetParams(ctx, keeper.TestParams()) addrDels := simapp.AddTestAddrsIncremental(app, ctx, 2, sdk.TokensFromConsensusPower(200))