Refactor x/ibc to ADR 031 (#7576)
* WIP: Refactor x/ibc to ADR 031 * updated handler * removed unsued * fix * Add proto service for ibc/transfer * lint * remove old upgrade handler * added doc * review changes * fix tests * formatter * Add MsgServer wiring in RegisterServices Co-authored-by: Aaron Craelius <aaronc@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
parent
eba4c8a264
commit
155a6ad7fd
|
@ -7,6 +7,12 @@ import "gogoproto/gogo.proto";
|
|||
import "cosmos/base/v1beta1/coin.proto";
|
||||
import "ibc/core/client/v1/client.proto";
|
||||
|
||||
// Msg defines the ibc/transfer Msg service.
|
||||
service Msg {
|
||||
// Transfer defines a rpc handler method for MsgTransfer.
|
||||
rpc Transfer(MsgTransfer) returns (MsgTransferResponse);
|
||||
}
|
||||
|
||||
// MsgTransfer defines a msg to transfer fungible tokens (i.e Coins) between
|
||||
// ICS20 enabled chains. See ICS Spec here:
|
||||
// https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures
|
||||
|
@ -33,6 +39,9 @@ message MsgTransfer {
|
|||
uint64 timeout_timestamp = 7 [(gogoproto.moretags) = "yaml:\"timeout_timestamp\""];
|
||||
}
|
||||
|
||||
// MsgTransferResponse defines the Msg/Transfer response type.
|
||||
message MsgTransferResponse { }
|
||||
|
||||
// FungibleTokenPacketData defines a struct for the packet payload
|
||||
// See FungibleTokenPacketData spec:
|
||||
// https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures
|
||||
|
|
|
@ -6,6 +6,39 @@ option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types";
|
|||
import "gogoproto/gogo.proto";
|
||||
import "ibc/core/client/v1/client.proto";
|
||||
|
||||
// Msg defines the ibc/channel Msg service.
|
||||
service Msg {
|
||||
// ChannelOpenInit defines a rpc handler method for MsgChannelOpenInit.
|
||||
rpc ChannelOpenInit(MsgChannelOpenInit) returns (MsgChannelOpenInitResponse);
|
||||
|
||||
// ChannelOpenTry defines a rpc handler method for MsgChannelOpenTry.
|
||||
rpc ChannelOpenTry(MsgChannelOpenTry) returns (MsgChannelOpenTryResponse);
|
||||
|
||||
// ChannelOpenAck defines a rpc handler method for MsgChannelOpenAck.
|
||||
rpc ChannelOpenAck(MsgChannelOpenAck) returns (MsgChannelOpenAckResponse);
|
||||
|
||||
// ChannelOpenConfirm defines a rpc handler method for MsgChannelOpenConfirm.
|
||||
rpc ChannelOpenConfirm(MsgChannelOpenConfirm) returns (MsgChannelOpenConfirmResponse);
|
||||
|
||||
// ChannelCloseInit defines a rpc handler method for MsgChannelCloseInit.
|
||||
rpc ChannelCloseInit(MsgChannelCloseInit) returns (MsgChannelCloseInitResponse);
|
||||
|
||||
// ChannelCloseConfirm defines a rpc handler method for MsgChannelCloseConfirm.
|
||||
rpc ChannelCloseConfirm(MsgChannelCloseConfirm) returns (MsgChannelCloseConfirmResponse);
|
||||
|
||||
// RecvPacket defines a rpc handler method for MsgRecvPacket.
|
||||
rpc RecvPacket(MsgRecvPacket) returns (MsgRecvPacketResponse);
|
||||
|
||||
// Timeout defines a rpc handler method for MsgTimeout.
|
||||
rpc Timeout(MsgTimeout) returns (MsgTimeoutResponse);
|
||||
|
||||
// TimeoutOnClose defines a rpc handler method for MsgTimeoutOnClose.
|
||||
rpc TimeoutOnClose(MsgTimeoutOnClose) returns (MsgTimeoutOnCloseResponse);
|
||||
|
||||
// Acknowledgement defines a rpc handler method for MsgAcknowledgement.
|
||||
rpc Acknowledgement(MsgAcknowledgement) returns (MsgAcknowledgementResponse);
|
||||
}
|
||||
|
||||
// MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It
|
||||
// is called by a relayer on Chain A.
|
||||
message MsgChannelOpenInit {
|
||||
|
@ -18,7 +51,10 @@ message MsgChannelOpenInit {
|
|||
string signer = 4;
|
||||
}
|
||||
|
||||
// MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel
|
||||
// MsgChannelOpenInitResponse defines the Msg/ChannelOpenInit response type.
|
||||
message MsgChannelOpenInitResponse {}
|
||||
|
||||
// MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel
|
||||
// on Chain B.
|
||||
message MsgChannelOpenTry {
|
||||
option (gogoproto.equal) = false;
|
||||
|
@ -35,6 +71,9 @@ message MsgChannelOpenTry {
|
|||
string signer = 8;
|
||||
}
|
||||
|
||||
// MsgChannelOpenTryResponse defines the Msg/ChannelOpenTry response type.
|
||||
message MsgChannelOpenTryResponse {}
|
||||
|
||||
// MsgChannelOpenAck defines a msg sent by a Relayer to Chain A to acknowledge
|
||||
// the change of channel state to TRYOPEN on Chain B.
|
||||
message MsgChannelOpenAck {
|
||||
|
@ -51,6 +90,9 @@ message MsgChannelOpenAck {
|
|||
string signer = 7;
|
||||
}
|
||||
|
||||
// MsgChannelOpenAckResponse defines the Msg/ChannelOpenAck response type.
|
||||
message MsgChannelOpenAckResponse {}
|
||||
|
||||
// MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain B to
|
||||
// acknowledge the change of channel state to OPEN on Chain A.
|
||||
message MsgChannelOpenConfirm {
|
||||
|
@ -65,6 +107,9 @@ message MsgChannelOpenConfirm {
|
|||
string signer = 5;
|
||||
}
|
||||
|
||||
// MsgChannelOpenConfirmResponse defines the Msg/ChannelOpenConfirm response type.
|
||||
message MsgChannelOpenConfirmResponse {}
|
||||
|
||||
// MsgChannelCloseInit defines a msg sent by a Relayer to Chain A
|
||||
// to close a channel with Chain B.
|
||||
message MsgChannelCloseInit {
|
||||
|
@ -76,6 +121,9 @@ message MsgChannelCloseInit {
|
|||
string signer = 3;
|
||||
}
|
||||
|
||||
// MsgChannelCloseInitResponse defines the Msg/ChannelCloseInit response type.
|
||||
message MsgChannelCloseInitResponse {}
|
||||
|
||||
// MsgChannelCloseConfirm defines a msg sent by a Relayer to Chain B
|
||||
// to acknowledge the change of channel state to CLOSED on Chain A.
|
||||
message MsgChannelCloseConfirm {
|
||||
|
@ -90,6 +138,9 @@ message MsgChannelCloseConfirm {
|
|||
string signer = 5;
|
||||
}
|
||||
|
||||
// MsgChannelCloseConfirmResponse defines the Msg/ChannelCloseConfirm response type.
|
||||
message MsgChannelCloseConfirmResponse {}
|
||||
|
||||
// MsgRecvPacket receives incoming IBC packet
|
||||
message MsgRecvPacket {
|
||||
option (gogoproto.equal) = false;
|
||||
|
@ -102,6 +153,9 @@ message MsgRecvPacket {
|
|||
string signer = 4;
|
||||
}
|
||||
|
||||
// MsgRecvPacketResponse defines the Msg/RecvPacket response type.
|
||||
message MsgRecvPacketResponse {}
|
||||
|
||||
// MsgTimeout receives timed-out packet
|
||||
message MsgTimeout {
|
||||
option (gogoproto.equal) = false;
|
||||
|
@ -115,6 +169,9 @@ message MsgTimeout {
|
|||
string signer = 5;
|
||||
}
|
||||
|
||||
// MsgTimeoutResponse defines the Msg/Timeout response type.
|
||||
message MsgTimeoutResponse {}
|
||||
|
||||
// MsgTimeoutOnClose timed-out packet upon counterparty channel closure.
|
||||
message MsgTimeoutOnClose {
|
||||
option (gogoproto.equal) = false;
|
||||
|
@ -129,6 +186,9 @@ message MsgTimeoutOnClose {
|
|||
string signer = 6;
|
||||
}
|
||||
|
||||
// MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type.
|
||||
message MsgTimeoutOnCloseResponse {}
|
||||
|
||||
// MsgAcknowledgement receives incoming IBC acknowledgement
|
||||
message MsgAcknowledgement {
|
||||
option (gogoproto.equal) = false;
|
||||
|
@ -142,6 +202,9 @@ message MsgAcknowledgement {
|
|||
string signer = 5;
|
||||
}
|
||||
|
||||
// MsgAcknowledgementResponse defines the Msg/Acknowledgement response type.
|
||||
message MsgAcknowledgementResponse {}
|
||||
|
||||
// Channel defines pipeline for exactly-once packet delivery between specific
|
||||
// modules on separate blockchains, which has at least one end capable of
|
||||
// sending packets and one end capable of receiving packets.
|
||||
|
|
|
@ -6,6 +6,91 @@ option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types";
|
|||
import "gogoproto/gogo.proto";
|
||||
import "google/protobuf/any.proto";
|
||||
|
||||
// Msg defines the ibc/client Msg service.
|
||||
service Msg {
|
||||
// CreateClient defines a rpc handler method for MsgCreateClient.
|
||||
rpc CreateClient(MsgCreateClient) returns (MsgCreateClientResponse);
|
||||
|
||||
// UpdateClient defines a rpc handler method for MsgUpdateClient.
|
||||
rpc UpdateClient(MsgUpdateClient) returns (MsgUpdateClientResponse);
|
||||
|
||||
// UpgradeClient defines a rpc handler method for MsgUpgradeClient.
|
||||
rpc UpgradeClient(MsgUpgradeClient) returns (MsgUpgradeClientResponse);
|
||||
|
||||
// SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour.
|
||||
rpc SubmitMisbehaviour(MsgSubmitMisbehaviour) returns (MsgSubmitMisbehaviourResponse);
|
||||
}
|
||||
|
||||
// MsgCreateClient defines a message to create an IBC client
|
||||
message MsgCreateClient {
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// client unique identifier
|
||||
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
|
||||
// light client state
|
||||
google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""];
|
||||
// consensus state associated with the client that corresponds to a given
|
||||
// height.
|
||||
google.protobuf.Any consensus_state = 3 [(gogoproto.moretags) = "yaml:\"consensus_state\""];
|
||||
// signer address
|
||||
string signer = 4;
|
||||
}
|
||||
|
||||
// MsgCreateClientResponse defines the Msg/CreateClient response type.
|
||||
message MsgCreateClientResponse { }
|
||||
|
||||
// MsgUpdateClient defines an sdk.Msg to update a IBC client state using
|
||||
// the given header.
|
||||
message MsgUpdateClient {
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// client unique identifier
|
||||
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
|
||||
// header to update the light client
|
||||
google.protobuf.Any header = 2;
|
||||
// signer address
|
||||
string signer = 3;
|
||||
}
|
||||
|
||||
// MsgUpdateClientResponse defines the Msg/UpdateClient response type.
|
||||
message MsgUpdateClientResponse { }
|
||||
|
||||
// MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state
|
||||
message MsgUpgradeClient {
|
||||
// client unique identifier
|
||||
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
|
||||
// upgraded client state
|
||||
google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""];
|
||||
// height at which old chain halts and upgrades (i.e last block executed)
|
||||
Height upgrade_height = 3 [(gogoproto.moretags) = "yaml:\"upgrade_height\""];
|
||||
// proof that old chain committed to new client
|
||||
bytes proof_upgrade = 4 [(gogoproto.moretags) = "yaml:\"proof_upgrade\""];
|
||||
// signer address
|
||||
string signer = 5;
|
||||
}
|
||||
|
||||
// MsgUpgradeClientResponse defines the Msg/UpgradeClient response type.
|
||||
message MsgUpgradeClientResponse { }
|
||||
|
||||
// MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for
|
||||
// light client misbehaviour.
|
||||
message MsgSubmitMisbehaviour {
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// client unique identifier
|
||||
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
|
||||
// misbehaviour used for freezing the light client
|
||||
google.protobuf.Any misbehaviour = 2;
|
||||
// signer address
|
||||
string signer = 3;
|
||||
}
|
||||
|
||||
// MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type.
|
||||
message MsgSubmitMisbehaviourResponse { }
|
||||
|
||||
// IdentifiedClientState defines a client state with an additional client
|
||||
// identifier field.
|
||||
message IdentifiedClientState {
|
||||
|
@ -48,64 +133,6 @@ message ClientUpdateProposal {
|
|||
google.protobuf.Any header = 4;
|
||||
}
|
||||
|
||||
// MsgCreateClient defines a message to create an IBC client
|
||||
message MsgCreateClient {
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// client unique identifier
|
||||
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
|
||||
// light client state
|
||||
google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""];
|
||||
// consensus state associated with the client that corresponds to a given
|
||||
// height.
|
||||
google.protobuf.Any consensus_state = 3 [(gogoproto.moretags) = "yaml:\"consensus_state\""];
|
||||
// signer address
|
||||
string signer = 4;
|
||||
}
|
||||
|
||||
// MsgUpdateClient defines an sdk.Msg to update a IBC client state using
|
||||
// the given header.
|
||||
message MsgUpdateClient {
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// client unique identifier
|
||||
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
|
||||
// header to update the light client
|
||||
google.protobuf.Any header = 2;
|
||||
// signer address
|
||||
string signer = 3;
|
||||
}
|
||||
|
||||
// MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state
|
||||
message MsgUpgradeClient {
|
||||
// client unique identifier
|
||||
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
|
||||
// upgraded client state
|
||||
google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""];
|
||||
// height at which old chain halts and upgrades (i.e last block executed)
|
||||
Height upgrade_height = 3 [(gogoproto.moretags) = "yaml:\"upgrade_height\""];
|
||||
// proof that old chain committed to new client
|
||||
bytes proof_upgrade = 4 [(gogoproto.moretags) = "yaml:\"proof_upgrade\""];
|
||||
// signer address
|
||||
string signer = 5;
|
||||
}
|
||||
|
||||
// MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for
|
||||
// light client misbehaviour.
|
||||
message MsgSubmitMisbehaviour {
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// client unique identifier
|
||||
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
|
||||
// misbehaviour used for freezing the light client
|
||||
google.protobuf.Any misbehaviour = 2;
|
||||
// signer address
|
||||
string signer = 3;
|
||||
}
|
||||
|
||||
// Height is a monotonically increasing data type
|
||||
// that can be compared against another Height for the purposes of updating and
|
||||
// freezing clients
|
||||
|
|
|
@ -8,6 +8,21 @@ import "google/protobuf/any.proto";
|
|||
import "ibc/core/commitment/v1/commitment.proto";
|
||||
import "ibc/core/client/v1/client.proto";
|
||||
|
||||
// Msg defines the ibc/connection Msg service.
|
||||
service Msg {
|
||||
// ConnectionOpenInit defines a rpc handler method for MsgConnectionOpenInit.
|
||||
rpc ConnectionOpenInit(MsgConnectionOpenInit) returns (MsgConnectionOpenInitResponse);
|
||||
|
||||
// ConnectionOpenTry defines a rpc handler method for MsgConnectionOpenTry.
|
||||
rpc ConnectionOpenTry(MsgConnectionOpenTry) returns (MsgConnectionOpenTryResponse);
|
||||
|
||||
// ConnectionOpenAck defines a rpc handler method for MsgConnectionOpenAck.
|
||||
rpc ConnectionOpenAck(MsgConnectionOpenAck) returns (MsgConnectionOpenAckResponse);
|
||||
|
||||
// ConnectionOpenConfirm defines a rpc handler method for MsgConnectionOpenConfirm.
|
||||
rpc ConnectionOpenConfirm(MsgConnectionOpenConfirm) returns (MsgConnectionOpenConfirmResponse);
|
||||
}
|
||||
|
||||
// MsgConnectionOpenInit defines the msg sent by an account on Chain A to
|
||||
// initialize a connection with Chain B.
|
||||
message MsgConnectionOpenInit {
|
||||
|
@ -21,6 +36,9 @@ message MsgConnectionOpenInit {
|
|||
string signer = 5;
|
||||
}
|
||||
|
||||
// MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response type.
|
||||
message MsgConnectionOpenInitResponse { }
|
||||
|
||||
// MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a
|
||||
// connection on Chain B.
|
||||
message MsgConnectionOpenTry {
|
||||
|
@ -47,6 +65,9 @@ message MsgConnectionOpenTry {
|
|||
string signer = 12;
|
||||
}
|
||||
|
||||
// MsgConnectionOpenTryResponse defines the Msg/ConnectionOpenTry response type.
|
||||
message MsgConnectionOpenTryResponse { }
|
||||
|
||||
// MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to
|
||||
// acknowledge the change of connection state to TRYOPEN on Chain B.
|
||||
message MsgConnectionOpenAck {
|
||||
|
@ -71,6 +92,9 @@ message MsgConnectionOpenAck {
|
|||
string signer = 10;
|
||||
}
|
||||
|
||||
// MsgConnectionOpenAckResponse defines the Msg/ConnectionOpenAck response type.
|
||||
message MsgConnectionOpenAckResponse { }
|
||||
|
||||
// MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to
|
||||
// acknowledge the change of connection state to OPEN on Chain A.
|
||||
message MsgConnectionOpenConfirm {
|
||||
|
@ -85,6 +109,9 @@ message MsgConnectionOpenConfirm {
|
|||
string signer = 4;
|
||||
}
|
||||
|
||||
// MsgConnectionOpenConfirmResponse defines the Msg/ConnectionOpenConfirm response type.
|
||||
message MsgConnectionOpenConfirmResponse { }
|
||||
|
||||
// ICS03 - Connection Data Structures as defined in
|
||||
// https://github.com/cosmos/ics/tree/master/spec/ics-003-connection-semantics#data-structures
|
||||
|
||||
|
|
|
@ -3,51 +3,21 @@ package transfer
|
|||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"
|
||||
)
|
||||
|
||||
// NewHandler returns sdk.Handler for IBC token transfer module messages
|
||||
func NewHandler(k keeper.Keeper) sdk.Handler {
|
||||
func NewHandler(k types.MsgServer) sdk.Handler {
|
||||
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
|
||||
ctx = ctx.WithEventManager(sdk.NewEventManager())
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case *types.MsgTransfer:
|
||||
return handleMsgTransfer(ctx, k, msg)
|
||||
res, err := k.Transfer(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
default:
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized ICS-20 transfer message type: %T", msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See createOutgoingPacket in spec:https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#packet-relay
|
||||
func handleMsgTransfer(ctx sdk.Context, k keeper.Keeper, msg *types.MsgTransfer) (*sdk.Result, error) {
|
||||
sender, err := sdk.AccAddressFromBech32(msg.Sender)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := k.SendTransfer(
|
||||
ctx, msg.SourcePort, msg.SourceChannel, msg.Token, sender, msg.Receiver, msg.TimeoutHeight, msg.TimeoutTimestamp,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
k.Logger(ctx).Info("IBC fungible token transfer", "token", msg.Token.Denom, "amount", msg.Token.Amount.String(), "sender", msg.Sender, "receiver", msg.Receiver)
|
||||
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
types.EventTypeTransfer,
|
||||
sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender),
|
||||
sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
|
||||
),
|
||||
})
|
||||
|
||||
return &sdk.Result{
|
||||
Events: ctx.EventManager().Events().ToABCIEvents(),
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"
|
||||
)
|
||||
|
||||
var _ types.MsgServer = Keeper{}
|
||||
|
||||
// See createOutgoingPacket in spec:https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#packet-relay
|
||||
|
||||
// Transfer defines a rpc handler method for MsgTransfer.
|
||||
func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
sender, err := sdk.AccAddressFromBech32(msg.Sender)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := k.SendTransfer(
|
||||
ctx, msg.SourcePort, msg.SourceChannel, msg.Token, sender, msg.Receiver, msg.TimeoutHeight, msg.TimeoutTimestamp,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
k.Logger(ctx).Info("IBC fungible token transfer", "token", msg.Token.Denom, "amount", msg.Token.Amount.String(), "sender", msg.Sender, "receiver", msg.Receiver)
|
||||
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
types.EventTypeTransfer,
|
||||
sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender),
|
||||
sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
|
||||
),
|
||||
})
|
||||
|
||||
return &types.MsgTransferResponse{}, nil
|
||||
}
|
|
@ -120,9 +120,9 @@ func (am AppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier {
|
|||
return nil
|
||||
}
|
||||
|
||||
// RegisterQueryService registers a GRPC query service to respond to the
|
||||
// module-specific GRPC queries.
|
||||
// RegisterServices registers module services.
|
||||
func (am AppModule) RegisterServices(cfg module.Configurator) {
|
||||
types.RegisterMsgServer(cfg.MsgServer(), am.keeper)
|
||||
types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,11 +4,16 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
types "github.com/cosmos/cosmos-sdk/types"
|
||||
grpc1 "github.com/gogo/protobuf/grpc"
|
||||
types1 "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
|
@ -80,6 +85,43 @@ func (m *MsgTransfer) XXX_DiscardUnknown() {
|
|||
|
||||
var xxx_messageInfo_MsgTransfer proto.InternalMessageInfo
|
||||
|
||||
// MsgTransferResponse defines the Msg/Transfer response type.
|
||||
type MsgTransferResponse struct {
|
||||
}
|
||||
|
||||
func (m *MsgTransferResponse) Reset() { *m = MsgTransferResponse{} }
|
||||
func (m *MsgTransferResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*MsgTransferResponse) ProtoMessage() {}
|
||||
func (*MsgTransferResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_5041673e96e97901, []int{1}
|
||||
}
|
||||
func (m *MsgTransferResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *MsgTransferResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_MsgTransferResponse.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 *MsgTransferResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_MsgTransferResponse.Merge(m, src)
|
||||
}
|
||||
func (m *MsgTransferResponse) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *MsgTransferResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_MsgTransferResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_MsgTransferResponse proto.InternalMessageInfo
|
||||
|
||||
// FungibleTokenPacketData defines a struct for the packet payload
|
||||
// See FungibleTokenPacketData spec:
|
||||
// https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures
|
||||
|
@ -98,7 +140,7 @@ func (m *FungibleTokenPacketData) Reset() { *m = FungibleTokenPacketData
|
|||
func (m *FungibleTokenPacketData) String() string { return proto.CompactTextString(m) }
|
||||
func (*FungibleTokenPacketData) ProtoMessage() {}
|
||||
func (*FungibleTokenPacketData) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_5041673e96e97901, []int{1}
|
||||
return fileDescriptor_5041673e96e97901, []int{2}
|
||||
}
|
||||
func (m *FungibleTokenPacketData) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
@ -169,7 +211,7 @@ func (m *DenomTrace) Reset() { *m = DenomTrace{} }
|
|||
func (m *DenomTrace) String() string { return proto.CompactTextString(m) }
|
||||
func (*DenomTrace) ProtoMessage() {}
|
||||
func (*DenomTrace) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_5041673e96e97901, []int{2}
|
||||
return fileDescriptor_5041673e96e97901, []int{3}
|
||||
}
|
||||
func (m *DenomTrace) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
@ -229,7 +271,7 @@ func (m *Params) Reset() { *m = Params{} }
|
|||
func (m *Params) String() string { return proto.CompactTextString(m) }
|
||||
func (*Params) ProtoMessage() {}
|
||||
func (*Params) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_5041673e96e97901, []int{3}
|
||||
return fileDescriptor_5041673e96e97901, []int{4}
|
||||
}
|
||||
func (m *Params) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
@ -274,6 +316,7 @@ func (m *Params) GetReceiveEnabled() bool {
|
|||
|
||||
func init() {
|
||||
proto.RegisterType((*MsgTransfer)(nil), "ibc.applications.transfer.v1.MsgTransfer")
|
||||
proto.RegisterType((*MsgTransferResponse)(nil), "ibc.applications.transfer.v1.MsgTransferResponse")
|
||||
proto.RegisterType((*FungibleTokenPacketData)(nil), "ibc.applications.transfer.v1.FungibleTokenPacketData")
|
||||
proto.RegisterType((*DenomTrace)(nil), "ibc.applications.transfer.v1.DenomTrace")
|
||||
proto.RegisterType((*Params)(nil), "ibc.applications.transfer.v1.Params")
|
||||
|
@ -284,45 +327,129 @@ func init() {
|
|||
}
|
||||
|
||||
var fileDescriptor_5041673e96e97901 = []byte{
|
||||
// 601 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x53, 0xcd, 0x6e, 0xd3, 0x4c,
|
||||
0x14, 0x8d, 0xdb, 0x34, 0x5f, 0x3b, 0xf9, 0x5a, 0x60, 0x28, 0xad, 0x1b, 0xb5, 0x76, 0xe5, 0x55,
|
||||
0x25, 0x84, 0xad, 0x80, 0x10, 0x52, 0x17, 0x80, 0xd2, 0x82, 0x60, 0x81, 0x54, 0x59, 0x59, 0x20,
|
||||
0x36, 0x61, 0x3c, 0x19, 0x9c, 0x51, 0xed, 0x19, 0x6b, 0x66, 0x12, 0x51, 0xf1, 0x02, 0xb0, 0xe3,
|
||||
0x11, 0xba, 0xe6, 0x49, 0xba, 0xec, 0x92, 0x95, 0x85, 0xda, 0x0d, 0xeb, 0x3c, 0x01, 0x9a, 0x9f,
|
||||
0x86, 0x04, 0xa9, 0x2b, 0xcf, 0xb9, 0xf7, 0x9c, 0x7b, 0xe6, 0xde, 0xeb, 0x01, 0x0f, 0x69, 0x86,
|
||||
0x13, 0x54, 0x55, 0x05, 0xc5, 0x48, 0x51, 0xce, 0x64, 0xa2, 0x04, 0x62, 0xf2, 0x13, 0x11, 0xc9,
|
||||
0xa4, 0x3b, 0x3b, 0xc7, 0x95, 0xe0, 0x8a, 0xc3, 0x5d, 0x9a, 0xe1, 0x78, 0x9e, 0x1c, 0xcf, 0x08,
|
||||
0x93, 0x6e, 0x67, 0x33, 0xe7, 0x39, 0x37, 0xc4, 0x44, 0x9f, 0xac, 0xa6, 0x13, 0x60, 0x2e, 0x4b,
|
||||
0x2e, 0x93, 0x0c, 0x49, 0x92, 0x4c, 0xba, 0x19, 0x51, 0xa8, 0x9b, 0x60, 0x4e, 0x99, 0xcb, 0x87,
|
||||
0xfa, 0x02, 0x98, 0x0b, 0x92, 0xe0, 0x82, 0x12, 0xa6, 0xb4, 0xad, 0x3d, 0x59, 0x42, 0xf4, 0x63,
|
||||
0x19, 0xb4, 0xdf, 0xc9, 0xbc, 0xef, 0x9c, 0xe0, 0x33, 0xd0, 0x96, 0x7c, 0x2c, 0x30, 0x19, 0x54,
|
||||
0x5c, 0x28, 0xdf, 0xdb, 0xf7, 0x0e, 0xd6, 0x7a, 0x5b, 0xd3, 0x3a, 0x84, 0x67, 0xa8, 0x2c, 0x0e,
|
||||
0xa3, 0xb9, 0x64, 0x94, 0x02, 0x8b, 0x4e, 0xb8, 0x50, 0xf0, 0x25, 0xd8, 0x70, 0x39, 0x3c, 0x42,
|
||||
0x8c, 0x91, 0xc2, 0x5f, 0x32, 0xda, 0x9d, 0x69, 0x1d, 0x3e, 0x58, 0xd0, 0xba, 0x7c, 0x94, 0xae,
|
||||
0xdb, 0xc0, 0x91, 0xc5, 0xf0, 0x29, 0x58, 0x51, 0xfc, 0x94, 0x30, 0x7f, 0x79, 0xdf, 0x3b, 0x68,
|
||||
0x3f, 0xde, 0x89, 0x6d, 0x6f, 0xb1, 0xee, 0x2d, 0x76, 0xbd, 0xc5, 0x47, 0x9c, 0xb2, 0x5e, 0xf3,
|
||||
0xa2, 0x0e, 0x1b, 0xa9, 0x65, 0xc3, 0x2d, 0xd0, 0x92, 0x84, 0x0d, 0x89, 0xf0, 0x9b, 0xda, 0x30,
|
||||
0x75, 0x08, 0x76, 0xc0, 0xaa, 0x20, 0x98, 0xd0, 0x09, 0x11, 0xfe, 0x8a, 0xc9, 0xcc, 0x30, 0xfc,
|
||||
0x08, 0x36, 0x14, 0x2d, 0x09, 0x1f, 0xab, 0xc1, 0x88, 0xd0, 0x7c, 0xa4, 0xfc, 0x96, 0xf1, 0xec,
|
||||
0xc4, 0x7a, 0x07, 0x7a, 0x5e, 0xb1, 0x9b, 0xd2, 0xa4, 0x1b, 0xbf, 0x31, 0x8c, 0xde, 0x9e, 0x36,
|
||||
0xfd, 0xdb, 0xcc, 0xa2, 0x3e, 0x4a, 0xd7, 0x5d, 0xc0, 0xb2, 0xe1, 0x5b, 0x70, 0xef, 0x86, 0xa1,
|
||||
0xbf, 0x52, 0xa1, 0xb2, 0xf2, 0xff, 0xdb, 0xf7, 0x0e, 0x9a, 0xbd, 0xdd, 0x69, 0x1d, 0xfa, 0x8b,
|
||||
0x45, 0x66, 0x94, 0x28, 0xbd, 0xeb, 0x62, 0xfd, 0x9b, 0xd0, 0xe1, 0xea, 0xd7, 0xf3, 0xb0, 0xf1,
|
||||
0xfb, 0x3c, 0x6c, 0x44, 0x5f, 0xc0, 0xf6, 0xeb, 0x31, 0xcb, 0x69, 0x56, 0x90, 0xbe, 0xee, 0xfd,
|
||||
0x04, 0xe1, 0x53, 0xa2, 0x8e, 0x91, 0x42, 0x70, 0x13, 0xac, 0x0c, 0x09, 0xe3, 0xa5, 0xdd, 0x58,
|
||||
0x6a, 0x81, 0x9e, 0x0d, 0x2a, 0xf9, 0x98, 0x29, 0xb3, 0x8c, 0x66, 0xea, 0xd0, 0xdc, 0xcc, 0x96,
|
||||
0x6f, 0x9d, 0x59, 0x73, 0x71, 0x66, 0xd1, 0x0b, 0x00, 0x8e, 0x75, 0xd1, 0xbe, 0x40, 0x98, 0x40,
|
||||
0x08, 0x9a, 0x15, 0x52, 0x23, 0x67, 0x67, 0xce, 0x70, 0x0f, 0x00, 0xbd, 0xab, 0x81, 0xbd, 0x88,
|
||||
0x59, 0x7f, 0xba, 0xa6, 0x23, 0x46, 0x17, 0x7d, 0xf3, 0x40, 0xeb, 0x04, 0x09, 0x54, 0x4a, 0x78,
|
||||
0x08, 0xfe, 0xd7, 0x8e, 0x03, 0xc2, 0x50, 0x56, 0x90, 0xa1, 0xa9, 0xb2, 0xda, 0xdb, 0x9e, 0xd6,
|
||||
0xe1, 0x7d, 0xf7, 0xab, 0xcc, 0x65, 0xa3, 0xb4, 0xad, 0xe1, 0x2b, 0x8b, 0xe0, 0x11, 0xb8, 0xe3,
|
||||
0xee, 0x34, 0x93, 0x2f, 0x19, 0x79, 0x67, 0x5a, 0x87, 0x5b, 0x56, 0xfe, 0x0f, 0x21, 0x4a, 0x37,
|
||||
0x5c, 0xc4, 0x15, 0xe9, 0xbd, 0xbf, 0xb8, 0x0a, 0xbc, 0xcb, 0xab, 0xc0, 0xfb, 0x75, 0x15, 0x78,
|
||||
0xdf, 0xaf, 0x83, 0xc6, 0xe5, 0x75, 0xd0, 0xf8, 0x79, 0x1d, 0x34, 0x3e, 0x3c, 0xcf, 0xa9, 0x1a,
|
||||
0x8d, 0xb3, 0x18, 0xf3, 0x32, 0x71, 0x8f, 0xcb, 0x7e, 0x1e, 0xc9, 0xe1, 0x69, 0xf2, 0x39, 0xb9,
|
||||
0xfd, 0x45, 0xab, 0xb3, 0x8a, 0xc8, 0xac, 0x65, 0xde, 0xd5, 0x93, 0x3f, 0x01, 0x00, 0x00, 0xff,
|
||||
0xff, 0xed, 0xa5, 0xb5, 0x3a, 0xfb, 0x03, 0x00, 0x00,
|
||||
// 638 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xcd, 0x6e, 0xd3, 0x40,
|
||||
0x10, 0x8e, 0x9b, 0x34, 0xa4, 0x1b, 0x5a, 0x60, 0xfb, 0xe7, 0x46, 0xad, 0x5d, 0xf9, 0x54, 0x84,
|
||||
0x58, 0x2b, 0x45, 0x08, 0xa9, 0x07, 0x40, 0x69, 0x41, 0x70, 0xa8, 0x54, 0x59, 0x39, 0x20, 0x2e,
|
||||
0x61, 0xbd, 0x59, 0x1c, 0xab, 0xf1, 0xae, 0xe5, 0xdd, 0x44, 0x54, 0xbc, 0x00, 0xdc, 0x78, 0x84,
|
||||
0x9e, 0x79, 0x92, 0x1e, 0x7b, 0xe4, 0x14, 0xa1, 0xf6, 0xc2, 0x39, 0x4f, 0x80, 0xf6, 0xa7, 0xc1,
|
||||
0x41, 0x2a, 0xe2, 0xe4, 0xfd, 0x66, 0xbe, 0x6f, 0x66, 0x67, 0x66, 0xc7, 0xe0, 0x51, 0x1a, 0x93,
|
||||
0x10, 0xe7, 0xf9, 0x30, 0x25, 0x58, 0xa6, 0x9c, 0x89, 0x50, 0x16, 0x98, 0x89, 0x8f, 0xb4, 0x08,
|
||||
0xc7, 0xed, 0xd9, 0x19, 0xe5, 0x05, 0x97, 0x1c, 0x6e, 0xa7, 0x31, 0x41, 0x65, 0x32, 0x9a, 0x11,
|
||||
0xc6, 0xed, 0xd6, 0x5a, 0xc2, 0x13, 0xae, 0x89, 0xa1, 0x3a, 0x19, 0x4d, 0xcb, 0x23, 0x5c, 0x64,
|
||||
0x5c, 0x84, 0x31, 0x16, 0x34, 0x1c, 0xb7, 0x63, 0x2a, 0x71, 0x3b, 0x24, 0x3c, 0x65, 0xd6, 0xef,
|
||||
0xab, 0x0b, 0x10, 0x5e, 0xd0, 0x90, 0x0c, 0x53, 0xca, 0xa4, 0x4a, 0x6b, 0x4e, 0x86, 0x10, 0x7c,
|
||||
0xaf, 0x82, 0xe6, 0xb1, 0x48, 0xba, 0x36, 0x13, 0x7c, 0x06, 0x9a, 0x82, 0x8f, 0x0a, 0x42, 0x7b,
|
||||
0x39, 0x2f, 0xa4, 0xeb, 0xec, 0x3a, 0x7b, 0x4b, 0x9d, 0x8d, 0xe9, 0xc4, 0x87, 0x67, 0x38, 0x1b,
|
||||
0x1e, 0x04, 0x25, 0x67, 0x10, 0x01, 0x83, 0x4e, 0x78, 0x21, 0xe1, 0x4b, 0xb0, 0x62, 0x7d, 0x64,
|
||||
0x80, 0x19, 0xa3, 0x43, 0x77, 0x41, 0x6b, 0xb7, 0xa6, 0x13, 0x7f, 0x7d, 0x4e, 0x6b, 0xfd, 0x41,
|
||||
0xb4, 0x6c, 0x0c, 0x87, 0x06, 0xc3, 0xa7, 0x60, 0x51, 0xf2, 0x53, 0xca, 0xdc, 0xea, 0xae, 0xb3,
|
||||
0xd7, 0xdc, 0xdf, 0x42, 0xa6, 0x36, 0xa4, 0x6a, 0x43, 0xb6, 0x36, 0x74, 0xc8, 0x53, 0xd6, 0xa9,
|
||||
0x5d, 0x4c, 0xfc, 0x4a, 0x64, 0xd8, 0x70, 0x03, 0xd4, 0x05, 0x65, 0x7d, 0x5a, 0xb8, 0x35, 0x95,
|
||||
0x30, 0xb2, 0x08, 0xb6, 0x40, 0xa3, 0xa0, 0x84, 0xa6, 0x63, 0x5a, 0xb8, 0x8b, 0xda, 0x33, 0xc3,
|
||||
0xf0, 0x03, 0x58, 0x91, 0x69, 0x46, 0xf9, 0x48, 0xf6, 0x06, 0x34, 0x4d, 0x06, 0xd2, 0xad, 0xeb,
|
||||
0x9c, 0x2d, 0xa4, 0x66, 0xa0, 0xfa, 0x85, 0x6c, 0x97, 0xc6, 0x6d, 0xf4, 0x46, 0x33, 0x3a, 0x3b,
|
||||
0x2a, 0xe9, 0x9f, 0x62, 0xe6, 0xf5, 0x41, 0xb4, 0x6c, 0x0d, 0x86, 0x0d, 0xdf, 0x82, 0x07, 0x37,
|
||||
0x0c, 0xf5, 0x15, 0x12, 0x67, 0xb9, 0x7b, 0x67, 0xd7, 0xd9, 0xab, 0x75, 0xb6, 0xa7, 0x13, 0xdf,
|
||||
0x9d, 0x0f, 0x32, 0xa3, 0x04, 0xd1, 0x7d, 0x6b, 0xeb, 0xde, 0x98, 0x0e, 0x1a, 0x5f, 0xce, 0xfd,
|
||||
0xca, 0xaf, 0x73, 0xbf, 0x12, 0xac, 0x83, 0xd5, 0xd2, 0xac, 0x22, 0x2a, 0x72, 0xce, 0x04, 0x0d,
|
||||
0x3e, 0x83, 0xcd, 0xd7, 0x23, 0x96, 0xa4, 0xf1, 0x90, 0x76, 0x55, 0x4b, 0x4e, 0x30, 0x39, 0xa5,
|
||||
0xf2, 0x08, 0x4b, 0x0c, 0xd7, 0xc0, 0x62, 0x9f, 0x32, 0x9e, 0x99, 0x41, 0x46, 0x06, 0xa8, 0x96,
|
||||
0xe1, 0x8c, 0x8f, 0x98, 0xd4, 0x33, 0xaa, 0x45, 0x16, 0x95, 0x5a, 0x59, 0xbd, 0xb5, 0x95, 0xb5,
|
||||
0xf9, 0x56, 0x06, 0x2f, 0x00, 0x38, 0x52, 0x41, 0xbb, 0x05, 0x26, 0x14, 0x42, 0x50, 0xcb, 0xb1,
|
||||
0x1c, 0xd8, 0x74, 0xfa, 0x0c, 0x77, 0x00, 0x50, 0x23, 0xec, 0x99, 0x8b, 0xe8, 0x57, 0x11, 0x2d,
|
||||
0x29, 0x8b, 0xd6, 0x05, 0x5f, 0x1d, 0x50, 0x3f, 0xc1, 0x05, 0xce, 0x04, 0x3c, 0x00, 0x77, 0x55,
|
||||
0xc6, 0x1e, 0x65, 0x38, 0x1e, 0xd2, 0xbe, 0x8e, 0xd2, 0xe8, 0x6c, 0x4e, 0x27, 0xfe, 0xaa, 0x7d,
|
||||
0x41, 0x25, 0x6f, 0x10, 0x35, 0x15, 0x7c, 0x65, 0x10, 0x3c, 0x04, 0xf7, 0xec, 0x9d, 0x66, 0xf2,
|
||||
0x05, 0x2d, 0x6f, 0x4d, 0x27, 0xfe, 0x86, 0x91, 0xff, 0x45, 0x08, 0xa2, 0x15, 0x6b, 0xb1, 0x41,
|
||||
0xf6, 0x39, 0xa8, 0x1e, 0x8b, 0x04, 0x0e, 0x40, 0x63, 0xb6, 0x10, 0x0f, 0xd1, 0xbf, 0xd6, 0x12,
|
||||
0x95, 0xe6, 0xd1, 0x6a, 0xff, 0x37, 0xf5, 0x66, 0x74, 0x9d, 0x77, 0x17, 0x57, 0x9e, 0x73, 0x79,
|
||||
0xe5, 0x39, 0x3f, 0xaf, 0x3c, 0xe7, 0xdb, 0xb5, 0x57, 0xb9, 0xbc, 0xf6, 0x2a, 0x3f, 0xae, 0xbd,
|
||||
0xca, 0xfb, 0xe7, 0x49, 0x2a, 0x07, 0xa3, 0x18, 0x11, 0x9e, 0x85, 0x76, 0xc9, 0xcd, 0xe7, 0xb1,
|
||||
0xe8, 0x9f, 0x86, 0x9f, 0xc2, 0xdb, 0xff, 0x2c, 0xf2, 0x2c, 0xa7, 0x22, 0xae, 0xeb, 0xfd, 0x7e,
|
||||
0xf2, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x34, 0x4e, 0x38, 0x40, 0x83, 0x04, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// MsgClient is the client API for Msg service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type MsgClient interface {
|
||||
// Transfer defines a rpc handler method for MsgTransfer.
|
||||
Transfer(ctx context.Context, in *MsgTransfer, opts ...grpc.CallOption) (*MsgTransferResponse, error)
|
||||
}
|
||||
|
||||
type msgClient struct {
|
||||
cc grpc1.ClientConn
|
||||
}
|
||||
|
||||
func NewMsgClient(cc grpc1.ClientConn) MsgClient {
|
||||
return &msgClient{cc}
|
||||
}
|
||||
|
||||
func (c *msgClient) Transfer(ctx context.Context, in *MsgTransfer, opts ...grpc.CallOption) (*MsgTransferResponse, error) {
|
||||
out := new(MsgTransferResponse)
|
||||
err := c.cc.Invoke(ctx, "/ibc.applications.transfer.v1.Msg/Transfer", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// MsgServer is the server API for Msg service.
|
||||
type MsgServer interface {
|
||||
// Transfer defines a rpc handler method for MsgTransfer.
|
||||
Transfer(context.Context, *MsgTransfer) (*MsgTransferResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedMsgServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedMsgServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedMsgServer) Transfer(ctx context.Context, req *MsgTransfer) (*MsgTransferResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Transfer not implemented")
|
||||
}
|
||||
|
||||
func RegisterMsgServer(s grpc1.Server, srv MsgServer) {
|
||||
s.RegisterService(&_Msg_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Msg_Transfer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(MsgTransfer)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MsgServer).Transfer(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/ibc.applications.transfer.v1.Msg/Transfer",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MsgServer).Transfer(ctx, req.(*MsgTransfer))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Msg_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "ibc.applications.transfer.v1.Msg",
|
||||
HandlerType: (*MsgServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Transfer",
|
||||
Handler: _Msg_Transfer_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "ibc/applications/transfer/v1/transfer.proto",
|
||||
}
|
||||
|
||||
func (m *MsgTransfer) Marshal() (dAtA []byte, err error) {
|
||||
|
@ -401,6 +528,29 @@ func (m *MsgTransfer) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *MsgTransferResponse) 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 *MsgTransferResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *MsgTransferResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *FungibleTokenPacketData) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
|
@ -573,6 +723,15 @@ func (m *MsgTransfer) Size() (n int) {
|
|||
return n
|
||||
}
|
||||
|
||||
func (m *MsgTransferResponse) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *FungibleTokenPacketData) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
|
@ -901,6 +1060,59 @@ func (m *MsgTransfer) Unmarshal(dAtA []byte) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
func (m *MsgTransferResponse) 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 ErrIntOverflowTransfer
|
||||
}
|
||||
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: MsgTransferResponse: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: MsgTransferResponse: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipTransfer(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthTransfer
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthTransfer
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *FungibleTokenPacketData) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
|
|
|
@ -1,132 +0,0 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
|
||||
)
|
||||
|
||||
// HandleMsgCreateClient defines the sdk.Handler for MsgCreateClient
|
||||
func HandleMsgCreateClient(ctx sdk.Context, k keeper.Keeper, msg *types.MsgCreateClient) (*sdk.Result, error) {
|
||||
clientState, err := types.UnpackClientState(msg.ClientState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
consensusState, err := types.UnpackConsensusState(msg.ConsensusState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = k.CreateClient(ctx, msg.ClientId, clientState, consensusState); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
types.EventTypeCreateClient,
|
||||
sdk.NewAttribute(types.AttributeKeyClientID, msg.ClientId),
|
||||
sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()),
|
||||
sdk.NewAttribute(types.AttributeKeyConsensusHeight, clientState.GetLatestHeight().String()),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
|
||||
),
|
||||
})
|
||||
|
||||
return &sdk.Result{
|
||||
Events: ctx.EventManager().Events().ToABCIEvents(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// HandleMsgUpdateClient defines the sdk.Handler for MsgUpdateClient
|
||||
func HandleMsgUpdateClient(ctx sdk.Context, k keeper.Keeper, msg *types.MsgUpdateClient) (*sdk.Result, error) {
|
||||
header, err := types.UnpackHeader(msg.Header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = k.UpdateClient(ctx, msg.ClientId, header); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx.EventManager().EmitEvent(
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
|
||||
),
|
||||
)
|
||||
|
||||
return &sdk.Result{
|
||||
Events: ctx.EventManager().Events().ToABCIEvents(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// HandleMsgUpgradeClient defines the sdk.Handler for MsgUpgradeClient
|
||||
func HandleMsgUpgradeClient(ctx sdk.Context, k keeper.Keeper, msg *types.MsgUpgradeClient) (*sdk.Result, error) {
|
||||
upgradedClient, err := types.UnpackClientState(msg.ClientState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := upgradedClient.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = k.UpgradeClient(ctx, msg.ClientId, upgradedClient, msg.UpgradeHeight, msg.ProofUpgrade); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx.EventManager().EmitEvent(
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
|
||||
),
|
||||
)
|
||||
|
||||
return &sdk.Result{
|
||||
Events: ctx.EventManager().Events().ToABCIEvents(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// HandleMsgSubmitMisbehaviour defines the Evidence module handler for submitting a
|
||||
// light client misbehaviour.
|
||||
func HandleMsgSubmitMisbehaviour(ctx sdk.Context, k keeper.Keeper, msg *types.MsgSubmitMisbehaviour) (*sdk.Result, error) {
|
||||
misbehaviour, err := types.UnpackMisbehaviour(msg.Misbehaviour)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := k.CheckMisbehaviourAndUpdateState(ctx, misbehaviour); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "failed to process misbehaviour for IBC client")
|
||||
}
|
||||
|
||||
ctx.EventManager().EmitEvent(
|
||||
sdk.NewEvent(
|
||||
types.EventTypeSubmitMisbehaviour,
|
||||
sdk.NewAttribute(types.AttributeKeyClientID, msg.ClientId),
|
||||
sdk.NewAttribute(types.AttributeKeyClientType, misbehaviour.ClientType()),
|
||||
sdk.NewAttribute(types.AttributeKeyConsensusHeight, misbehaviour.GetHeight().String()),
|
||||
),
|
||||
)
|
||||
|
||||
return &sdk.Result{
|
||||
Events: ctx.EventManager().Events().ToABCIEvents(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewClientUpdateProposalHandler defines the client update proposal handler
|
||||
func NewClientUpdateProposalHandler(k keeper.Keeper) govtypes.Handler {
|
||||
return func(ctx sdk.Context, content govtypes.Content) error {
|
||||
switch c := content.(type) {
|
||||
case *types.ClientUpdateProposal:
|
||||
return k.ClientUpdateProposal(ctx, c)
|
||||
|
||||
default:
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized ibc proposal content type: %T", c)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,220 +0,0 @@
|
|||
package client_test
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
client "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
|
||||
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
|
||||
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/core/exported"
|
||||
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types"
|
||||
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
|
||||
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
|
||||
)
|
||||
|
||||
func (suite *ClientTestSuite) TestNewClientUpdateProposalHandler() {
|
||||
var (
|
||||
content govtypes.Content
|
||||
err error
|
||||
)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"valid update client proposal", func() {
|
||||
clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint)
|
||||
clientState := suite.chainA.GetClientState(clientA)
|
||||
|
||||
tmClientState, ok := clientState.(*ibctmtypes.ClientState)
|
||||
suite.Require().True(ok)
|
||||
tmClientState.AllowUpdateAfterMisbehaviour = true
|
||||
tmClientState.FrozenHeight = tmClientState.LatestHeight
|
||||
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientA, tmClientState)
|
||||
|
||||
// use next header for chainB to update the client on chainA
|
||||
header, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientA)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, clientA, header)
|
||||
suite.Require().NoError(err)
|
||||
}, true,
|
||||
},
|
||||
{
|
||||
"nil proposal", func() {
|
||||
content = nil
|
||||
}, false,
|
||||
},
|
||||
{
|
||||
"unsupported proposal type", func() {
|
||||
content = distributiontypes.NewCommunityPoolSpendProposal(ibctesting.Title, ibctesting.Description, suite.chainA.SenderAccount.GetAddress(), sdk.NewCoins(sdk.NewCoin("communityfunds", sdk.NewInt(10))))
|
||||
}, false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
|
||||
tc.malleate()
|
||||
|
||||
proposalHandler := client.NewClientUpdateProposalHandler(suite.chainA.App.IBCKeeper.ClientKeeper)
|
||||
|
||||
err = proposalHandler(suite.chainA.GetContext(), content)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (suite *ClientTestSuite) TestUpgradeClient() {
|
||||
var (
|
||||
clientA string
|
||||
upgradedClient exported.ClientState
|
||||
upgradeHeight exported.Height
|
||||
msg *clienttypes.MsgUpgradeClient
|
||||
)
|
||||
|
||||
newClientHeight := clienttypes.NewHeight(1, 1)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
setup func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
name: "successful upgrade",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, ibctesting.DefaultConsensusParams, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
suite.coordinator.CommitBlock(suite.chainB)
|
||||
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
|
||||
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradeHeight, proofUpgrade, suite.chainA.SenderAccount.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
},
|
||||
expPass: true,
|
||||
},
|
||||
{
|
||||
name: "invalid upgrade: msg.ClientState does not contain valid clientstate",
|
||||
setup: func() {
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
proofUpgrade, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
|
||||
consState := ibctmtypes.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("app_hash")), []byte("next_vals_hash"))
|
||||
consAny, err := clienttypes.PackConsensusState(consState)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
height, _ := upgradeHeight.(types.Height)
|
||||
|
||||
msg = &types.MsgUpgradeClient{ClientId: clientA, ClientState: consAny, UpgradeHeight: &height, ProofUpgrade: proofUpgrade, Signer: suite.chainA.SenderAccount.GetAddress().String()}
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "invalid clientstate",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, ibctesting.DefaultConsensusParams, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
suite.coordinator.CommitBlock(suite.chainB)
|
||||
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
|
||||
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradeHeight, proofUpgrade, suite.chainA.SenderAccount.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "VerifyUpgrade fails",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, ibctesting.DefaultConsensusParams, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
suite.coordinator.CommitBlock(suite.chainB)
|
||||
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradeHeight, nil, suite.chainA.SenderAccount.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
clientA, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint)
|
||||
|
||||
tc.setup()
|
||||
|
||||
_, err := client.HandleMsgUpgradeClient(
|
||||
suite.chainA.GetContext(), suite.chainA.App.IBCKeeper.ClientKeeper, msg,
|
||||
)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err, "upgrade handler failed on valid case: %s", tc.name)
|
||||
newClient, ok := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(ok)
|
||||
suite.Require().Equal(upgradedClient, newClient)
|
||||
} else {
|
||||
suite.Require().Error(err, "upgrade handler passed on invalid case: %s", tc.name)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
|
||||
)
|
||||
|
||||
// NewClientUpdateProposalHandler defines the client update proposal handler
|
||||
func NewClientUpdateProposalHandler(k keeper.Keeper) govtypes.Handler {
|
||||
return func(ctx sdk.Context, content govtypes.Content) error {
|
||||
switch c := content.(type) {
|
||||
case *types.ClientUpdateProposal:
|
||||
return k.ClientUpdateProposal(ctx, c)
|
||||
|
||||
default:
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized ibc proposal content type: %T", c)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package client_test
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
client "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client"
|
||||
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
|
||||
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types"
|
||||
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
|
||||
)
|
||||
|
||||
func (suite *ClientTestSuite) TestNewClientUpdateProposalHandler() {
|
||||
var (
|
||||
content govtypes.Content
|
||||
err error
|
||||
)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"valid update client proposal", func() {
|
||||
clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint)
|
||||
clientState := suite.chainA.GetClientState(clientA)
|
||||
|
||||
tmClientState, ok := clientState.(*ibctmtypes.ClientState)
|
||||
suite.Require().True(ok)
|
||||
tmClientState.AllowUpdateAfterMisbehaviour = true
|
||||
tmClientState.FrozenHeight = tmClientState.LatestHeight
|
||||
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientA, tmClientState)
|
||||
|
||||
// use next header for chainB to update the client on chainA
|
||||
header, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientA)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, clientA, header)
|
||||
suite.Require().NoError(err)
|
||||
}, true,
|
||||
},
|
||||
{
|
||||
"nil proposal", func() {
|
||||
content = nil
|
||||
}, false,
|
||||
},
|
||||
{
|
||||
"unsupported proposal type", func() {
|
||||
content = distributiontypes.NewCommunityPoolSpendProposal(ibctesting.Title, ibctesting.Description, suite.chainA.SenderAccount.GetAddress(), sdk.NewCoins(sdk.NewCoin("communityfunds", sdk.NewInt(10))))
|
||||
}, false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
|
||||
tc.malleate()
|
||||
|
||||
proposalHandler := client.NewClientUpdateProposalHandler(suite.chainA.App.IBCKeeper.ClientKeeper)
|
||||
|
||||
err = proposalHandler(suite.chainA.GetContext(), content)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,135 +0,0 @@
|
|||
package connection
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types"
|
||||
)
|
||||
|
||||
// HandleMsgConnectionOpenInit defines the sdk.Handler for MsgConnectionOpenInit
|
||||
func HandleMsgConnectionOpenInit(ctx sdk.Context, k keeper.Keeper, msg *types.MsgConnectionOpenInit) (*sdk.Result, error) {
|
||||
if err := k.ConnOpenInit(
|
||||
ctx, msg.ConnectionId, msg.ClientId, msg.Counterparty, msg.Version,
|
||||
); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "connection handshake open init failed")
|
||||
}
|
||||
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
types.EventTypeConnectionOpenInit,
|
||||
sdk.NewAttribute(types.AttributeKeyConnectionID, msg.ConnectionId),
|
||||
sdk.NewAttribute(types.AttributeKeyClientID, msg.ClientId),
|
||||
sdk.NewAttribute(types.AttributeKeyCounterpartyClientID, msg.Counterparty.ClientId),
|
||||
sdk.NewAttribute(types.AttributeKeyCounterpartyConnectionID, msg.Counterparty.ConnectionId),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
|
||||
),
|
||||
})
|
||||
|
||||
return &sdk.Result{
|
||||
Events: ctx.EventManager().Events().ToABCIEvents(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// HandleMsgConnectionOpenTry defines the sdk.Handler for MsgConnectionOpenTry
|
||||
func HandleMsgConnectionOpenTry(ctx sdk.Context, k keeper.Keeper, msg *types.MsgConnectionOpenTry) (*sdk.Result, error) {
|
||||
targetClient, err := clienttypes.UnpackClientState(msg.ClientState)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "client in msg is not exported.ClientState. invalid client: %v.", targetClient)
|
||||
}
|
||||
|
||||
if err := k.ConnOpenTry(
|
||||
ctx, msg.DesiredConnectionId, msg.CounterpartyChosenConnectionId, msg.Counterparty, msg.ClientId, targetClient,
|
||||
msg.CounterpartyVersions, msg.ProofInit, msg.ProofClient, msg.ProofConsensus,
|
||||
msg.ProofHeight, msg.ConsensusHeight,
|
||||
); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "connection handshake open try failed")
|
||||
}
|
||||
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
types.EventTypeConnectionOpenTry,
|
||||
sdk.NewAttribute(types.AttributeKeyConnectionID, msg.DesiredConnectionId),
|
||||
sdk.NewAttribute(types.AttributeKeyClientID, msg.ClientId),
|
||||
sdk.NewAttribute(types.AttributeKeyCounterpartyClientID, msg.Counterparty.ClientId),
|
||||
sdk.NewAttribute(types.AttributeKeyCounterpartyConnectionID, msg.Counterparty.ConnectionId),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
|
||||
),
|
||||
})
|
||||
|
||||
return &sdk.Result{
|
||||
Events: ctx.EventManager().Events().ToABCIEvents(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// HandleMsgConnectionOpenAck defines the sdk.Handler for MsgConnectionOpenAck
|
||||
func HandleMsgConnectionOpenAck(ctx sdk.Context, k keeper.Keeper, msg *types.MsgConnectionOpenAck) (*sdk.Result, error) {
|
||||
targetClient, err := clienttypes.UnpackClientState(msg.ClientState)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "client in msg is not exported.ClientState. invalid client: %v", targetClient)
|
||||
}
|
||||
|
||||
if err := k.ConnOpenAck(
|
||||
ctx, msg.ConnectionId, targetClient, msg.Version, msg.CounterpartyConnectionId,
|
||||
msg.ProofTry, msg.ProofClient, msg.ProofConsensus,
|
||||
msg.ProofHeight, msg.ConsensusHeight,
|
||||
); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "connection handshake open ack failed")
|
||||
}
|
||||
|
||||
connectionEnd, _ := k.GetConnection(ctx, msg.ConnectionId)
|
||||
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
types.EventTypeConnectionOpenAck,
|
||||
sdk.NewAttribute(types.AttributeKeyConnectionID, msg.ConnectionId),
|
||||
sdk.NewAttribute(types.AttributeKeyClientID, connectionEnd.ClientId),
|
||||
sdk.NewAttribute(types.AttributeKeyCounterpartyClientID, connectionEnd.Counterparty.ClientId),
|
||||
sdk.NewAttribute(types.AttributeKeyCounterpartyConnectionID, connectionEnd.Counterparty.ConnectionId),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
|
||||
),
|
||||
})
|
||||
|
||||
return &sdk.Result{
|
||||
Events: ctx.EventManager().Events().ToABCIEvents(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// HandleMsgConnectionOpenConfirm defines the sdk.Handler for MsgConnectionOpenConfirm
|
||||
func HandleMsgConnectionOpenConfirm(ctx sdk.Context, k keeper.Keeper, msg *types.MsgConnectionOpenConfirm) (*sdk.Result, error) {
|
||||
if err := k.ConnOpenConfirm(
|
||||
ctx, msg.ConnectionId, msg.ProofAck, msg.ProofHeight,
|
||||
); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "connection handshake open confirm failed")
|
||||
}
|
||||
|
||||
connectionEnd, _ := k.GetConnection(ctx, msg.ConnectionId)
|
||||
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
types.EventTypeConnectionOpenConfirm,
|
||||
sdk.NewAttribute(types.AttributeKeyConnectionID, msg.ConnectionId),
|
||||
sdk.NewAttribute(types.AttributeKeyClientID, connectionEnd.ClientId),
|
||||
sdk.NewAttribute(types.AttributeKeyCounterpartyClientID, connectionEnd.Counterparty.ClientId),
|
||||
sdk.NewAttribute(types.AttributeKeyCounterpartyConnectionID, connectionEnd.Counterparty.ConnectionId),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
|
||||
),
|
||||
})
|
||||
|
||||
return &sdk.Result{
|
||||
Events: ctx.EventManager().Events().ToABCIEvents(),
|
||||
}, nil
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,9 @@ package ibc_test
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
|
@ -20,6 +22,42 @@ import (
|
|||
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
|
||||
)
|
||||
|
||||
const (
|
||||
connectionID = "connectionidone"
|
||||
clientID = "clientidone"
|
||||
connectionID2 = "connectionidtwo"
|
||||
clientID2 = "clientidtwo"
|
||||
|
||||
port1 = "firstport"
|
||||
port2 = "secondport"
|
||||
|
||||
channel1 = "firstchannel"
|
||||
channel2 = "secondchannel"
|
||||
)
|
||||
|
||||
var clientHeight = clienttypes.NewHeight(0, 10)
|
||||
|
||||
type IBCTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
coordinator *ibctesting.Coordinator
|
||||
|
||||
chainA *ibctesting.TestChain
|
||||
chainB *ibctesting.TestChain
|
||||
}
|
||||
|
||||
// SetupTest creates a coordinator with 2 test chains.
|
||||
func (suite *IBCTestSuite) SetupTest() {
|
||||
suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2)
|
||||
|
||||
suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0))
|
||||
suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1))
|
||||
}
|
||||
|
||||
func TestIBCTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(IBCTestSuite))
|
||||
}
|
||||
|
||||
func (suite *IBCTestSuite) TestValidateGenesis() {
|
||||
header := suite.chainA.CreateTMClientHeader(suite.chainA.ChainID, suite.chainA.CurrentHeader.Height, clienttypes.NewHeight(0, uint64(suite.chainA.CurrentHeader.Height-1)), suite.chainA.CurrentHeader.Time, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers)
|
||||
|
||||
|
|
|
@ -1,18 +1,11 @@
|
|||
package ibc
|
||||
|
||||
import (
|
||||
"github.com/armon/go-metrics"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/telemetry"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
client "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client"
|
||||
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
|
||||
connection "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection"
|
||||
connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types"
|
||||
channel "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel"
|
||||
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"
|
||||
porttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/core/keeper"
|
||||
)
|
||||
|
||||
|
@ -24,340 +17,75 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
|
|||
switch msg := msg.(type) {
|
||||
// IBC client msg interface types
|
||||
case *clienttypes.MsgCreateClient:
|
||||
return client.HandleMsgCreateClient(ctx, k.ClientKeeper, msg)
|
||||
res, err := k.CreateClient(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
case *clienttypes.MsgUpdateClient:
|
||||
return client.HandleMsgUpdateClient(ctx, k.ClientKeeper, msg)
|
||||
res, err := k.UpdateClient(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
case *clienttypes.MsgSubmitMisbehaviour:
|
||||
return client.HandleMsgSubmitMisbehaviour(ctx, k.ClientKeeper, msg)
|
||||
res, err := k.SubmitMisbehaviour(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
// IBC connection msgs
|
||||
case *connectiontypes.MsgConnectionOpenInit:
|
||||
return connection.HandleMsgConnectionOpenInit(ctx, k.ConnectionKeeper, msg)
|
||||
res, err := k.ConnectionOpenInit(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
case *connectiontypes.MsgConnectionOpenTry:
|
||||
return connection.HandleMsgConnectionOpenTry(ctx, k.ConnectionKeeper, msg)
|
||||
res, err := k.ConnectionOpenTry(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
case *connectiontypes.MsgConnectionOpenAck:
|
||||
return connection.HandleMsgConnectionOpenAck(ctx, k.ConnectionKeeper, msg)
|
||||
res, err := k.ConnectionOpenAck(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
case *connectiontypes.MsgConnectionOpenConfirm:
|
||||
return connection.HandleMsgConnectionOpenConfirm(ctx, k.ConnectionKeeper, msg)
|
||||
res, err := k.ConnectionOpenConfirm(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
// IBC channel msgs
|
||||
case *channeltypes.MsgChannelOpenInit:
|
||||
// Lookup module by port capability
|
||||
module, portCap, err := k.PortKeeper.LookupModuleByPort(ctx, msg.PortId)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
res, cap, err := channel.HandleMsgChannelOpenInit(ctx, k.ChannelKeeper, portCap, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
if err = cbs.OnChanOpenInit(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, msg.ChannelId, cap, msg.Channel.Counterparty, msg.Channel.Version); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "channel open init callback failed")
|
||||
}
|
||||
|
||||
return res, nil
|
||||
res, err := k.ChannelOpenInit(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
case *channeltypes.MsgChannelOpenTry:
|
||||
// Lookup module by port capability
|
||||
module, portCap, err := k.PortKeeper.LookupModuleByPort(ctx, msg.PortId)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
res, cap, err := channel.HandleMsgChannelOpenTry(ctx, k.ChannelKeeper, portCap, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
if err = cbs.OnChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, msg.DesiredChannelId, cap, msg.Channel.Counterparty, msg.Channel.Version, msg.CounterpartyVersion); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "channel open try callback failed")
|
||||
}
|
||||
|
||||
return res, nil
|
||||
res, err := k.ChannelOpenTry(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
case *channeltypes.MsgChannelOpenAck:
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
if err = cbs.OnChanOpenAck(ctx, msg.PortId, msg.ChannelId, msg.CounterpartyVersion); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "channel open ack callback failed")
|
||||
}
|
||||
|
||||
return channel.HandleMsgChannelOpenAck(ctx, k.ChannelKeeper, cap, msg)
|
||||
res, err := k.ChannelOpenAck(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
case *channeltypes.MsgChannelOpenConfirm:
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
if err = cbs.OnChanOpenConfirm(ctx, msg.PortId, msg.ChannelId); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "channel open confirm callback failed")
|
||||
}
|
||||
|
||||
return channel.HandleMsgChannelOpenConfirm(ctx, k.ChannelKeeper, cap, msg)
|
||||
res, err := k.ChannelOpenConfirm(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
case *channeltypes.MsgChannelCloseInit:
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
if err = cbs.OnChanCloseInit(ctx, msg.PortId, msg.ChannelId); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "channel close init callback failed")
|
||||
}
|
||||
|
||||
return channel.HandleMsgChannelCloseInit(ctx, k.ChannelKeeper, cap, msg)
|
||||
res, err := k.ChannelCloseInit(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
case *channeltypes.MsgChannelCloseConfirm:
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
if err = cbs.OnChanCloseConfirm(ctx, msg.PortId, msg.ChannelId); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "channel close confirm callback failed")
|
||||
}
|
||||
|
||||
return channel.HandleMsgChannelCloseConfirm(ctx, k.ChannelKeeper, cap, msg)
|
||||
res, err := k.ChannelCloseConfirm(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
// IBC packet msgs get routed to the appropriate module callback
|
||||
case *channeltypes.MsgRecvPacket:
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.DestinationPort, msg.Packet.DestinationChannel)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
// Perform TAO verification
|
||||
if err := k.ChannelKeeper.RecvPacket(ctx, msg.Packet, msg.Proof, msg.ProofHeight); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "receive packet verification failed")
|
||||
}
|
||||
|
||||
// Perform application logic callback
|
||||
res, ack, err := cbs.OnRecvPacket(ctx, msg.Packet)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "receive packet callback failed")
|
||||
}
|
||||
|
||||
if err := k.ChannelKeeper.WriteReceipt(ctx, cap, msg.Packet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set packet acknowledgement only if the acknowledgement is not nil.
|
||||
// NOTE: IBC applications modules may call the WriteAcknowledgement asynchronously if the
|
||||
// acknowledgement is nil.
|
||||
if ack != nil {
|
||||
if err := k.ChannelKeeper.WriteAcknowledgement(ctx, msg.Packet, ack); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
telemetry.IncrCounterWithLabels(
|
||||
[]string{"tx", "msg", "ibc", msg.Type()},
|
||||
1,
|
||||
[]metrics.Label{
|
||||
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
|
||||
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
|
||||
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
|
||||
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
|
||||
},
|
||||
)
|
||||
}()
|
||||
|
||||
return res, nil
|
||||
res, err := k.RecvPacket(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
case *channeltypes.MsgAcknowledgement:
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
// Perform TAO verification
|
||||
if err := k.ChannelKeeper.AcknowledgePacket(ctx, msg.Packet, msg.Acknowledgement, msg.Proof, msg.ProofHeight); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "acknowledge packet verification failed")
|
||||
}
|
||||
|
||||
// Perform application logic callback
|
||||
res, err := cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "acknowledge packet callback failed")
|
||||
}
|
||||
|
||||
// Delete packet commitment
|
||||
if err = k.ChannelKeeper.AcknowledgementExecuted(ctx, cap, msg.Packet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
telemetry.IncrCounterWithLabels(
|
||||
[]string{"tx", "msg", "ibc", msg.Type()},
|
||||
1,
|
||||
[]metrics.Label{
|
||||
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
|
||||
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
|
||||
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
|
||||
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
|
||||
},
|
||||
)
|
||||
}()
|
||||
|
||||
return res, nil
|
||||
res, err := k.Acknowledgement(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
case *channeltypes.MsgTimeout:
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
// Perform TAO verification
|
||||
if err := k.ChannelKeeper.TimeoutPacket(ctx, msg.Packet, msg.Proof, msg.ProofHeight, msg.NextSequenceRecv); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "timeout packet verification failed")
|
||||
}
|
||||
|
||||
// Perform application logic callback
|
||||
res, err := cbs.OnTimeoutPacket(ctx, msg.Packet)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "timeout packet callback failed")
|
||||
}
|
||||
|
||||
// Delete packet commitment
|
||||
if err = k.ChannelKeeper.TimeoutExecuted(ctx, cap, msg.Packet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
telemetry.IncrCounterWithLabels(
|
||||
[]string{"ibc", "timeout", "packet"},
|
||||
1,
|
||||
[]metrics.Label{
|
||||
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
|
||||
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
|
||||
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
|
||||
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
|
||||
telemetry.NewLabel("timeout-type", "height"),
|
||||
},
|
||||
)
|
||||
}()
|
||||
|
||||
return res, nil
|
||||
res, err := k.Timeout(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
case *channeltypes.MsgTimeoutOnClose:
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
// Perform TAO verification
|
||||
if err := k.ChannelKeeper.TimeoutOnClose(ctx, cap, msg.Packet, msg.Proof, msg.ProofClose, msg.ProofHeight, msg.NextSequenceRecv); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "timeout on close packet verification failed")
|
||||
}
|
||||
|
||||
// Perform application logic callback
|
||||
// NOTE: MsgTimeout and MsgTimeoutOnClose use the same "OnTimeoutPacket"
|
||||
// application logic callback.
|
||||
res, err := cbs.OnTimeoutPacket(ctx, msg.Packet)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "timeout packet callback failed")
|
||||
}
|
||||
|
||||
// Delete packet commitment
|
||||
if err = k.ChannelKeeper.TimeoutExecuted(ctx, cap, msg.Packet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
telemetry.IncrCounterWithLabels(
|
||||
[]string{"ibc", "timeout", "packet"},
|
||||
1,
|
||||
[]metrics.Label{
|
||||
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
|
||||
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
|
||||
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
|
||||
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
|
||||
telemetry.NewLabel("timeout-type", "channel-closed"),
|
||||
},
|
||||
)
|
||||
}()
|
||||
|
||||
return res, nil
|
||||
res, err := k.TimeoutOnClose(sdk.WrapSDKContext(ctx), msg)
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
|
||||
default:
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized IBC message type: %T", msg)
|
||||
|
|
|
@ -0,0 +1,622 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/armon/go-metrics"
|
||||
"github.com/cosmos/cosmos-sdk/telemetry"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
|
||||
connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types"
|
||||
channel "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel"
|
||||
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"
|
||||
porttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types"
|
||||
)
|
||||
|
||||
var _ clienttypes.MsgServer = Keeper{}
|
||||
var _ connectiontypes.MsgServer = Keeper{}
|
||||
var _ channeltypes.MsgServer = Keeper{}
|
||||
|
||||
// CreateClient defines a rpc handler method for MsgCreateClient.
|
||||
func (k Keeper) CreateClient(goCtx context.Context, msg *clienttypes.MsgCreateClient) (*clienttypes.MsgCreateClientResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
clientState, err := clienttypes.UnpackClientState(msg.ClientState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
consensusState, err := clienttypes.UnpackConsensusState(msg.ConsensusState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = k.ClientKeeper.CreateClient(ctx, msg.ClientId, clientState, consensusState); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
clienttypes.EventTypeCreateClient,
|
||||
sdk.NewAttribute(clienttypes.AttributeKeyClientID, msg.ClientId),
|
||||
sdk.NewAttribute(clienttypes.AttributeKeyClientType, clientState.ClientType()),
|
||||
sdk.NewAttribute(clienttypes.AttributeKeyConsensusHeight, clientState.GetLatestHeight().String()),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, clienttypes.AttributeValueCategory),
|
||||
),
|
||||
})
|
||||
|
||||
return &clienttypes.MsgCreateClientResponse{}, nil
|
||||
}
|
||||
|
||||
// UpdateClient defines a rpc handler method for MsgUpdateClient.
|
||||
func (k Keeper) UpdateClient(goCtx context.Context, msg *clienttypes.MsgUpdateClient) (*clienttypes.MsgUpdateClientResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
header, err := clienttypes.UnpackHeader(msg.Header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = k.ClientKeeper.UpdateClient(ctx, msg.ClientId, header); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx.EventManager().EmitEvent(
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, clienttypes.AttributeValueCategory),
|
||||
),
|
||||
)
|
||||
|
||||
return &clienttypes.MsgUpdateClientResponse{}, nil
|
||||
}
|
||||
|
||||
// UpgradeClient defines a rpc handler method for MsgUpgradeClient.
|
||||
func (k Keeper) UpgradeClient(goCtx context.Context, msg *clienttypes.MsgUpgradeClient) (*clienttypes.MsgUpgradeClientResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
upgradedClient, err := clienttypes.UnpackClientState(msg.ClientState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := upgradedClient.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = k.ClientKeeper.UpgradeClient(ctx, msg.ClientId, upgradedClient, msg.UpgradeHeight, msg.ProofUpgrade); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx.EventManager().EmitEvent(
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, clienttypes.AttributeValueCategory),
|
||||
),
|
||||
)
|
||||
|
||||
return &clienttypes.MsgUpgradeClientResponse{}, nil
|
||||
}
|
||||
|
||||
// SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour.
|
||||
func (k Keeper) SubmitMisbehaviour(goCtx context.Context, msg *clienttypes.MsgSubmitMisbehaviour) (*clienttypes.MsgSubmitMisbehaviourResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
misbehaviour, err := clienttypes.UnpackMisbehaviour(msg.Misbehaviour)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := k.ClientKeeper.CheckMisbehaviourAndUpdateState(ctx, misbehaviour); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "failed to process misbehaviour for IBC client")
|
||||
}
|
||||
|
||||
ctx.EventManager().EmitEvent(
|
||||
sdk.NewEvent(
|
||||
clienttypes.EventTypeSubmitMisbehaviour,
|
||||
sdk.NewAttribute(clienttypes.AttributeKeyClientID, msg.ClientId),
|
||||
sdk.NewAttribute(clienttypes.AttributeKeyClientType, misbehaviour.ClientType()),
|
||||
sdk.NewAttribute(clienttypes.AttributeKeyConsensusHeight, misbehaviour.GetHeight().String()),
|
||||
),
|
||||
)
|
||||
|
||||
return &clienttypes.MsgSubmitMisbehaviourResponse{}, nil
|
||||
}
|
||||
|
||||
// ConnectionOpenInit defines a rpc handler method for MsgConnectionOpenInit.
|
||||
func (k Keeper) ConnectionOpenInit(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenInit) (*connectiontypes.MsgConnectionOpenInitResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
if err := k.ConnectionKeeper.ConnOpenInit(
|
||||
ctx, msg.ConnectionId, msg.ClientId, msg.Counterparty, msg.Version,
|
||||
); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "connection handshake open init failed")
|
||||
}
|
||||
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
connectiontypes.EventTypeConnectionOpenInit,
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, msg.ConnectionId),
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyClientID, msg.ClientId),
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, msg.Counterparty.ClientId),
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, msg.Counterparty.ConnectionId),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory),
|
||||
),
|
||||
})
|
||||
|
||||
return &connectiontypes.MsgConnectionOpenInitResponse{}, nil
|
||||
}
|
||||
|
||||
// ConnectionOpenTry defines a rpc handler method for MsgConnectionOpenTry.
|
||||
func (k Keeper) ConnectionOpenTry(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenTry) (*connectiontypes.MsgConnectionOpenTryResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
targetClient, err := clienttypes.UnpackClientState(msg.ClientState)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "client in msg is not exported.ClientState. invalid client: %v.", targetClient)
|
||||
}
|
||||
|
||||
if err := k.ConnectionKeeper.ConnOpenTry(
|
||||
ctx, msg.DesiredConnectionId, msg.CounterpartyChosenConnectionId, msg.Counterparty, msg.ClientId, targetClient,
|
||||
msg.CounterpartyVersions, msg.ProofInit, msg.ProofClient, msg.ProofConsensus,
|
||||
msg.ProofHeight, msg.ConsensusHeight,
|
||||
); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "connection handshake open try failed")
|
||||
}
|
||||
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
connectiontypes.EventTypeConnectionOpenTry,
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, msg.DesiredConnectionId),
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyClientID, msg.ClientId),
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, msg.Counterparty.ClientId),
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, msg.Counterparty.ConnectionId),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory),
|
||||
),
|
||||
})
|
||||
|
||||
return &connectiontypes.MsgConnectionOpenTryResponse{}, nil
|
||||
}
|
||||
|
||||
// ConnectionOpenAck defines a rpc handler method for MsgConnectionOpenAck.
|
||||
func (k Keeper) ConnectionOpenAck(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenAck) (*connectiontypes.MsgConnectionOpenAckResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
targetClient, err := clienttypes.UnpackClientState(msg.ClientState)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "client in msg is not exported.ClientState. invalid client: %v", targetClient)
|
||||
}
|
||||
|
||||
if err := k.ConnectionKeeper.ConnOpenAck(
|
||||
ctx, msg.ConnectionId, targetClient, msg.Version, msg.CounterpartyConnectionId,
|
||||
msg.ProofTry, msg.ProofClient, msg.ProofConsensus,
|
||||
msg.ProofHeight, msg.ConsensusHeight,
|
||||
); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "connection handshake open ack failed")
|
||||
}
|
||||
|
||||
connectionEnd, _ := k.ConnectionKeeper.GetConnection(ctx, msg.ConnectionId)
|
||||
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
connectiontypes.EventTypeConnectionOpenAck,
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, msg.ConnectionId),
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyClientID, connectionEnd.ClientId),
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, connectionEnd.Counterparty.ClientId),
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, connectionEnd.Counterparty.ConnectionId),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory),
|
||||
),
|
||||
})
|
||||
|
||||
return &connectiontypes.MsgConnectionOpenAckResponse{}, nil
|
||||
}
|
||||
|
||||
// ConnectionOpenConfirm defines a rpc handler method for MsgConnectionOpenConfirm.
|
||||
func (k Keeper) ConnectionOpenConfirm(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenConfirm) (*connectiontypes.MsgConnectionOpenConfirmResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
if err := k.ConnectionKeeper.ConnOpenConfirm(
|
||||
ctx, msg.ConnectionId, msg.ProofAck, msg.ProofHeight,
|
||||
); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "connection handshake open confirm failed")
|
||||
}
|
||||
|
||||
connectionEnd, _ := k.ConnectionKeeper.GetConnection(ctx, msg.ConnectionId)
|
||||
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
connectiontypes.EventTypeConnectionOpenConfirm,
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, msg.ConnectionId),
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyClientID, connectionEnd.ClientId),
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, connectionEnd.Counterparty.ClientId),
|
||||
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, connectionEnd.Counterparty.ConnectionId),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory),
|
||||
),
|
||||
})
|
||||
|
||||
return &connectiontypes.MsgConnectionOpenConfirmResponse{}, nil
|
||||
}
|
||||
|
||||
// ChannelOpenInit defines a rpc handler method for MsgChannelOpenInit.
|
||||
func (k Keeper) ChannelOpenInit(goCtx context.Context, msg *channeltypes.MsgChannelOpenInit) (*channeltypes.MsgChannelOpenInitResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
// Lookup module by port capability
|
||||
module, portCap, err := k.PortKeeper.LookupModuleByPort(ctx, msg.PortId)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
_, cap, err := channel.HandleMsgChannelOpenInit(ctx, k.ChannelKeeper, portCap, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
if err = cbs.OnChanOpenInit(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, msg.ChannelId, cap, msg.Channel.Counterparty, msg.Channel.Version); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "channel open init callback failed")
|
||||
}
|
||||
|
||||
return &channeltypes.MsgChannelOpenInitResponse{}, nil
|
||||
}
|
||||
|
||||
// ChannelOpenTry defines a rpc handler method for MsgChannelOpenTry.
|
||||
func (k Keeper) ChannelOpenTry(goCtx context.Context, msg *channeltypes.MsgChannelOpenTry) (*channeltypes.MsgChannelOpenTryResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
// Lookup module by port capability
|
||||
module, portCap, err := k.PortKeeper.LookupModuleByPort(ctx, msg.PortId)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
_, cap, err := channel.HandleMsgChannelOpenTry(ctx, k.ChannelKeeper, portCap, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
if err = cbs.OnChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, msg.DesiredChannelId, cap, msg.Channel.Counterparty, msg.Channel.Version, msg.CounterpartyVersion); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "channel open try callback failed")
|
||||
}
|
||||
|
||||
return &channeltypes.MsgChannelOpenTryResponse{}, nil
|
||||
}
|
||||
|
||||
// ChannelOpenAck defines a rpc handler method for MsgChannelOpenAck.
|
||||
func (k Keeper) ChannelOpenAck(goCtx context.Context, msg *channeltypes.MsgChannelOpenAck) (*channeltypes.MsgChannelOpenAckResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
if err = cbs.OnChanOpenAck(ctx, msg.PortId, msg.ChannelId, msg.CounterpartyVersion); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "channel open ack callback failed")
|
||||
}
|
||||
|
||||
_, err = channel.HandleMsgChannelOpenAck(ctx, k.ChannelKeeper, cap, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &channeltypes.MsgChannelOpenAckResponse{}, nil
|
||||
}
|
||||
|
||||
// ChannelOpenConfirm defines a rpc handler method for MsgChannelOpenConfirm.
|
||||
func (k Keeper) ChannelOpenConfirm(goCtx context.Context, msg *channeltypes.MsgChannelOpenConfirm) (*channeltypes.MsgChannelOpenConfirmResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
if err = cbs.OnChanOpenConfirm(ctx, msg.PortId, msg.ChannelId); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "channel open confirm callback failed")
|
||||
}
|
||||
|
||||
_, err = channel.HandleMsgChannelOpenConfirm(ctx, k.ChannelKeeper, cap, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &channeltypes.MsgChannelOpenConfirmResponse{}, nil
|
||||
}
|
||||
|
||||
// ChannelCloseInit defines a rpc handler method for MsgChannelCloseInit.
|
||||
func (k Keeper) ChannelCloseInit(goCtx context.Context, msg *channeltypes.MsgChannelCloseInit) (*channeltypes.MsgChannelCloseInitResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
if err = cbs.OnChanCloseInit(ctx, msg.PortId, msg.ChannelId); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "channel close init callback failed")
|
||||
}
|
||||
|
||||
_, err = channel.HandleMsgChannelCloseInit(ctx, k.ChannelKeeper, cap, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &channeltypes.MsgChannelCloseInitResponse{}, nil
|
||||
}
|
||||
|
||||
// ChannelCloseConfirm defines a rpc handler method for MsgChannelCloseConfirm.
|
||||
func (k Keeper) ChannelCloseConfirm(goCtx context.Context, msg *channeltypes.MsgChannelCloseConfirm) (*channeltypes.MsgChannelCloseConfirmResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
if err = cbs.OnChanCloseConfirm(ctx, msg.PortId, msg.ChannelId); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "channel close confirm callback failed")
|
||||
}
|
||||
|
||||
_, err = channel.HandleMsgChannelCloseConfirm(ctx, k.ChannelKeeper, cap, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &channeltypes.MsgChannelCloseConfirmResponse{}, nil
|
||||
}
|
||||
|
||||
// RecvPacket defines a rpc handler method for MsgRecvPacket.
|
||||
func (k Keeper) RecvPacket(goCtx context.Context, msg *channeltypes.MsgRecvPacket) (*channeltypes.MsgRecvPacketResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.DestinationPort, msg.Packet.DestinationChannel)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
// Perform TAO verification
|
||||
if err := k.ChannelKeeper.RecvPacket(ctx, msg.Packet, msg.Proof, msg.ProofHeight); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "receive packet verification failed")
|
||||
}
|
||||
|
||||
// Perform application logic callback
|
||||
_, ack, err := cbs.OnRecvPacket(ctx, msg.Packet)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "receive packet callback failed")
|
||||
}
|
||||
|
||||
if err := k.ChannelKeeper.WriteReceipt(ctx, cap, msg.Packet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set packet acknowledgement only if the acknowledgement is not nil.
|
||||
// NOTE: IBC applications modules may call the WriteAcknowledgement asynchronously if the
|
||||
// acknowledgement is nil.
|
||||
if ack != nil {
|
||||
if err := k.ChannelKeeper.WriteAcknowledgement(ctx, msg.Packet, ack); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
telemetry.IncrCounterWithLabels(
|
||||
[]string{"tx", "msg", "ibc", msg.Type()},
|
||||
1,
|
||||
[]metrics.Label{
|
||||
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
|
||||
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
|
||||
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
|
||||
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
|
||||
},
|
||||
)
|
||||
}()
|
||||
|
||||
return &channeltypes.MsgRecvPacketResponse{}, nil
|
||||
}
|
||||
|
||||
// Timeout defines a rpc handler method for MsgTimeout.
|
||||
func (k Keeper) Timeout(goCtx context.Context, msg *channeltypes.MsgTimeout) (*channeltypes.MsgTimeoutResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
// Perform TAO verification
|
||||
if err := k.ChannelKeeper.TimeoutPacket(ctx, msg.Packet, msg.Proof, msg.ProofHeight, msg.NextSequenceRecv); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "timeout packet verification failed")
|
||||
}
|
||||
|
||||
// Perform application logic callback
|
||||
_, err = cbs.OnTimeoutPacket(ctx, msg.Packet)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "timeout packet callback failed")
|
||||
}
|
||||
|
||||
// Delete packet commitment
|
||||
if err = k.ChannelKeeper.TimeoutExecuted(ctx, cap, msg.Packet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
telemetry.IncrCounterWithLabels(
|
||||
[]string{"ibc", "timeout", "packet"},
|
||||
1,
|
||||
[]metrics.Label{
|
||||
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
|
||||
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
|
||||
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
|
||||
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
|
||||
telemetry.NewLabel("timeout-type", "height"),
|
||||
},
|
||||
)
|
||||
}()
|
||||
|
||||
return &channeltypes.MsgTimeoutResponse{}, nil
|
||||
}
|
||||
|
||||
// TimeoutOnClose defines a rpc handler method for MsgTimeoutOnClose.
|
||||
func (k Keeper) TimeoutOnClose(goCtx context.Context, msg *channeltypes.MsgTimeoutOnClose) (*channeltypes.MsgTimeoutOnCloseResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
// Perform TAO verification
|
||||
if err := k.ChannelKeeper.TimeoutOnClose(ctx, cap, msg.Packet, msg.Proof, msg.ProofClose, msg.ProofHeight, msg.NextSequenceRecv); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "timeout on close packet verification failed")
|
||||
}
|
||||
|
||||
// Perform application logic callback
|
||||
// NOTE: MsgTimeout and MsgTimeoutOnClose use the same "OnTimeoutPacket"
|
||||
// application logic callback.
|
||||
_, err = cbs.OnTimeoutPacket(ctx, msg.Packet)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "timeout packet callback failed")
|
||||
}
|
||||
|
||||
// Delete packet commitment
|
||||
if err = k.ChannelKeeper.TimeoutExecuted(ctx, cap, msg.Packet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
telemetry.IncrCounterWithLabels(
|
||||
[]string{"ibc", "timeout", "packet"},
|
||||
1,
|
||||
[]metrics.Label{
|
||||
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
|
||||
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
|
||||
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
|
||||
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
|
||||
telemetry.NewLabel("timeout-type", "channel-closed"),
|
||||
},
|
||||
)
|
||||
}()
|
||||
|
||||
return &channeltypes.MsgTimeoutOnCloseResponse{}, nil
|
||||
}
|
||||
|
||||
// Acknowledgement defines a rpc handler method for MsgAcknowledgement.
|
||||
func (k Keeper) Acknowledgement(goCtx context.Context, msg *channeltypes.MsgAcknowledgement) (*channeltypes.MsgAcknowledgementResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
// Lookup module by channel capability
|
||||
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||
}
|
||||
|
||||
// Retrieve callbacks from router
|
||||
cbs, ok := k.Router.GetRoute(module)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
|
||||
}
|
||||
|
||||
// Perform TAO verification
|
||||
if err := k.ChannelKeeper.AcknowledgePacket(ctx, msg.Packet, msg.Acknowledgement, msg.Proof, msg.ProofHeight); err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "acknowledge packet verification failed")
|
||||
}
|
||||
|
||||
// Perform application logic callback
|
||||
_, err = cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "acknowledge packet callback failed")
|
||||
}
|
||||
|
||||
// Delete packet commitment
|
||||
if err = k.ChannelKeeper.AcknowledgementExecuted(ctx, cap, msg.Packet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
telemetry.IncrCounterWithLabels(
|
||||
[]string{"tx", "msg", "ibc", msg.Type()},
|
||||
1,
|
||||
[]metrics.Label{
|
||||
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
|
||||
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
|
||||
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
|
||||
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
|
||||
},
|
||||
)
|
||||
}()
|
||||
|
||||
return &channeltypes.MsgAcknowledgementResponse{}, nil
|
||||
}
|
|
@ -1,39 +1,31 @@
|
|||
package ibc_test
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
ibc "github.com/cosmos/cosmos-sdk/x/ibc/core"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
|
||||
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"
|
||||
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types"
|
||||
host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/core/exported"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/core/keeper"
|
||||
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types"
|
||||
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
|
||||
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
|
||||
)
|
||||
|
||||
const (
|
||||
connectionID = "connectionidone"
|
||||
clientID = "clientidone"
|
||||
connectionID2 = "connectionidtwo"
|
||||
clientID2 = "clientidtwo"
|
||||
|
||||
port1 = "firstport"
|
||||
port2 = "secondport"
|
||||
|
||||
channel1 = "firstchannel"
|
||||
channel2 = "secondchannel"
|
||||
|
||||
height = 10
|
||||
)
|
||||
const height = 10
|
||||
|
||||
var (
|
||||
timeoutHeight = clienttypes.NewHeight(0, 10000)
|
||||
maxSequence = uint64(10)
|
||||
clientHeight = clienttypes.NewHeight(0, 10)
|
||||
)
|
||||
|
||||
type IBCTestSuite struct {
|
||||
type KeeperTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
coordinator *ibctesting.Coordinator
|
||||
|
@ -43,7 +35,7 @@ type IBCTestSuite struct {
|
|||
}
|
||||
|
||||
// SetupTest creates a coordinator with 2 test chains.
|
||||
func (suite *IBCTestSuite) SetupTest() {
|
||||
func (suite *KeeperTestSuite) SetupTest() {
|
||||
suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2)
|
||||
|
||||
suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0))
|
||||
|
@ -51,7 +43,7 @@ func (suite *IBCTestSuite) SetupTest() {
|
|||
}
|
||||
|
||||
func TestIBCTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(IBCTestSuite))
|
||||
suite.Run(t, new(KeeperTestSuite))
|
||||
}
|
||||
|
||||
// tests the IBC handler receiving a packet on ordered and unordered channels.
|
||||
|
@ -59,7 +51,7 @@ func TestIBCTestSuite(t *testing.T) {
|
|||
// tests high level properties like ordering and basic sanity checks. More
|
||||
// rigorous testing of 'RecvPacket' and 'WriteReceipt' can be found in the
|
||||
// 04-channel/keeper/packet_test.go.
|
||||
func (suite *IBCTestSuite) TestHandleRecvPacket() {
|
||||
func (suite *KeeperTestSuite) TestHandleRecvPacket() {
|
||||
var (
|
||||
packet channeltypes.Packet
|
||||
)
|
||||
|
@ -143,8 +135,6 @@ func (suite *IBCTestSuite) TestHandleRecvPacket() {
|
|||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
|
||||
handler := ibc.NewHandler(*suite.chainB.App.IBCKeeper)
|
||||
|
||||
tc.malleate()
|
||||
|
||||
// get proof of packet commitment from chainA
|
||||
|
@ -154,13 +144,13 @@ func (suite *IBCTestSuite) TestHandleRecvPacket() {
|
|||
msg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, suite.chainB.SenderAccount.GetAddress())
|
||||
|
||||
// ante-handle RecvPacket
|
||||
_, err := handler(suite.chainB.GetContext(), msg)
|
||||
_, err := keeper.Keeper.RecvPacket(*suite.chainB.App.IBCKeeper, sdk.WrapSDKContext(suite.chainB.GetContext()), msg)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// replay should fail since state changes occur
|
||||
_, err := handler(suite.chainB.GetContext(), msg)
|
||||
_, err := keeper.Keeper.RecvPacket(*suite.chainB.App.IBCKeeper, sdk.WrapSDKContext(suite.chainB.GetContext()), msg)
|
||||
suite.Require().Error(err)
|
||||
|
||||
// verify ack was written
|
||||
|
@ -179,7 +169,7 @@ func (suite *IBCTestSuite) TestHandleRecvPacket() {
|
|||
// occurs. It test high level properties like ordering and basic sanity
|
||||
// checks. More rigorous testing of 'AcknowledgePacket' and 'AcknowledgementExecuted'
|
||||
// can be found in the 04-channel/keeper/packet_test.go.
|
||||
func (suite *IBCTestSuite) TestHandleAcknowledgePacket() {
|
||||
func (suite *KeeperTestSuite) TestHandleAcknowledgePacket() {
|
||||
var (
|
||||
packet channeltypes.Packet
|
||||
)
|
||||
|
@ -303,8 +293,6 @@ func (suite *IBCTestSuite) TestHandleAcknowledgePacket() {
|
|||
suite.SetupTest() // reset
|
||||
ibctesting.TestHash = ibctesting.MockAcknowledgement
|
||||
|
||||
handler := ibc.NewHandler(*suite.chainA.App.IBCKeeper)
|
||||
|
||||
tc.malleate()
|
||||
|
||||
packetKey := host.KeyPacketAcknowledgement(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
|
||||
|
@ -312,13 +300,13 @@ func (suite *IBCTestSuite) TestHandleAcknowledgePacket() {
|
|||
|
||||
msg := channeltypes.NewMsgAcknowledgement(packet, ibctesting.MockAcknowledgement, proof, proofHeight, suite.chainA.SenderAccount.GetAddress())
|
||||
|
||||
_, err := handler(suite.chainA.GetContext(), msg)
|
||||
_, err := keeper.Keeper.Acknowledgement(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// replay should an error
|
||||
_, err := handler(suite.chainA.GetContext(), msg)
|
||||
_, err := keeper.Keeper.Acknowledgement(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
|
||||
suite.Require().Error(err)
|
||||
|
||||
// verify packet commitment was deleted on source chain
|
||||
|
@ -337,7 +325,7 @@ func (suite *IBCTestSuite) TestHandleAcknowledgePacket() {
|
|||
// high level properties like ordering and basic sanity checks. More
|
||||
// rigorous testing of 'TimeoutPacket' and 'TimeoutExecuted' can be found in
|
||||
// the 04-channel/keeper/timeout_test.go.
|
||||
func (suite *IBCTestSuite) TestHandleTimeoutPacket() {
|
||||
func (suite *KeeperTestSuite) TestHandleTimeoutPacket() {
|
||||
var (
|
||||
packet channeltypes.Packet
|
||||
packetKey []byte
|
||||
|
@ -427,21 +415,19 @@ func (suite *IBCTestSuite) TestHandleTimeoutPacket() {
|
|||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
|
||||
handler := ibc.NewHandler(*suite.chainA.App.IBCKeeper)
|
||||
|
||||
tc.malleate()
|
||||
|
||||
proof, proofHeight := suite.chainB.QueryProof(packetKey)
|
||||
|
||||
msg := channeltypes.NewMsgTimeout(packet, 1, proof, proofHeight, suite.chainA.SenderAccount.GetAddress())
|
||||
|
||||
_, err := handler(suite.chainA.GetContext(), msg)
|
||||
_, err := keeper.Keeper.Timeout(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// replay should return an error
|
||||
_, err := handler(suite.chainA.GetContext(), msg)
|
||||
_, err := keeper.Keeper.Timeout(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
|
||||
suite.Require().Error(err)
|
||||
|
||||
// verify packet commitment was deleted on source chain
|
||||
|
@ -460,7 +446,7 @@ func (suite *IBCTestSuite) TestHandleTimeoutPacket() {
|
|||
// commitment occurs. It tests high level properties like ordering and basic
|
||||
// sanity checks. More rigorous testing of 'TimeoutOnClose' and
|
||||
//'TimeoutExecuted' can be found in the 04-channel/keeper/timeout_test.go.
|
||||
func (suite *IBCTestSuite) TestHandleTimeoutOnClosePacket() {
|
||||
func (suite *KeeperTestSuite) TestHandleTimeoutOnClosePacket() {
|
||||
var (
|
||||
packet channeltypes.Packet
|
||||
packetKey []byte
|
||||
|
@ -608,8 +594,6 @@ func (suite *IBCTestSuite) TestHandleTimeoutOnClosePacket() {
|
|||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
|
||||
handler := ibc.NewHandler(*suite.chainA.App.IBCKeeper)
|
||||
|
||||
tc.malleate()
|
||||
|
||||
proof, proofHeight := suite.chainB.QueryProof(packetKey)
|
||||
|
@ -619,13 +603,13 @@ func (suite *IBCTestSuite) TestHandleTimeoutOnClosePacket() {
|
|||
|
||||
msg := channeltypes.NewMsgTimeoutOnClose(packet, 1, proof, proofClosed, proofHeight, suite.chainA.SenderAccount.GetAddress())
|
||||
|
||||
_, err := handler(suite.chainA.GetContext(), msg)
|
||||
_, err := keeper.Keeper.TimeoutOnClose(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// replay should return an error
|
||||
_, err := handler(suite.chainA.GetContext(), msg)
|
||||
_, err := keeper.Keeper.TimeoutOnClose(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
|
||||
suite.Require().Error(err)
|
||||
|
||||
// verify packet commitment was deleted on source chain
|
||||
|
@ -638,3 +622,140 @@ func (suite *IBCTestSuite) TestHandleTimeoutOnClosePacket() {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
var (
|
||||
clientA string
|
||||
upgradedClient exported.ClientState
|
||||
upgradeHeight exported.Height
|
||||
msg *clienttypes.MsgUpgradeClient
|
||||
)
|
||||
|
||||
newClientHeight := clienttypes.NewHeight(1, 1)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
setup func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
name: "successful upgrade",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, ibctesting.DefaultConsensusParams, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
suite.coordinator.CommitBlock(suite.chainB)
|
||||
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
|
||||
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradeHeight, proofUpgrade, suite.chainA.SenderAccount.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
},
|
||||
expPass: true,
|
||||
},
|
||||
{
|
||||
name: "invalid upgrade: msg.ClientState does not contain valid clientstate",
|
||||
setup: func() {
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
proofUpgrade, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
|
||||
consState := ibctmtypes.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("app_hash")), []byte("next_vals_hash"))
|
||||
consAny, err := clienttypes.PackConsensusState(consState)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
height, _ := upgradeHeight.(clienttypes.Height)
|
||||
|
||||
msg = &clienttypes.MsgUpgradeClient{ClientId: clientA, ClientState: consAny, UpgradeHeight: &height, ProofUpgrade: proofUpgrade, Signer: suite.chainA.SenderAccount.GetAddress().String()}
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "invalid clientstate",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, ibctesting.DefaultConsensusParams, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
suite.coordinator.CommitBlock(suite.chainB)
|
||||
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
|
||||
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradeHeight, proofUpgrade, suite.chainA.SenderAccount.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "VerifyUpgrade fails",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, ibctesting.DefaultConsensusParams, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
suite.coordinator.CommitBlock(suite.chainB)
|
||||
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradeHeight, nil, suite.chainA.SenderAccount.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
clientA, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, ibctesting.Tendermint)
|
||||
|
||||
tc.setup()
|
||||
|
||||
_, err := keeper.Keeper.UpgradeClient(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err, "upgrade handler failed on valid case: %s", tc.name)
|
||||
newClient, ok := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(ok)
|
||||
suite.Require().Equal(upgradedClient, newClient)
|
||||
} else {
|
||||
suite.Require().Error(err, "upgrade handler passed on invalid case: %s", tc.name)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -130,8 +130,11 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd
|
|||
return nil
|
||||
}
|
||||
|
||||
// RegisterQueryService registers the gRPC query service for the ibc module.
|
||||
// RegisterServices registers module services.
|
||||
func (am AppModule) RegisterServices(cfg module.Configurator) {
|
||||
clienttypes.RegisterMsgServer(cfg.MsgServer(), am.keeper)
|
||||
connectiontypes.RegisterMsgServer(cfg.MsgServer(), am.keeper)
|
||||
channeltypes.RegisterMsgServer(cfg.MsgServer(), am.keeper)
|
||||
types.RegisterQueryService(cfg.QueryServer(), am.keeper)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue