Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R4R: Dynamic Capabilities with Routing #5888

Merged
merged 25 commits into from
Apr 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
57aacb4
start integrating capabilities
AdityaSripal Mar 26, 2020
1ed4923
switch to using port authenticate
AdityaSripal Mar 26, 2020
8ef8225
fix build and address first review
AdityaSripal Mar 26, 2020
06e7b80
remove capabilities from msgs and return them on channel handlers
AdityaSripal Mar 27, 2020
7e01aac
implement channel callbacks and capability injection
AdityaSripal Mar 28, 2020
5979b3b
route packets through ibc handler and then to module
AdityaSripal Mar 28, 2020
bddc7a9
start implementing transfer with new routing logic
AdityaSripal Mar 28, 2020
18f7207
fix packet msg routes
AdityaSripal Mar 28, 2020
ff0dbef
implement routing from @cwgoes comment
AdityaSripal Mar 31, 2020
8086e42
address @cwgoes comments
AdityaSripal Mar 31, 2020
56a4c9c
address @fedekunze comments
AdityaSripal Mar 31, 2020
b282f99
start working on tests, prove GetCapability bug
AdityaSripal Apr 1, 2020
287bd62
fix channel tests
AdityaSripal Apr 1, 2020
4c9b105
fix port tests
AdityaSripal Apr 1, 2020
ca07bf7
add get owners test
AdityaSripal Apr 1, 2020
d7dfea1
fix conflicts
AdityaSripal Apr 2, 2020
9b1aeda
update to latest master
AdityaSripal Apr 2, 2020
d23c401
Update x/ibc/05-port/types/module.go
AdityaSripal Apr 3, 2020
7eb7c51
test capability claiming and don't panic on invalid route
AdityaSripal Apr 3, 2020
056d759
Merge branch 'aditya/ibc-routing' of https://github.com/cosmos/cosmos…
AdityaSripal Apr 3, 2020
dca2a0b
deduplicate
AdityaSripal Apr 3, 2020
0e1775b
Require sending capability to SendPacket
AdityaSripal Apr 4, 2020
a6cfc6a
appease linter
AdityaSripal Apr 4, 2020
d08a246
fix conflicts
AdityaSripal Apr 4, 2020
b92d5f7
fix conflicts, build, tests
AdityaSripal Apr 6, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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