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 8 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
11 changes: 7 additions & 4 deletions simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,16 +176,19 @@ 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(
app.cdc, keys[capability.StoreKey], memKeys[capability.MemStoreKey],
)
scopedIBCKeeper := app.CapabilityKeeper.ScopeToModule(ibc.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(
app.cdc, keys[capability.StoreKey], memKeys[capability.MemStoreKey],
)
app.SupplyKeeper = supply.NewKeeper(
appCodec, keys[supply.StoreKey], app.AccountKeeper, app.BankKeeper, maccPerms,
)
Expand Down Expand Up @@ -236,7 +239,7 @@ func NewSimApp(
)

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)
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(),
}, 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(),
}, 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
104 changes: 47 additions & 57 deletions x/ibc/04-channel/keeper/handshake.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/capability"
connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection"
connectionexported "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/exported"
porttypes "github.com/cosmos/cosmos-sdk/x/ibc/05-port/types"

"github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported"
"github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
commitmentexported "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/exported"
ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types"
)

// CounterpartyHops returns the connection hops of the counterparty channel.
Expand All @@ -33,38 +36,44 @@ func (k Keeper) ChanOpenInit(
connectionHops []string,
portID,
channelID string,
portCap capability.Capability,
counterparty types.Counterparty,
version string,
) error {
) (capability.Capability, error) {
// channel identifier and connection hop length checked on msg.ValidateBasic()

_, found := k.GetChannel(ctx, portID, channelID)
if found {
return sdkerrors.Wrap(types.ErrChannelExists, channelID)
return nil, sdkerrors.Wrap(types.ErrChannelExists, channelID)
}

connectionEnd, found := k.connectionKeeper.GetConnection(ctx, connectionHops[0])
if !found {
return sdkerrors.Wrap(connection.ErrConnectionNotFound, connectionHops[0])
return nil, sdkerrors.Wrap(connection.ErrConnectionNotFound, connectionHops[0])
}

if connectionEnd.GetState() == connectionexported.UNINITIALIZED {
return sdkerrors.Wrap(
return nil, sdkerrors.Wrap(
connection.ErrInvalidConnectionState,
"connection state cannot be UNINITIALIZED",
)
}

if !k.portKeeper.Authenticate(ctx, portCap, portID) {
return nil, sdkerrors.Wrap(porttypes.ErrInvalidPort, "caller does not own port capability")
}

channel := types.NewChannel(exported.INIT, order, counterparty, connectionHops, version)
k.SetChannel(ctx, portID, channelID, channel)

// TODO: blocked by #5542
// key := ""
// k.SetChannelCapability(ctx, portID, channelID, key)
capKey, err := k.scopedKeeper.NewCapability(ctx, ibctypes.ChannelCapabilityPath(portID, channelID))
if err != nil {
return nil, sdkerrors.Wrap(types.ErrInvalidChannelCapability, err.Error())
}
k.SetNextSequenceSend(ctx, portID, channelID, 1)
k.SetNextSequenceRecv(ctx, portID, channelID, 1)

return nil
return capKey, nil
}

// ChanOpenTry is called by a module to accept the first step of a channel opening
Expand All @@ -75,12 +84,13 @@ func (k Keeper) ChanOpenTry(
connectionHops []string,
portID,
channelID string,
portCap capability.Capability,
counterparty types.Counterparty,
version,
counterpartyVersion string,
proofInit commitmentexported.Proof,
proofHeight uint64,
) error {
) (capability.Capability, error) {
// channel identifier and connection hop length checked on msg.ValidateBasic()

previousChannel, found := k.GetChannel(ctx, portID, channelID)
Expand All @@ -93,19 +103,17 @@ func (k Keeper) ChanOpenTry(
sdkerrors.Wrap(types.ErrInvalidChannel, "cannot relay connection attempt")
}

// TODO: blocked by #5542
// key := sdk.NewKVStoreKey(portID)
// if !k.portKeeper.Authenticate(key, portID) {
// return sdkerrors.Wrap(port.ErrInvalidPort, portID)
// }
if !k.portKeeper.Authenticate(ctx, portCap, portID) {
return nil, sdkerrors.Wrap(porttypes.ErrInvalidPort, "caller does not own port capability")
}

connectionEnd, found := k.connectionKeeper.GetConnection(ctx, connectionHops[0])
if !found {
return sdkerrors.Wrap(connection.ErrConnectionNotFound, connectionHops[0])
return nil, sdkerrors.Wrap(connection.ErrConnectionNotFound, connectionHops[0])
}

if connectionEnd.GetState() != connectionexported.OPEN {
return sdkerrors.Wrapf(
return nil, sdkerrors.Wrapf(
connection.ErrInvalidConnectionState,
"connection state is not OPEN (got %s)", connectionEnd.GetState().String(),
)
Expand Down Expand Up @@ -133,26 +141,28 @@ func (k Keeper) ChanOpenTry(
ctx, connectionEnd, proofHeight, proofInit,
counterparty.PortID, counterparty.ChannelID, expectedChannel,
); err != nil {
return err
return nil, err
}

k.SetChannel(ctx, portID, channelID, channel)

// TODO: blocked by #5542
// key := ""
// k.SetChannelCapability(ctx, portID, channelID, key)
capKey, err := k.scopedKeeper.NewCapability(ctx, ibctypes.ChannelCapabilityPath(portID, channelID))
if err != nil {
return nil, sdkerrors.Wrap(types.ErrInvalidChannelCapability, err.Error())
}
k.SetNextSequenceSend(ctx, portID, channelID, 1)
k.SetNextSequenceRecv(ctx, portID, channelID, 1)

return nil
return capKey, nil
}

// ChanOpenAck is called by the handshake-originating module to acknowledge the
// acceptance of the initial request by the counterparty module on the other chain.
func (k Keeper) ChanOpenAck(
ctx sdk.Context,
portID,
channelID,
channelID string,
chanCap capability.Capability,
counterpartyVersion string,
proofTry commitmentexported.Proof,
proofHeight uint64,
Expand All @@ -169,11 +179,9 @@ func (k Keeper) ChanOpenAck(
)
}

// TODO: blocked by #5542
// key := sdk.NewKVStoreKey(portID)
// if !k.portKeeper.Authenticate(key, portID) {
// return sdkerrors.Wrap(port.ErrInvalidPort, portID)
// }
if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, ibctypes.ChannelCapabilityPath(portID, channelID)) {
return sdkerrors.Wrap(types.ErrChannelCapabilityNotFound, "caller does not own capability for channel")
}

connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0])
if !found {
Expand Down Expand Up @@ -221,6 +229,7 @@ func (k Keeper) ChanOpenConfirm(
ctx sdk.Context,
portID,
channelID string,
chanCap capability.Capability,
proofAck commitmentexported.Proof,
proofHeight uint64,
) error {
Expand All @@ -236,16 +245,9 @@ func (k Keeper) ChanOpenConfirm(
)
}

// TODO: blocked by #5542
// capkey, found := k.GetChannelCapability(ctx, portID, channelID)
// if !found {
// return sdkerrors.Wrap(types.ErrChannelCapabilityNotFound, channelID)
// }

// key := sdk.NewKVStoreKey(capkey)
// if !k.portKeeper.Authenticate(key, portID) {
// return sdkerrors.Wrap(port.ErrInvalidPort, portID)
// }
if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, ibctypes.ChannelCapabilityPath(portID, channelID)) {
return sdkerrors.Wrap(types.ErrChannelCapabilityNotFound, "caller does not own capability for channel")
}

connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0])
if !found {
Expand Down Expand Up @@ -296,17 +298,11 @@ func (k Keeper) ChanCloseInit(
ctx sdk.Context,
portID,
channelID string,
chanCap capability.Capability,
) error {
// TODO: blocked by #5542
// capkey, found := k.GetChannelCapability(ctx, portID, channelID)
// if !found {
// return sdkerrors.Wrap(types.ErrChannelCapabilityNotFound, channelID)
// }

// key := sdk.NewKVStoreKey(capkey)
// if !k.portKeeper.Authenticate(key, portID) {
// return sdkerrors.Wrap(port.ErrInvalidPort, portID)
// }
if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, ibctypes.ChannelCapabilityPath(portID, channelID)) {
return sdkerrors.Wrap(types.ErrChannelCapabilityNotFound, "caller does not own capability for channel")
}

channel, found := k.GetChannel(ctx, portID, channelID)
if !found {
Expand Down Expand Up @@ -341,19 +337,13 @@ func (k Keeper) ChanCloseConfirm(
ctx sdk.Context,
portID,
channelID string,
chanCap capability.Capability,
proofInit commitmentexported.Proof,
proofHeight uint64,
) error {
// TODO: blocked by #5542
// capkey, found := k.GetChannelCapability(ctx, portID, channelID)
// if !found {
// return sdkerrors.Wrap(types.ErrChannelCapabilityNotFound, channelID)
// }

// key := sdk.NewKVStoreKey(capkey)
// if !k.portKeeper.Authenticate(key, portID) {
// return sdkerrors.Wrap(port.ErrInvalidPort, portID)
// }
if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, ibctypes.ChannelCapabilityPath(portID, channelID)) {
return sdkerrors.Wrap(types.ErrChannelCapabilityNotFound, "caller does not own capability for channel")
}

channel, found := k.GetChannel(ctx, portID, channelID)
if !found {
Expand Down
Loading