Skip to content

Commit

Permalink
Merge PR #4679: Extended permissions for module accounts
Browse files Browse the repository at this point in the history
  • Loading branch information
colin-axner authored and alexanderbez committed Jul 6, 2019
1 parent 1a7f31f commit 1c9a188
Show file tree
Hide file tree
Showing 23 changed files with 419 additions and 138 deletions.
10 changes: 6 additions & 4 deletions docs/spec/supply/01_concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ The `ModuleAccount` interface is defined as follows:

```go
type ModuleAccount interface {
auth.Account // same methods as the Account interface
GetName() string // name of the module; used to obtain the address
GetPermission() string // permission of module account (minter/burner/holder)
auth.Account // same methods as the Account interface
GetName() string // name of the module; used to obtain the address
GetPermissions() []string // permissions of module account
HasPermission(string) bool
}
```

Expand All @@ -51,10 +52,11 @@ Each `ModuleAccount` has a different set of permissions that provide different
object capabilities to perform certain actions. Permissions need to be
registered upon the creation of the supply `Keeper` so that every time a
`ModuleAccount` calls the allowed functions, the `Keeper` can lookup the
permission to that specific account and perform or not the action.
permissions to that specific account and perform or not the action.

The available permissions are:

- `Basic`: is allowed to only transfer its coins to other accounts.
- `Minter`: allows for a module to mint a specific amount of coins as well as perform the `Basic` permissioned actions.
- `Burner`: allows for a module to burn a specific amount of coins as well as perform the `Basic` permissioned actions.
- `Staking`: allows for a module to delegate and undelegate a specific amount of coins.
14 changes: 9 additions & 5 deletions simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,15 +144,19 @@ func NewSimApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bo
crisisSubspace := app.paramsKeeper.Subspace(crisis.DefaultParamspace)

// account permissions
basicModuleAccs := []string{auth.FeeCollectorName, distr.ModuleName}
minterModuleAccs := []string{mint.ModuleName}
burnerModuleAccs := []string{staking.BondedPoolName, staking.NotBondedPoolName, gov.ModuleName}
maccPerms := map[string][]string{
auth.FeeCollectorName: []string{supply.Basic},
distr.ModuleName: []string{supply.Basic},
mint.ModuleName: []string{supply.Minter},
staking.BondedPoolName: []string{supply.Burner, supply.Staking},
staking.NotBondedPoolName: []string{supply.Burner, supply.Staking},
gov.ModuleName: []string{supply.Burner},
}

// add keepers
app.accountKeeper = auth.NewAccountKeeper(app.cdc, app.keyAccount, authSubspace, auth.ProtoBaseAccount)
app.bankKeeper = bank.NewBaseKeeper(app.accountKeeper, bankSubspace, bank.DefaultCodespace)
app.supplyKeeper = supply.NewKeeper(app.cdc, app.keySupply, app.accountKeeper,
app.bankKeeper, supply.DefaultCodespace, basicModuleAccs, minterModuleAccs, burnerModuleAccs)
app.supplyKeeper = supply.NewKeeper(app.cdc, app.keySupply, app.accountKeeper, app.bankKeeper, supply.DefaultCodespace, maccPerms)
stakingKeeper := staking.NewKeeper(app.cdc, app.keyStaking, app.tkeyStaking,
app.supplyKeeper, stakingSubspace, staking.DefaultCodespace)
app.mintKeeper = mint.NewKeeper(app.cdc, app.keyMint, mintSubspace, &stakingKeeper, app.supplyKeeper, auth.FeeCollectorName)
Expand Down
28 changes: 19 additions & 9 deletions x/auth/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package auth

import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/crypto"

"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store"
Expand All @@ -25,18 +25,28 @@ type testInput struct {
// moduleAccount defines an account for modules that holds coins on a pool
type moduleAccount struct {
*types.BaseAccount
Name string `json:"name" yaml:"name"` // name of the module
Permission string `json:"permission" yaml"permission"` // permission of module account (minter/burner/holder)
name string `json:"name" yaml:"name"` // name of the module
permissions []string `json:"permissions" yaml"permissions"` // permissions of module account
}

// HasPermission returns whether or not the module account has permission.
func (ma moduleAccount) HasPermission(permission string) bool {
for _, perm := range ma.permissions {
if perm == permission {
return true
}
}
return false
}

// GetName returns the the name of the holder's module
func (ma moduleAccount) GetName() string {
return ma.Name
return ma.name
}

// GetPermission returns permission granted to the module account (holder/minter/burner)
func (ma moduleAccount) GetPermission() string {
return ma.Permission
// GetPermissions returns permissions granted to the module account
func (ma moduleAccount) GetPermissions() []string {
return ma.permissions
}

func setupTestInput() testInput {
Expand Down Expand Up @@ -125,8 +135,8 @@ func (sk DummySupplyKeeper) GetModuleAccount(ctx sdk.Context, moduleName string)
// create a new module account
macc := &moduleAccount{
BaseAccount: &baseAcc,
Name: moduleName,
Permission: "basic",
name: moduleName,
permissions: []string{"basic"},
}

maccI := (sk.ak.NewAccount(ctx, macc)).(exported.ModuleAccountI)
Expand Down
13 changes: 9 additions & 4 deletions x/distribution/keeper/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,13 @@ func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initPower int64,
ctx := sdk.NewContext(ms, abci.Header{ChainID: "foochainid"}, isCheckTx, log.NewNopLogger())
accountKeeper := auth.NewAccountKeeper(cdc, keyAcc, pk.Subspace(auth.DefaultParamspace), auth.ProtoBaseAccount)
bankKeeper := bank.NewBaseKeeper(accountKeeper, pk.Subspace(bank.DefaultParamspace), bank.DefaultCodespace)
supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bankKeeper, supply.DefaultCodespace,
[]string{auth.FeeCollectorName, types.ModuleName}, []string{}, []string{staking.NotBondedPoolName, staking.BondedPoolName})
maccPerms := map[string][]string{
auth.FeeCollectorName: []string{supply.Basic},
types.ModuleName: []string{supply.Basic},
staking.NotBondedPoolName: []string{supply.Burner, supply.Staking},
staking.BondedPoolName: []string{supply.Burner, supply.Staking},
}
supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bankKeeper, supply.DefaultCodespace, maccPerms)

sk := staking.NewKeeper(cdc, keyStaking, tkeyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace), staking.DefaultCodespace)
sk.SetParams(ctx, staking.DefaultParams())
Expand All @@ -140,8 +145,8 @@ func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initPower int64,

// create module accounts
feeCollectorAcc := supply.NewEmptyModuleAccount(auth.FeeCollectorName, supply.Basic)
notBondedPool := supply.NewEmptyModuleAccount(staking.NotBondedPoolName, supply.Burner)
bondPool := supply.NewEmptyModuleAccount(staking.BondedPoolName, supply.Burner)
notBondedPool := supply.NewEmptyModuleAccount(staking.NotBondedPoolName, supply.Burner, supply.Staking)
bondPool := supply.NewEmptyModuleAccount(staking.BondedPoolName, supply.Burner, supply.Staking)
distrAcc := supply.NewEmptyModuleAccount(types.ModuleName, supply.Basic)

keeper.supplyKeeper.SetModuleAccount(ctx, feeCollectorAcc)
Expand Down
32 changes: 16 additions & 16 deletions x/genaccounts/genesis_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ type GenesisAccount struct {
EndTime int64 `json:"end_time" yaml:"end_time"` // vesting end time (UNIX Epoch time)

// module account fields
ModuleName string `json:"module_name" yaml:"module_name"` // name of the module account
ModulePermission string `json:"module_permission" yaml:"module_permission"` // permission of module account
ModuleName string `json:"module_name" yaml:"module_name"` // name of the module account
ModulePermissions []string `json:"module_permissions" yaml:"module_permissions"` // permissions of module account
}

// Validate checks for errors on the vesting and module account parameters
Expand All @@ -53,20 +53,20 @@ func (ga GenesisAccount) Validate() error {
// NewGenesisAccountRaw creates a new GenesisAccount object
func NewGenesisAccountRaw(address sdk.AccAddress, coins,
vestingAmount sdk.Coins, vestingStartTime, vestingEndTime int64,
module, permission string) GenesisAccount {
module string, permissions ...string) GenesisAccount {

return GenesisAccount{
Address: address,
Coins: coins,
Sequence: 0,
AccountNumber: 0, // ignored set by the account keeper during InitGenesis
OriginalVesting: vestingAmount,
DelegatedFree: sdk.Coins{}, // ignored
DelegatedVesting: sdk.Coins{}, // ignored
StartTime: vestingStartTime,
EndTime: vestingEndTime,
ModuleName: module,
ModulePermission: permission,
Address: address,
Coins: coins,
Sequence: 0,
AccountNumber: 0, // ignored set by the account keeper during InitGenesis
OriginalVesting: vestingAmount,
DelegatedFree: sdk.Coins{}, // ignored
DelegatedVesting: sdk.Coins{}, // ignored
StartTime: vestingStartTime,
EndTime: vestingEndTime,
ModuleName: module,
ModulePermissions: permissions,
}
}

Expand Down Expand Up @@ -102,7 +102,7 @@ func NewGenesisAccountI(acc authexported.Account) (GenesisAccount, error) {
gacc.EndTime = acc.GetEndTime()
case supplyexported.ModuleAccountI:
gacc.ModuleName = acc.GetName()
gacc.ModulePermission = acc.GetPermission()
gacc.ModulePermissions = acc.GetPermissions()
}

return gacc, nil
Expand Down Expand Up @@ -131,7 +131,7 @@ func (ga *GenesisAccount) ToAccount() auth.Account {

// module accounts
if ga.ModuleName != "" {
return supply.NewModuleAccount(bacc, ga.ModuleName, ga.ModulePermission)
return supply.NewModuleAccount(bacc, ga.ModuleName, ga.ModulePermissions...)
}

return bacc
Expand Down
12 changes: 8 additions & 4 deletions x/gov/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,12 @@ func getMockApp(t *testing.T, numGenAccs int, genState GenesisState, genAccs []a

bk := bank.NewBaseKeeper(mApp.AccountKeeper, mApp.ParamsKeeper.Subspace(bank.DefaultParamspace), bank.DefaultCodespace)

supplyKeeper := supply.NewKeeper(mApp.Cdc, keySupply, mApp.AccountKeeper, bk, supply.DefaultCodespace,
[]string{}, []string{}, []string{types.ModuleName, staking.NotBondedPoolName, staking.BondedPoolName})
maccPerms := map[string][]string{
types.ModuleName: []string{supply.Burner},
staking.NotBondedPoolName: []string{supply.Burner, supply.Staking},
staking.BondedPoolName: []string{supply.Burner, supply.Staking},
}
supplyKeeper := supply.NewKeeper(mApp.Cdc, keySupply, mApp.AccountKeeper, bk, supply.DefaultCodespace, maccPerms)
sk := staking.NewKeeper(mApp.Cdc, keyStaking, tKeyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace), staking.DefaultCodespace)

keeper := NewKeeper(mApp.Cdc, keyGov, pk, pk.Subspace("testgov"), supplyKeeper, sk, DefaultCodespace, rtr)
Expand Down Expand Up @@ -108,8 +112,8 @@ func getInitChainer(mapp *mock.App, keeper Keeper, stakingKeeper staking.Keeper,

// set module accounts
govAcc := supply.NewEmptyModuleAccount(types.ModuleName, supply.Burner)
notBondedPool := supply.NewEmptyModuleAccount(staking.NotBondedPoolName, supply.Burner)
bondPool := supply.NewEmptyModuleAccount(staking.BondedPoolName, supply.Burner)
notBondedPool := supply.NewEmptyModuleAccount(staking.NotBondedPoolName, supply.Burner, supply.Staking)
bondPool := supply.NewEmptyModuleAccount(staking.BondedPoolName, supply.Burner, supply.Staking)

supplyKeeper.SetModuleAccount(ctx, govAcc)
supplyKeeper.SetModuleAccount(ctx, notBondedPool)
Expand Down
9 changes: 7 additions & 2 deletions x/mint/internal/keeper/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,13 @@ func newTestInput(t *testing.T) testInput {
paramsKeeper := params.NewKeeper(types.ModuleCdc, keyParams, tkeyParams, params.DefaultCodespace)
accountKeeper := auth.NewAccountKeeper(types.ModuleCdc, keyAcc, paramsKeeper.Subspace(auth.DefaultParamspace), auth.ProtoBaseAccount)
bankKeeper := bank.NewBaseKeeper(accountKeeper, paramsKeeper.Subspace(bank.DefaultParamspace), bank.DefaultCodespace)
supplyKeeper := supply.NewKeeper(types.ModuleCdc, keySupply, accountKeeper, bankKeeper, supply.DefaultCodespace,
[]string{auth.FeeCollectorName}, []string{types.ModuleName}, []string{staking.NotBondedPoolName, staking.BondedPoolName})
maccPerms := map[string][]string{
auth.FeeCollectorName: []string{supply.Basic},
types.ModuleName: []string{supply.Minter},
staking.NotBondedPoolName: []string{supply.Burner, supply.Staking},
staking.BondedPoolName: []string{supply.Burner, supply.Staking},
}
supplyKeeper := supply.NewKeeper(types.ModuleCdc, keySupply, accountKeeper, bankKeeper, supply.DefaultCodespace, maccPerms)
supplyKeeper.SetSupply(ctx, supply.NewSupply(sdk.Coins{}))

stakingKeeper := staking.NewKeeper(
Expand Down
12 changes: 8 additions & 4 deletions x/slashing/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,12 @@ func getMockApp(t *testing.T) (*mock.App, staking.Keeper, Keeper) {
keySupply := sdk.NewKVStoreKey(supply.StoreKey)

bankKeeper := bank.NewBaseKeeper(mapp.AccountKeeper, mapp.ParamsKeeper.Subspace(bank.DefaultParamspace), bank.DefaultCodespace)
supplyKeeper := supply.NewKeeper(mapp.Cdc, keySupply, mapp.AccountKeeper, bankKeeper, supply.DefaultCodespace,
[]string{auth.FeeCollectorName}, []string{}, []string{staking.NotBondedPoolName, staking.BondedPoolName})
maccPerms := map[string][]string{
auth.FeeCollectorName: []string{supply.Basic},
staking.NotBondedPoolName: []string{supply.Burner, supply.Staking},
staking.BondedPoolName: []string{supply.Burner, supply.Staking},
}
supplyKeeper := supply.NewKeeper(mapp.Cdc, keySupply, mapp.AccountKeeper, bankKeeper, supply.DefaultCodespace, maccPerms)
stakingKeeper := staking.NewKeeper(mapp.Cdc, keyStaking, tkeyStaking, supplyKeeper, mapp.ParamsKeeper.Subspace(staking.DefaultParamspace), staking.DefaultCodespace)
keeper := NewKeeper(mapp.Cdc, keySlashing, stakingKeeper, mapp.ParamsKeeper.Subspace(DefaultParamspace), DefaultCodespace)
mapp.Router().AddRoute(staking.RouterKey, staking.NewHandler(stakingKeeper))
Expand Down Expand Up @@ -66,8 +70,8 @@ func getInitChainer(mapp *mock.App, keeper staking.Keeper, accountKeeper types.A
return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
// set module accounts
feeCollector := supply.NewEmptyModuleAccount(auth.FeeCollectorName, supply.Basic)
notBondedPool := supply.NewEmptyModuleAccount(types.NotBondedPoolName, supply.Burner)
bondPool := supply.NewEmptyModuleAccount(types.BondedPoolName, supply.Burner)
notBondedPool := supply.NewEmptyModuleAccount(types.NotBondedPoolName, supply.Burner, supply.Staking)
bondPool := supply.NewEmptyModuleAccount(types.BondedPoolName, supply.Burner, supply.Staking)

supplyKeeper.SetModuleAccount(ctx, feeCollector)
supplyKeeper.SetModuleAccount(ctx, bondPool)
Expand Down
12 changes: 8 additions & 4 deletions x/slashing/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,12 @@ func createTestInput(t *testing.T, defaults Params) (sdk.Context, bank.Keeper, s
accountKeeper := auth.NewAccountKeeper(cdc, keyAcc, paramsKeeper.Subspace(auth.DefaultParamspace), auth.ProtoBaseAccount)

bk := bank.NewBaseKeeper(accountKeeper, paramsKeeper.Subspace(bank.DefaultParamspace), bank.DefaultCodespace)
supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bk, supply.DefaultCodespace,
[]string{auth.FeeCollectorName}, []string{}, []string{staking.NotBondedPoolName, staking.BondedPoolName})
maccPerms := map[string][]string{
auth.FeeCollectorName: []string{supply.Basic},
staking.NotBondedPoolName: []string{supply.Burner, supply.Staking},
staking.BondedPoolName: []string{supply.Burner, supply.Staking},
}
supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bk, supply.DefaultCodespace, maccPerms)

totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens.MulRaw(int64(len(addrs)))))
supplyKeeper.SetSupply(ctx, supply.NewSupply(totalSupply))
Expand All @@ -88,8 +92,8 @@ func createTestInput(t *testing.T, defaults Params) (sdk.Context, bank.Keeper, s

// set module accounts
feeCollectorAcc := supply.NewEmptyModuleAccount(auth.FeeCollectorName, supply.Basic)
notBondedPool := supply.NewEmptyModuleAccount(staking.NotBondedPoolName, supply.Burner)
bondPool := supply.NewEmptyModuleAccount(staking.BondedPoolName, supply.Burner)
notBondedPool := supply.NewEmptyModuleAccount(staking.NotBondedPoolName, supply.Burner, supply.Staking)
bondPool := supply.NewEmptyModuleAccount(staking.BondedPoolName, supply.Burner, supply.Staking)

supplyKeeper.SetModuleAccount(ctx, feeCollectorAcc)
supplyKeeper.SetModuleAccount(ctx, bondPool)
Expand Down
12 changes: 8 additions & 4 deletions x/staking/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ func getMockApp(t *testing.T) (*mock.App, Keeper) {
keySupply := sdk.NewKVStoreKey(supply.StoreKey)

bankKeeper := bank.NewBaseKeeper(mApp.AccountKeeper, mApp.ParamsKeeper.Subspace(bank.DefaultParamspace), bank.DefaultCodespace)
supplyKeeper := supply.NewKeeper(mApp.Cdc, keySupply, mApp.AccountKeeper, bankKeeper, supply.DefaultCodespace,
[]string{auth.FeeCollectorName}, []string{}, []string{types.NotBondedPoolName, types.BondedPoolName})
maccPerms := map[string][]string{
auth.FeeCollectorName: []string{supply.Basic},
types.NotBondedPoolName: []string{supply.Burner, supply.Staking},
types.BondedPoolName: []string{supply.Burner, supply.Staking},
}
supplyKeeper := supply.NewKeeper(mApp.Cdc, keySupply, mApp.AccountKeeper, bankKeeper, supply.DefaultCodespace, maccPerms)
keeper := NewKeeper(mApp.Cdc, keyStaking, tkeyStaking, supplyKeeper, mApp.ParamsKeeper.Subspace(DefaultParamspace), DefaultCodespace)

mApp.Router().AddRoute(RouterKey, NewHandler(keeper))
Expand Down Expand Up @@ -57,8 +61,8 @@ func getInitChainer(mapp *mock.App, keeper Keeper, accountKeeper types.AccountKe

// set module accounts
feeCollector := supply.NewEmptyModuleAccount(auth.FeeCollectorName, supply.Basic)
notBondedPool := supply.NewEmptyModuleAccount(types.NotBondedPoolName, supply.Burner)
bondPool := supply.NewEmptyModuleAccount(types.BondedPoolName, supply.Burner)
notBondedPool := supply.NewEmptyModuleAccount(types.NotBondedPoolName, supply.Burner, supply.Staking)
bondPool := supply.NewEmptyModuleAccount(types.BondedPoolName, supply.Burner, supply.Staking)

supplyKeeper.SetModuleAccount(ctx, feeCollector)
supplyKeeper.SetModuleAccount(ctx, bondPool)
Expand Down
12 changes: 8 additions & 4 deletions x/staking/keeper/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,12 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initPower int64) (sdk.Context
bank.DefaultCodespace,
)

supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bk, supply.DefaultCodespace,
[]string{auth.FeeCollectorName}, []string{}, []string{types.NotBondedPoolName, types.BondedPoolName})
maccPerms := map[string][]string{
auth.FeeCollectorName: []string{supply.Basic},
types.NotBondedPoolName: []string{supply.Burner, supply.Staking},
types.BondedPoolName: []string{supply.Burner, supply.Staking},
}
supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bk, supply.DefaultCodespace, maccPerms)

initTokens := sdk.TokensFromConsensusPower(initPower)
initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens))
Expand All @@ -138,8 +142,8 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initPower int64) (sdk.Context

// set module accounts
feeCollectorAcc := supply.NewEmptyModuleAccount(auth.FeeCollectorName, supply.Basic)
notBondedPool := supply.NewEmptyModuleAccount(types.NotBondedPoolName, supply.Burner)
bondPool := supply.NewEmptyModuleAccount(types.BondedPoolName, supply.Burner)
notBondedPool := supply.NewEmptyModuleAccount(types.NotBondedPoolName, supply.Burner, supply.Staking)
bondPool := supply.NewEmptyModuleAccount(types.BondedPoolName, supply.Burner, supply.Staking)

err = notBondedPool.SetCoins(totalSupply)
require.NoError(t, err)
Expand Down
1 change: 1 addition & 0 deletions x/supply/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const (
Basic = types.Basic
Minter = types.Minter
Burner = types.Burner
Staking = types.Staking
)

var (
Expand Down
3 changes: 2 additions & 1 deletion x/supply/exported/exported.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ import "github.com/cosmos/cosmos-sdk/x/auth/exported"
type ModuleAccountI interface {
exported.Account
GetName() string
GetPermission() string
GetPermissions() []string
HasPermission(string) bool
}
Loading

0 comments on commit 1c9a188

Please sign in to comment.