Skip to content

Commit

Permalink
Abstract Tendermint ABCI proof queries for IBC into a single function (
Browse files Browse the repository at this point in the history
…cosmos#7250)

* add single query function

* fix lint
  • Loading branch information
colin-axner authored Sep 7, 2020
1 parent 64b6bb5 commit 221a28f
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 116 deletions.
47 changes: 12 additions & 35 deletions x/ibc/02-client/client/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package utils
import (
"context"

abci "github.com/tendermint/tendermint/abci/types"
tmtypes "github.com/tendermint/tendermint/types"

"github.com/cosmos/cosmos-sdk/client"
Expand All @@ -13,12 +12,12 @@ import (
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/client"
"github.com/cosmos/cosmos-sdk/x/ibc/exported"
)

// QueryClientState returns a client state.
// If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise,
// it uses the gRPC query client.
// QueryClientState returns a client state. If prove is true, it performs an ABCI store query
// in order to retrieve the merkle proof. Otherwise, it uses the gRPC query client.
func QueryClientState(
clientCtx client.Context, clientID string, prove bool,
) (*types.QueryClientStateResponse, error) {
Expand All @@ -38,20 +37,16 @@ func QueryClientState(
func QueryClientStateABCI(
clientCtx client.Context, clientID string,
) (*types.QueryClientStateResponse, error) {
req := abci.RequestQuery{
Path: "store/ibc/key",
Data: host.FullKeyClientPath(clientID, host.KeyClientState()),
Prove: true,
}
key := host.FullKeyClientPath(clientID, host.KeyClientState())

res, err := clientCtx.QueryABCI(req)
value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key)
if err != nil {
return nil, err
}

cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry)

clientState, err := types.UnmarshalClientState(cdc, res.Value)
clientState, err := types.UnmarshalClientState(cdc, value)
if err != nil {
return nil, err
}
Expand All @@ -61,20 +56,12 @@ func QueryClientStateABCI(
return nil, err
}

proofBz, err := cdc.MarshalBinaryBare(res.ProofOps)
if err != nil {
return nil, err
}

// TODO: retrieve epoch-number from chain-id
height := types.NewHeight(0, uint64(res.Height))
clientStateRes := types.NewQueryClientStateResponse(clientID, anyClientState, proofBz, height)
clientStateRes := types.NewQueryClientStateResponse(clientID, anyClientState, proofBz, proofHeight)
return clientStateRes, nil
}

// QueryConsensusState returns a consensus state.
// If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise,
// it uses the gRPC query client.
// QueryConsensusState returns a consensus state. If prove is true, it performs an ABCI store
// query in order to retrieve the merkle proof. Otherwise, it uses the gRPC query client.
func QueryConsensusState(
clientCtx client.Context, clientID string, height exported.Height, prove, latestHeight bool,
) (*types.QueryConsensusStateResponse, error) {
Expand All @@ -98,20 +85,16 @@ func QueryConsensusState(
func QueryConsensusStateABCI(
clientCtx client.Context, clientID string, height exported.Height,
) (*types.QueryConsensusStateResponse, error) {
req := abci.RequestQuery{
Path: "store/ibc/key",
Data: host.FullKeyClientPath(clientID, host.KeyConsensusState(height)),
Prove: true,
}
key := host.FullKeyClientPath(clientID, host.KeyConsensusState(height))

res, err := clientCtx.QueryABCI(req)
value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key)
if err != nil {
return nil, err
}

cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry)

cs, err := types.UnmarshalConsensusState(cdc, res.Value)
cs, err := types.UnmarshalConsensusState(cdc, value)
if err != nil {
return nil, err
}
Expand All @@ -121,13 +104,7 @@ func QueryConsensusStateABCI(
return nil, err
}

proofBz, err := cdc.MarshalBinaryBare(res.ProofOps)
if err != nil {
return nil, err
}

// TODO: retrieve epoch-number from chain-id
proofHeight := types.NewHeight(0, uint64(res.Height))
return types.NewQueryConsensusStateResponse(clientID, anyConsensusState, proofBz, proofHeight), nil
}

Expand Down
39 changes: 7 additions & 32 deletions x/ibc/03-connection/client/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ import (

"github.com/pkg/errors"

abci "github.com/tendermint/tendermint/abci/types"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
clientutils "github.com/cosmos/cosmos-sdk/x/ibc/02-client/client/utils"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/client"
"github.com/cosmos/cosmos-sdk/x/ibc/exported"
)

Expand All @@ -38,31 +37,20 @@ func QueryConnection(
}

func queryConnectionABCI(clientCtx client.Context, connectionID string) (*types.QueryConnectionResponse, error) {
req := abci.RequestQuery{
Path: "store/ibc/key",
Data: host.KeyConnection(connectionID),
Prove: true,
}
key := host.KeyConnection(connectionID)

res, err := clientCtx.QueryABCI(req)
value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key)
if err != nil {
return nil, err
}

cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry)

var connection types.ConnectionEnd
if err := cdc.UnmarshalBinaryBare(res.Value, &connection); err != nil {
if err := cdc.UnmarshalBinaryBare(value, &connection); err != nil {
return nil, err
}

proofBz, err := cdc.MarshalBinaryBare(res.ProofOps)
if err != nil {
return nil, err
}

// TODO: Retrieve epoch number from chain-id
proofHeight := clienttypes.NewHeight(0, uint64(res.Height))
return types.NewQueryConnectionResponse(connectionID, connection, proofBz, proofHeight), nil
}

Expand All @@ -85,31 +73,18 @@ func QueryClientConnections(
}

func queryClientConnectionsABCI(clientCtx client.Context, clientID string) (*types.QueryClientConnectionsResponse, error) {
req := abci.RequestQuery{
Path: "store/ibc/key",
Data: host.KeyClientConnections(clientID),
Prove: true,
}
key := host.KeyClientConnections(clientID)

res, err := clientCtx.QueryABCI(req)
value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key)
if err != nil {
return nil, err
}

cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry)

var paths []string
if err := clientCtx.LegacyAmino.UnmarshalBinaryBare(res.Value, &paths); err != nil {
return nil, err
}

proofBz, err := cdc.MarshalBinaryBare(res.ProofOps)
if err != nil {
if err := clientCtx.LegacyAmino.UnmarshalBinaryBare(value, paths); err != nil {
return nil, err
}

// TODO: Retrieve epoch number from chain-id
proofHeight := clienttypes.NewHeight(0, uint64(res.Height))
return types.NewQueryClientConnectionsResponse(clientID, paths, proofBz, proofHeight), nil
}

Expand Down
61 changes: 12 additions & 49 deletions x/ibc/04-channel/client/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import (
"context"
"encoding/binary"

abci "github.com/tendermint/tendermint/abci/types"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
clientutils "github.com/cosmos/cosmos-sdk/x/ibc/02-client/client/utils"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/client"
"github.com/cosmos/cosmos-sdk/x/ibc/exported"
)

Expand Down Expand Up @@ -40,29 +39,15 @@ func QueryPacketCommitment(
func queryPacketCommitmentABCI(
clientCtx client.Context, portID, channelID string, sequence uint64,
) (*types.QueryPacketCommitmentResponse, error) {
req := abci.RequestQuery{
Path: "store/ibc/key",
Data: host.KeyPacketCommitment(portID, channelID, sequence),
Prove: true,
}

res, err := clientCtx.QueryABCI(req)
if err != nil {
return nil, err
}

cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry)
key := host.KeyPacketCommitment(portID, channelID, sequence)

proofBz, err := cdc.MarshalBinaryBare(res.ProofOps)
value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key)
if err != nil {
return nil, err
}

// FIXME: height + 1 is returned as the proof height
// Issue: https://github.com/cosmos/cosmos-sdk/issues/6567
// TODO: retrieve epoch number from chain-id
height := clienttypes.NewHeight(0, uint64(res.Height+1))
return types.NewQueryPacketCommitmentResponse(portID, channelID, sequence, res.Value, proofBz, height), nil
return types.NewQueryPacketCommitmentResponse(portID, channelID, sequence, value, proofBz, proofHeight), nil
}

// QueryChannel returns a channel end.
Expand All @@ -85,32 +70,21 @@ func QueryChannel(
}

func queryChannelABCI(clientCtx client.Context, portID, channelID string) (*types.QueryChannelResponse, error) {
req := abci.RequestQuery{
Path: "store/ibc/key",
Data: host.KeyChannel(portID, channelID),
Prove: true,
}
key := host.KeyChannel(portID, channelID)

res, err := clientCtx.QueryABCI(req)
value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key)
if err != nil {
return nil, err
}

cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry)

var channel types.Channel
if err := cdc.UnmarshalBinaryBare(res.Value, &channel); err != nil {
return nil, err
}

proofBz, err := cdc.MarshalBinaryBare(res.ProofOps)
if err != nil {
if err := cdc.UnmarshalBinaryBare(value, &channel); err != nil {
return nil, err
}

// TODO: retrieve epoch number from chain-id
height := clienttypes.NewHeight(0, uint64(res.Height))
return types.NewQueryChannelResponse(portID, channelID, channel, proofBz, height), nil
return types.NewQueryChannelResponse(portID, channelID, channel, proofBz, proofHeight), nil
}

// QueryChannelClientState returns the ClientState of a channel end. If
Expand Down Expand Up @@ -237,26 +211,15 @@ func QueryNextSequenceReceive(
}

func queryNextSequenceRecvABCI(clientCtx client.Context, portID, channelID string) (*types.QueryNextSequenceReceiveResponse, error) {
req := abci.RequestQuery{
Path: "store/ibc/key",
Data: host.KeyNextSequenceRecv(portID, channelID),
Prove: true,
}
key := host.KeyNextSequenceRecv(portID, channelID)

res, err := clientCtx.QueryABCI(req)
value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key)
if err != nil {
return nil, err
}

cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry)

proofBz, err := cdc.MarshalBinaryBare(res.ProofOps)
if err != nil {
return nil, err
}
sequence := binary.BigEndian.Uint64(value)

sequence := binary.BigEndian.Uint64(res.Value)
// TODO: retrieve epoch number from chain-id
height := clienttypes.NewHeight(0, uint64(res.Height))
return types.NewQueryNextSequenceReceiveResponse(portID, channelID, sequence, proofBz, height), nil
return types.NewQueryNextSequenceReceiveResponse(portID, channelID, sequence, proofBz, proofHeight), nil
}
44 changes: 44 additions & 0 deletions x/ibc/client/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package client

import (
"fmt"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
abci "github.com/tendermint/tendermint/abci/types"
)

// QueryTendermintProof performs an ABCI query with the given key and returns the value
// of the query, the proto encoded merkle proof for the query and the height
// at which the proof will succeed on a tendermint verifier (one above the
// returned IAVL version height).
// Issue: https://github.com/cosmos/cosmos-sdk/issues/6567
func QueryTendermintProof(clientCtx client.Context, key []byte) ([]byte, []byte, clienttypes.Height, error) {
req := abci.RequestQuery{
Path: fmt.Sprintf("store/%s/key", host.StoreKey),
Data: key,
Prove: true,
}

res, err := clientCtx.QueryABCI(req)
if err != nil {
return nil, nil, clienttypes.Height{}, err
}

merkleProof := commitmenttypes.MerkleProof{
Proof: res.ProofOps,
}

cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry)

proofBz, err := cdc.MarshalBinaryBare(&merkleProof)
if err != nil {
return nil, nil, clienttypes.Height{}, err
}

// TODO: retrieve epoch number from chain-id
return res.Value, proofBz, clienttypes.NewHeight(0, uint64(res.Height)+1), nil
}

0 comments on commit 221a28f

Please sign in to comment.