Skip to content

Commit

Permalink
Merge PR #5888: Dynamic Capabilities with Routing
Browse files Browse the repository at this point in the history
  • Loading branch information
AdityaSripal authored Apr 7, 2020
1 parent df5bada commit 9448610
Show file tree
Hide file tree
Showing 31 changed files with 978 additions and 228 deletions.
30 changes: 25 additions & 5 deletions simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/ibc"
ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/02-client"
port "github.com/cosmos/cosmos-sdk/x/ibc/05-port"
transfer "github.com/cosmos/cosmos-sdk/x/ibc/20-transfer"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/cosmos/cosmos-sdk/x/params"
Expand Down Expand Up @@ -123,6 +124,10 @@ type SimApp struct {
EvidenceKeeper evidence.Keeper
TransferKeeper transfer.Keeper

// make scoped keepers public for test purposes
ScopedIBCKeeper capability.ScopedKeeper
ScopedTransferKeeper capability.ScopedKeeper

// the module manager
mm *module.Manager

Expand Down Expand Up @@ -173,14 +178,18 @@ func NewSimApp(
app.subspaces[crisis.ModuleName] = app.ParamsKeeper.Subspace(crisis.DefaultParamspace)
app.subspaces[evidence.ModuleName] = app.ParamsKeeper.Subspace(evidence.DefaultParamspace)

// add capability keeper and ScopeToModule for ibc module
app.CapabilityKeeper = capability.NewKeeper(appCodec, keys[capability.StoreKey])
scopedIBCKeeper := app.CapabilityKeeper.ScopeToModule(ibc.ModuleName)
scopedTransferKeeper := app.CapabilityKeeper.ScopeToModule(transfer.ModuleName)

// add keepers
app.AccountKeeper = auth.NewAccountKeeper(
appCodec, keys[auth.StoreKey], app.subspaces[auth.ModuleName], auth.ProtoBaseAccount,
)
app.BankKeeper = bank.NewBaseKeeper(
appCodec, keys[bank.StoreKey], app.AccountKeeper, app.subspaces[bank.ModuleName], app.BlacklistedAccAddrs(),
)
app.CapabilityKeeper = capability.NewKeeper(appCodec, keys[capability.StoreKey])
app.SupplyKeeper = supply.NewKeeper(
appCodec, keys[supply.StoreKey], app.AccountKeeper, app.BankKeeper, maccPerms,
)
Expand Down Expand Up @@ -230,15 +239,23 @@ func NewSimApp(
staking.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
)

// Create IBC Keeper
app.IBCKeeper = ibc.NewKeeper(
app.cdc, keys[ibc.StoreKey], app.StakingKeeper,
app.cdc, keys[ibc.StoreKey], app.StakingKeeper, scopedIBCKeeper,
)

transferCapKey := app.IBCKeeper.PortKeeper.BindPort(bank.ModuleName)
// Create Transfer Keepers
app.TransferKeeper = transfer.NewKeeper(
app.cdc, keys[transfer.StoreKey], transferCapKey,
app.cdc, keys[transfer.StoreKey],
app.IBCKeeper.ChannelKeeper, app.BankKeeper, app.SupplyKeeper,
scopedTransferKeeper,
)
transferModule := transfer.NewAppModule(app.TransferKeeper)

// Create static IBC router, add transfer route, then set and seal it
ibcRouter := port.NewRouter()
ibcRouter.AddRoute(transfer.ModuleName, transferModule)
app.IBCKeeper.SetRouter(ibcRouter)

// NOTE: Any module instantiated in the module manager that is later modified
// must be passed by reference here.
Expand All @@ -257,7 +274,7 @@ func NewSimApp(
upgrade.NewAppModule(app.UpgradeKeeper),
evidence.NewAppModule(app.EvidenceKeeper),
ibc.NewAppModule(app.IBCKeeper),
transfer.NewAppModule(app.TransferKeeper),
transferModule,
)

// During begin block slashing happens after distr.BeginBlocker so that
Expand Down Expand Up @@ -323,6 +340,9 @@ func NewSimApp(
ctx := app.BaseApp.NewContext(true, abci.Header{})
app.CapabilityKeeper.InitializeAndSeal(ctx)

app.ScopedIBCKeeper = scopedIBCKeeper
app.ScopedTransferKeeper = scopedTransferKeeper

return app
}

Expand Down
44 changes: 44 additions & 0 deletions x/capability/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,50 @@ func (sk ScopedKeeper) GetCapability(ctx sdk.Context, name string) (*types.Capab
return cap, true
}

// Get all the Owners that own the capability associated with the name this ScopedKeeper uses
// to refer to the capability
func (sk ScopedKeeper) GetOwners(ctx sdk.Context, name string) (*types.CapabilityOwners, bool) {
cap, ok := sk.GetCapability(ctx, name)
if !ok {
return nil, false
}

prefixStore := prefix.NewStore(ctx.KVStore(sk.storeKey), types.KeyPrefixIndexCapability)
indexKey := types.IndexToKey(cap.GetIndex())

var capOwners types.CapabilityOwners

bz := prefixStore.Get(indexKey)
if len(bz) == 0 {
return nil, false
}

sk.cdc.MustUnmarshalBinaryBare(bz, &capOwners)
return &capOwners, true

}

// LookupModules returns all the module owners for a given capability
// as a string array, the capability is also returned along with a boolean success flag
func (sk ScopedKeeper) LookupModules(ctx sdk.Context, name string) ([]string, *types.Capability, bool) {
cap, ok := sk.GetCapability(ctx, name)
if !ok {
return nil, nil, false
}

capOwners, ok := sk.GetOwners(ctx, name)
if !ok {
return nil, nil, false
}

mods := make([]string, len(capOwners.Owners))
for i, co := range capOwners.Owners {
mods[i] = co.Module
}
return mods, cap, true

}

func (sk ScopedKeeper) addOwner(ctx sdk.Context, cap *types.Capability, name string) error {
prefixStore := prefix.NewStore(ctx.KVStore(sk.storeKey), types.KeyPrefixIndexCapability)
indexKey := types.IndexToKey(cap.GetIndex())
Expand Down
69 changes: 69 additions & 0 deletions x/capability/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,11 @@ func (suite *KeeperTestSuite) TestAuthenticateCapability() {
suite.Require().NoError(err)
suite.Require().NotNil(cap2)

got, ok := sk1.GetCapability(suite.ctx, "transfer")
suite.Require().True(ok)

suite.Require().True(sk1.AuthenticateCapability(suite.ctx, cap1, "transfer"))
suite.Require().True(sk1.AuthenticateCapability(suite.ctx, got, "transfer"))
suite.Require().False(sk1.AuthenticateCapability(suite.ctx, cap1, "invalid"))
suite.Require().False(sk1.AuthenticateCapability(suite.ctx, cap2, "transfer"))

Expand Down Expand Up @@ -144,6 +148,71 @@ func (suite *KeeperTestSuite) TestClaimCapability() {
suite.Require().Equal(cap, got)
}

func (suite *KeeperTestSuite) TestGetOwners() {
sk1 := suite.keeper.ScopeToModule(bank.ModuleName)
sk2 := suite.keeper.ScopeToModule(staking.ModuleName)
sk3 := suite.keeper.ScopeToModule("foo")

sks := []keeper.ScopedKeeper{sk1, sk2, sk3}

cap, err := sk1.NewCapability(suite.ctx, "transfer")
suite.Require().NoError(err)
suite.Require().NotNil(cap)

suite.Require().NoError(sk2.ClaimCapability(suite.ctx, cap, "transfer"))
suite.Require().NoError(sk3.ClaimCapability(suite.ctx, cap, "transfer"))

expectedOrder := []string{bank.ModuleName, "foo", staking.ModuleName}
// Ensure all scoped keepers can get owners
for _, sk := range sks {
owners, ok := sk.GetOwners(suite.ctx, "transfer")
mods, cap, mok := sk.LookupModules(suite.ctx, "transfer")

suite.Require().True(ok, "could not retrieve owners")
suite.Require().NotNil(owners, "owners is nil")

suite.Require().True(mok, "could not retrieve modules")
suite.Require().NotNil(cap, "capability is nil")
suite.Require().NotNil(mods, "modules is nil")

suite.Require().Equal(len(expectedOrder), len(owners.Owners), "length of owners is unexpected")
for i, o := range owners.Owners {
// Require owner is in expected position
suite.Require().Equal(expectedOrder[i], o.Module, "module is unexpected")
suite.Require().Equal(expectedOrder[i], mods[i], "module in lookup is unexpected")
}
}

// foo module releases capability
err = sk3.ReleaseCapability(suite.ctx, cap)
suite.Require().Nil(err, "could not release capability")

// new expected order and scoped capabilities
expectedOrder = []string{bank.ModuleName, staking.ModuleName}
sks = []keeper.ScopedKeeper{sk1, sk2}

// Ensure all scoped keepers can get owners
for _, sk := range sks {
owners, ok := sk.GetOwners(suite.ctx, "transfer")
mods, cap, mok := sk.LookupModules(suite.ctx, "transfer")

suite.Require().True(ok, "could not retrieve owners")
suite.Require().NotNil(owners, "owners is nil")

suite.Require().True(mok, "could not retrieve modules")
suite.Require().NotNil(cap, "capability is nil")
suite.Require().NotNil(mods, "modules is nil")

suite.Require().Equal(len(expectedOrder), len(owners.Owners), "length of owners is unexpected")
for i, o := range owners.Owners {
// Require owner is in expected position
suite.Require().Equal(expectedOrder[i], o.Module, "module is unexpected")
suite.Require().Equal(expectedOrder[i], mods[i], "module in lookup is unexpected")
}
}

}

func (suite *KeeperTestSuite) TestReleaseCapability() {
sk1 := suite.keeper.ScopeToModule(bank.ModuleName)
sk2 := suite.keeper.ScopeToModule(staking.ModuleName)
Expand Down
37 changes: 19 additions & 18 deletions x/ibc/04-channel/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ package channel

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/capability"
"github.com/cosmos/cosmos-sdk/x/ibc/04-channel/keeper"
"github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
)

// HandleMsgChannelOpenInit defines the sdk.Handler for MsgChannelOpenInit
func HandleMsgChannelOpenInit(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelOpenInit) (*sdk.Result, error) {
err := k.ChanOpenInit(
func HandleMsgChannelOpenInit(ctx sdk.Context, k keeper.Keeper, portCap *capability.Capability, msg types.MsgChannelOpenInit) (*sdk.Result, *capability.Capability, error) {
capKey, err := k.ChanOpenInit(
ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortID, msg.ChannelID,
msg.Channel.Counterparty, msg.Channel.Version,
portCap, msg.Channel.Counterparty, msg.Channel.Version,
)
if err != nil {
return nil, err
return nil, nil, err
}

ctx.EventManager().EmitEvents(sdk.Events{
Expand All @@ -34,16 +35,16 @@ func HandleMsgChannelOpenInit(ctx sdk.Context, k keeper.Keeper, msg types.MsgCha

return &sdk.Result{
Events: ctx.EventManager().Events().ToABCIEvents(),
}, nil
}, capKey, nil
}

// HandleMsgChannelOpenTry defines the sdk.Handler for MsgChannelOpenTry
func HandleMsgChannelOpenTry(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelOpenTry) (*sdk.Result, error) {
err := k.ChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortID, msg.ChannelID,
msg.Channel.Counterparty, msg.Channel.Version, msg.CounterpartyVersion, msg.ProofInit, msg.ProofHeight,
func HandleMsgChannelOpenTry(ctx sdk.Context, k keeper.Keeper, portCap *capability.Capability, msg types.MsgChannelOpenTry) (*sdk.Result, *capability.Capability, error) {
capKey, err := k.ChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortID, msg.ChannelID,
portCap, msg.Channel.Counterparty, msg.Channel.Version, msg.CounterpartyVersion, msg.ProofInit, msg.ProofHeight,
)
if err != nil {
return nil, err
return nil, nil, err
}

ctx.EventManager().EmitEvents(sdk.Events{
Expand All @@ -64,13 +65,13 @@ func HandleMsgChannelOpenTry(ctx sdk.Context, k keeper.Keeper, msg types.MsgChan

return &sdk.Result{
Events: ctx.EventManager().Events().ToABCIEvents(),
}, nil
}, capKey, nil
}

// HandleMsgChannelOpenAck defines the sdk.Handler for MsgChannelOpenAck
func HandleMsgChannelOpenAck(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelOpenAck) (*sdk.Result, error) {
func HandleMsgChannelOpenAck(ctx sdk.Context, k keeper.Keeper, channelCap *capability.Capability, msg types.MsgChannelOpenAck) (*sdk.Result, error) {
err := k.ChanOpenAck(
ctx, msg.PortID, msg.ChannelID, msg.CounterpartyVersion, msg.ProofTry, msg.ProofHeight,
ctx, msg.PortID, msg.ChannelID, channelCap, msg.CounterpartyVersion, msg.ProofTry, msg.ProofHeight,
)
if err != nil {
return nil, err
Expand All @@ -95,8 +96,8 @@ func HandleMsgChannelOpenAck(ctx sdk.Context, k keeper.Keeper, msg types.MsgChan
}

// HandleMsgChannelOpenConfirm defines the sdk.Handler for MsgChannelOpenConfirm
func HandleMsgChannelOpenConfirm(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelOpenConfirm) (*sdk.Result, error) {
err := k.ChanOpenConfirm(ctx, msg.PortID, msg.ChannelID, msg.ProofAck, msg.ProofHeight)
func HandleMsgChannelOpenConfirm(ctx sdk.Context, k keeper.Keeper, channelCap *capability.Capability, msg types.MsgChannelOpenConfirm) (*sdk.Result, error) {
err := k.ChanOpenConfirm(ctx, msg.PortID, msg.ChannelID, channelCap, msg.ProofAck, msg.ProofHeight)
if err != nil {
return nil, err
}
Expand All @@ -120,8 +121,8 @@ func HandleMsgChannelOpenConfirm(ctx sdk.Context, k keeper.Keeper, msg types.Msg
}

// HandleMsgChannelCloseInit defines the sdk.Handler for MsgChannelCloseInit
func HandleMsgChannelCloseInit(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelCloseInit) (*sdk.Result, error) {
err := k.ChanCloseInit(ctx, msg.PortID, msg.ChannelID)
func HandleMsgChannelCloseInit(ctx sdk.Context, k keeper.Keeper, channelCap *capability.Capability, msg types.MsgChannelCloseInit) (*sdk.Result, error) {
err := k.ChanCloseInit(ctx, msg.PortID, msg.ChannelID, channelCap)
if err != nil {
return nil, err
}
Expand All @@ -145,8 +146,8 @@ func HandleMsgChannelCloseInit(ctx sdk.Context, k keeper.Keeper, msg types.MsgCh
}

// HandleMsgChannelCloseConfirm defines the sdk.Handler for MsgChannelCloseConfirm
func HandleMsgChannelCloseConfirm(ctx sdk.Context, k keeper.Keeper, msg types.MsgChannelCloseConfirm) (*sdk.Result, error) {
err := k.ChanCloseConfirm(ctx, msg.PortID, msg.ChannelID, msg.ProofInit, msg.ProofHeight)
func HandleMsgChannelCloseConfirm(ctx sdk.Context, k keeper.Keeper, channelCap *capability.Capability, msg types.MsgChannelCloseConfirm) (*sdk.Result, error) {
err := k.ChanCloseConfirm(ctx, msg.PortID, msg.ChannelID, channelCap, msg.ProofInit, msg.ProofHeight)
if err != nil {
return nil, err
}
Expand Down
Loading

0 comments on commit 9448610

Please sign in to comment.