x/ibc: packet commitment deletion after ack verification (#6292)
* add deletion of packet commitments to AcknowledgePacket and remove CleanupPacket * update tests * add replay test for unordered channels * add cleanup back, update tests * remove nolint * add timeoutonclose handling and fix * add check for deleted packets * Update x/ibc/04-channel/keeper/keeper.go Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> * add ackexecuted and update tests * add timeoutexecuted back and update test * move events to executed funcs * update handler * update godoc Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
parent
47d0fed2b0
commit
654b2fdd10
|
@ -2,8 +2,8 @@ package client
|
||||||
|
|
||||||
// autogenerated code using github.com/rigelrozanski/multitool
|
// autogenerated code using github.com/rigelrozanski/multitool
|
||||||
// aliases generated for the following subdirectories:
|
// aliases generated for the following subdirectories:
|
||||||
// ALIASGEN: github.com/cosmos/cosmos-sdk/x/ibc/02-client/keeper
|
|
||||||
// ALIASGEN: github.com/cosmos/cosmos-sdk/x/ibc/02-client/types
|
// ALIASGEN: github.com/cosmos/cosmos-sdk/x/ibc/02-client/types
|
||||||
|
// ALIASGEN: github.com/cosmos/cosmos-sdk/x/ibc/02-client/keeper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/keeper"
|
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/keeper"
|
||||||
|
@ -11,45 +11,61 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AttributeKeyClientID = types.AttributeKeyClientID
|
AttributeKeyClientID = types.AttributeKeyClientID
|
||||||
AttrbuteKeyClientType = types.AttributeKeyClientType
|
AttributeKeyClientType = types.AttributeKeyClientType
|
||||||
SubModuleName = types.SubModuleName
|
SubModuleName = types.SubModuleName
|
||||||
RouterKey = types.RouterKey
|
RouterKey = types.RouterKey
|
||||||
QuerierRoute = types.QuerierRoute
|
QuerierRoute = types.QuerierRoute
|
||||||
QueryAllClients = types.QueryAllClients
|
QueryAllClients = types.QueryAllClients
|
||||||
QueryClientState = types.QueryClientState
|
QueryClientState = types.QueryClientState
|
||||||
QueryConsensusState = types.QueryConsensusState
|
QueryConsensusState = types.QueryConsensusState
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// functions aliases
|
// functions aliases
|
||||||
|
RegisterCodec = types.RegisterCodec
|
||||||
|
SetSubModuleCodec = types.SetSubModuleCodec
|
||||||
|
NewClientConsensusStates = types.NewClientConsensusStates
|
||||||
|
NewGenesisState = types.NewGenesisState
|
||||||
|
DefaultGenesisState = types.DefaultGenesisState
|
||||||
|
NewQueryAllClientsParams = types.NewQueryAllClientsParams
|
||||||
|
NewClientStateResponse = types.NewClientStateResponse
|
||||||
|
NewConsensusStateResponse = types.NewConsensusStateResponse
|
||||||
NewKeeper = keeper.NewKeeper
|
NewKeeper = keeper.NewKeeper
|
||||||
QuerierClients = keeper.QuerierClients
|
QuerierClients = keeper.QuerierClients
|
||||||
RegisterCodec = types.RegisterCodec
|
|
||||||
ErrClientExists = types.ErrClientExists
|
|
||||||
ErrClientNotFound = types.ErrClientNotFound
|
|
||||||
ErrClientFrozen = types.ErrClientFrozen
|
|
||||||
ErrConsensusStateNotFound = types.ErrConsensusStateNotFound
|
|
||||||
ErrInvalidConsensus = types.ErrInvalidConsensus
|
|
||||||
ErrClientTypeNotFound = types.ErrClientTypeNotFound
|
|
||||||
ErrInvalidClientType = types.ErrInvalidClientType
|
|
||||||
ErrRootNotFound = types.ErrRootNotFound
|
|
||||||
ErrInvalidHeader = types.ErrInvalidHeader
|
|
||||||
ErrInvalidEvidence = types.ErrInvalidEvidence
|
|
||||||
DefaultGenesisState = types.DefaultGenesisState
|
|
||||||
NewGenesisState = types.NewGenesisState
|
|
||||||
NewClientConsensusStates = types.NewClientConsensusStates
|
|
||||||
|
|
||||||
// variable aliases
|
// variable aliases
|
||||||
SubModuleCdc = types.SubModuleCdc
|
SubModuleCdc = types.SubModuleCdc
|
||||||
EventTypeCreateClient = types.EventTypeCreateClient
|
ErrClientExists = types.ErrClientExists
|
||||||
EventTypeUpdateClient = types.EventTypeUpdateClient
|
ErrClientNotFound = types.ErrClientNotFound
|
||||||
AttributeValueCategory = types.AttributeValueCategory
|
ErrClientFrozen = types.ErrClientFrozen
|
||||||
|
ErrConsensusStateNotFound = types.ErrConsensusStateNotFound
|
||||||
|
ErrInvalidConsensus = types.ErrInvalidConsensus
|
||||||
|
ErrClientTypeNotFound = types.ErrClientTypeNotFound
|
||||||
|
ErrInvalidClientType = types.ErrInvalidClientType
|
||||||
|
ErrRootNotFound = types.ErrRootNotFound
|
||||||
|
ErrInvalidHeader = types.ErrInvalidHeader
|
||||||
|
ErrInvalidEvidence = types.ErrInvalidEvidence
|
||||||
|
ErrFailedClientConsensusStateVerification = types.ErrFailedClientConsensusStateVerification
|
||||||
|
ErrFailedConnectionStateVerification = types.ErrFailedConnectionStateVerification
|
||||||
|
ErrFailedChannelStateVerification = types.ErrFailedChannelStateVerification
|
||||||
|
ErrFailedPacketCommitmentVerification = types.ErrFailedPacketCommitmentVerification
|
||||||
|
ErrFailedPacketAckVerification = types.ErrFailedPacketAckVerification
|
||||||
|
ErrFailedPacketAckAbsenceVerification = types.ErrFailedPacketAckAbsenceVerification
|
||||||
|
ErrFailedNextSeqRecvVerification = types.ErrFailedNextSeqRecvVerification
|
||||||
|
ErrSelfConsensusStateNotFound = types.ErrSelfConsensusStateNotFound
|
||||||
|
EventTypeCreateClient = types.EventTypeCreateClient
|
||||||
|
EventTypeUpdateClient = types.EventTypeUpdateClient
|
||||||
|
EventTypeSubmitMisbehaviour = types.EventTypeSubmitMisbehaviour
|
||||||
|
AttributeValueCategory = types.AttributeValueCategory
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Keeper = keeper.Keeper
|
StakingKeeper = types.StakingKeeper
|
||||||
StakingKeeper = types.StakingKeeper
|
ConsensusStates = types.ClientConsensusStates
|
||||||
GenesisState = types.GenesisState
|
GenesisState = types.GenesisState
|
||||||
ConsensusStates = types.ClientConsensusStates
|
QueryAllClientsParams = types.QueryAllClientsParams
|
||||||
|
StateResponse = types.StateResponse
|
||||||
|
ConsensusStateResponse = types.ConsensusStateResponse
|
||||||
|
Keeper = keeper.Keeper
|
||||||
)
|
)
|
||||||
|
|
|
@ -47,7 +47,7 @@ func HandleMsgCreateClient(ctx sdk.Context, k Keeper, msg exported.MsgCreateClie
|
||||||
sdk.NewEvent(
|
sdk.NewEvent(
|
||||||
EventTypeCreateClient,
|
EventTypeCreateClient,
|
||||||
sdk.NewAttribute(AttributeKeyClientID, msg.GetClientID()),
|
sdk.NewAttribute(AttributeKeyClientID, msg.GetClientID()),
|
||||||
sdk.NewAttribute(AttrbuteKeyClientType, msg.GetClientType()),
|
sdk.NewAttribute(AttributeKeyClientType, msg.GetClientType()),
|
||||||
),
|
),
|
||||||
sdk.NewEvent(
|
sdk.NewEvent(
|
||||||
sdk.EventTypeMessage,
|
sdk.EventTypeMessage,
|
||||||
|
|
|
@ -85,7 +85,7 @@ func (suite *KeeperTestSuite) TestChanOpenTry() {
|
||||||
{"success", func() {
|
{"success", func() {
|
||||||
suite.chainA.CreateClient(suite.chainB)
|
suite.chainA.CreateClient(suite.chainB)
|
||||||
suite.chainB.CreateClient(suite.chainA)
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
_ = suite.chainA.createConnection(
|
suite.chainA.createConnection(
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
|
@ -94,27 +94,27 @@ func (suite *KeeperTestSuite) TestChanOpenTry() {
|
||||||
suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.INIT, types.ORDERED, testConnectionIDA)
|
suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.INIT, types.ORDERED, testConnectionIDA)
|
||||||
}, true},
|
}, true},
|
||||||
{"previous channel with invalid state", func() {
|
{"previous channel with invalid state", func() {
|
||||||
_ = suite.chainA.createChannel(
|
suite.chainA.createChannel(
|
||||||
testPort2, testChannel2, testPort1, testChannel1, types.UNINITIALIZED,
|
testPort2, testChannel2, testPort1, testChannel1, types.UNINITIALIZED,
|
||||||
types.ORDERED, testConnectionIDB,
|
types.ORDERED, testConnectionIDB,
|
||||||
)
|
)
|
||||||
}, false},
|
}, false},
|
||||||
{"connection doesn't exist", func() {}, false},
|
{"connection doesn't exist", func() {}, false},
|
||||||
{"connection is not OPEN", func() {
|
{"connection is not OPEN", func() {
|
||||||
_ = suite.chainA.createConnection(
|
suite.chainA.createConnection(
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
||||||
connection.INIT,
|
connection.INIT,
|
||||||
)
|
)
|
||||||
}, false},
|
}, false},
|
||||||
{"consensus state not found", func() {
|
{"consensus state not found", func() {
|
||||||
_ = suite.chainA.createConnection(
|
suite.chainA.createConnection(
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
}, false},
|
}, false},
|
||||||
{"channel verification failed", func() {
|
{"channel verification failed", func() {
|
||||||
suite.chainA.CreateClient(suite.chainB)
|
suite.chainA.CreateClient(suite.chainB)
|
||||||
_ = suite.chainA.createConnection(
|
suite.chainA.createConnection(
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
|
@ -122,7 +122,7 @@ func (suite *KeeperTestSuite) TestChanOpenTry() {
|
||||||
{"port capability not found", func() {
|
{"port capability not found", func() {
|
||||||
suite.chainA.CreateClient(suite.chainB)
|
suite.chainA.CreateClient(suite.chainB)
|
||||||
suite.chainB.CreateClient(suite.chainA)
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
_ = suite.chainA.createConnection(
|
suite.chainA.createConnection(
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
|
@ -187,11 +187,11 @@ func (suite *KeeperTestSuite) TestChanOpenAck() {
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainB.createConnection(
|
suite.chainB.createConnection(
|
||||||
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainA.createChannel(
|
suite.chainA.createChannel(
|
||||||
testPort1, testChannel1, testPort2, testChannel2, types.INIT,
|
testPort1, testChannel1, testPort2, testChannel2, types.INIT,
|
||||||
types.ORDERED, testConnectionIDB,
|
types.ORDERED, testConnectionIDB,
|
||||||
)
|
)
|
||||||
|
@ -202,44 +202,44 @@ func (suite *KeeperTestSuite) TestChanOpenAck() {
|
||||||
}, true},
|
}, true},
|
||||||
{"channel doesn't exist", func() {}, false},
|
{"channel doesn't exist", func() {}, false},
|
||||||
{"channel state is not INIT or TRYOPEN", func() {
|
{"channel state is not INIT or TRYOPEN", func() {
|
||||||
_ = suite.chainB.createChannel(
|
suite.chainB.createChannel(
|
||||||
testPort1, testChannel1, testPort2, testChannel2, types.UNINITIALIZED,
|
testPort1, testChannel1, testPort2, testChannel2, types.UNINITIALIZED,
|
||||||
types.ORDERED, testConnectionIDA,
|
types.ORDERED, testConnectionIDA,
|
||||||
)
|
)
|
||||||
}, false},
|
}, false},
|
||||||
{"connection not found", func() {
|
{"connection not found", func() {
|
||||||
_ = suite.chainB.createChannel(
|
suite.chainB.createChannel(
|
||||||
testPort1, testChannel1, testPort2, testChannel2, types.TRYOPEN,
|
testPort1, testChannel1, testPort2, testChannel2, types.TRYOPEN,
|
||||||
types.ORDERED, testConnectionIDA,
|
types.ORDERED, testConnectionIDA,
|
||||||
)
|
)
|
||||||
}, false},
|
}, false},
|
||||||
{"connection is not OPEN", func() {
|
{"connection is not OPEN", func() {
|
||||||
_ = suite.chainB.createConnection(
|
suite.chainB.createConnection(
|
||||||
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
||||||
connection.TRYOPEN,
|
connection.TRYOPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainB.createChannel(
|
suite.chainB.createChannel(
|
||||||
testPort1, testChannel1, testPort2, testChannel2, types.TRYOPEN,
|
testPort1, testChannel1, testPort2, testChannel2, types.TRYOPEN,
|
||||||
types.ORDERED, testConnectionIDA,
|
types.ORDERED, testConnectionIDA,
|
||||||
)
|
)
|
||||||
}, false},
|
}, false},
|
||||||
{"consensus state not found", func() {
|
{"consensus state not found", func() {
|
||||||
_ = suite.chainB.createConnection(
|
suite.chainB.createConnection(
|
||||||
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainB.createChannel(
|
suite.chainB.createChannel(
|
||||||
testPort1, testChannel1, testPort2, testChannel2, types.TRYOPEN,
|
testPort1, testChannel1, testPort2, testChannel2, types.TRYOPEN,
|
||||||
types.ORDERED, testConnectionIDA,
|
types.ORDERED, testConnectionIDA,
|
||||||
)
|
)
|
||||||
}, false},
|
}, false},
|
||||||
{"channel verification failed", func() {
|
{"channel verification failed", func() {
|
||||||
suite.chainB.CreateClient(suite.chainA)
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
_ = suite.chainB.createConnection(
|
suite.chainB.createConnection(
|
||||||
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainB.createChannel(
|
suite.chainB.createChannel(
|
||||||
testPort1, testChannel1, testPort2, testChannel2, types.TRYOPEN,
|
testPort1, testChannel1, testPort2, testChannel2, types.TRYOPEN,
|
||||||
types.ORDERED, testConnectionIDA,
|
types.ORDERED, testConnectionIDA,
|
||||||
)
|
)
|
||||||
|
@ -251,11 +251,11 @@ func (suite *KeeperTestSuite) TestChanOpenAck() {
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainB.createConnection(
|
suite.chainB.createConnection(
|
||||||
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainA.createChannel(
|
suite.chainA.createChannel(
|
||||||
testPort1, testChannel1, testPort2, testChannel2, types.INIT,
|
testPort1, testChannel1, testPort2, testChannel2, types.INIT,
|
||||||
types.ORDERED, testConnectionIDB,
|
types.ORDERED, testConnectionIDB,
|
||||||
)
|
)
|
||||||
|
@ -308,69 +308,7 @@ func (suite *KeeperTestSuite) TestChanOpenConfirm() {
|
||||||
{"success", func() {
|
{"success", func() {
|
||||||
suite.chainA.CreateClient(suite.chainB)
|
suite.chainA.CreateClient(suite.chainB)
|
||||||
suite.chainB.CreateClient(suite.chainA)
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
_ = suite.chainA.createConnection(
|
suite.chainA.createConnection(
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
|
||||||
connection.TRYOPEN,
|
|
||||||
)
|
|
||||||
_ = suite.chainB.createConnection(
|
|
||||||
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
|
||||||
connection.OPEN,
|
|
||||||
)
|
|
||||||
_ = suite.chainA.createChannel(
|
|
||||||
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
|
||||||
types.ORDERED, testConnectionIDB,
|
|
||||||
)
|
|
||||||
_ = suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2,
|
|
||||||
types.TRYOPEN, types.ORDERED, testConnectionIDA)
|
|
||||||
}, true},
|
|
||||||
{"channel doesn't exist", func() {}, false},
|
|
||||||
{"channel state is not TRYOPEN", func() {
|
|
||||||
_ = suite.chainA.createChannel(
|
|
||||||
testPort1, testChannel1, testPort2, testChannel2, types.UNINITIALIZED,
|
|
||||||
types.ORDERED, testConnectionIDB,
|
|
||||||
)
|
|
||||||
}, false},
|
|
||||||
{"connection not found", func() {
|
|
||||||
_ = suite.chainA.createChannel(
|
|
||||||
testPort2, testChannel2, testPort1, testChannel1, types.TRYOPEN,
|
|
||||||
types.ORDERED, testConnectionIDB,
|
|
||||||
)
|
|
||||||
}, false},
|
|
||||||
{"connection is not OPEN", func() {
|
|
||||||
_ = suite.chainA.createConnection(
|
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
|
||||||
connection.TRYOPEN,
|
|
||||||
)
|
|
||||||
_ = suite.chainA.createChannel(
|
|
||||||
testPort2, testChannel2, testPort1, testChannel1, types.TRYOPEN,
|
|
||||||
types.ORDERED, testConnectionIDB,
|
|
||||||
)
|
|
||||||
}, false},
|
|
||||||
{"consensus state not found", func() {
|
|
||||||
_ = suite.chainA.createConnection(
|
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
|
||||||
connection.OPEN,
|
|
||||||
)
|
|
||||||
_ = suite.chainA.createChannel(
|
|
||||||
testPort2, testChannel2, testPort1, testChannel1, types.TRYOPEN,
|
|
||||||
types.ORDERED, testConnectionIDB,
|
|
||||||
)
|
|
||||||
}, false},
|
|
||||||
{"channel verification failed", func() {
|
|
||||||
suite.chainA.CreateClient(suite.chainB)
|
|
||||||
_ = suite.chainA.createConnection(
|
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
|
||||||
connection.OPEN,
|
|
||||||
)
|
|
||||||
_ = suite.chainA.createChannel(
|
|
||||||
testPort2, testChannel2, testPort1, testChannel1, types.TRYOPEN,
|
|
||||||
types.ORDERED, testConnectionIDB,
|
|
||||||
)
|
|
||||||
}, false},
|
|
||||||
{"channel capability not found", func() {
|
|
||||||
suite.chainA.CreateClient(suite.chainB)
|
|
||||||
suite.chainB.CreateClient(suite.chainA)
|
|
||||||
_ = suite.chainA.createConnection(
|
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
||||||
connection.TRYOPEN,
|
connection.TRYOPEN,
|
||||||
)
|
)
|
||||||
|
@ -378,7 +316,69 @@ func (suite *KeeperTestSuite) TestChanOpenConfirm() {
|
||||||
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainA.createChannel(
|
suite.chainA.createChannel(
|
||||||
|
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
||||||
|
types.ORDERED, testConnectionIDB,
|
||||||
|
)
|
||||||
|
suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2,
|
||||||
|
types.TRYOPEN, types.ORDERED, testConnectionIDA)
|
||||||
|
}, true},
|
||||||
|
{"channel doesn't exist", func() {}, false},
|
||||||
|
{"channel state is not TRYOPEN", func() {
|
||||||
|
suite.chainA.createChannel(
|
||||||
|
testPort1, testChannel1, testPort2, testChannel2, types.UNINITIALIZED,
|
||||||
|
types.ORDERED, testConnectionIDB,
|
||||||
|
)
|
||||||
|
}, false},
|
||||||
|
{"connection not found", func() {
|
||||||
|
suite.chainA.createChannel(
|
||||||
|
testPort2, testChannel2, testPort1, testChannel1, types.TRYOPEN,
|
||||||
|
types.ORDERED, testConnectionIDB,
|
||||||
|
)
|
||||||
|
}, false},
|
||||||
|
{"connection is not OPEN", func() {
|
||||||
|
suite.chainA.createConnection(
|
||||||
|
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
||||||
|
connection.TRYOPEN,
|
||||||
|
)
|
||||||
|
suite.chainA.createChannel(
|
||||||
|
testPort2, testChannel2, testPort1, testChannel1, types.TRYOPEN,
|
||||||
|
types.ORDERED, testConnectionIDB,
|
||||||
|
)
|
||||||
|
}, false},
|
||||||
|
{"consensus state not found", func() {
|
||||||
|
suite.chainA.createConnection(
|
||||||
|
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
||||||
|
connection.OPEN,
|
||||||
|
)
|
||||||
|
suite.chainA.createChannel(
|
||||||
|
testPort2, testChannel2, testPort1, testChannel1, types.TRYOPEN,
|
||||||
|
types.ORDERED, testConnectionIDB,
|
||||||
|
)
|
||||||
|
}, false},
|
||||||
|
{"channel verification failed", func() {
|
||||||
|
suite.chainA.CreateClient(suite.chainB)
|
||||||
|
suite.chainA.createConnection(
|
||||||
|
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
||||||
|
connection.OPEN,
|
||||||
|
)
|
||||||
|
suite.chainA.createChannel(
|
||||||
|
testPort2, testChannel2, testPort1, testChannel1, types.TRYOPEN,
|
||||||
|
types.ORDERED, testConnectionIDB,
|
||||||
|
)
|
||||||
|
}, false},
|
||||||
|
{"channel capability not found", func() {
|
||||||
|
suite.chainA.CreateClient(suite.chainB)
|
||||||
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
|
suite.chainA.createConnection(
|
||||||
|
testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA,
|
||||||
|
connection.TRYOPEN,
|
||||||
|
)
|
||||||
|
suite.chainB.createConnection(
|
||||||
|
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
||||||
|
connection.OPEN,
|
||||||
|
)
|
||||||
|
suite.chainA.createChannel(
|
||||||
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
||||||
types.ORDERED, testConnectionIDB,
|
types.ORDERED, testConnectionIDB,
|
||||||
)
|
)
|
||||||
|
@ -426,45 +426,45 @@ func (suite *KeeperTestSuite) TestChanCloseInit() {
|
||||||
testCases := []testCase{
|
testCases := []testCase{
|
||||||
{"success", func() {
|
{"success", func() {
|
||||||
suite.chainB.CreateClient(suite.chainA)
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
_ = suite.chainA.createConnection(
|
suite.chainA.createConnection(
|
||||||
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainA.createChannel(
|
suite.chainA.createChannel(
|
||||||
testPort1, testChannel1, testPort2, testChannel2, types.OPEN,
|
testPort1, testChannel1, testPort2, testChannel2, types.OPEN,
|
||||||
types.ORDERED, testConnectionIDA,
|
types.ORDERED, testConnectionIDA,
|
||||||
)
|
)
|
||||||
}, true},
|
}, true},
|
||||||
{"channel doesn't exist", func() {}, false},
|
{"channel doesn't exist", func() {}, false},
|
||||||
{"channel state is CLOSED", func() {
|
{"channel state is CLOSED", func() {
|
||||||
_ = suite.chainA.createChannel(
|
suite.chainA.createChannel(
|
||||||
testPort1, testChannel1, testPort2, testChannel2, types.CLOSED,
|
testPort1, testChannel1, testPort2, testChannel2, types.CLOSED,
|
||||||
types.ORDERED, testConnectionIDB,
|
types.ORDERED, testConnectionIDB,
|
||||||
)
|
)
|
||||||
}, false},
|
}, false},
|
||||||
{"connection not found", func() {
|
{"connection not found", func() {
|
||||||
_ = suite.chainA.createChannel(
|
suite.chainA.createChannel(
|
||||||
testPort1, testChannel1, testPort2, testChannel2, types.OPEN,
|
testPort1, testChannel1, testPort2, testChannel2, types.OPEN,
|
||||||
types.ORDERED, testConnectionIDA,
|
types.ORDERED, testConnectionIDA,
|
||||||
)
|
)
|
||||||
}, false},
|
}, false},
|
||||||
{"connection is not OPEN", func() {
|
{"connection is not OPEN", func() {
|
||||||
_ = suite.chainA.createConnection(
|
suite.chainA.createConnection(
|
||||||
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
||||||
connection.TRYOPEN,
|
connection.TRYOPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainA.createChannel(
|
suite.chainA.createChannel(
|
||||||
testPort1, testChannel1, testPort2, testChannel2, types.UNINITIALIZED,
|
testPort1, testChannel1, testPort2, testChannel2, types.UNINITIALIZED,
|
||||||
types.ORDERED, testConnectionIDA,
|
types.ORDERED, testConnectionIDA,
|
||||||
)
|
)
|
||||||
}, false},
|
}, false},
|
||||||
{"channel capability not found", func() {
|
{"channel capability not found", func() {
|
||||||
suite.chainB.CreateClient(suite.chainA)
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
_ = suite.chainA.createConnection(
|
suite.chainA.createConnection(
|
||||||
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainA.createChannel(
|
suite.chainA.createChannel(
|
||||||
testPort1, testChannel1, testPort2, testChannel2, types.OPEN,
|
testPort1, testChannel1, testPort2, testChannel2, types.OPEN,
|
||||||
types.ORDERED, testConnectionIDA,
|
types.ORDERED, testConnectionIDA,
|
||||||
)
|
)
|
||||||
|
@ -504,7 +504,7 @@ func (suite *KeeperTestSuite) TestChanCloseConfirm() {
|
||||||
{"success", func() {
|
{"success", func() {
|
||||||
suite.chainA.CreateClient(suite.chainB)
|
suite.chainA.CreateClient(suite.chainB)
|
||||||
suite.chainB.CreateClient(suite.chainA)
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
_ = suite.chainB.createConnection(
|
suite.chainB.createConnection(
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDA, testClientIDB,
|
testConnectionIDB, testConnectionIDA, testClientIDA, testClientIDB,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
|
@ -512,7 +512,7 @@ func (suite *KeeperTestSuite) TestChanCloseConfirm() {
|
||||||
testConnectionIDA, testConnectionIDB, testClientIDB, testClientIDA,
|
testConnectionIDA, testConnectionIDB, testClientIDB, testClientIDA,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainB.createChannel(
|
suite.chainB.createChannel(
|
||||||
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
||||||
types.ORDERED, testConnectionIDB,
|
types.ORDERED, testConnectionIDB,
|
||||||
)
|
)
|
||||||
|
@ -523,44 +523,44 @@ func (suite *KeeperTestSuite) TestChanCloseConfirm() {
|
||||||
}, true},
|
}, true},
|
||||||
{"channel doesn't exist", func() {}, false},
|
{"channel doesn't exist", func() {}, false},
|
||||||
{"channel state is CLOSED", func() {
|
{"channel state is CLOSED", func() {
|
||||||
_ = suite.chainB.createChannel(
|
suite.chainB.createChannel(
|
||||||
testPort2, testChannel2, testPort1, testChannel1, types.CLOSED,
|
testPort2, testChannel2, testPort1, testChannel1, types.CLOSED,
|
||||||
types.ORDERED, testConnectionIDB,
|
types.ORDERED, testConnectionIDB,
|
||||||
)
|
)
|
||||||
}, false},
|
}, false},
|
||||||
{"connection not found", func() {
|
{"connection not found", func() {
|
||||||
_ = suite.chainB.createChannel(
|
suite.chainB.createChannel(
|
||||||
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
||||||
types.ORDERED, testConnectionIDA,
|
types.ORDERED, testConnectionIDA,
|
||||||
)
|
)
|
||||||
}, false},
|
}, false},
|
||||||
{"connection is not OPEN", func() {
|
{"connection is not OPEN", func() {
|
||||||
_ = suite.chainB.createConnection(
|
suite.chainB.createConnection(
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDA, testClientIDB,
|
testConnectionIDB, testConnectionIDA, testClientIDA, testClientIDB,
|
||||||
connection.TRYOPEN,
|
connection.TRYOPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainB.createChannel(
|
suite.chainB.createChannel(
|
||||||
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
||||||
types.ORDERED, testConnectionIDB,
|
types.ORDERED, testConnectionIDB,
|
||||||
)
|
)
|
||||||
}, false},
|
}, false},
|
||||||
{"consensus state not found", func() {
|
{"consensus state not found", func() {
|
||||||
_ = suite.chainB.createConnection(
|
suite.chainB.createConnection(
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDA, testClientIDB,
|
testConnectionIDB, testConnectionIDA, testClientIDA, testClientIDB,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainB.createChannel(
|
suite.chainB.createChannel(
|
||||||
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
||||||
types.ORDERED, testConnectionIDB,
|
types.ORDERED, testConnectionIDB,
|
||||||
)
|
)
|
||||||
}, false},
|
}, false},
|
||||||
{"channel verification failed", func() {
|
{"channel verification failed", func() {
|
||||||
suite.chainB.CreateClient(suite.chainA)
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
_ = suite.chainB.createConnection(
|
suite.chainB.createConnection(
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDA, testClientIDB,
|
testConnectionIDB, testConnectionIDA, testClientIDA, testClientIDB,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainB.createChannel(
|
suite.chainB.createChannel(
|
||||||
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
||||||
types.ORDERED, testConnectionIDB,
|
types.ORDERED, testConnectionIDB,
|
||||||
)
|
)
|
||||||
|
@ -568,7 +568,7 @@ func (suite *KeeperTestSuite) TestChanCloseConfirm() {
|
||||||
{"channel capability not found", func() {
|
{"channel capability not found", func() {
|
||||||
suite.chainA.CreateClient(suite.chainB)
|
suite.chainA.CreateClient(suite.chainB)
|
||||||
suite.chainB.CreateClient(suite.chainA)
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
_ = suite.chainB.createConnection(
|
suite.chainB.createConnection(
|
||||||
testConnectionIDB, testConnectionIDA, testClientIDA, testClientIDB,
|
testConnectionIDB, testConnectionIDA, testClientIDA, testClientIDB,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
|
@ -576,7 +576,7 @@ func (suite *KeeperTestSuite) TestChanCloseConfirm() {
|
||||||
testConnectionIDA, testConnectionIDB, testClientIDB, testClientIDA,
|
testConnectionIDA, testConnectionIDB, testClientIDB, testClientIDA,
|
||||||
connection.OPEN,
|
connection.OPEN,
|
||||||
)
|
)
|
||||||
_ = suite.chainB.createChannel(
|
suite.chainB.createChannel(
|
||||||
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
testPort2, testChannel2, testPort1, testChannel1, types.OPEN,
|
||||||
types.ORDERED, testConnectionIDB,
|
types.ORDERED, testConnectionIDB,
|
||||||
)
|
)
|
||||||
|
|
|
@ -128,6 +128,11 @@ func (k Keeper) GetPacketCommitment(ctx sdk.Context, portID, channelID string, s
|
||||||
return bz
|
return bz
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasPacketCommitment returns true if the packet commitment exists
|
||||||
|
func (k Keeper) HasPacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64) bool {
|
||||||
|
return len(k.GetPacketCommitment(ctx, portID, channelID, sequence)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
// SetPacketCommitment sets the packet commitment hash to the store
|
// SetPacketCommitment sets the packet commitment hash to the store
|
||||||
func (k Keeper) SetPacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64, commitmentHash []byte) {
|
func (k Keeper) SetPacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64, commitmentHash []byte) {
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
@ -139,6 +144,19 @@ func (k Keeper) deletePacketCommitment(ctx sdk.Context, portID, channelID string
|
||||||
store.Delete(host.KeyPacketCommitment(portID, channelID, sequence))
|
store.Delete(host.KeyPacketCommitment(portID, channelID, sequence))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// deletePacketCommitmentsLTE removes all consecutive packet commitments less than or equal to sequence
|
||||||
|
//
|
||||||
|
// CONTRACT: this function can only be used for ORDERED channel batch clearing
|
||||||
|
func (k Keeper) deletePacketCommitmentsLTE(ctx sdk.Context, portID, channelID string, sequence uint64) {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
for i := sequence; i > 0; i-- {
|
||||||
|
if !k.HasPacketCommitment(ctx, portID, channelID, i) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
store.Delete(host.KeyPacketCommitment(portID, channelID, i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SetPacketAcknowledgement sets the packet ack hash to the store
|
// SetPacketAcknowledgement sets the packet ack hash to the store
|
||||||
func (k Keeper) SetPacketAcknowledgement(ctx sdk.Context, portID, channelID string, sequence uint64, ackHash []byte) {
|
func (k Keeper) SetPacketAcknowledgement(ctx sdk.Context, portID, channelID string, sequence uint64, ackHash []byte) {
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
|
|
@ -432,8 +432,10 @@ func (chain *TestChain) createChannel(
|
||||||
state types.State, order types.Order, connectionID string,
|
state types.State, order types.Order, connectionID string,
|
||||||
) types.Channel {
|
) types.Channel {
|
||||||
counterparty := types.NewCounterparty(counterpartyPortID, counterpartyChannelID)
|
counterparty := types.NewCounterparty(counterpartyPortID, counterpartyChannelID)
|
||||||
|
|
||||||
|
// sets channel with given state
|
||||||
channel := types.NewChannel(state, order, counterparty,
|
channel := types.NewChannel(state, order, counterparty,
|
||||||
[]string{connectionID}, "1.0",
|
[]string{connectionID}, testChannelVersion,
|
||||||
)
|
)
|
||||||
ctx := chain.GetContext()
|
ctx := chain.GetContext()
|
||||||
chain.App.IBCKeeper.ChannelKeeper.SetChannel(ctx, portID, channelID, channel)
|
chain.App.IBCKeeper.ChannelKeeper.SetChannel(ctx, portID, channelID, channel)
|
||||||
|
|
|
@ -292,9 +292,10 @@ func (k Keeper) PacketExecuted(
|
||||||
|
|
||||||
// AcknowledgePacket is called by a module to process the acknowledgement of a
|
// AcknowledgePacket is called by a module to process the acknowledgement of a
|
||||||
// packet previously sent by the calling module on a channel to a counterparty
|
// packet previously sent by the calling module on a channel to a counterparty
|
||||||
// module on the counterparty chain. acknowledgePacket also cleans up the packet
|
// module on the counterparty chain. Its intended usage is within the ante
|
||||||
// commitment, which is no longer necessary since the packet has been received
|
// handler. A subsequent call to AcknowledgementExecuted will clean up the
|
||||||
// and acted upon.
|
// packet commitment, which is no longer necessary since the packet has been
|
||||||
|
// received and acted upon.
|
||||||
func (k Keeper) AcknowledgePacket(
|
func (k Keeper) AcknowledgePacket(
|
||||||
ctx sdk.Context,
|
ctx sdk.Context,
|
||||||
packet exported.PacketI,
|
packet exported.PacketI,
|
||||||
|
@ -304,7 +305,10 @@ func (k Keeper) AcknowledgePacket(
|
||||||
) (exported.PacketI, error) {
|
) (exported.PacketI, error) {
|
||||||
channel, found := k.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel())
|
channel, found := k.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel())
|
||||||
if !found {
|
if !found {
|
||||||
return nil, sdkerrors.Wrap(types.ErrChannelNotFound, packet.GetSourceChannel())
|
return nil, sdkerrors.Wrapf(
|
||||||
|
types.ErrChannelNotFound,
|
||||||
|
packet.GetSourcePort(), packet.GetSourceChannel(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if channel.State != types.OPEN {
|
if channel.State != types.OPEN {
|
||||||
|
@ -314,7 +318,7 @@ func (k Keeper) AcknowledgePacket(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: RecvPacket is called by the AnteHandler which acts upon the packet.Route(),
|
// NOTE: AcknowledgePacket is called by the AnteHandler which acts upon the packet.Route(),
|
||||||
// so the capability authentication can be omitted here
|
// so the capability authentication can be omitted here
|
||||||
|
|
||||||
// packet must have been sent to the channel's counterparty
|
// packet must have been sent to the channel's counterparty
|
||||||
|
@ -377,6 +381,38 @@ func (k Keeper) AcknowledgePacket(
|
||||||
k.SetNextSequenceAck(ctx, packet.GetDestPort(), packet.GetDestChannel(), nextSequenceAck+1)
|
k.SetNextSequenceAck(ctx, packet.GetDestPort(), packet.GetDestChannel(), nextSequenceAck+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: the remaining code is located in the AcknowledgementExecuted function
|
||||||
|
return packet, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AcknowledgementExecuted deletes the packet commitment from this chain.
|
||||||
|
// It is assumed that the acknowledgement verification has already occurred.
|
||||||
|
//
|
||||||
|
// NOTE: this function must be called in the handler
|
||||||
|
func (k Keeper) AcknowledgementExecuted(
|
||||||
|
ctx sdk.Context,
|
||||||
|
chanCap *capability.Capability,
|
||||||
|
packet exported.PacketI,
|
||||||
|
) error {
|
||||||
|
// sanity check
|
||||||
|
_, found := k.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel())
|
||||||
|
if !found {
|
||||||
|
return sdkerrors.Wrapf(
|
||||||
|
types.ErrChannelNotFound,
|
||||||
|
packet.GetSourcePort(), packet.GetSourceChannel(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
capName := host.ChannelCapabilityPath(packet.GetSourcePort(), packet.GetSourceChannel())
|
||||||
|
if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, capName) {
|
||||||
|
return sdkerrors.Wrap(
|
||||||
|
types.ErrInvalidChannelCapability,
|
||||||
|
"channel capability failed authentication",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
k.deletePacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
|
||||||
|
|
||||||
// log that a packet has been acknowledged
|
// log that a packet has been acknowledged
|
||||||
k.Logger(ctx).Info(fmt.Sprintf("packet acknowledged: %v", packet))
|
k.Logger(ctx).Info(fmt.Sprintf("packet acknowledged: %v", packet))
|
||||||
|
|
||||||
|
@ -394,21 +430,26 @@ func (k Keeper) AcknowledgePacket(
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
return packet, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanupPacket is called by a module to remove a received packet commitment
|
// CleanupPacket is called by a module to remove a received packet commitment
|
||||||
// from storage. The receiving end must have already processed the packet
|
// from storage. The receiving end must have already processed the packet
|
||||||
// (whether regularly or past timeout).
|
// (whether regularly or past timeout).
|
||||||
//
|
//
|
||||||
// In the ORDERED channel case, CleanupPacket cleans-up a packet on an ordered
|
// In the ORDERED channel case, CleanupPacket cleans-up all packets on an ordered
|
||||||
// channel by proving that the packet has been received on the other end.
|
// channel less than or equal to the packet's sequence by proving that the packet
|
||||||
|
// has been received on the other end.
|
||||||
//
|
//
|
||||||
// In the UNORDERED channel case, CleanupPacket cleans-up a packet on an
|
// In the UNORDERED channel case, CleanupPacket cleans-up a packet on an
|
||||||
// unordered channel by proving that the associated acknowledgement has been
|
// unordered channel by proving that the associated acknowledgement has been
|
||||||
//written.
|
// written.
|
||||||
|
//
|
||||||
|
// NOTE: this functionality is not compatible with calling AcknowledgePacket
|
||||||
|
// and must be handled at the application level.
|
||||||
func (k Keeper) CleanupPacket(
|
func (k Keeper) CleanupPacket(
|
||||||
ctx sdk.Context,
|
ctx sdk.Context,
|
||||||
|
chanCap *capability.Capability,
|
||||||
packet exported.PacketI,
|
packet exported.PacketI,
|
||||||
proof commitmentexported.Proof,
|
proof commitmentexported.Proof,
|
||||||
proofHeight,
|
proofHeight,
|
||||||
|
@ -427,17 +468,13 @@ func (k Keeper) CleanupPacket(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: blocked by #5542
|
capName := host.ChannelCapabilityPath(packet.GetSourcePort(), packet.GetSourceChannel())
|
||||||
// capKey, found := k.GetChannelCapability(ctx, packet.GetSourcePort(), packet.GetSourceChannel())
|
if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, capName) {
|
||||||
// if !found {
|
return nil, sdkerrors.Wrap(
|
||||||
// return nil, types.ErrChannelCapabilityNotFound
|
types.ErrInvalidChannelCapability,
|
||||||
// }
|
"channel capability failed authentication",
|
||||||
|
)
|
||||||
// portCapabilityKey := sdk.NewKVStoreKey(capKey)
|
}
|
||||||
|
|
||||||
// if !k.portKeeper.Authenticate(portCapabilityKey, packet.GetSourcePort()) {
|
|
||||||
// return nil, sdkerrors.Wrapf(port.ErrInvalidPort, "invalid source port: %s", packet.GetSourcePort())
|
|
||||||
// }
|
|
||||||
|
|
||||||
if packet.GetDestPort() != channel.Counterparty.PortID {
|
if packet.GetDestPort() != channel.Counterparty.PortID {
|
||||||
return nil, sdkerrors.Wrapf(types.ErrInvalidPacket,
|
return nil, sdkerrors.Wrapf(types.ErrInvalidPacket,
|
||||||
|
@ -459,40 +496,51 @@ func (k Keeper) CleanupPacket(
|
||||||
|
|
||||||
// check that packet has been received on the other end
|
// check that packet has been received on the other end
|
||||||
if nextSequenceRecv <= packet.GetSequence() {
|
if nextSequenceRecv <= packet.GetSequence() {
|
||||||
return nil, sdkerrors.Wrap(types.ErrInvalidPacket, "packet already received")
|
return nil, sdkerrors.Wrap(types.ErrInvalidPacket, "packet hasn't been received")
|
||||||
}
|
}
|
||||||
|
|
||||||
commitment := k.GetPacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
|
commitment := k.GetPacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
|
||||||
|
|
||||||
// verify we sent the packet and haven't cleared it out yet
|
// verify we sent the packet and haven't cleared it out yet
|
||||||
if !bytes.Equal(commitment, types.CommitPacket(packet)) {
|
if !bytes.Equal(commitment, types.CommitPacket(packet)) {
|
||||||
return nil, sdkerrors.Wrap(types.ErrInvalidPacket, "packet hasn't been sent")
|
return nil, sdkerrors.Wrap(types.ErrInvalidPacket, "packet hasn't been sent or has been cleaned up")
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
switch channel.Ordering {
|
switch channel.Ordering {
|
||||||
case types.ORDERED:
|
case types.ORDERED:
|
||||||
// check that the recv sequence is as claimed
|
// check that the recv sequence is as claimed
|
||||||
err = k.connectionKeeper.VerifyNextSequenceRecv(
|
if err := k.connectionKeeper.VerifyNextSequenceRecv(
|
||||||
ctx, connectionEnd, proofHeight, proof,
|
ctx, connectionEnd, proofHeight, proof,
|
||||||
packet.GetDestPort(), packet.GetDestChannel(), nextSequenceRecv,
|
packet.GetDestPort(), packet.GetDestChannel(), nextSequenceRecv,
|
||||||
)
|
); err != nil {
|
||||||
|
return nil, sdkerrors.Wrap(
|
||||||
|
client.ErrFailedNextSeqRecvVerification,
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete all packet commitments with a sequence less than or equal to the packet's sequence
|
||||||
|
k.deletePacketCommitmentsLTE(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
|
||||||
|
|
||||||
case types.UNORDERED:
|
case types.UNORDERED:
|
||||||
err = k.connectionKeeper.VerifyPacketAcknowledgement(
|
if err := k.connectionKeeper.VerifyPacketAcknowledgement(
|
||||||
ctx, connectionEnd, proofHeight, proof,
|
ctx, connectionEnd, proofHeight, proof,
|
||||||
packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(),
|
packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(),
|
||||||
acknowledgement,
|
acknowledgement,
|
||||||
)
|
); err != nil {
|
||||||
|
return nil, sdkerrors.Wrap(
|
||||||
|
client.ErrFailedPacketAckVerification,
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete the packet commitment
|
||||||
|
k.deletePacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic(sdkerrors.Wrapf(types.ErrInvalidChannelOrdering, channel.Ordering.String()))
|
panic(sdkerrors.Wrapf(types.ErrInvalidChannelOrdering, channel.Ordering.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, sdkerrors.Wrap(err, "packet verification failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
k.deletePacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
|
|
||||||
|
|
||||||
// log that a packet has been acknowledged
|
// log that a packet has been acknowledged
|
||||||
k.Logger(ctx).Info(fmt.Sprintf("packet cleaned-up: %v", packet))
|
k.Logger(ctx).Info(fmt.Sprintf("packet cleaned-up: %v", packet))
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection"
|
connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection"
|
||||||
"github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported"
|
"github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported"
|
||||||
"github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
|
"github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
|
||||||
|
commitmentexported "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/exported"
|
||||||
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
|
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -265,7 +266,7 @@ func (suite *KeeperTestSuite) TestAcknowledgePacket() {
|
||||||
}.GetBytes()
|
}.GetBytes()
|
||||||
|
|
||||||
testCases := []testCase{
|
testCases := []testCase{
|
||||||
{"success", func() {
|
{"success on ordered channel", func() {
|
||||||
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
||||||
suite.chainB.CreateClient(suite.chainA)
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
suite.chainA.CreateClient(suite.chainB)
|
suite.chainA.CreateClient(suite.chainB)
|
||||||
|
@ -277,6 +278,19 @@ func (suite *KeeperTestSuite) TestAcknowledgePacket() {
|
||||||
suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketAcknowledgement(suite.chainA.GetContext(), testPort2, testChannel2, 1, types.CommitAcknowledgement(ack))
|
suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketAcknowledgement(suite.chainA.GetContext(), testPort2, testChannel2, 1, types.CommitAcknowledgement(ack))
|
||||||
suite.chainB.App.IBCKeeper.ChannelKeeper.SetNextSequenceAck(suite.chainB.GetContext(), counterparty.GetPortID(), counterparty.GetChannelID(), 1)
|
suite.chainB.App.IBCKeeper.ChannelKeeper.SetNextSequenceAck(suite.chainB.GetContext(), counterparty.GetPortID(), counterparty.GetChannelID(), 1)
|
||||||
}, true},
|
}, true},
|
||||||
|
{"success on unordered channel", func() {
|
||||||
|
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
||||||
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
|
suite.chainA.CreateClient(suite.chainB)
|
||||||
|
suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connection.OPEN)
|
||||||
|
suite.chainA.createConnection(testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA, connection.OPEN)
|
||||||
|
suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.OPEN, types.UNORDERED, testConnectionIDA)
|
||||||
|
suite.chainA.createChannel(testPort2, testChannel2, testPort1, testChannel1, types.OPEN, types.UNORDERED, testConnectionIDB)
|
||||||
|
suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainB.GetContext(), testPort1, testChannel1, 1, types.CommitPacket(packet))
|
||||||
|
suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketAcknowledgement(suite.chainA.GetContext(), testPort2, testChannel2, 1, types.CommitAcknowledgement(ack))
|
||||||
|
suite.chainB.App.IBCKeeper.ChannelKeeper.SetNextSequenceAck(suite.chainB.GetContext(), counterparty.GetPortID(), counterparty.GetChannelID(), 1)
|
||||||
|
}, true},
|
||||||
|
|
||||||
{"channel not found", func() {}, false},
|
{"channel not found", func() {}, false},
|
||||||
{"channel not open", func() {
|
{"channel not open", func() {
|
||||||
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
||||||
|
@ -347,6 +361,7 @@ func (suite *KeeperTestSuite) TestAcknowledgePacket() {
|
||||||
|
|
||||||
ctx := suite.chainB.GetContext()
|
ctx := suite.chainB.GetContext()
|
||||||
packetOut, err := suite.chainB.App.IBCKeeper.ChannelKeeper.AcknowledgePacket(ctx, packet, ack, proof, proofHeight+1)
|
packetOut, err := suite.chainB.App.IBCKeeper.ChannelKeeper.AcknowledgePacket(ctx, packet, ack, proof, proofHeight+1)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
suite.Require().NotNil(packetOut)
|
suite.Require().NotNil(packetOut)
|
||||||
|
@ -358,18 +373,89 @@ func (suite *KeeperTestSuite) TestAcknowledgePacket() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestAcknowledgementExectued verifies that packet commitments are deleted after
|
||||||
|
// capabilities are verified.
|
||||||
|
func (suite *KeeperTestSuite) TestAcknowledgementExecuted() {
|
||||||
|
sequence := uint64(1)
|
||||||
|
counterparty := types.NewCounterparty(testPort2, testChannel2)
|
||||||
|
|
||||||
|
var (
|
||||||
|
packet types.Packet
|
||||||
|
chanCap *capability.Capability
|
||||||
|
)
|
||||||
|
|
||||||
|
testCases := []testCase{
|
||||||
|
{"success ORDERED", func() {
|
||||||
|
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), sequence, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
||||||
|
suite.chainA.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.OPEN, types.ORDERED, testConnectionIDA)
|
||||||
|
suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), sequence, types.CommitPacket(packet))
|
||||||
|
}, true},
|
||||||
|
{"channel not found", func() {}, false},
|
||||||
|
{"incorrect capability", func() {
|
||||||
|
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), sequence, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
||||||
|
suite.chainA.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.OPEN, types.ORDERED, testConnectionIDA)
|
||||||
|
chanCap = capability.NewCapability(100)
|
||||||
|
}, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tc := range testCases {
|
||||||
|
tc := tc
|
||||||
|
suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() {
|
||||||
|
suite.SetupTest() // reset
|
||||||
|
|
||||||
|
var err error
|
||||||
|
chanCap, err = suite.chainA.App.ScopedIBCKeeper.NewCapability(
|
||||||
|
suite.chainA.GetContext(), host.ChannelCapabilityPath(testPort1, testChannel1),
|
||||||
|
)
|
||||||
|
suite.Require().NoError(err, "could not create capability")
|
||||||
|
|
||||||
|
tc.malleate()
|
||||||
|
|
||||||
|
err = suite.chainA.App.IBCKeeper.ChannelKeeper.AcknowledgementExecuted(suite.chainA.GetContext(), chanCap, packet)
|
||||||
|
pc := suite.chainA.App.IBCKeeper.ChannelKeeper.GetPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.Nil(pc)
|
||||||
|
} else {
|
||||||
|
suite.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
func (suite *KeeperTestSuite) TestCleanupPacket() {
|
func (suite *KeeperTestSuite) TestCleanupPacket() {
|
||||||
counterparty := types.NewCounterparty(testPort2, testChannel2)
|
counterparty := types.NewCounterparty(testPort2, testChannel2)
|
||||||
packetKey := host.KeyPacketAcknowledgement(testPort2, testChannel2, 1)
|
unorderedPacketKey := host.KeyPacketAcknowledgement(testPort2, testChannel2, 1)
|
||||||
|
orderedPacketKey := host.KeyNextSequenceRecv(testPort2, testChannel2)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
packet types.Packet
|
packet types.Packet
|
||||||
nextSeqRecv uint64
|
nextSeqRecv uint64
|
||||||
|
ordered bool
|
||||||
)
|
)
|
||||||
|
|
||||||
ack := []byte("ack")
|
ack := []byte("ack")
|
||||||
|
|
||||||
testCases := []testCase{
|
testCases := []testCase{
|
||||||
{"success", func() {
|
{"success on ordered channel", func() {
|
||||||
|
ordered = true
|
||||||
|
nextSeqRecv = 6
|
||||||
|
suite.chainA.CreateClient(suite.chainB)
|
||||||
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
|
suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connection.OPEN)
|
||||||
|
suite.chainA.createConnection(testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA, connection.OPEN)
|
||||||
|
suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.OPEN, types.ORDERED, testConnectionIDA)
|
||||||
|
suite.chainA.createChannel(testPort2, testChannel2, testPort1, testChannel1, types.OPEN, types.ORDERED, testConnectionIDB)
|
||||||
|
// create several packet commitments
|
||||||
|
for i := uint64(1); i < nextSeqRecv; i++ {
|
||||||
|
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), i, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
||||||
|
suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainB.GetContext(), testPort1, testChannel1, i, types.CommitPacket(packet))
|
||||||
|
}
|
||||||
|
// set next sequence recv
|
||||||
|
suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(suite.chainA.GetContext(), testPort2, testChannel2, nextSeqRecv)
|
||||||
|
}, true},
|
||||||
|
{"success on unordered channel", func() {
|
||||||
|
ordered = false
|
||||||
nextSeqRecv = 10
|
nextSeqRecv = 10
|
||||||
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
||||||
suite.chainA.CreateClient(suite.chainB)
|
suite.chainA.CreateClient(suite.chainB)
|
||||||
|
@ -383,6 +469,7 @@ func (suite *KeeperTestSuite) TestCleanupPacket() {
|
||||||
}, true},
|
}, true},
|
||||||
{"channel not found", func() {}, false},
|
{"channel not found", func() {}, false},
|
||||||
{"channel not open", func() {
|
{"channel not open", func() {
|
||||||
|
ordered = true
|
||||||
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
||||||
suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.CLOSED, types.ORDERED, testConnectionIDA)
|
suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.CLOSED, types.ORDERED, testConnectionIDA)
|
||||||
}, false},
|
}, false},
|
||||||
|
@ -423,6 +510,7 @@ func (suite *KeeperTestSuite) TestCleanupPacket() {
|
||||||
}, false},
|
}, false},
|
||||||
{"packet ack verification failed", func() {
|
{"packet ack verification failed", func() {
|
||||||
nextSeqRecv = 10
|
nextSeqRecv = 10
|
||||||
|
ordered = false
|
||||||
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
||||||
suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connection.OPEN)
|
suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connection.OPEN)
|
||||||
suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.OPEN, types.UNORDERED, testConnectionIDA)
|
suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.OPEN, types.UNORDERED, testConnectionIDA)
|
||||||
|
@ -433,6 +521,9 @@ func (suite *KeeperTestSuite) TestCleanupPacket() {
|
||||||
for i, tc := range testCases {
|
for i, tc := range testCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() {
|
suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() {
|
||||||
|
var proof commitmentexported.Proof
|
||||||
|
var proofHeight uint64
|
||||||
|
|
||||||
suite.SetupTest() // reset
|
suite.SetupTest() // reset
|
||||||
tc.malleate()
|
tc.malleate()
|
||||||
|
|
||||||
|
@ -440,14 +531,32 @@ func (suite *KeeperTestSuite) TestCleanupPacket() {
|
||||||
|
|
||||||
suite.chainB.updateClient(suite.chainA)
|
suite.chainB.updateClient(suite.chainA)
|
||||||
suite.chainA.updateClient(suite.chainB)
|
suite.chainA.updateClient(suite.chainB)
|
||||||
proof, proofHeight := queryProof(suite.chainA, packetKey)
|
|
||||||
|
if ordered {
|
||||||
|
proof, proofHeight = queryProof(suite.chainA, orderedPacketKey)
|
||||||
|
} else {
|
||||||
|
proof, proofHeight = queryProof(suite.chainA, unorderedPacketKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
cap, err := suite.chainB.App.ScopedIBCKeeper.NewCapability(ctx, host.ChannelCapabilityPath(testPort1, testChannel1))
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
packetOut, err := suite.chainB.App.IBCKeeper.ChannelKeeper.CleanupPacket(ctx, packet, proof, proofHeight+1, nextSeqRecv, ack)
|
packetOut, err := suite.chainB.App.IBCKeeper.ChannelKeeper.CleanupPacket(ctx, cap, packet, proof, proofHeight+1, nextSeqRecv, ack)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
suite.Require().NotNil(packetOut)
|
suite.Require().NotNil(packetOut)
|
||||||
|
|
||||||
|
if ordered {
|
||||||
|
for i := uint64(1); i < nextSeqRecv; i++ {
|
||||||
|
pc := suite.chainB.App.IBCKeeper.ChannelKeeper.GetPacketCommitment(ctx, testPort1, testChannel1, i)
|
||||||
|
suite.Require().Nil(pc)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pc := suite.chainB.App.IBCKeeper.ChannelKeeper.GetPacketCommitment(ctx, testPort1, testChannel1, packet.GetSequence())
|
||||||
|
suite.Require().Nil(pc)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
packetOut, err := suite.chainB.App.IBCKeeper.ChannelKeeper.CleanupPacket(ctx, packet, proof, proofHeight, nextSeqRecv, ack)
|
packetOut, err := suite.chainB.App.IBCKeeper.ChannelKeeper.CleanupPacket(ctx, cap, packet, proof, proofHeight, nextSeqRecv, ack)
|
||||||
suite.Require().Error(err)
|
suite.Require().Error(err)
|
||||||
suite.Require().Nil(packetOut)
|
suite.Require().Nil(packetOut)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,8 @@ import (
|
||||||
// packet to a counterparty module, where the timeout height has passed on the
|
// packet to a counterparty module, where the timeout height has passed on the
|
||||||
// counterparty chain without the packet being committed, to prove that the
|
// counterparty chain without the packet being committed, to prove that the
|
||||||
// packet can no longer be executed and to allow the calling module to safely
|
// packet can no longer be executed and to allow the calling module to safely
|
||||||
// perform appropriate state transitions.
|
// perform appropriate state transitions. Its intended usage is within the
|
||||||
|
// ante handler.
|
||||||
func (k Keeper) TimeoutPacket(
|
func (k Keeper) TimeoutPacket(
|
||||||
ctx sdk.Context,
|
ctx sdk.Context,
|
||||||
packet exported.PacketI,
|
packet exported.PacketI,
|
||||||
|
@ -109,6 +110,39 @@ func (k Keeper) TimeoutPacket(
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: the remaining code is located in the TimeoutExecuted function
|
||||||
|
return packet, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimeoutExecuted deletes the commitment send from this chain after it verifies timeout.
|
||||||
|
// If the timed-out packet came from an ORDERED channel then this channel will be closed.
|
||||||
|
//
|
||||||
|
// NOTE: this function must be called in the handler
|
||||||
|
func (k Keeper) TimeoutExecuted(
|
||||||
|
ctx sdk.Context,
|
||||||
|
chanCap *capability.Capability,
|
||||||
|
packet exported.PacketI,
|
||||||
|
) error {
|
||||||
|
channel, found := k.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel())
|
||||||
|
if !found {
|
||||||
|
return sdkerrors.Wrapf(types.ErrChannelNotFound, packet.GetSourcePort(), packet.GetSourceChannel())
|
||||||
|
}
|
||||||
|
|
||||||
|
capName := host.ChannelCapabilityPath(packet.GetSourcePort(), packet.GetSourceChannel())
|
||||||
|
if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, capName) {
|
||||||
|
return sdkerrors.Wrap(
|
||||||
|
types.ErrChannelCapabilityNotFound,
|
||||||
|
"caller does not own capability for channel",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
k.deletePacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
|
||||||
|
|
||||||
|
if channel.Ordering == types.ORDERED {
|
||||||
|
channel.State = types.CLOSED
|
||||||
|
k.SetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), channel)
|
||||||
|
}
|
||||||
|
|
||||||
k.Logger(ctx).Info(fmt.Sprintf("packet timed-out: %v", packet))
|
k.Logger(ctx).Info(fmt.Sprintf("packet timed-out: %v", packet))
|
||||||
|
|
||||||
// emit an event marking that we have processed the timeout
|
// emit an event marking that we have processed the timeout
|
||||||
|
@ -125,28 +159,6 @@ func (k Keeper) TimeoutPacket(
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
// NOTE: the remaining code is located on the TimeoutExecuted function
|
|
||||||
return packet, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TimeoutExecuted deletes the commitment send from this chain after it verifies timeout
|
|
||||||
func (k Keeper) TimeoutExecuted(ctx sdk.Context, chanCap *capability.Capability, packet exported.PacketI) error {
|
|
||||||
channel, found := k.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel())
|
|
||||||
if !found {
|
|
||||||
return sdkerrors.Wrapf(types.ErrChannelNotFound, packet.GetSourcePort(), packet.GetSourceChannel())
|
|
||||||
}
|
|
||||||
|
|
||||||
if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, host.ChannelCapabilityPath(packet.GetSourcePort(), packet.GetSourceChannel())) {
|
|
||||||
return sdkerrors.Wrap(types.ErrChannelCapabilityNotFound, "caller does not own capability for channel")
|
|
||||||
}
|
|
||||||
|
|
||||||
k.deletePacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
|
|
||||||
|
|
||||||
if channel.Ordering == types.ORDERED {
|
|
||||||
channel.State = types.CLOSED
|
|
||||||
k.SetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), channel)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +167,8 @@ func (k Keeper) TimeoutExecuted(ctx sdk.Context, chanCap *capability.Capability,
|
||||||
// never be received (even if the timeoutHeight has not yet been reached).
|
// never be received (even if the timeoutHeight has not yet been reached).
|
||||||
func (k Keeper) TimeoutOnClose(
|
func (k Keeper) TimeoutOnClose(
|
||||||
ctx sdk.Context,
|
ctx sdk.Context,
|
||||||
packet types.Packet, // nolint: interfacer
|
chanCap *capability.Capability,
|
||||||
|
packet exported.PacketI,
|
||||||
proof,
|
proof,
|
||||||
proofClosed commitmentexported.Proof,
|
proofClosed commitmentexported.Proof,
|
||||||
proofHeight,
|
proofHeight,
|
||||||
|
@ -166,17 +179,13 @@ func (k Keeper) TimeoutOnClose(
|
||||||
return nil, sdkerrors.Wrapf(types.ErrChannelNotFound, packet.GetSourcePort(), packet.GetSourceChannel())
|
return nil, sdkerrors.Wrapf(types.ErrChannelNotFound, packet.GetSourcePort(), packet.GetSourceChannel())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: blocked by #5542
|
capName := host.ChannelCapabilityPath(packet.GetSourcePort(), packet.GetSourceChannel())
|
||||||
// capKey, found := k.GetChannelCapability(ctx, packet.GetSourcePort(), packet.GetSourceChannel())
|
if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, capName) {
|
||||||
// if !found {
|
return nil, sdkerrors.Wrap(
|
||||||
// return nil, types.ErrChannelCapabilityNotFound
|
types.ErrInvalidChannelCapability,
|
||||||
// }
|
"channel capability failed authentication",
|
||||||
|
)
|
||||||
// portCapabilityKey := sdk.NewKVStoreKey(capKey)
|
}
|
||||||
|
|
||||||
// if !k.portKeeper.Authenticate(portCapabilityKey, packet.GetSourcePort()) {
|
|
||||||
// return nil, sdkerrors.Wrap(port.ErrInvalidPort, packet.GetSourcePort())
|
|
||||||
// }
|
|
||||||
|
|
||||||
if packet.GetDestPort() != channel.Counterparty.PortID {
|
if packet.GetDestPort() != channel.Counterparty.PortID {
|
||||||
return nil, sdkerrors.Wrapf(
|
return nil, sdkerrors.Wrapf(
|
||||||
|
@ -227,6 +236,11 @@ func (k Keeper) TimeoutOnClose(
|
||||||
var err error
|
var err error
|
||||||
switch channel.Ordering {
|
switch channel.Ordering {
|
||||||
case types.ORDERED:
|
case types.ORDERED:
|
||||||
|
// check that packet has not been received
|
||||||
|
if nextSequenceRecv > packet.GetSequence() {
|
||||||
|
return nil, sdkerrors.Wrap(types.ErrInvalidPacket, "packet already received")
|
||||||
|
}
|
||||||
|
|
||||||
// check that the recv sequence is as claimed
|
// check that the recv sequence is as claimed
|
||||||
err = k.connectionKeeper.VerifyNextSequenceRecv(
|
err = k.connectionKeeper.VerifyNextSequenceRecv(
|
||||||
ctx, connectionEnd, proofHeight, proof,
|
ctx, connectionEnd, proofHeight, proof,
|
||||||
|
@ -235,7 +249,7 @@ func (k Keeper) TimeoutOnClose(
|
||||||
case types.UNORDERED:
|
case types.UNORDERED:
|
||||||
err = k.connectionKeeper.VerifyPacketAcknowledgementAbsence(
|
err = k.connectionKeeper.VerifyPacketAcknowledgementAbsence(
|
||||||
ctx, connectionEnd, proofHeight, proof,
|
ctx, connectionEnd, proofHeight, proof,
|
||||||
packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence(),
|
packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(),
|
||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
panic(sdkerrors.Wrapf(types.ErrInvalidChannelOrdering, channel.Ordering.String()))
|
panic(sdkerrors.Wrapf(types.ErrInvalidChannelOrdering, channel.Ordering.String()))
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/capability"
|
"github.com/cosmos/cosmos-sdk/x/capability"
|
||||||
connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection"
|
connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection"
|
||||||
"github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
|
"github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
|
||||||
|
commitmentexported "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/exported"
|
||||||
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
|
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -104,14 +105,21 @@ func (suite *KeeperTestSuite) TestTimeoutPacket() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestTimeoutExectued verifies that packet commitments are deleted after
|
||||||
|
// capabilities are verified.
|
||||||
func (suite *KeeperTestSuite) TestTimeoutExecuted() {
|
func (suite *KeeperTestSuite) TestTimeoutExecuted() {
|
||||||
var packet types.Packet
|
sequence := uint64(1)
|
||||||
|
|
||||||
|
var (
|
||||||
|
packet types.Packet
|
||||||
|
chanCap *capability.Capability
|
||||||
|
)
|
||||||
|
|
||||||
var chanCap *capability.Capability
|
|
||||||
testCases := []testCase{
|
testCases := []testCase{
|
||||||
{"success ORDERED", func() {
|
{"success ORDERED", func() {
|
||||||
packet = types.NewPacket(newMockTimeoutPacket().GetBytes(), 1, testPort1, testChannel1, testPort2, testChannel2, timeoutHeight, disabledTimeoutTimestamp)
|
packet = types.NewPacket(newMockTimeoutPacket().GetBytes(), 1, testPort1, testChannel1, testPort2, testChannel2, timeoutHeight, disabledTimeoutTimestamp)
|
||||||
suite.chainA.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.OPEN, types.ORDERED, testConnectionIDA)
|
suite.chainA.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.OPEN, types.ORDERED, testConnectionIDA)
|
||||||
|
suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), sequence, types.CommitPacket(packet))
|
||||||
}, true},
|
}, true},
|
||||||
{"channel not found", func() {}, false},
|
{"channel not found", func() {}, false},
|
||||||
{"incorrect capability", func() {
|
{"incorrect capability", func() {
|
||||||
|
@ -135,11 +143,13 @@ func (suite *KeeperTestSuite) TestTimeoutExecuted() {
|
||||||
tc.malleate()
|
tc.malleate()
|
||||||
|
|
||||||
err = suite.chainA.App.IBCKeeper.ChannelKeeper.TimeoutExecuted(suite.chainA.GetContext(), chanCap, packet)
|
err = suite.chainA.App.IBCKeeper.ChannelKeeper.TimeoutExecuted(suite.chainA.GetContext(), chanCap, packet)
|
||||||
|
pc := suite.chainA.App.IBCKeeper.ChannelKeeper.GetPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), sequence)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err)
|
suite.NoError(err)
|
||||||
|
suite.Nil(pc)
|
||||||
} else {
|
} else {
|
||||||
suite.Require().Error(err)
|
suite.Error(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -147,15 +157,31 @@ func (suite *KeeperTestSuite) TestTimeoutExecuted() {
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) TestTimeoutOnClose() {
|
func (suite *KeeperTestSuite) TestTimeoutOnClose() {
|
||||||
channelKey := host.KeyChannel(testPort2, testChannel2)
|
channelKey := host.KeyChannel(testPort2, testChannel2)
|
||||||
packetKey := host.KeyPacketAcknowledgement(testPort1, testChannel1, 2)
|
unorderedPacketKey := host.KeyPacketAcknowledgement(testPort2, testChannel2, 2)
|
||||||
|
orderedPacketKey := host.KeyNextSequenceRecv(testPort2, testChannel2)
|
||||||
|
|
||||||
counterparty := types.NewCounterparty(testPort2, testChannel2)
|
counterparty := types.NewCounterparty(testPort2, testChannel2)
|
||||||
var (
|
var (
|
||||||
packet types.Packet
|
packet types.Packet
|
||||||
nextSeqRecv uint64
|
nextSeqRecv uint64
|
||||||
|
ordered bool
|
||||||
)
|
)
|
||||||
|
|
||||||
testCases := []testCase{
|
testCases := []testCase{
|
||||||
{"success", func() {
|
{"success on ordered channel", func() {
|
||||||
|
ordered = true
|
||||||
|
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
||||||
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
|
suite.chainA.CreateClient(suite.chainB)
|
||||||
|
suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connection.OPEN)
|
||||||
|
suite.chainA.createConnection(testConnectionIDB, testConnectionIDA, testClientIDB, testClientIDA, connection.OPEN)
|
||||||
|
suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.OPEN, types.ORDERED, testConnectionIDA)
|
||||||
|
suite.chainA.createChannel(testPort2, testChannel2, testPort1, testChannel1, types.CLOSED, types.ORDERED, testConnectionIDB) // channel on chainA is closed
|
||||||
|
suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainB.GetContext(), testPort1, testChannel1, 2, types.CommitPacket(packet))
|
||||||
|
suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(suite.chainA.GetContext(), testPort2, testChannel2, nextSeqRecv)
|
||||||
|
}, true},
|
||||||
|
{"success on unordered channel", func() {
|
||||||
|
ordered = false
|
||||||
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
||||||
suite.chainB.CreateClient(suite.chainA)
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
suite.chainA.CreateClient(suite.chainB)
|
suite.chainA.CreateClient(suite.chainB)
|
||||||
|
@ -164,10 +190,10 @@ func (suite *KeeperTestSuite) TestTimeoutOnClose() {
|
||||||
suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.OPEN, types.UNORDERED, testConnectionIDA)
|
suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.OPEN, types.UNORDERED, testConnectionIDA)
|
||||||
suite.chainA.createChannel(testPort2, testChannel2, testPort1, testChannel1, types.CLOSED, types.UNORDERED, testConnectionIDB) // channel on chainA is closed
|
suite.chainA.createChannel(testPort2, testChannel2, testPort1, testChannel1, types.CLOSED, types.UNORDERED, testConnectionIDB) // channel on chainA is closed
|
||||||
suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainB.GetContext(), testPort1, testChannel1, 2, types.CommitPacket(packet))
|
suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainB.GetContext(), testPort1, testChannel1, 2, types.CommitPacket(packet))
|
||||||
suite.chainB.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(suite.chainB.GetContext(), testPort1, testChannel1, nextSeqRecv)
|
|
||||||
}, true},
|
}, true},
|
||||||
{"channel not found", func() {}, false},
|
{"channel not found", func() {}, false},
|
||||||
{"packet dest port ≠ channel counterparty port", func() {
|
{"packet dest port ≠ channel counterparty port", func() {
|
||||||
|
ordered = true
|
||||||
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 1, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
||||||
suite.chainB.createChannel(testPort1, testChannel1, testPort3, testChannel2, types.OPEN, types.ORDERED, testConnectionIDA)
|
suite.chainB.createChannel(testPort1, testChannel1, testPort3, testChannel2, types.OPEN, types.ORDERED, testConnectionIDA)
|
||||||
}, false},
|
}, false},
|
||||||
|
@ -185,6 +211,7 @@ func (suite *KeeperTestSuite) TestTimeoutOnClose() {
|
||||||
suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.OPEN, types.ORDERED, testConnectionIDA)
|
suite.chainB.createChannel(testPort1, testChannel1, testPort2, testChannel2, types.OPEN, types.ORDERED, testConnectionIDA)
|
||||||
}, false},
|
}, false},
|
||||||
{"channel verification failed", func() {
|
{"channel verification failed", func() {
|
||||||
|
ordered = false
|
||||||
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
||||||
suite.chainB.CreateClient(suite.chainA)
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connection.OPEN)
|
suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connection.OPEN)
|
||||||
|
@ -193,6 +220,7 @@ func (suite *KeeperTestSuite) TestTimeoutOnClose() {
|
||||||
suite.chainB.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(suite.chainB.GetContext(), testPort1, testChannel1, nextSeqRecv)
|
suite.chainB.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(suite.chainB.GetContext(), testPort1, testChannel1, nextSeqRecv)
|
||||||
}, false},
|
}, false},
|
||||||
{"next seq receive verification failed", func() {
|
{"next seq receive verification failed", func() {
|
||||||
|
ordered = true
|
||||||
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
||||||
suite.chainB.CreateClient(suite.chainA)
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connection.OPEN)
|
suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connection.OPEN)
|
||||||
|
@ -201,6 +229,7 @@ func (suite *KeeperTestSuite) TestTimeoutOnClose() {
|
||||||
suite.chainB.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(suite.chainB.GetContext(), testPort1, testChannel1, nextSeqRecv)
|
suite.chainB.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(suite.chainB.GetContext(), testPort1, testChannel1, nextSeqRecv)
|
||||||
}, false},
|
}, false},
|
||||||
{"packet ack verification failed", func() {
|
{"packet ack verification failed", func() {
|
||||||
|
ordered = false
|
||||||
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
packet = types.NewPacket(mockSuccessPacket{}.GetBytes(), 2, testPort1, testChannel1, counterparty.GetPortID(), counterparty.GetChannelID(), timeoutHeight, disabledTimeoutTimestamp)
|
||||||
suite.chainB.CreateClient(suite.chainA)
|
suite.chainB.CreateClient(suite.chainA)
|
||||||
suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connection.OPEN)
|
suite.chainB.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, connection.OPEN)
|
||||||
|
@ -213,22 +242,32 @@ func (suite *KeeperTestSuite) TestTimeoutOnClose() {
|
||||||
for i, tc := range testCases {
|
for i, tc := range testCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() {
|
suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() {
|
||||||
|
var proof commitmentexported.Proof
|
||||||
|
|
||||||
suite.SetupTest() // reset
|
suite.SetupTest() // reset
|
||||||
tc.malleate()
|
tc.malleate()
|
||||||
|
|
||||||
suite.chainB.updateClient(suite.chainA)
|
suite.chainB.updateClient(suite.chainA)
|
||||||
suite.chainA.updateClient(suite.chainB)
|
suite.chainA.updateClient(suite.chainB)
|
||||||
proofClosed, proofHeight := queryProof(suite.chainA, channelKey)
|
proofClosed, proofHeight := queryProof(suite.chainA, channelKey)
|
||||||
proofAckAbsence, _ := queryProof(suite.chainA, packetKey)
|
|
||||||
|
if ordered {
|
||||||
|
proof, _ = queryProof(suite.chainA, orderedPacketKey)
|
||||||
|
} else {
|
||||||
|
proof, _ = queryProof(suite.chainA, unorderedPacketKey)
|
||||||
|
}
|
||||||
|
|
||||||
ctx := suite.chainB.GetContext()
|
ctx := suite.chainB.GetContext()
|
||||||
|
cap, err := suite.chainB.App.ScopedIBCKeeper.NewCapability(ctx, host.ChannelCapabilityPath(testPort1, testChannel1))
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
packetOut, err := suite.chainB.App.IBCKeeper.ChannelKeeper.TimeoutOnClose(ctx, packet, proofAckAbsence, proofClosed, proofHeight+1, nextSeqRecv)
|
packetOut, err := suite.chainB.App.IBCKeeper.ChannelKeeper.TimeoutOnClose(ctx, cap, packet, proof, proofClosed, proofHeight+1, nextSeqRecv)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
suite.Require().NotNil(packetOut)
|
suite.Require().NotNil(packetOut)
|
||||||
} else {
|
} else {
|
||||||
// switch the proofs to invalidate them
|
// switch the proofs to invalidate them
|
||||||
packetOut, err := suite.chainB.App.IBCKeeper.ChannelKeeper.TimeoutOnClose(ctx, packet, proofClosed, proofAckAbsence, proofHeight+1, nextSeqRecv)
|
packetOut, err := suite.chainB.App.IBCKeeper.ChannelKeeper.TimeoutOnClose(ctx, cap, packet, proofClosed, proof, proofHeight+1, nextSeqRecv)
|
||||||
suite.Require().Error(err)
|
suite.Require().Error(err)
|
||||||
suite.Require().Nil(packetOut)
|
suite.Require().Nil(packetOut)
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,7 @@ func NewHandler(k Keeper) sdk.Handler {
|
||||||
|
|
||||||
case channel.MsgAcknowledgement:
|
case channel.MsgAcknowledgement:
|
||||||
// Lookup module by channel capability
|
// Lookup module by channel capability
|
||||||
module, _, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel)
|
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,19 @@ func NewHandler(k Keeper) sdk.Handler {
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, sdkerrors.Wrapf(port.ErrInvalidRoute, "route not found to module: %s", module)
|
return nil, sdkerrors.Wrapf(port.ErrInvalidRoute, "route not found to module: %s", module)
|
||||||
}
|
}
|
||||||
return cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement)
|
|
||||||
|
// Perform application logic callback
|
||||||
|
res, err := cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete packet commitment
|
||||||
|
if err = k.ChannelKeeper.AcknowledgementExecuted(ctx, cap, msg.Packet); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
|
||||||
case channel.MsgTimeout:
|
case channel.MsgTimeout:
|
||||||
// Lookup module by channel capability
|
// Lookup module by channel capability
|
||||||
|
@ -195,16 +207,19 @@ func NewHandler(k Keeper) sdk.Handler {
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, sdkerrors.Wrapf(port.ErrInvalidRoute, "route not found to module: %s", module)
|
return nil, sdkerrors.Wrapf(port.ErrInvalidRoute, "route not found to module: %s", module)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Perform application logic callback
|
||||||
res, err := cbs.OnTimeoutPacket(ctx, msg.Packet)
|
res, err := cbs.OnTimeoutPacket(ctx, msg.Packet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete packet commitment
|
||||||
|
if err = k.ChannelKeeper.TimeoutExecuted(ctx, cap, msg.Packet); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = k.ChannelKeeper.TimeoutExecuted(ctx, cap, msg.Packet)
|
|
||||||
if err != nil {
|
return res, nil
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return res, err
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized IBC message type: %T", msg)
|
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized IBC message type: %T", msg)
|
||||||
|
|
Loading…
Reference in New Issue