Skip to content
This repository was archived by the owner on Oct 3, 2022. It is now read-only.

Commit

Permalink
Merge pull request #14 from decipherhub/feature/implement-onRecvPacket
Browse files Browse the repository at this point in the history
Feature/implement SubmitCrossChainQueryResult
  • Loading branch information
Woojinger authored Sep 26, 2022
2 parents 52c84c7 + 957f1a8 commit 4e1c426
Show file tree
Hide file tree
Showing 13 changed files with 913 additions and 768 deletions.
93 changes: 34 additions & 59 deletions docs/ibc/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,11 @@

- [QueryResult](#ibc.applications.ibc_query.v1.QueryResult)

- [ibc/applications/ibc_query/v1/event.proto](#ibc/applications/ibc_query/v1/event.proto)
- [EventQuerySubmitted](#ibc.applications.ibc_query.v1.EventQuerySubmitted)

- [ibc/applications/ibc_query/v1/genesis.proto](#ibc/applications/ibc_query/v1/genesis.proto)
- [GenesisState](#ibc.applications.ibc_query.v1.GenesisState)

- [ibc/applications/ibc_query/v1/packet.proto](#ibc/applications/ibc_query/v1/packet.proto)
- [IBCQueryPacketData](#ibc.applications.ibc_query.v1.IBCQueryPacketData)
- [IBCQueryResultPacketData](#ibc.applications.ibc_query.v1.IBCQueryResultPacketData)

- [ibc/applications/ibc_query/v1/query.proto](#ibc/applications/ibc_query/v1/query.proto)
- [QueryCrossChainQueryResult](#ibc.applications.ibc_query.v1.QueryCrossChainQueryResult)
Expand All @@ -105,6 +101,8 @@
- [ibc/applications/ibc_query/v1/tx.proto](#ibc/applications/ibc_query/v1/tx.proto)
- [MsgSubmitCrossChainQuery](#ibc.applications.ibc_query.v1.MsgSubmitCrossChainQuery)
- [MsgSubmitCrossChainQueryResponse](#ibc.applications.ibc_query.v1.MsgSubmitCrossChainQueryResponse)
- [MsgSubmitCrossChainQueryResult](#ibc.applications.ibc_query.v1.MsgSubmitCrossChainQueryResult)
- [MsgSubmitCrossChainQueryResultResponse](#ibc.applications.ibc_query.v1.MsgSubmitCrossChainQueryResultResponse)

- [Msg](#ibc.applications.ibc_query.v1.Msg)

Expand Down Expand Up @@ -1516,41 +1514,6 @@ QueryResult



<a name="ibc/applications/ibc_query/v1/event.proto"></a>
<p align="right"><a href="#top">Top</a></p>

## ibc/applications/ibc_query/v1/event.proto



<a name="ibc.applications.ibc_query.v1.EventQuerySubmitted"></a>

### EventQuerySubmitted
EventQuerySubmitted emitted when process MsgSubmitCrossChainQuery tx


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `id` | [string](#string) | | |
| `path` | [string](#string) | | |
| `local_timeout_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | |
| `local_timeout_stamp` | [uint64](#uint64) | | |
| `query_height` | [uint64](#uint64) | | |





<!-- end messages -->

<!-- end enums -->

<!-- end HasExtensions -->

<!-- end services -->



<a name="ibc/applications/ibc_query/v1/genesis.proto"></a>
<p align="right"><a href="#top">Top</a></p>

Expand Down Expand Up @@ -1607,26 +1570,6 @@ IBCQueryPacketData defines a struct for the cross chain query packet payload




<a name="ibc.applications.ibc_query.v1.IBCQueryResultPacketData"></a>

### IBCQueryResultPacketData
IBCQueryPacketData defines a struct for the cross chain query result packet payload


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `id` | [string](#string) | | |
| `path` | [string](#string) | | |
| `query_height` | [uint64](#uint64) | | |
| `result` | [QueryResult](#ibc.applications.ibc_query.v1.QueryResult) | | |
| `data` | [bytes](#bytes) | | |
| `proof_specs` | [ics23.ProofSpec](#ics23.ProofSpec) | repeated | TODO: Proof specifications used in verifying counterparty state |





<!-- end messages -->

<!-- end enums -->
Expand Down Expand Up @@ -1740,6 +1683,37 @@ MsgSubmitCrossChainQueryResponse




<a name="ibc.applications.ibc_query.v1.MsgSubmitCrossChainQueryResult"></a>

### MsgSubmitCrossChainQueryResult
MsgSubmitCrossChainQueryResult


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `id` | [string](#string) | | |
| `path` | [string](#string) | | |
| `query_height` | [uint64](#uint64) | | |
| `result` | [QueryResult](#ibc.applications.ibc_query.v1.QueryResult) | | |
| `data` | [bytes](#bytes) | | |
| `sender` | [string](#string) | | |
| `proof_specs` | [ics23.ProofSpec](#ics23.ProofSpec) | repeated | TODO: Proof specifications used in verifying counterparty state |






<a name="ibc.applications.ibc_query.v1.MsgSubmitCrossChainQueryResultResponse"></a>

### MsgSubmitCrossChainQueryResultResponse
MsgSubmitCrossChainQueryResultResponse





<!-- end messages -->

<!-- end enums -->
Expand All @@ -1755,6 +1729,7 @@ Msg
| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
| `SubmitCrossChainQuery` | [MsgSubmitCrossChainQuery](#ibc.applications.ibc_query.v1.MsgSubmitCrossChainQuery) | [MsgSubmitCrossChainQueryResponse](#ibc.applications.ibc_query.v1.MsgSubmitCrossChainQueryResponse) | submit query request | |
| `SubmitCrossChainQueryResult` | [MsgSubmitCrossChainQueryResult](#ibc.applications.ibc_query.v1.MsgSubmitCrossChainQueryResult) | [MsgSubmitCrossChainQueryResultResponse](#ibc.applications.ibc_query.v1.MsgSubmitCrossChainQueryResultResponse) | submit query result | |

<!-- end services -->

Expand Down
2 changes: 1 addition & 1 deletion modules/apps/31-ibc-query/keeper/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func EmitQueryEvent(ctx sdk.Context, query *types.MsgSubmitCrossChainQuery) {
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventSendQuery,
sdk.NewAttribute(types.AttributeKeyQueryID, query.GetQueryId()),
sdk.NewAttribute(types.AttributeKeyQueryID, query.GetId()),
sdk.NewAttribute(types.AttributeKeyQueryHeight, fmt.Sprintf("%d", query.GetQueryHeight())),
sdk.NewAttribute(types.AttributeKeyQueryPath, fmt.Sprintf("%x", query.GetQueryPath())),
),
Expand Down
44 changes: 39 additions & 5 deletions modules/apps/31-ibc-query/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ func (k Keeper) SubmitCrossChainQuery(goCtx context.Context, msg *types.MsgSubmi
currentHeight := clienttypes.GetSelfHeight(ctx)

// Sanity-check that localTimeoutHeight.
if msg.LocalTimeoutHeight.RevisionHeight <= currentHeight.RevisionHeight {
if msg.LocalTimeoutHeight.RevisionHeight > 0 && msg.LocalTimeoutHeight.RevisionHeight <= currentHeight.RevisionHeight {
return nil, sdkerrors.Wrapf(
types.ErrTimeout,
"localTimeoutHeight is not 0 and current height >= localTimeoutHeight(%d >= %d)", currentHeight.RevisionHeight, msg.LocalTimeoutHeight.RevisionHeight,
"localTimeoutHeight > 0 and current height >= localTimeoutHeight(%d >= %d)", currentHeight.RevisionHeight, msg.LocalTimeoutHeight.RevisionHeight,
)
}
// Sanity-check that localTimeoutTimestamp
if msg.LocalTimeoutStamp <= currentTimestamp {
if msg.LocalTimeoutStamp > 0 && msg.LocalTimeoutStamp <= currentTimestamp {
return nil, sdkerrors.Wrapf(
types.ErrTimeout,
"localTimeoutTimestamp is not 0 and current timestamp >= localTimeoutTimestamp(%d >= %d)", currentTimestamp, msg.LocalTimeoutStamp,
"localTimeoutTimestamp > 0 and current timestamp >= localTimeoutTimestamp(%d >= %d)", currentTimestamp, msg.LocalTimeoutStamp,
)
}

Expand All @@ -52,10 +52,44 @@ func (k Keeper) SubmitCrossChainQuery(goCtx context.Context, msg *types.MsgSubmi
}

// Log the query request
k.Logger(ctx).Info("query sent", "query_id", msg.GetQueryId())
k.Logger(ctx).Info("query sent", "query_id", msg.GetId())

// emit event
EmitQueryEvent(ctx, msg)

return &types.MsgSubmitCrossChainQueryResponse{QueryId: query.Id}, nil
}

func (k Keeper) SubmitCrossChainQueryResult(goCtx context.Context, msg *types.MsgSubmitCrossChainQueryResult) (*types.MsgSubmitCrossChainQueryResultResponse, error) {
// UnwrapSDKContext
ctx := sdk.UnwrapSDKContext(goCtx)

queryResult := types.CrossChainQueryResult{
Id: msg.Id,
Result: msg.Result,
Data: msg.Data,
}

query, found := k.GetCrossChainQuery(ctx, queryResult.Id)
// if CrossChainQuery of queryId doesn't exist in store, other relayer already submitted CrossChainQueryResult
if !found {
return nil, sdkerrors.Wrapf(types.ErrCrossChainQueryNotFound, "cannot find ICS-31 cross chain query id %s", queryResult.Id)
}

k.DeleteCrossChainQuery(ctx, queryResult.Id)

// check Timeout by comparing the latest height of chain, latest timestamp
selfHeight := clienttypes.GetSelfHeight(ctx)
selfBlockTime := uint64(ctx.BlockTime().UnixNano())
if selfHeight.GTE(query.LocalTimeoutHeight) {
queryResult.Result = types.QueryResult_QUERY_RESULT_TIMEOUT
}
if selfBlockTime >= query.LocalTimeoutTimestamp {
queryResult.Result = types.QueryResult_QUERY_RESULT_TIMEOUT
}

// store result in privateStore
k.SetCrossChainQueryResult(ctx, queryResult)

return &types.MsgSubmitCrossChainQueryResultResponse{}, nil
}
134 changes: 115 additions & 19 deletions modules/apps/31-ibc-query/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,22 @@ import (
"github.com/cosmos/ibc-go/v4/modules/apps/31-ibc-query/types"
clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types"
ibctesting "github.com/cosmos/ibc-go/v4/testing"
"time"
)

const (
portid = "testportid"
chanid = "channel-0"
)

var (
timeoutHeight = clienttypes.NewHeight(0, 100)
timeoutTimestamp = uint64(0)
addr = sdk.AccAddress("testaddr111111111111").String()
queryHeight = clienttypes.NewHeight(0, 1)
)

func (suite *KeeperTestSuite) TestSubmitCrossChainQuery() {
var (
path *ibctesting.Path
msg *types.MsgSubmitCrossChainQuery
path *ibctesting.Path
msg *types.MsgSubmitCrossChainQuery
queryHeight int64
timeoutHeight clienttypes.Height
timeoutTimestamp uint64
addr string
)

testCases := []struct {
Expand All @@ -35,7 +33,10 @@ func (suite *KeeperTestSuite) TestSubmitCrossChainQuery() {
true,
func() {
suite.coordinator.CreateChannels(path)
msg = types.NewMsgSubmitCrossChainQuery("query-1", "test/query_path", timeoutHeight, timeoutTimestamp, queryHeight.RevisionHeight, addr, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
queryHeight = suite.chainB.GetContext().BlockHeight()
timeoutHeight = clienttypes.NewHeight(0, uint64(suite.chainA.GetContext().BlockHeight()+50))
timeoutTimestamp = uint64(suite.chainA.GetContext().BlockTime().UnixNano() + 5000000)
msg = types.NewMsgSubmitCrossChainQuery("query-1", "test/query_path", timeoutHeight, timeoutTimestamp, uint64(queryHeight), addr, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
},
},
}
Expand All @@ -46,22 +47,117 @@ func (suite *KeeperTestSuite) TestSubmitCrossChainQuery() {
suite.coordinator.SetupConnections(path)

tc.malleate()

res, err := suite.chainA.GetSimApp().IBCQueryKeeper.SubmitCrossChainQuery(sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
if tc.expPass {
res, err := suite.chainA.GetSimApp().IBCQueryKeeper.SubmitCrossChainQuery(sdk.WrapSDKContext(suite.chainA.GetContext()), msg)

suite.Require().NoError(err)
suite.Require().NotNil(res)
queryResult, found := suite.chainA.GetSimApp().IBCQueryKeeper.GetCrossChainQuery(suite.chainA.GetContext(), "query-1")

suite.Require().True(found)
suite.Require().Equal("query-1", queryResult.Id)
suite.Require().Equal("test/query_path", queryResult.Path)
suite.Require().Equal(timeoutHeight.RevisionHeight, queryResult.LocalTimeoutHeight.RevisionHeight)
suite.Require().Equal(timeoutTimestamp, queryResult.LocalTimeoutTimestamp)
suite.Require().Equal(queryHeight.RevisionHeight, queryResult.QueryHeight)
suite.Require().Equal(msg.Id, queryResult.Id)
suite.Require().Equal(msg.Path, queryResult.Path)
suite.Require().Equal(msg.LocalTimeoutHeight.RevisionHeight, queryResult.LocalTimeoutHeight.RevisionHeight)
suite.Require().Equal(msg.LocalTimeoutStamp, queryResult.LocalTimeoutTimestamp)
suite.Require().Equal(msg.QueryHeight, queryResult.QueryHeight)
suite.Require().Equal(addr, queryResult.ClientId)
}
}
}

func (suite *KeeperTestSuite) TestSubmitCrossChainQueryResult() {
var (
path *ibctesting.Path
successResult = types.QueryResult_QUERY_RESULT_SUCCESS
failResult = types.QueryResult_QUERY_RESULT_FAILURE
timeoutResult = types.QueryResult_QUERY_RESULT_TIMEOUT
crossChainQuery types.CrossChainQuery
queryResultData []byte
chainAHeight int64
chainATimestamp uint64
)

testCases := []struct {
name string
queryResult types.QueryResult
malleate func()
expPass bool
expResult types.QueryResult
}{
{"success receive from queried chain", successResult, func() {
crossChainQuery = types.CrossChainQuery{
Id: "1",
Path: "test/query-1",
LocalTimeoutHeight: clienttypes.NewHeight(0, uint64(chainAHeight+50)),
LocalTimeoutTimestamp: chainATimestamp + uint64(time.Minute.Nanoseconds()),
QueryHeight: uint64(suite.chainB.CurrentHeader.Height),
ClientId: suite.chainB.CurrentHeader.ChainID,
}
queryResultData = []byte("query result data")
}, true, successResult},
{"fail receive from queried chain", failResult, func() {
crossChainQuery = types.CrossChainQuery{
Id: "2",
Path: "test/query-2",
LocalTimeoutHeight: clienttypes.NewHeight(0, uint64(chainAHeight+50)),
LocalTimeoutTimestamp: chainATimestamp + uint64(time.Minute.Nanoseconds()),
QueryHeight: uint64(suite.chainB.CurrentHeader.Height),
ClientId: suite.chainB.CurrentHeader.ChainID,
}
queryResultData = []byte("query result data2")
}, true, failResult},
{"timeout because of block height", successResult, func() {
crossChainQuery = types.CrossChainQuery{
Id: "3",
Path: "test/query-3",
LocalTimeoutHeight: clienttypes.NewHeight(0, uint64(chainAHeight-1)),
LocalTimeoutTimestamp: chainATimestamp + uint64(time.Minute.Nanoseconds()),
QueryHeight: uint64(suite.chainB.CurrentHeader.Height),
ClientId: suite.chainB.CurrentHeader.ChainID,
}
queryResultData = []byte("query result data3")
}, true, timeoutResult},
{"timeout because of block timestamp", failResult, func() {
crossChainQuery = types.CrossChainQuery{
Id: "4",
Path: "test/query-4",
LocalTimeoutHeight: clienttypes.NewHeight(0, uint64(chainAHeight+50)),
LocalTimeoutTimestamp: chainATimestamp - 30,
QueryHeight: uint64(suite.chainB.CurrentHeader.Height),
ClientId: suite.chainB.CurrentHeader.ChainID,
}
queryResultData = []byte("query result data4")
}, true, timeoutResult},
}

for _, tc := range testCases {
suite.SetupTest()
path = NewQueryPath(suite.chainA, suite.chainB)
suite.coordinator.SetupConnections(path)

chainAHeight = suite.chainA.GetContext().BlockHeight()
chainATimestamp = uint64(suite.chainA.GetContext().BlockTime().UnixNano())

tc.malleate()

query := crossChainQuery
suite.chainA.GetSimApp().IBCQueryKeeper.SetCrossChainQuery(suite.chainA.GetContext(), query)

queryResultMsg := types.NewMsgSubmitCrossChainQueryResult(query.Id, query.Path, query.QueryHeight, tc.queryResult, queryResultData, nil)
_, err := suite.chainA.GetSimApp().IBCQueryKeeper.SubmitCrossChainQueryResult(sdk.WrapSDKContext(suite.chainA.GetContext()), queryResultMsg)
suite.Require().NoError(err)
if tc.expPass {
result, isUnmarshal := suite.chainA.GetSimApp().IBCQueryKeeper.GetCrossChainQueryResult(suite.chainA.GetContext(), query.Id)
suite.Require().True(isUnmarshal)
suite.Require().Equal(queryResultData, result.GetData())
switch tc.expResult {
case successResult:
suite.Require().Equal(successResult, result.GetResult())
case failResult:
suite.Require().Equal(failResult, result.GetResult())
case timeoutResult:
suite.Require().Equal(timeoutResult, result.GetResult())
}
} else {
suite.Require().Error(err)
}
}
}
Loading

0 comments on commit 4e1c426

Please sign in to comment.