ConsensusState is retrieved by light clients in verifyXYZ as necessary (#7005)
* move con state retrieval to verify funcs * refactor tm client state tests * fix build * Apply suggestions from code review Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Aditya <adityasripal@gmail.com> * apply @fedekunze review comments * apply @AdityaSripal review comment Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Aditya <adityasripal@gmail.com>
This commit is contained in:
parent
308c879b11
commit
d752a7b21f
|
@ -46,7 +46,6 @@ type ClientState interface {
|
||||||
proof []byte,
|
proof []byte,
|
||||||
connectionID string,
|
connectionID string,
|
||||||
connectionEnd connectionexported.ConnectionI,
|
connectionEnd connectionexported.ConnectionI,
|
||||||
consensusState ConsensusState,
|
|
||||||
) error
|
) error
|
||||||
VerifyChannelState(
|
VerifyChannelState(
|
||||||
store sdk.KVStore,
|
store sdk.KVStore,
|
||||||
|
@ -57,7 +56,6 @@ type ClientState interface {
|
||||||
portID,
|
portID,
|
||||||
channelID string,
|
channelID string,
|
||||||
channel channelexported.ChannelI,
|
channel channelexported.ChannelI,
|
||||||
consensusState ConsensusState,
|
|
||||||
) error
|
) error
|
||||||
VerifyPacketCommitment(
|
VerifyPacketCommitment(
|
||||||
store sdk.KVStore,
|
store sdk.KVStore,
|
||||||
|
@ -69,7 +67,6 @@ type ClientState interface {
|
||||||
channelID string,
|
channelID string,
|
||||||
sequence uint64,
|
sequence uint64,
|
||||||
commitmentBytes []byte,
|
commitmentBytes []byte,
|
||||||
consensusState ConsensusState,
|
|
||||||
) error
|
) error
|
||||||
VerifyPacketAcknowledgement(
|
VerifyPacketAcknowledgement(
|
||||||
store sdk.KVStore,
|
store sdk.KVStore,
|
||||||
|
@ -81,7 +78,6 @@ type ClientState interface {
|
||||||
channelID string,
|
channelID string,
|
||||||
sequence uint64,
|
sequence uint64,
|
||||||
acknowledgement []byte,
|
acknowledgement []byte,
|
||||||
consensusState ConsensusState,
|
|
||||||
) error
|
) error
|
||||||
VerifyPacketAcknowledgementAbsence(
|
VerifyPacketAcknowledgementAbsence(
|
||||||
store sdk.KVStore,
|
store sdk.KVStore,
|
||||||
|
@ -92,7 +88,6 @@ type ClientState interface {
|
||||||
portID,
|
portID,
|
||||||
channelID string,
|
channelID string,
|
||||||
sequence uint64,
|
sequence uint64,
|
||||||
consensusState ConsensusState,
|
|
||||||
) error
|
) error
|
||||||
VerifyNextSequenceRecv(
|
VerifyNextSequenceRecv(
|
||||||
store sdk.KVStore,
|
store sdk.KVStore,
|
||||||
|
@ -103,7 +98,6 @@ type ClientState interface {
|
||||||
portID,
|
portID,
|
||||||
channelID string,
|
channelID string,
|
||||||
nextSequenceRecv uint64,
|
nextSequenceRecv uint64,
|
||||||
consensusState ConsensusState,
|
|
||||||
) error
|
) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ func (k Keeper) VerifyClientConsensusState(
|
||||||
k.clientKeeper.ClientStore(ctx, clientID), k.cdc, targetConsState.GetRoot(), height,
|
k.clientKeeper.ClientStore(ctx, clientID), k.cdc, targetConsState.GetRoot(), height,
|
||||||
connection.GetCounterparty().GetClientID(), consensusHeight, connection.GetCounterparty().GetPrefix(), proof, consensusState,
|
connection.GetCounterparty().GetClientID(), consensusHeight, connection.GetCounterparty().GetPrefix(), proof, consensusState,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return sdkerrors.Wrap(err, "failed consensus state verification")
|
return sdkerrors.Wrapf(err, "failed consensus state verification for client (%s)", connection.GetClientID())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -55,22 +55,11 @@ func (k Keeper) VerifyConnectionState(
|
||||||
return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
|
return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move to specific clients; blocked by #5502
|
|
||||||
consensusState, found := k.clientKeeper.GetClientConsensusState(
|
|
||||||
ctx, connection.GetClientID(), height,
|
|
||||||
)
|
|
||||||
if !found {
|
|
||||||
return sdkerrors.Wrapf(
|
|
||||||
clienttypes.ErrConsensusStateNotFound,
|
|
||||||
"clientID (%s), height (%d)", connection.GetClientID(), height,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := clientState.VerifyConnectionState(
|
if err := clientState.VerifyConnectionState(
|
||||||
k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
|
k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
|
||||||
connection.GetCounterparty().GetPrefix(), proof, connectionID, connectionEnd, consensusState,
|
connection.GetCounterparty().GetPrefix(), proof, connectionID, connectionEnd,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return sdkerrors.Wrap(err, "failed connection state verification")
|
return sdkerrors.Wrapf(err, "failed connection state verification for client (%s)", connection.GetClientID())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -92,23 +81,12 @@ func (k Keeper) VerifyChannelState(
|
||||||
return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
|
return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move to specific clients; blocked by #5502
|
|
||||||
consensusState, found := k.clientKeeper.GetClientConsensusState(
|
|
||||||
ctx, connection.GetClientID(), height,
|
|
||||||
)
|
|
||||||
if !found {
|
|
||||||
return sdkerrors.Wrapf(
|
|
||||||
clienttypes.ErrConsensusStateNotFound,
|
|
||||||
"clientID (%s), height (%d)", connection.GetClientID(), height,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := clientState.VerifyChannelState(
|
if err := clientState.VerifyChannelState(
|
||||||
k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
|
k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
|
||||||
connection.GetCounterparty().GetPrefix(), proof,
|
connection.GetCounterparty().GetPrefix(), proof,
|
||||||
portID, channelID, channel, consensusState,
|
portID, channelID, channel,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return sdkerrors.Wrap(err, "failed channel state verification")
|
return sdkerrors.Wrapf(err, "failed channel state verification for client (%s)", connection.GetClientID())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -131,23 +109,12 @@ func (k Keeper) VerifyPacketCommitment(
|
||||||
return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
|
return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move to specific clients; blocked by #5502
|
|
||||||
consensusState, found := k.clientKeeper.GetClientConsensusState(
|
|
||||||
ctx, connection.GetClientID(), height,
|
|
||||||
)
|
|
||||||
if !found {
|
|
||||||
return sdkerrors.Wrapf(
|
|
||||||
clienttypes.ErrConsensusStateNotFound,
|
|
||||||
"clientID (%s), height (%d)", connection.GetClientID(), height,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := clientState.VerifyPacketCommitment(
|
if err := clientState.VerifyPacketCommitment(
|
||||||
k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
|
k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
|
||||||
connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
|
connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
|
||||||
sequence, commitmentBytes, consensusState,
|
sequence, commitmentBytes,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return sdkerrors.Wrap(err, "failed packet commitment verification")
|
return sdkerrors.Wrapf(err, "failed packet commitment verification for client (%s)", connection.GetClientID())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -170,23 +137,12 @@ func (k Keeper) VerifyPacketAcknowledgement(
|
||||||
return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
|
return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move to specific clients; blocked by #5502
|
|
||||||
consensusState, found := k.clientKeeper.GetClientConsensusState(
|
|
||||||
ctx, connection.GetClientID(), height,
|
|
||||||
)
|
|
||||||
if !found {
|
|
||||||
return sdkerrors.Wrapf(
|
|
||||||
clienttypes.ErrConsensusStateNotFound,
|
|
||||||
"clientID (%s), height (%d)", connection.GetClientID(), height,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := clientState.VerifyPacketAcknowledgement(
|
if err := clientState.VerifyPacketAcknowledgement(
|
||||||
k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
|
k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
|
||||||
connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
|
connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
|
||||||
sequence, acknowledgement, consensusState,
|
sequence, acknowledgement,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return sdkerrors.Wrap(err, "failed packet acknowledgement verification")
|
return sdkerrors.Wrapf(err, "failed packet acknowledgement verification for client (%s)", connection.GetClientID())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -209,23 +165,12 @@ func (k Keeper) VerifyPacketAcknowledgementAbsence(
|
||||||
return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
|
return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move to specific clients; blocked by #5502
|
|
||||||
consensusState, found := k.clientKeeper.GetClientConsensusState(
|
|
||||||
ctx, connection.GetClientID(), height,
|
|
||||||
)
|
|
||||||
if !found {
|
|
||||||
return sdkerrors.Wrapf(
|
|
||||||
clienttypes.ErrConsensusStateNotFound,
|
|
||||||
"clientID (%s), height (%d)", connection.GetClientID(), height,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := clientState.VerifyPacketAcknowledgementAbsence(
|
if err := clientState.VerifyPacketAcknowledgementAbsence(
|
||||||
k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
|
k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
|
||||||
connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
|
connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
|
||||||
sequence, consensusState,
|
sequence,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return sdkerrors.Wrap(err, "failed packet acknowledgement absence verification")
|
return sdkerrors.Wrapf(err, "failed packet acknowledgement absence verification for client (%s)", connection.GetClientID())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -247,23 +192,12 @@ func (k Keeper) VerifyNextSequenceRecv(
|
||||||
return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
|
return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move to specific clients; blocked by #5502
|
|
||||||
consensusState, found := k.clientKeeper.GetClientConsensusState(
|
|
||||||
ctx, connection.GetClientID(), height,
|
|
||||||
)
|
|
||||||
if !found {
|
|
||||||
return sdkerrors.Wrapf(
|
|
||||||
clienttypes.ErrConsensusStateNotFound,
|
|
||||||
"clientID (%s), height (%d)", connection.GetClientID(), height,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := clientState.VerifyNextSequenceRecv(
|
if err := clientState.VerifyNextSequenceRecv(
|
||||||
k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
|
k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height,
|
||||||
connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
|
connection.GetCounterparty().GetPrefix(), proof, portID, channelID,
|
||||||
nextSequenceRecv, consensusState,
|
nextSequenceRecv,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return sdkerrors.Wrap(err, "failed next sequence receive verification")
|
return sdkerrors.Wrapf(err, "failed next sequence receive verification for client (%s)", connection.GetClientID())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -123,7 +123,7 @@ func (cs ClientState) GetProofSpecs() []*ics23.ProofSpec {
|
||||||
// VerifyClientConsensusState verifies a proof of the consensus state of the
|
// VerifyClientConsensusState verifies a proof of the consensus state of the
|
||||||
// Tendermint client stored on the target machine.
|
// Tendermint client stored on the target machine.
|
||||||
func (cs ClientState) VerifyClientConsensusState(
|
func (cs ClientState) VerifyClientConsensusState(
|
||||||
_ sdk.KVStore,
|
store sdk.KVStore,
|
||||||
cdc codec.BinaryMarshaler,
|
cdc codec.BinaryMarshaler,
|
||||||
provingRoot commitmentexported.Root,
|
provingRoot commitmentexported.Root,
|
||||||
height uint64,
|
height uint64,
|
||||||
|
@ -133,7 +133,7 @@ func (cs ClientState) VerifyClientConsensusState(
|
||||||
proof []byte,
|
proof []byte,
|
||||||
consensusState clientexported.ConsensusState,
|
consensusState clientexported.ConsensusState,
|
||||||
) error {
|
) error {
|
||||||
merkleProof, err := sanitizeVerificationArgs(cdc, cs, height, prefix, proof, consensusState)
|
merkleProof, _, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -144,6 +144,15 @@ func (cs ClientState) VerifyClientConsensusState(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if consensusState == nil {
|
||||||
|
return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "consensus state cannot be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := consensusState.(*ConsensusState)
|
||||||
|
if !ok {
|
||||||
|
return sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "invalid consensus type %T, expected %T", consensusState, &ConsensusState{})
|
||||||
|
}
|
||||||
|
|
||||||
bz, err := codec.MarshalAny(cdc, consensusState)
|
bz, err := codec.MarshalAny(cdc, consensusState)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -159,16 +168,15 @@ func (cs ClientState) VerifyClientConsensusState(
|
||||||
// VerifyConnectionState verifies a proof of the connection state of the
|
// VerifyConnectionState verifies a proof of the connection state of the
|
||||||
// specified connection end stored on the target machine.
|
// specified connection end stored on the target machine.
|
||||||
func (cs ClientState) VerifyConnectionState(
|
func (cs ClientState) VerifyConnectionState(
|
||||||
_ sdk.KVStore,
|
store sdk.KVStore,
|
||||||
cdc codec.BinaryMarshaler,
|
cdc codec.BinaryMarshaler,
|
||||||
height uint64,
|
height uint64,
|
||||||
prefix commitmentexported.Prefix,
|
prefix commitmentexported.Prefix,
|
||||||
proof []byte,
|
proof []byte,
|
||||||
connectionID string,
|
connectionID string,
|
||||||
connectionEnd connectionexported.ConnectionI,
|
connectionEnd connectionexported.ConnectionI,
|
||||||
consensusState clientexported.ConsensusState,
|
|
||||||
) error {
|
) error {
|
||||||
merkleProof, err := sanitizeVerificationArgs(cdc, cs, height, prefix, proof, consensusState)
|
merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -198,7 +206,7 @@ func (cs ClientState) VerifyConnectionState(
|
||||||
// VerifyChannelState verifies a proof of the channel state of the specified
|
// VerifyChannelState verifies a proof of the channel state of the specified
|
||||||
// channel end, under the specified port, stored on the target machine.
|
// channel end, under the specified port, stored on the target machine.
|
||||||
func (cs ClientState) VerifyChannelState(
|
func (cs ClientState) VerifyChannelState(
|
||||||
_ sdk.KVStore,
|
store sdk.KVStore,
|
||||||
cdc codec.BinaryMarshaler,
|
cdc codec.BinaryMarshaler,
|
||||||
height uint64,
|
height uint64,
|
||||||
prefix commitmentexported.Prefix,
|
prefix commitmentexported.Prefix,
|
||||||
|
@ -206,9 +214,8 @@ func (cs ClientState) VerifyChannelState(
|
||||||
portID,
|
portID,
|
||||||
channelID string,
|
channelID string,
|
||||||
channel channelexported.ChannelI,
|
channel channelexported.ChannelI,
|
||||||
consensusState clientexported.ConsensusState,
|
|
||||||
) error {
|
) error {
|
||||||
merkleProof, err := sanitizeVerificationArgs(cdc, cs, height, prefix, proof, consensusState)
|
merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -238,7 +245,7 @@ func (cs ClientState) VerifyChannelState(
|
||||||
// VerifyPacketCommitment verifies a proof of an outgoing packet commitment at
|
// VerifyPacketCommitment verifies a proof of an outgoing packet commitment at
|
||||||
// the specified port, specified channel, and specified sequence.
|
// the specified port, specified channel, and specified sequence.
|
||||||
func (cs ClientState) VerifyPacketCommitment(
|
func (cs ClientState) VerifyPacketCommitment(
|
||||||
_ sdk.KVStore,
|
store sdk.KVStore,
|
||||||
cdc codec.BinaryMarshaler,
|
cdc codec.BinaryMarshaler,
|
||||||
height uint64,
|
height uint64,
|
||||||
prefix commitmentexported.Prefix,
|
prefix commitmentexported.Prefix,
|
||||||
|
@ -247,9 +254,8 @@ func (cs ClientState) VerifyPacketCommitment(
|
||||||
channelID string,
|
channelID string,
|
||||||
sequence uint64,
|
sequence uint64,
|
||||||
commitmentBytes []byte,
|
commitmentBytes []byte,
|
||||||
consensusState clientexported.ConsensusState,
|
|
||||||
) error {
|
) error {
|
||||||
merkleProof, err := sanitizeVerificationArgs(cdc, cs, height, prefix, proof, consensusState)
|
merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -269,7 +275,7 @@ func (cs ClientState) VerifyPacketCommitment(
|
||||||
// VerifyPacketAcknowledgement verifies a proof of an incoming packet
|
// VerifyPacketAcknowledgement verifies a proof of an incoming packet
|
||||||
// acknowledgement at the specified port, specified channel, and specified sequence.
|
// acknowledgement at the specified port, specified channel, and specified sequence.
|
||||||
func (cs ClientState) VerifyPacketAcknowledgement(
|
func (cs ClientState) VerifyPacketAcknowledgement(
|
||||||
_ sdk.KVStore,
|
store sdk.KVStore,
|
||||||
cdc codec.BinaryMarshaler,
|
cdc codec.BinaryMarshaler,
|
||||||
height uint64,
|
height uint64,
|
||||||
prefix commitmentexported.Prefix,
|
prefix commitmentexported.Prefix,
|
||||||
|
@ -278,9 +284,8 @@ func (cs ClientState) VerifyPacketAcknowledgement(
|
||||||
channelID string,
|
channelID string,
|
||||||
sequence uint64,
|
sequence uint64,
|
||||||
acknowledgement []byte,
|
acknowledgement []byte,
|
||||||
consensusState clientexported.ConsensusState,
|
|
||||||
) error {
|
) error {
|
||||||
merkleProof, err := sanitizeVerificationArgs(cdc, cs, height, prefix, proof, consensusState)
|
merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -301,7 +306,7 @@ func (cs ClientState) VerifyPacketAcknowledgement(
|
||||||
// incoming packet acknowledgement at the specified port, specified channel, and
|
// incoming packet acknowledgement at the specified port, specified channel, and
|
||||||
// specified sequence.
|
// specified sequence.
|
||||||
func (cs ClientState) VerifyPacketAcknowledgementAbsence(
|
func (cs ClientState) VerifyPacketAcknowledgementAbsence(
|
||||||
_ sdk.KVStore,
|
store sdk.KVStore,
|
||||||
cdc codec.BinaryMarshaler,
|
cdc codec.BinaryMarshaler,
|
||||||
height uint64,
|
height uint64,
|
||||||
prefix commitmentexported.Prefix,
|
prefix commitmentexported.Prefix,
|
||||||
|
@ -309,9 +314,8 @@ func (cs ClientState) VerifyPacketAcknowledgementAbsence(
|
||||||
portID,
|
portID,
|
||||||
channelID string,
|
channelID string,
|
||||||
sequence uint64,
|
sequence uint64,
|
||||||
consensusState clientexported.ConsensusState,
|
|
||||||
) error {
|
) error {
|
||||||
merkleProof, err := sanitizeVerificationArgs(cdc, cs, height, prefix, proof, consensusState)
|
merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -331,7 +335,7 @@ func (cs ClientState) VerifyPacketAcknowledgementAbsence(
|
||||||
// VerifyNextSequenceRecv verifies a proof of the next sequence number to be
|
// VerifyNextSequenceRecv verifies a proof of the next sequence number to be
|
||||||
// received of the specified channel at the specified port.
|
// received of the specified channel at the specified port.
|
||||||
func (cs ClientState) VerifyNextSequenceRecv(
|
func (cs ClientState) VerifyNextSequenceRecv(
|
||||||
_ sdk.KVStore,
|
store sdk.KVStore,
|
||||||
cdc codec.BinaryMarshaler,
|
cdc codec.BinaryMarshaler,
|
||||||
height uint64,
|
height uint64,
|
||||||
prefix commitmentexported.Prefix,
|
prefix commitmentexported.Prefix,
|
||||||
|
@ -339,9 +343,8 @@ func (cs ClientState) VerifyNextSequenceRecv(
|
||||||
portID,
|
portID,
|
||||||
channelID string,
|
channelID string,
|
||||||
nextSequenceRecv uint64,
|
nextSequenceRecv uint64,
|
||||||
consensusState clientexported.ConsensusState,
|
|
||||||
) error {
|
) error {
|
||||||
merkleProof, err := sanitizeVerificationArgs(cdc, cs, height, prefix, proof, consensusState)
|
merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -360,53 +363,49 @@ func (cs ClientState) VerifyNextSequenceRecv(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// sanitizeVerificationArgs perfoms the basic checks on the arguments that are
|
// produceVerificationArgs perfoms the basic checks on the arguments that are
|
||||||
// shared between the verification functions and returns the unmarshalled
|
// shared between the verification functions and returns the unmarshalled
|
||||||
// merkle proof and an error if one occurred.
|
// merkle proof, the consensus state and an error if one occurred.
|
||||||
func sanitizeVerificationArgs(
|
func produceVerificationArgs(
|
||||||
|
store sdk.KVStore,
|
||||||
cdc codec.BinaryMarshaler,
|
cdc codec.BinaryMarshaler,
|
||||||
cs ClientState,
|
cs ClientState,
|
||||||
height uint64,
|
height uint64,
|
||||||
prefix commitmentexported.Prefix,
|
prefix commitmentexported.Prefix,
|
||||||
proof []byte,
|
proof []byte,
|
||||||
consensusState clientexported.ConsensusState,
|
) (merkleProof commitmenttypes.MerkleProof, consensusState *ConsensusState, err error) {
|
||||||
) (merkleProof commitmenttypes.MerkleProof, err error) {
|
|
||||||
if cs.GetLatestHeight() < height {
|
if cs.GetLatestHeight() < height {
|
||||||
return commitmenttypes.MerkleProof{}, sdkerrors.Wrapf(
|
return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrapf(
|
||||||
sdkerrors.ErrInvalidHeight,
|
sdkerrors.ErrInvalidHeight,
|
||||||
"client state height < proof height (%d < %d)", cs.GetLatestHeight(), height,
|
"client state height < proof height (%d < %d)", cs.GetLatestHeight(), height,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if cs.IsFrozen() && cs.FrozenHeight <= height {
|
if cs.IsFrozen() && cs.FrozenHeight <= height {
|
||||||
return commitmenttypes.MerkleProof{}, clienttypes.ErrClientFrozen
|
return commitmenttypes.MerkleProof{}, nil, clienttypes.ErrClientFrozen
|
||||||
}
|
}
|
||||||
|
|
||||||
if prefix == nil {
|
if prefix == nil {
|
||||||
return commitmenttypes.MerkleProof{}, sdkerrors.Wrap(commitmenttypes.ErrInvalidPrefix, "prefix cannot be empty")
|
return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrap(commitmenttypes.ErrInvalidPrefix, "prefix cannot be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, ok := prefix.(*commitmenttypes.MerklePrefix)
|
_, ok := prefix.(*commitmenttypes.MerklePrefix)
|
||||||
if !ok {
|
if !ok {
|
||||||
return commitmenttypes.MerkleProof{}, sdkerrors.Wrapf(commitmenttypes.ErrInvalidPrefix, "invalid prefix type %T, expected *MerklePrefix", prefix)
|
return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrapf(commitmenttypes.ErrInvalidPrefix, "invalid prefix type %T, expected *MerklePrefix", prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
if proof == nil {
|
if proof == nil {
|
||||||
return commitmenttypes.MerkleProof{}, sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "proof cannot be empty")
|
return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "proof cannot be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = cdc.UnmarshalBinaryBare(proof, &merkleProof); err != nil {
|
if err = cdc.UnmarshalBinaryBare(proof, &merkleProof); err != nil {
|
||||||
return commitmenttypes.MerkleProof{}, sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "failed to unmarshal proof into commitment merkle proof")
|
return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "failed to unmarshal proof into commitment merkle proof")
|
||||||
}
|
}
|
||||||
|
|
||||||
if consensusState == nil {
|
consensusState, err = GetConsensusState(store, cdc, height)
|
||||||
return commitmenttypes.MerkleProof{}, sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "consensus state cannot be empty")
|
if err != nil {
|
||||||
|
return commitmenttypes.MerkleProof{}, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, ok = consensusState.(*ConsensusState)
|
return merkleProof, consensusState, nil
|
||||||
if !ok {
|
|
||||||
return commitmenttypes.MerkleProof{}, sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "invalid consensus type %T, expected %T", consensusState, &ConsensusState{})
|
|
||||||
}
|
|
||||||
|
|
||||||
return merkleProof, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,13 @@ package types_test
|
||||||
import (
|
import (
|
||||||
ics23 "github.com/confio/ics23/go"
|
ics23 "github.com/confio/ics23/go"
|
||||||
|
|
||||||
connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
|
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
|
||||||
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
|
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
|
"github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
|
||||||
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
|
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
|
||||||
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
|
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
|
||||||
|
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
|
||||||
|
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -18,6 +20,10 @@ const (
|
||||||
testSequence = 1
|
testSequence = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
invalidProof = []byte("invalid proof")
|
||||||
|
)
|
||||||
|
|
||||||
func (suite *TendermintTestSuite) TestValidate() {
|
func (suite *TendermintTestSuite) TestValidate() {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -160,478 +166,506 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test verification of the connection on chainB being represented in the
|
||||||
|
// light client on chainA
|
||||||
func (suite *TendermintTestSuite) TestVerifyConnectionState() {
|
func (suite *TendermintTestSuite) TestVerifyConnectionState() {
|
||||||
counterparty := connectiontypes.NewCounterparty("clientB", testConnectionID, commitmenttypes.NewMerklePrefix([]byte("ibc")))
|
var (
|
||||||
conn := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "clientA", counterparty, []string{"1.0.0"})
|
clientState *types.ClientState
|
||||||
|
proof []byte
|
||||||
|
proofHeight uint64
|
||||||
|
prefix commitmenttypes.MerklePrefix
|
||||||
|
)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
clientState *ibctmtypes.ClientState
|
malleate func()
|
||||||
connection connectiontypes.ConnectionEnd
|
expPass bool
|
||||||
consensusState ibctmtypes.ConsensusState
|
|
||||||
prefix commitmenttypes.MerklePrefix
|
|
||||||
proof []byte
|
|
||||||
expPass bool
|
|
||||||
}{
|
}{
|
||||||
// FIXME: uncomment
|
|
||||||
// {
|
|
||||||
// name: "successful verification",
|
|
||||||
// clientState: ibctmtypes.NewClientState(chainID, chainID, chainID, height, commitmenttypes.GetSDKSpecs()),
|
|
||||||
// connection: conn,
|
|
||||||
// consensusState: ibctmtypes.ConsensusState{
|
|
||||||
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
// },
|
|
||||||
// prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
// expPass: true,
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
name: "ApplyPrefix failed",
|
"successful verification", func() {}, true,
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
|
||||||
connection: conn,
|
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.MerklePrefix{},
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "latest client height < height",
|
"ApplyPrefix failed", func() {
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
prefix = commitmenttypes.MerklePrefix{}
|
||||||
connection: conn,
|
}, false,
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "client is frozen",
|
"latest client height < height", func() {
|
||||||
clientState: &ibctmtypes.ClientState{LatestHeight: height, FrozenHeight: height - 1},
|
proofHeight = clientState.LatestHeight + 1
|
||||||
connection: conn,
|
}, false,
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "proof verification failed",
|
"client is frozen", func() {
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
clientState.FrozenHeight = 1
|
||||||
connection: conn,
|
}, false,
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
},
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
{
|
||||||
NextValidatorsHash: suite.valsHash,
|
"proof verification failed", func() {
|
||||||
},
|
proof = invalidProof
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
}, false,
|
||||||
proof: []byte{},
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
|
|
||||||
err := tc.clientState.VerifyConnectionState(
|
suite.Run(tc.name, func() {
|
||||||
nil, suite.cdc, height, tc.prefix, tc.proof, testConnectionID, tc.connection, tc.consensusState,
|
suite.SetupTest() // reset
|
||||||
)
|
|
||||||
|
|
||||||
if tc.expPass {
|
// setup testing conditions
|
||||||
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
|
clientA, _, _, connB, _, _ := suite.coordinator.Setup(suite.chainA, suite.chainB)
|
||||||
} else {
|
connection := suite.chainB.GetConnection(connB)
|
||||||
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
|
|
||||||
}
|
var ok bool
|
||||||
|
clientStateI := suite.chainA.GetClientState(clientA)
|
||||||
|
clientState, ok = clientStateI.(*types.ClientState)
|
||||||
|
suite.Require().True(ok)
|
||||||
|
|
||||||
|
prefix = suite.chainB.GetPrefix()
|
||||||
|
|
||||||
|
// make connection proof
|
||||||
|
connectionKey := host.KeyConnection(connB.ID)
|
||||||
|
proof, proofHeight = suite.chainB.QueryProof(connectionKey)
|
||||||
|
|
||||||
|
tc.malleate() // make changes as necessary
|
||||||
|
|
||||||
|
store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA)
|
||||||
|
|
||||||
|
err := clientState.VerifyConnectionState(
|
||||||
|
store, suite.chainA.Codec, proofHeight, &prefix, proof, connB.ID, connection,
|
||||||
|
)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test verification of the channel on chainB being represented in the light
|
||||||
|
// client on chainA
|
||||||
func (suite *TendermintTestSuite) TestVerifyChannelState() {
|
func (suite *TendermintTestSuite) TestVerifyChannelState() {
|
||||||
counterparty := channeltypes.NewCounterparty(testPortID, testChannelID)
|
var (
|
||||||
ch := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, counterparty, []string{testConnectionID}, "1.0.0")
|
clientState *types.ClientState
|
||||||
|
proof []byte
|
||||||
|
proofHeight uint64
|
||||||
|
prefix commitmenttypes.MerklePrefix
|
||||||
|
)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
clientState *ibctmtypes.ClientState
|
malleate func()
|
||||||
channel channeltypes.Channel
|
expPass bool
|
||||||
consensusState ibctmtypes.ConsensusState
|
|
||||||
prefix commitmenttypes.MerklePrefix
|
|
||||||
proof []byte
|
|
||||||
expPass bool
|
|
||||||
}{
|
}{
|
||||||
// FIXME: uncomment
|
|
||||||
// {
|
|
||||||
// name: "successful verification",
|
|
||||||
// clientState: ibctmtypes.NewClientState(chainID, height, commitmenttypes.GetSDKSpecs()),
|
|
||||||
// connection: conn,
|
|
||||||
// consensusState: ibctmtypes.ConsensusState{
|
|
||||||
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
// },
|
|
||||||
// prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
// expPass: true,
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
name: "ApplyPrefix failed",
|
"successful verification", func() {}, true,
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
|
||||||
channel: ch,
|
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.MerklePrefix{},
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "latest client height < height",
|
"ApplyPrefix failed", func() {
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
prefix = commitmenttypes.MerklePrefix{}
|
||||||
channel: ch,
|
}, false,
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "client is frozen",
|
"latest client height < height", func() {
|
||||||
clientState: &ibctmtypes.ClientState{LatestHeight: height, FrozenHeight: height - 1},
|
proofHeight = clientState.LatestHeight + 1
|
||||||
channel: ch,
|
}, false,
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "proof verification failed",
|
"client is frozen", func() {
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
clientState.FrozenHeight = 1
|
||||||
channel: ch,
|
}, false,
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
},
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
{
|
||||||
NextValidatorsHash: suite.valsHash,
|
"proof verification failed", func() {
|
||||||
},
|
proof = invalidProof
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
}, false,
|
||||||
proof: []byte{},
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
|
|
||||||
err := tc.clientState.VerifyChannelState(
|
suite.Run(tc.name, func() {
|
||||||
nil, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, &tc.channel, tc.consensusState,
|
suite.SetupTest() // reset
|
||||||
)
|
|
||||||
|
|
||||||
if tc.expPass {
|
// setup testing conditions
|
||||||
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
|
clientA, _, _, _, _, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
|
||||||
} else {
|
channel := suite.chainB.GetChannel(channelB)
|
||||||
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
|
|
||||||
}
|
var ok bool
|
||||||
|
clientStateI := suite.chainA.GetClientState(clientA)
|
||||||
|
clientState, ok = clientStateI.(*types.ClientState)
|
||||||
|
suite.Require().True(ok)
|
||||||
|
|
||||||
|
prefix = suite.chainB.GetPrefix()
|
||||||
|
|
||||||
|
// make channel proof
|
||||||
|
channelKey := host.KeyChannel(channelB.PortID, channelB.ID)
|
||||||
|
proof, proofHeight = suite.chainB.QueryProof(channelKey)
|
||||||
|
|
||||||
|
tc.malleate() // make changes as necessary
|
||||||
|
|
||||||
|
store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA)
|
||||||
|
|
||||||
|
err := clientState.VerifyChannelState(
|
||||||
|
store, suite.chainA.Codec, proofHeight, &prefix, proof,
|
||||||
|
channelB.PortID, channelB.ID, channel,
|
||||||
|
)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test verification of the packet commitment on chainB being represented
|
||||||
|
// in the light client on chainA. A send from chainB to chainA is simulated.
|
||||||
func (suite *TendermintTestSuite) TestVerifyPacketCommitment() {
|
func (suite *TendermintTestSuite) TestVerifyPacketCommitment() {
|
||||||
|
var (
|
||||||
|
clientState *types.ClientState
|
||||||
|
proof []byte
|
||||||
|
proofHeight uint64
|
||||||
|
prefix commitmenttypes.MerklePrefix
|
||||||
|
)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
clientState *ibctmtypes.ClientState
|
malleate func()
|
||||||
commitment []byte
|
expPass bool
|
||||||
consensusState ibctmtypes.ConsensusState
|
|
||||||
prefix commitmenttypes.MerklePrefix
|
|
||||||
proof []byte
|
|
||||||
expPass bool
|
|
||||||
}{
|
}{
|
||||||
// FIXME: uncomment
|
|
||||||
// {
|
|
||||||
// name: "successful verification",
|
|
||||||
// clientState: ibctmtypes.NewClientState(chainID, height, commitmenttypes.GetSDKSpecs()),
|
|
||||||
// connection: conn,
|
|
||||||
// consensusState: ibctmtypes.ConsensusState{
|
|
||||||
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
// },
|
|
||||||
// prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
// expPass: true,
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
name: "ApplyPrefix failed",
|
"successful verification", func() {}, true,
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
|
||||||
commitment: []byte{},
|
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.MerklePrefix{},
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "latest client height < height",
|
"ApplyPrefix failed", func() {
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
prefix = commitmenttypes.MerklePrefix{}
|
||||||
commitment: []byte{},
|
}, false,
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "client is frozen",
|
"latest client height < height", func() {
|
||||||
clientState: &ibctmtypes.ClientState{LatestHeight: height, FrozenHeight: height - 1},
|
proofHeight = clientState.LatestHeight + 1
|
||||||
commitment: []byte{},
|
}, false,
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "proof verification failed",
|
"client is frozen", func() {
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
clientState.FrozenHeight = 1
|
||||||
commitment: []byte{},
|
}, false,
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
},
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
{
|
||||||
NextValidatorsHash: suite.valsHash,
|
"proof verification failed", func() {
|
||||||
},
|
proof = invalidProof
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
}, false,
|
||||||
proof: []byte{},
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
|
|
||||||
err := tc.clientState.VerifyPacketCommitment(
|
suite.Run(tc.name, func() {
|
||||||
nil, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence, tc.commitment, tc.consensusState,
|
suite.SetupTest() // reset
|
||||||
)
|
|
||||||
|
|
||||||
if tc.expPass {
|
// setup testing conditions
|
||||||
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
|
clientA, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
|
||||||
} else {
|
packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelB.PortID, channelB.ID, channelA.PortID, channelA.ID, 100, 0)
|
||||||
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
|
err := suite.coordinator.SendPacket(suite.chainB, suite.chainA, packet, clientA)
|
||||||
}
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
var ok bool
|
||||||
|
clientStateI := suite.chainA.GetClientState(clientA)
|
||||||
|
clientState, ok = clientStateI.(*types.ClientState)
|
||||||
|
suite.Require().True(ok)
|
||||||
|
|
||||||
|
prefix = suite.chainB.GetPrefix()
|
||||||
|
|
||||||
|
// make packet commitment proof
|
||||||
|
packetKey := host.KeyPacketCommitment(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
|
||||||
|
proof, proofHeight = suite.chainB.QueryProof(packetKey)
|
||||||
|
|
||||||
|
tc.malleate() // make changes as necessary
|
||||||
|
|
||||||
|
store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA)
|
||||||
|
|
||||||
|
err = clientState.VerifyPacketCommitment(
|
||||||
|
store, suite.chainA.Codec, proofHeight, &prefix, proof,
|
||||||
|
packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence(), channeltypes.CommitPacket(packet),
|
||||||
|
)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test verification of the acknowledgement on chainB being represented
|
||||||
|
// in the light client on chainA. A send and ack from chainA to chainB
|
||||||
|
// is simulated.
|
||||||
func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() {
|
func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() {
|
||||||
|
var (
|
||||||
|
clientState *types.ClientState
|
||||||
|
proof []byte
|
||||||
|
proofHeight uint64
|
||||||
|
prefix commitmenttypes.MerklePrefix
|
||||||
|
)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
clientState *ibctmtypes.ClientState
|
malleate func()
|
||||||
ack []byte
|
expPass bool
|
||||||
consensusState ibctmtypes.ConsensusState
|
|
||||||
prefix commitmenttypes.MerklePrefix
|
|
||||||
proof []byte
|
|
||||||
expPass bool
|
|
||||||
}{
|
}{
|
||||||
// FIXME: uncomment
|
|
||||||
// {
|
|
||||||
// name: "successful verification",
|
|
||||||
// clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
|
||||||
// connection: conn,
|
|
||||||
// consensusState: ibctmtypes.ConsensusState{
|
|
||||||
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
// },
|
|
||||||
// prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
// expPass: true,
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
name: "ApplyPrefix failed",
|
"successful verification", func() {}, true,
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
|
||||||
ack: []byte{},
|
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.MerklePrefix{},
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "latest client height < height",
|
"ApplyPrefix failed", func() {
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
prefix = commitmenttypes.MerklePrefix{}
|
||||||
ack: []byte{},
|
}, false,
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "client is frozen",
|
"latest client height < height", func() {
|
||||||
clientState: &ibctmtypes.ClientState{LatestHeight: height, FrozenHeight: height - 1},
|
proofHeight = clientState.LatestHeight + 1
|
||||||
ack: []byte{},
|
}, false,
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "proof verification failed",
|
"client is frozen", func() {
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
clientState.FrozenHeight = 1
|
||||||
ack: []byte{},
|
}, false,
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
},
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
{
|
||||||
NextValidatorsHash: suite.valsHash,
|
"proof verification failed", func() {
|
||||||
},
|
proof = invalidProof
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
}, false,
|
||||||
proof: []byte{},
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
|
|
||||||
err := tc.clientState.VerifyPacketAcknowledgement(
|
suite.Run(tc.name, func() {
|
||||||
nil, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence, tc.ack, tc.consensusState,
|
suite.SetupTest() // reset
|
||||||
)
|
|
||||||
|
|
||||||
if tc.expPass {
|
// setup testing conditions
|
||||||
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
|
clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
|
||||||
} else {
|
packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, 100, 0)
|
||||||
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
|
|
||||||
}
|
// send packet
|
||||||
|
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
// write ack
|
||||||
|
err = suite.coordinator.PacketExecuted(suite.chainB, suite.chainA, packet, clientA)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
var ok bool
|
||||||
|
clientStateI := suite.chainA.GetClientState(clientA)
|
||||||
|
clientState, ok = clientStateI.(*types.ClientState)
|
||||||
|
suite.Require().True(ok)
|
||||||
|
|
||||||
|
prefix = suite.chainB.GetPrefix()
|
||||||
|
|
||||||
|
// make packet acknowledgement proof
|
||||||
|
acknowledgementKey := host.KeyPacketAcknowledgement(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
|
||||||
|
proof, proofHeight = suite.chainB.QueryProof(acknowledgementKey)
|
||||||
|
|
||||||
|
tc.malleate() // make changes as necessary
|
||||||
|
|
||||||
|
store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA)
|
||||||
|
|
||||||
|
err = clientState.VerifyPacketAcknowledgement(
|
||||||
|
store, suite.chainA.Codec, proofHeight, &prefix, proof,
|
||||||
|
packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), ibctesting.TestHash,
|
||||||
|
)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test verification of the absent acknowledgement on chainB being represented
|
||||||
|
// in the light client on chainA. A send from chainB to chainA is simulated, but
|
||||||
|
// no receive.
|
||||||
func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() {
|
func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() {
|
||||||
|
var (
|
||||||
|
clientState *types.ClientState
|
||||||
|
proof []byte
|
||||||
|
proofHeight uint64
|
||||||
|
prefix commitmenttypes.MerklePrefix
|
||||||
|
)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
clientState *ibctmtypes.ClientState
|
malleate func()
|
||||||
consensusState ibctmtypes.ConsensusState
|
expPass bool
|
||||||
prefix commitmenttypes.MerklePrefix
|
|
||||||
proof []byte
|
|
||||||
expPass bool
|
|
||||||
}{
|
}{
|
||||||
// FIXME: uncomment
|
|
||||||
// {
|
|
||||||
// name: "successful verification",
|
|
||||||
// clientState: ibctmtypes.NewClientState(chainID, chainID, height, commitmenttypes.GetSDKSpecs()),
|
|
||||||
// connection: conn,
|
|
||||||
// consensusState: ibctmtypes.ConsensusState{
|
|
||||||
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
// },
|
|
||||||
// prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
// expPass: true,
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
name: "ApplyPrefix failed",
|
"successful verification", func() {}, true,
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.MerklePrefix{},
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "latest client height < height",
|
"ApplyPrefix failed", func() {
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
prefix = commitmenttypes.MerklePrefix{}
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
}, false,
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "client is frozen",
|
"latest client height < height", func() {
|
||||||
clientState: &ibctmtypes.ClientState{LatestHeight: height, FrozenHeight: height - 1},
|
proofHeight = clientState.LatestHeight + 1
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
}, false,
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "proof verification failed",
|
"client is frozen", func() {
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
clientState.FrozenHeight = 1
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
}, false,
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
},
|
||||||
NextValidatorsHash: suite.valsHash,
|
{
|
||||||
},
|
"proof verification failed", func() {
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
proof = invalidProof
|
||||||
proof: []byte{},
|
}, false,
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
|
|
||||||
err := tc.clientState.VerifyPacketAcknowledgementAbsence(
|
suite.Run(tc.name, func() {
|
||||||
nil, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence, tc.consensusState,
|
suite.SetupTest() // reset
|
||||||
)
|
|
||||||
|
|
||||||
if tc.expPass {
|
// setup testing conditions
|
||||||
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
|
clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
|
||||||
} else {
|
packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, 100, 0)
|
||||||
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
|
|
||||||
}
|
// send packet, but no recv
|
||||||
|
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
// need to update chainA's client representing chainB to prove missing ack
|
||||||
|
suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, clientexported.Tendermint)
|
||||||
|
|
||||||
|
var ok bool
|
||||||
|
clientStateI := suite.chainA.GetClientState(clientA)
|
||||||
|
clientState, ok = clientStateI.(*types.ClientState)
|
||||||
|
suite.Require().True(ok)
|
||||||
|
|
||||||
|
prefix = suite.chainB.GetPrefix()
|
||||||
|
|
||||||
|
// make packet acknowledgement absence proof
|
||||||
|
acknowledgementKey := host.KeyPacketAcknowledgement(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
|
||||||
|
proof, proofHeight = suite.chainB.QueryProof(acknowledgementKey)
|
||||||
|
|
||||||
|
tc.malleate() // make changes as necessary
|
||||||
|
|
||||||
|
store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA)
|
||||||
|
|
||||||
|
err = clientState.VerifyPacketAcknowledgementAbsence(
|
||||||
|
store, suite.chainA.Codec, proofHeight, &prefix, proof,
|
||||||
|
packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(),
|
||||||
|
)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test verification of the next receive sequence on chainB being represented
|
||||||
|
// in the light client on chainA. A send and receive from chainB to chainA is
|
||||||
|
// simulated.
|
||||||
func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() {
|
func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() {
|
||||||
|
var (
|
||||||
|
clientState *types.ClientState
|
||||||
|
proof []byte
|
||||||
|
proofHeight uint64
|
||||||
|
prefix commitmenttypes.MerklePrefix
|
||||||
|
)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
clientState *ibctmtypes.ClientState
|
malleate func()
|
||||||
consensusState ibctmtypes.ConsensusState
|
expPass bool
|
||||||
prefix commitmenttypes.MerklePrefix
|
|
||||||
proof []byte
|
|
||||||
expPass bool
|
|
||||||
}{
|
}{
|
||||||
// FIXME: uncomment
|
|
||||||
// {
|
|
||||||
// name: "successful verification",
|
|
||||||
// clientState: ibctmtypes.NewClientState(chainID, height, commitmenttypes.GetSDKSpecs()),
|
|
||||||
// connection: conn,
|
|
||||||
// consensusState: ibctmtypes.ConsensusState{
|
|
||||||
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
// },
|
|
||||||
// prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
// expPass: true,
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
name: "ApplyPrefix failed",
|
"successful verification", func() {}, true,
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.MerklePrefix{},
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "latest client height < height",
|
"ApplyPrefix failed", func() {
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
prefix = commitmenttypes.MerklePrefix{}
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
}, false,
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "client is frozen",
|
"latest client height < height", func() {
|
||||||
clientState: &ibctmtypes.ClientState{LatestHeight: height, FrozenHeight: height - 1},
|
proofHeight = clientState.LatestHeight + 1
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
}, false,
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
|
||||||
},
|
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "proof verification failed",
|
"client is frozen", func() {
|
||||||
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
clientState.FrozenHeight = 1
|
||||||
consensusState: ibctmtypes.ConsensusState{
|
}, false,
|
||||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
},
|
||||||
NextValidatorsHash: suite.valsHash,
|
{
|
||||||
},
|
"proof verification failed", func() {
|
||||||
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
|
proof = invalidProof
|
||||||
proof: []byte{},
|
}, false,
|
||||||
expPass: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
|
|
||||||
err := tc.clientState.VerifyNextSequenceRecv(
|
suite.Run(tc.name, func() {
|
||||||
nil, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence, tc.consensusState,
|
suite.SetupTest() // reset
|
||||||
)
|
|
||||||
|
|
||||||
if tc.expPass {
|
// setup testing conditions
|
||||||
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
|
clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
|
||||||
} else {
|
packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, 100, 0)
|
||||||
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
|
|
||||||
}
|
// send packet
|
||||||
|
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
// write ack, next seq recv incremented
|
||||||
|
err = suite.coordinator.PacketExecuted(suite.chainB, suite.chainA, packet, clientA)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
// need to update chainA's client representing chainB
|
||||||
|
suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, clientexported.Tendermint)
|
||||||
|
|
||||||
|
var ok bool
|
||||||
|
clientStateI := suite.chainA.GetClientState(clientA)
|
||||||
|
clientState, ok = clientStateI.(*types.ClientState)
|
||||||
|
suite.Require().True(ok)
|
||||||
|
|
||||||
|
prefix = suite.chainB.GetPrefix()
|
||||||
|
|
||||||
|
// make next seq recv proof
|
||||||
|
nextSeqRecvKey := host.KeyNextSequenceRecv(packet.GetDestPort(), packet.GetDestChannel())
|
||||||
|
proof, proofHeight = suite.chainB.QueryProof(nextSeqRecvKey)
|
||||||
|
|
||||||
|
tc.malleate() // make changes as necessary
|
||||||
|
|
||||||
|
store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA)
|
||||||
|
|
||||||
|
err = clientState.VerifyNextSequenceRecv(
|
||||||
|
store, suite.chainA.Codec, proofHeight, &prefix, proof,
|
||||||
|
packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(),
|
||||||
|
)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
|
||||||
|
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
|
||||||
|
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetConsensusState retrieves the consensus state from the client prefixed
|
||||||
|
// store. An error is returned if the consensus state does not exist.
|
||||||
|
func GetConsensusState(store sdk.KVStore, cdc codec.BinaryMarshaler, height uint64) (*ConsensusState, error) {
|
||||||
|
bz := store.Get(host.KeyConsensusState(height))
|
||||||
|
if bz == nil {
|
||||||
|
return nil, sdkerrors.Wrapf(
|
||||||
|
clienttypes.ErrConsensusStateNotFound,
|
||||||
|
"consensus state does not exist for height %d", height,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var consensusStateI clientexported.ConsensusState
|
||||||
|
if err := codec.UnmarshalAny(cdc, &consensusStateI, bz); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
consensusState, ok := consensusStateI.(*ConsensusState)
|
||||||
|
if !ok {
|
||||||
|
return nil, sdkerrors.Wrapf(
|
||||||
|
clienttypes.ErrInvalidConsensus,
|
||||||
|
"invalid consensus type %T, expected %T", consensusState, &ConsensusState{},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return consensusState, nil
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
package types_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
|
||||||
|
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (suite *TendermintTestSuite) TestGetConsensusState() {
|
||||||
|
var (
|
||||||
|
height uint64
|
||||||
|
clientA string
|
||||||
|
)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
malleate func()
|
||||||
|
expPass bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"success", func() {}, true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"consensus state not found", func() {
|
||||||
|
// use height with no consensus state set
|
||||||
|
height = height + 1
|
||||||
|
}, false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"not a consensus state interface", func() {
|
||||||
|
// marshal an empty client state and set as consensus state
|
||||||
|
store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA)
|
||||||
|
clientStateBz := suite.chainA.App.IBCKeeper.ClientKeeper.MustMarshalClientState(&types.ClientState{})
|
||||||
|
store.Set(host.KeyConsensusState(height), clientStateBz)
|
||||||
|
}, false,
|
||||||
|
},
|
||||||
|
// TODO: uncomment upon merge of solomachine
|
||||||
|
// {
|
||||||
|
// "invalid consensus state (solomachine)", func() {
|
||||||
|
// // marshal and set solomachine consensus state
|
||||||
|
// store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA)
|
||||||
|
// consensusStateBz := suite.chainA.App.IBCKeeper.ClientKeeper.MustMarshalConsensusState(&solomachinetypes.ConsensusState{})
|
||||||
|
// store.Set(host.KeyConsensusState(height), consensusStateBz)
|
||||||
|
// }, false,
|
||||||
|
// },
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
tc := tc
|
||||||
|
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
suite.SetupTest()
|
||||||
|
|
||||||
|
clientA, _, _, _, _, _ = suite.coordinator.Setup(suite.chainA, suite.chainB)
|
||||||
|
clientState := suite.chainA.GetClientState(clientA)
|
||||||
|
height = clientState.GetLatestHeight()
|
||||||
|
|
||||||
|
tc.malleate() // change vars as necessary
|
||||||
|
|
||||||
|
store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA)
|
||||||
|
consensusState, err := types.GetConsensusState(store, suite.chainA.Codec, height)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
expConsensusState, found := suite.chainA.GetConsensusState(clientA, height)
|
||||||
|
suite.Require().True(found)
|
||||||
|
suite.Require().Equal(expConsensusState, consensusState)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
suite.Require().Nil(consensusState)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
|
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
|
||||||
|
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -28,6 +29,13 @@ const (
|
||||||
type TendermintTestSuite struct {
|
type TendermintTestSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
|
|
||||||
|
coordinator *ibctesting.Coordinator
|
||||||
|
|
||||||
|
// testing chains used for convenience and readability
|
||||||
|
chainA *ibctesting.TestChain
|
||||||
|
chainB *ibctesting.TestChain
|
||||||
|
|
||||||
|
// TODO: deprecate usage in favor of testing package
|
||||||
ctx sdk.Context
|
ctx sdk.Context
|
||||||
aminoCdc *codec.LegacyAmino
|
aminoCdc *codec.LegacyAmino
|
||||||
cdc codec.Marshaler
|
cdc codec.Marshaler
|
||||||
|
@ -39,6 +47,11 @@ type TendermintTestSuite struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *TendermintTestSuite) SetupTest() {
|
func (suite *TendermintTestSuite) SetupTest() {
|
||||||
|
suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2)
|
||||||
|
suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0))
|
||||||
|
suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1))
|
||||||
|
|
||||||
|
// TODO: deprecate usage in favor of testing package
|
||||||
checkTx := false
|
checkTx := false
|
||||||
app := simapp.Setup(checkTx)
|
app := simapp.Setup(checkTx)
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,6 @@ func (cs ClientState) VerifyConnectionState(
|
||||||
_ []byte,
|
_ []byte,
|
||||||
connectionID string,
|
connectionID string,
|
||||||
connectionEnd connectionexported.ConnectionI,
|
connectionEnd connectionexported.ConnectionI,
|
||||||
_ clientexported.ConsensusState,
|
|
||||||
) error {
|
) error {
|
||||||
path, err := commitmenttypes.ApplyPrefix(prefix, host.ConnectionPath(connectionID))
|
path, err := commitmenttypes.ApplyPrefix(prefix, host.ConnectionPath(connectionID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -130,7 +129,6 @@ func (cs ClientState) VerifyChannelState(
|
||||||
portID,
|
portID,
|
||||||
channelID string,
|
channelID string,
|
||||||
channel channelexported.ChannelI,
|
channel channelexported.ChannelI,
|
||||||
_ clientexported.ConsensusState,
|
|
||||||
) error {
|
) error {
|
||||||
path, err := commitmenttypes.ApplyPrefix(prefix, host.ChannelPath(portID, channelID))
|
path, err := commitmenttypes.ApplyPrefix(prefix, host.ChannelPath(portID, channelID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -170,7 +168,6 @@ func (cs ClientState) VerifyPacketCommitment(
|
||||||
channelID string,
|
channelID string,
|
||||||
sequence uint64,
|
sequence uint64,
|
||||||
commitmentBytes []byte,
|
commitmentBytes []byte,
|
||||||
_ clientexported.ConsensusState,
|
|
||||||
) error {
|
) error {
|
||||||
path, err := commitmenttypes.ApplyPrefix(prefix, host.PacketCommitmentPath(portID, channelID, sequence))
|
path, err := commitmenttypes.ApplyPrefix(prefix, host.PacketCommitmentPath(portID, channelID, sequence))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -204,7 +201,6 @@ func (cs ClientState) VerifyPacketAcknowledgement(
|
||||||
channelID string,
|
channelID string,
|
||||||
sequence uint64,
|
sequence uint64,
|
||||||
acknowledgement []byte,
|
acknowledgement []byte,
|
||||||
_ clientexported.ConsensusState,
|
|
||||||
) error {
|
) error {
|
||||||
path, err := commitmenttypes.ApplyPrefix(prefix, host.PacketAcknowledgementPath(portID, channelID, sequence))
|
path, err := commitmenttypes.ApplyPrefix(prefix, host.PacketAcknowledgementPath(portID, channelID, sequence))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -238,7 +234,6 @@ func (cs ClientState) VerifyPacketAcknowledgementAbsence(
|
||||||
portID,
|
portID,
|
||||||
channelID string,
|
channelID string,
|
||||||
sequence uint64,
|
sequence uint64,
|
||||||
_ clientexported.ConsensusState,
|
|
||||||
) error {
|
) error {
|
||||||
path, err := commitmenttypes.ApplyPrefix(prefix, host.PacketAcknowledgementPath(portID, channelID, sequence))
|
path, err := commitmenttypes.ApplyPrefix(prefix, host.PacketAcknowledgementPath(portID, channelID, sequence))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -264,7 +259,6 @@ func (cs ClientState) VerifyNextSequenceRecv(
|
||||||
portID,
|
portID,
|
||||||
channelID string,
|
channelID string,
|
||||||
nextSequenceRecv uint64,
|
nextSequenceRecv uint64,
|
||||||
_ clientexported.ConsensusState,
|
|
||||||
) error {
|
) error {
|
||||||
path, err := commitmenttypes.ApplyPrefix(prefix, host.NextSequenceRecvPath(portID, channelID))
|
path, err := commitmenttypes.ApplyPrefix(prefix, host.NextSequenceRecvPath(portID, channelID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -88,7 +88,7 @@ func (suite *LocalhostTestSuite) TestVerifyConnectionState() {
|
||||||
tc := tc
|
tc := tc
|
||||||
|
|
||||||
err := tc.clientState.VerifyConnectionState(
|
err := tc.clientState.VerifyConnectionState(
|
||||||
suite.store, suite.cdc, height, tc.prefix, tc.proof, testConnectionID, &tc.connection, nil,
|
suite.store, suite.cdc, height, tc.prefix, tc.proof, testConnectionID, &tc.connection,
|
||||||
)
|
)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
|
@ -139,7 +139,7 @@ func (suite *LocalhostTestSuite) TestVerifyChannelState() {
|
||||||
tc := tc
|
tc := tc
|
||||||
|
|
||||||
err := tc.clientState.VerifyChannelState(
|
err := tc.clientState.VerifyChannelState(
|
||||||
suite.store, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, &tc.channel, nil,
|
suite.store, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, &tc.channel,
|
||||||
)
|
)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
|
@ -194,7 +194,7 @@ func (suite *LocalhostTestSuite) TestVerifyPacketCommitment() {
|
||||||
tc := tc
|
tc := tc
|
||||||
|
|
||||||
err := tc.clientState.VerifyPacketCommitment(
|
err := tc.clientState.VerifyPacketCommitment(
|
||||||
suite.store, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence, tc.commitment, nil,
|
suite.store, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence, tc.commitment,
|
||||||
)
|
)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
|
@ -249,7 +249,7 @@ func (suite *LocalhostTestSuite) TestVerifyPacketAcknowledgement() {
|
||||||
tc := tc
|
tc := tc
|
||||||
|
|
||||||
err := tc.clientState.VerifyPacketAcknowledgement(
|
err := tc.clientState.VerifyPacketAcknowledgement(
|
||||||
suite.store, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence, tc.ack, nil,
|
suite.store, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence, tc.ack,
|
||||||
)
|
)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
|
@ -280,7 +280,7 @@ func (suite *LocalhostTestSuite) TestVerifyPacketAcknowledgementAbsence() {
|
||||||
tc := tc
|
tc := tc
|
||||||
|
|
||||||
err := tc.clientState.VerifyPacketAcknowledgementAbsence(
|
err := tc.clientState.VerifyPacketAcknowledgementAbsence(
|
||||||
suite.store, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence, nil,
|
suite.store, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence,
|
||||||
)
|
)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
|
@ -330,7 +330,7 @@ func (suite *LocalhostTestSuite) TestVerifyNextSeqRecv() {
|
||||||
tc := tc
|
tc := tc
|
||||||
|
|
||||||
err := tc.clientState.VerifyNextSequenceRecv(
|
err := tc.clientState.VerifyNextSequenceRecv(
|
||||||
suite.store, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence, nil,
|
suite.store, suite.cdc, height, tc.prefix, tc.proof, testPortID, testChannelID, testSequence,
|
||||||
)
|
)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/tendermint/tendermint/version"
|
"github.com/tendermint/tendermint/version"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
@ -70,6 +71,7 @@ type TestChain struct {
|
||||||
CurrentHeader abci.Header // header for current block height
|
CurrentHeader abci.Header // header for current block height
|
||||||
QueryServer types.QueryServer
|
QueryServer types.QueryServer
|
||||||
TxConfig client.TxConfig
|
TxConfig client.TxConfig
|
||||||
|
Codec codec.BinaryMarshaler
|
||||||
|
|
||||||
Vals *tmtypes.ValidatorSet
|
Vals *tmtypes.ValidatorSet
|
||||||
Signers []tmtypes.PrivValidator
|
Signers []tmtypes.PrivValidator
|
||||||
|
@ -127,6 +129,7 @@ func NewTestChain(t *testing.T, chainID string) *TestChain {
|
||||||
CurrentHeader: header,
|
CurrentHeader: header,
|
||||||
QueryServer: app.IBCKeeper,
|
QueryServer: app.IBCKeeper,
|
||||||
TxConfig: txConfig,
|
TxConfig: txConfig,
|
||||||
|
Codec: app.AppCodec(),
|
||||||
Vals: valSet,
|
Vals: valSet,
|
||||||
Signers: signers,
|
Signers: signers,
|
||||||
senderPrivKey: senderPrivKey,
|
senderPrivKey: senderPrivKey,
|
||||||
|
|
Loading…
Reference in New Issue