From b40035e811d8ad3bae33fc48a6ef508244de2b6f Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Wed, 31 Jul 2024 17:56:37 +0200 Subject: [PATCH 01/32] redesign the ICQ module documentation --- .../modules/interchain-queries/TODO.md | 137 +++++++ .../neutron/modules/interchain-queries/api.md | 361 ++++++++++++++++++ .../modules/interchain-queries/client.md | 238 ------------ .../modules/interchain-queries/events.md | 17 - .../modules/interchain-queries/explanation.md | 96 +++++ .../modules/interchain-queries/how-to.md | 193 ++++++++++ .../modules/interchain-queries/known-bugs.md | 5 + .../modules/interchain-queries/messages.md | 196 ---------- .../modules/interchain-queries/overview.md | 166 +------- .../modules/interchain-queries/state.md | 7 - sidebars.js | 8 +- 11 files changed, 804 insertions(+), 620 deletions(-) create mode 100644 docs/neutron/modules/interchain-queries/TODO.md create mode 100644 docs/neutron/modules/interchain-queries/api.md delete mode 100644 docs/neutron/modules/interchain-queries/client.md delete mode 100644 docs/neutron/modules/interchain-queries/events.md create mode 100644 docs/neutron/modules/interchain-queries/explanation.md create mode 100644 docs/neutron/modules/interchain-queries/how-to.md create mode 100644 docs/neutron/modules/interchain-queries/known-bugs.md delete mode 100644 docs/neutron/modules/interchain-queries/messages.md delete mode 100644 docs/neutron/modules/interchain-queries/state.md diff --git a/docs/neutron/modules/interchain-queries/TODO.md b/docs/neutron/modules/interchain-queries/TODO.md new file mode 100644 index 000000000..4213a5af8 --- /dev/null +++ b/docs/neutron/modules/interchain-queries/TODO.md @@ -0,0 +1,137 @@ +# TODO + +## Explanation: How Interchain Query results are removed? + +- KV query results are removed immediately +- TX query results are removed in EndBlock in an amount based on the module's `tx_query_removal_limit` value + +## Explanation: Configuring your own remote chain RPC node for TX ICQ usage + +If running your own RPC node for the target chain, make sure to [configure](https://docs.cometbft.com/v0.38/core/configuration) it's `indexer` parameter the way it is sufficient for the transactions filter you define for your queries. + +... add something else probably + +## Explanation: What are sudo calls? + +## Explanation: Limited gas for sudo calls + +- reasoning +- what is the value and how to get the current value +- guidelines how to write sudo handlers (preserve sudo data, then process it in another outer call) + +## Explanation: How to find the right IBC connection ID for an Interchain Query? + +- explain clients and connections +- add links to IBC docs +- ICQs depend on IBC clients in terms of data authenticity and the client should be trustworthy (i.e. owned by the protocol) + +## Explanation: Guidelines on transactions_filter definition + +Since events themselves are not part of the consensus and are not included in the transaction result, it's necessary to +[implement additional checks](https://github.com/neutron-org/neutron-sdk/blob/c197ceacc1c23d2f1283be91f8f90c2be1328db0/contracts/neutron_interchain_queries/src/contract.rs#L197) +in your `SudoTXQueryResult` handler to check that result transactions satisfies your transactions filter. For instance, you can check that messages in the transactions have proper types, payload, etc. +If your contract does not have such checks, malicious relayer can send a fully valid Tendermint transaction which does not satisfy your defined transactions filter, and your business-logic can be broken. + +> NOTE: when registering a TX-query, you write the transaction filters as filters for transaction events. When you check the submitted transaction in your contracts, though, you can only check the information that is stored on-chain (i.e., message fields for messages in a transaction). To put it another way, the set of values that you can use to filter transactions is the intersection of the values that are added to transaction events (used by the ICQ relayer to perform the search) and the values included directly to sdk.Msgs (can be used by your code to check whether the submitted transaction matches your query). + +You can see more info, examples and recommendations about proper transactions result handling [here](https://github.com/neutron-org/neutron-sdk/blob/v0.5.0/contracts/neutron_interchain_txs/src/contract.rs#L439). + + +```json +[{"field": "{eventType}.{attributeKey}", "val": "{attributeValue}", "op": "gte"}, ...] +``` + +Maximum allowed amount of filters is 32. Supplying more filters than allowed will return an error. + +Supported operators: +* `eq` +* `lt` +* `gt` +* `lte` +* `gte` + +The ICQ relayer can easily parse this format and compose it into usual [Tendermint syntax](https://docs.tendermint.com/v0.33/app-dev/indexing-transactions.html#querying-transactions) for searching transactions. + +Suppose you want to search for transactions that meet specific conditions on a remote chain. You can build a query using various filters to narrow down the search. + +##### Finding Transfer Transactions with a Specific Amount + +```json +[{"field": "transfer.amount", "op": "eq", "val": 1000}] +``` + +This filter searches for all transfer transactions with an exact amount of 1000. The ICQ relayer converts it into the Tendermint search string: + +``` +"transfer.amount" = 1000 +``` + +##### Searching for Transactions within a Range of Dates + +```json +[{"field": "timestamp", "op": "gte", "val": "2023-01-01T00:00:00Z"}, {"field": "timestamp", "op": "lt", "val": "2023-02-01T00:00:00Z"}] +``` + +This filter queries for all transactions that were processed between January 1, 2023, and February 1, 2023. The corresponding Tendermint search string would be: + +``` +"timestamp" >= "2023-01-01T00:00:00Z" AND "timestamp" < "2023-02-01T00:00:00Z" +``` + +##### Combining Multiple Conditions + +```json +[{"field": "message.module", "op": "eq", "val": "bank"}, {"field": "transfer.sender", "op": "eq", "val": "neutron1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrstdxvff"}, {"field": "transfer.amount", "op": "gt", "val": 500}] +``` + +This example searches for bank transfer transactions sent by a specific address (`neutron1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrstdxvff`) and with an amount greater than 500. The search string would be: + +``` +"message.module" = "bank" AND "transfer.sender" = "neutron1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrstdxvff" AND "transfer.amount" > 500 +``` + +##### Effects of Filters + +The filters in the `transactions_filter` field allow for refined and targeted querying of transactions. Some effects of applying these filters are: + +- **Increased Efficiency**: By narrowing down the search criteria, the query can return results more quickly, reducing the computational resources required. +- **Improved Relevance**: Filters ensure that only transactions that meet specific criteria are returned, making the results more relevant to the user's needs. +- **Flexibility**: Users can combine different operators and fields to create complex queries that match their exact requirements. +- **Error Handling**: Providing incorrect or conflicting filters might result in an error, so the filter structure must be carefully constructed to avoid issues. + +By understanding the usage of the `transactions_filter` field, developers and users can leverage the power of targeted querying to interact with remote chains in a more effective and efficient manner. + +##### Having Fewer or More Filters + +###### Fewer Filters +**Pros:** +- **Broader Results**: Using fewer filters will generally lead to a larger result set, capturing more transactions that meet broad criteria. +- **Faster Execution**: With less complexity, the query may execute more quickly, as there are fewer conditions to evaluate. + +**Cons:** +- **Less Precision**: Fewer filters may lead to less relevant results if the query is too broad. + +###### More Filters +**Pros:** +- **More Specific Results**: More filters allow for more targeted and precise queries, narrowing down the result set to only the most relevant transactions. +- **Enhanced Control**: More filters offer greater control over the query, enabling more complex and nuanced searches. + +**Cons:** +- **Slower Execution**: More complex queries with multiple filters may take longer to execute, as each additional condition adds to the computational load. +- **Potential Overfitting**: Too many filters may lead to an overly narrow search, missing relevant transactions or even resulting in no results at all if the filters are too restrictive. + +##### Good Practices + +1. **Start with Core Criteria**: Identify the essential criteria for your query and start with those filters. It helps to focus on what you really need from the results. +2. **Incrementally Refine**: If needed, add additional filters incrementally to refine the results, testing at each stage to ensure relevance. +3. **Avoid Redundancy**: Ensure that each filter adds value to the query and that there are no redundant or conflicting filters. +4. **Test Performance**: Consider testing the query with different numbers of filters to gauge performance and result relevance, especially if using many filters. +5. **Use the Maximum Limit Wisely**: Note that the maximum allowed amount of 32 filters is a technical constraint. + +##### How Many Filters Do You Need? + +The optimal number of filters depends on the specific use case and the balance between precision and performance. Generally, it's best to use the minimum number of filters that provide the necessary specificity for your query. Using too few may yield irrelevant results, while using too many may overly narrow the search or impact performance. + +##### Conclusion + +The number of filters in a query is a vital consideration, influencing both the relevance of the results and the performance of the query. Striking the right balance requires a thoughtful approach, considering the specific needs of the query, and adhering to good practices for constructing and refining filters. diff --git a/docs/neutron/modules/interchain-queries/api.md b/docs/neutron/modules/interchain-queries/api.md new file mode 100644 index 000000000..91fd70946 --- /dev/null +++ b/docs/neutron/modules/interchain-queries/api.md @@ -0,0 +1,361 @@ +# API + +This page contains the interchainqueries module's interface description: the endpoints the module exposes and the sudo messages the module issues. Each endpoint is explained in a dedicated section with links to request and response models, and an example of interaction with the module via the endpoint. The links to the request and response models also provide more information about request parameters and response values. + +Please be aware that the examples do not necessarily reflect the current state on the chain; they are listed here only to visualize the request formation and response payload in a user-friendly way. + +**Endpoints** + +This section lists piblic RPC API of the interchainqueries module. + +Queries: +- [Params](#params); +- [RegisteredQueries](#registeredqueries); +- [RegisteredQuery](#registeredquery); +- [QueryResult](#queryresult); +- [LastRemoteHeight](#lastremoteheight). + +Messages: +- [RegisterInterchainQuery](#registerinterchainquery); +- [SubmitQueryResult](#submitqueryresult); +- [RemoveInterchainQuery](#removeinterchainquery); +- [UpdateInterchainQuery](#updateinterchainquery); +- [UpdateParams](#updateparams). + +**Sudo** + +This section lists sudo messages issued by the interchainqueries module to smart contracts owning Interchain Queries. + +- [MessageTxQueryResult](#messagetxqueryresult) +- [MessageKvQueryResult](#messagekvqueryresult) + +## Queries + +### Params + +Queries the current parameters of the module. + +- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryParamsRequest) +- [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryParamsResponse) + +
+ Example + +```sh +curl -X 'GET' \ + 'https://rest-lb.neutron.org/neutron/interchainqueries/params' \ + -H 'accept: application/json' + ``` + +```json +{ + "params": { + "query_submit_timeout": "1036800", + "query_deposit": [ + { + "denom": "untrn", + "amount": "1000000" + } + ], + "tx_query_removal_limit": "10000" + } +} +``` +
+ +### RegisteredQueries + +Queries all the registered Interchain Queries in the module with filtration by owner and/or connection ID. + +- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryRegisteredQueriesRequest) +- [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryRegisteredQueriesResponse) + +
+ Example + +```sh +curl -X 'GET' \ + 'https://rest-lb-pion.ntrn.tech/neutron/interchainqueries/registered_queries?owners=neutron1zf2tdlq9pn8jq680rlsgwtsgljt54ctu0ulj8cm4s6r93mdmjuwqpurmf4&owners=neutron1sj5zhzmejs5q4t54zfgpkua6z0w0m87tz0sdzzqv8j0f5nwsv4fqmerty7' \ + -H 'accept: application/json' +``` + +```json +{ + "registered_queries": [ + { + "id": "30", + "owner": "neutron1sj5zhzmejs5q4t54zfgpkua6z0w0m87tz0sdzzqv8j0f5nwsv4fqmerty7", + "query_type": "tx", + "keys": [], + "transactions_filter": "[{\"field\":\"transfer.recipient\",\"op\":\"Eq\",\"value\":\"cosmos1mclft0hv4f385j2t4luwfz4gthn264alvufx7fjvkwd99qhl4e9sf4g87w\"},{\"field\":\"tx.height\",\"op\":\"Gte\",\"value\":2644737}]", + "connection_id": "connection-8", + "update_period": "6", + "last_submitted_result_local_height": "0", + "last_submitted_result_remote_height": null, + "deposit": [ + { + "denom": "untrn", + "amount": "1000000" + } + ], + "submit_timeout": "1036800", + "registered_at_height": "2644737" + }, + { + "id": "62", + "owner": "neutron1zf2tdlq9pn8jq680rlsgwtsgljt54ctu0ulj8cm4s6r93mdmjuwqpurmf4", + "query_type": "kv", + "keys": [ + { + "path": "bank", + "key": "AhRF6XHZfYzFmJGcX7lKP98y5ZeMgnVubHM=" + } + ], + "transactions_filter": "", + "connection_id": "connection-130", + "update_period": "30", + "last_submitted_result_local_height": "8544484", + "last_submitted_result_remote_height": { + "revision_number": "1", + "revision_height": "3036139" + }, + "deposit": [ + { + "denom": "untrn", + "amount": "1000000" + } + ], + "submit_timeout": "1036800", + "registered_at_height": "8542104" + } + ], + "pagination": { + "next_key": null, + "total": "2" + } +} +``` +
+ +**Might be interesting:** +- [Why is the Proof field nullified in QueryResult RPC response?](/neutron/modules/interchain-queries/explanation#why-is-the-proof-field-nullified-in-queryresult-rpc-response) +- [Why doesn't interchainqueries module store TX-typed query results?](/neutron/modules/interchain-queries/explanation#why-doesnt-interchainqueries-module-store-tx-typed-query-results) + +### RegisteredQuery + +Queries a registered Interchain Query by ID. + +- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryRegisteredQueryRequest) +- [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryRegisteredQueryResponse) + +
+ Example + +```sh +curl -X 'GET' \ + 'https://rest-lb-pion.ntrn.tech/neutron/interchainqueries/registered_query?query_id=62' \ + -H 'accept: application/json' + ``` + +```json +{ + "registered_query": { + "id": "62", + "owner": "neutron1zf2tdlq9pn8jq680rlsgwtsgljt54ctu0ulj8cm4s6r93mdmjuwqpurmf4", + "query_type": "kv", + "keys": [ + { + "path": "bank", + "key": "AhRF6XHZfYzFmJGcX7lKP98y5ZeMgnVubHM=" + } + ], + "transactions_filter": "", + "connection_id": "connection-130", + "update_period": "30", + "last_submitted_result_local_height": "8544484", + "last_submitted_result_remote_height": { + "revision_number": "1", + "revision_height": "3036139" + }, + "deposit": [ + { + "denom": "untrn", + "amount": "1000000" + } + ], + "submit_timeout": "1036800", + "registered_at_height": "8542104" + } +} +``` +
+ +**Might be interesting:** +- [Why is the Proof field nullified in QueryResult RPC response?](/neutron/modules/interchain-queries/explanation#why-is-the-proof-field-nullified-in-queryresult-rpc-response) +- [Why doesn't interchainqueries module store TX-typed query results?](/neutron/modules/interchain-queries/explanation#why-doesnt-interchainqueries-module-store-tx-typed-query-results) + +### QueryResult + +Queries the last successfully submitted result of an Interchain Query. + +- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryQueryResultRequest) +- [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryQueryResultResponse) + +
+ Example + +```sh +curl -X 'GET' \ + 'https://rest-lb-pion.ntrn.tech/neutron/interchainqueries/query_result?query_id=62' \ + -H 'accept: application/json' + ``` + +```json +{ + "result": { + "kv_results": [ + { + "storage_prefix": "bank", + "key": "AhRF6XHZfYzFmJGcX7lKP98y5ZeMgnVubHM=", + "value": "CgR1bmxzEgczOTk3NDkx", + "Proof": null + } + ], + "block": null, + "height": "3036139", + "revision": "1", + "allow_kv_callbacks": false + } +} +``` +
+ +**Might be interesting:** +- [Why is the Proof field nullified in QueryResult RPC response?](/neutron/modules/interchain-queries/explanation#why-is-the-proof-field-nullified-in-queryresult-rpc-response) +- [Why doesn't interchainqueries module store TX-typed query results?](/neutron/modules/interchain-queries/explanation#why-doesnt-interchainqueries-module-store-tx-typed-query-results) + +### LastRemoteHeight + +Queries the last height of a remote chain known to the IBC client behind a given connection ID. + +- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryLastRemoteHeightRequest) +- [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryLastRemoteHeightResponse) + +
+ Example + +```sh +curl -X 'GET' \ + 'https://rest-lb-pion.ntrn.tech/neutron/interchainqueries/remote_height?connection_id=connection-92' \ + -H 'accept: application/json' + ``` + +```json +{ + "height": "5788175" +} +``` +
+ +## Messages + +### RegisterInterchainQuery + +Registers a new Interchain Query in the interchainqueries module. This message is supposed to be issues only by a smart contract. The caller contract is charged a query registration deposit automatically in the amount defined as the module's query deposit parameter. The deposit is paid back on the query removal. Make sure to have enough assets on the contract's account at the time of the message execution. + +Returns an ID assigned to the registered query. Handle this message response via a reply handler in order to make use of the ID. + +- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgRegisterInterchainQueryRequest) +- [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgRegisterInterchainQueryResponse) + +Events emission on success: +- `type=neutron`, attributes: + - `module=interchainqueries`; + - `action=query_updated`; + - other attributes with query parameters: `query_id`, `connection_id`, `owner`, `type`, `tx_filter`, `kv_key`. + +**Might be interesting:** +- [How to register an Interchain Query using neutron-sdk](/neutron/modules/interchain-queries/how-to#how-to-register-an-interchain-query-using-neutron-sdk) +- [How to register a KV-typed Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-kv-typed-interchain-query-with-custom-keys) +- [How to register a TX-typed Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-tx-typed-interchain-query-with-custom-keys) +- [Why is there a query creation deposit?](/neutron/modules/interchain-queries/how-to#why-is-there-a-query-creation-deposit) +- [Impossibility to retrieve and prove KV data with nil values](/neutron/modules/interchain-queries/known-bugs#impossibility-to-retrieve-and-prove-kv-data-with-nil-values) + +### SubmitQueryResult + +Submits a result of an Interchain Query execution to the chain. This message handling may include passing of the result to the query's owner smart contract for processing which might be a pretty gas-consumable operation. + +- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgSubmitQueryResultRequest) +- [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgSubmitQueryResultResponse) + +**Might be interesting:** +- [What happens if a sudo callback to a smart contract owning an Interchain Query fails?](/neutron/modules/interchain-queries/explanation#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails) +- [Impossibility to retrieve and prove KV data with nil values](/neutron/modules/interchain-queries/known-bugs#impossibility-to-retrieve-and-prove-kv-data-with-nil-values) + +### RemoveInterchainQuery + +Removes a given Interchain Query and its results from the module. Can be removed only by the owner of the query during the query's submit timeout, and by anyone after the query has been timed out. The query deposit is returned to the caller on a success call. + +- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgRemoveInterchainQueryRequest) +- [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgRemoveInterchainQueryResponse) + +Events emission on success: +- `type=neutron`, attributes: + - `module=interchainqueries`; + - `action=query_removed`; + - other attributes with query parameters: `query_id`, `connection_id`, `owner`, `type`, `tx_filter`, `kv_key`. + +**Might be interesting:** +- [What are the rules for creation deposit refund?](/neutron/modules/interchain-queries/explanation#what-are-the-rules-for-creation-deposit-refund) + +### UpdateInterchainQuery + +Updates parameters of a registered Interchain Query. Only callable by the owner of the query. + +- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgUpdateInterchainQueryRequest) +- [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgUpdateInterchainQueryResponse) + +Events emission on success: +- `type=neutron`, attributes: + - `module=interchainqueries`; + - `action=query_updated`; + - other attributes with query parameters: `query_id`, `connection_id`, `owner`, `type`, `tx_filter`, `kv_key`. + +### UpdateParams + +Updates params of the interchainqueries module. Only callable by the module's authority. + +- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgUpdateParamsRequest) +- [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgUpdateParamsResponse) + +## Sudo + +### MessageTxQueryResult + +MessageTxQueryResult is the model of the sudo message sent to a smart contract on a TX-typed Interchain Query result submission. The owner of a TX-typed Interchain Query must define a `sudo` entry_point for handling `tx_query_result` messages and place the needed logic there. The `tx_query_result` handler is treated by the interchainqueries module as a callback that is called each time a TX-typed query result is submitted. + +- [Message model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/contractmanager/types#MessageTxQueryResult) +- [Message model in neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/sudo/msg/enum.SudoMsg.html#variant.TxQueryResult) + +Events emission on failure: +- `type=sudo`, attributes: + - attributes with the failure parameters: `_contract_address`, `failure_id`, `error`. + +**Might be interesting:** +- [What happens if a sudo callback to a smart contract owning an Interchain Query fails?](/neutron/modules/interchain-queries/explanation#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails) + +### MessageKvQueryResult + +MessageKVQueryResult is the model of the sudo message sent to a smart contract on a KV-typed Interchain Query result submission. If the owner of a KV-typed Interchain Query wants to handle the query updates, it must define a `sudo` entry_point for handling `kv_query_result` messages and place the needed logic there. The `kv_query_result` handler is treated by the interchainqueries module as a callback that is called each time a KV-typed query result is submitted. + +Note that there is no query result sent, only the query ID. In order to access the actual result, use the Query/QueryResult RPC of the interchainqueries module. + +- [Message model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/contractmanager/types#MessageKVQueryResult) +- [Message model in neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/sudo/msg/enum.SudoMsg.html#variant.KVQueryResult) + +Events emission on failure: +- `type=sudo`, attributes: + - attributes with the failure parameters: `_contract_address`, `failure_id`, `error`. + +**Might be interesting:** +- [What happens if a sudo callback to a smart contract owning an Interchain Query fails?](/neutron/modules/interchain-queries/explanation#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails) diff --git a/docs/neutron/modules/interchain-queries/client.md b/docs/neutron/modules/interchain-queries/client.md deleted file mode 100644 index 25c43e3c7..000000000 --- a/docs/neutron/modules/interchain-queries/client.md +++ /dev/null @@ -1,238 +0,0 @@ -# Client - -## Transactions - -### submit-query-result - -Submits query result: -```shell -neutrond tx interchainqueries submit-query-result [query-id] [result-file] -``` - -
- Example - Register an interchain query to get delegations of delegator on remote chain: - -```shell -neutrond tx interchainqueries submit-query-result result.json --from demowallet1 --gas 10000000 --gas-adjustment 1.4 --gas-prices 0.5stake --broadcast-mode block --chain-id test-1 -``` - -Example content of `result.json` file: -```json -{ - "kv_results": [ - { - "storage_prefix": "staking", - "key": "MRQE7KnWf7BcUyQTX/rb+q7XJL590xQE7KnWf7BcUyQTX/rb+q7XJL590w==", - "value": "Ci5uZXV0cm9uMXFuazJuNG5sa3B3OXhmcW50bGFkaDc0dzZ1anR1bHduNmR3cTh6EjVuZXV0cm9udmFsb3BlcjFxbmsybjRubGtwdzl4ZnFudGxhZGg3NHc2dWp0dWx3bnFzaGVweBocNzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMA==", - "Proof": { - "ops": [ - { - "type": "ics23:iavl", - "key": "MRQE7KnWf7BcUyQTX/rb+q7XJL590xQE7KnWf7BcUyQTX/rb+q7XJL590w==", - "data": "CvwDCisxFATsqdZ/sFxTJBNf+tv6rtckvn3TFATsqdZ/sFxTJBNf+tv6rtckvn3TEoUBCi5uZXV0cm9uMXFuazJuNG5sa3B3OXhmcW50bGFkaDc0dzZ1anR1bHduNmR3cTh6EjVuZXV0cm9udmFsb3BlcjFxbmsybjRubGtwdzl4ZnFudGxhZGg3NHc2dWp0dWx3bnFzaGVweBocNzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMBoLCAEYASABKgMAAgIiKQgBEiUCBAQg/XaR47+Bw1YRGxSWwyiaAq5OSBQJIJ1qSFWbOe/5msIgIisIARIEBAgYIBohIK8BCwRz+Fod0SUgzLUhUK6VU2mEVhOqM53DZgtpytmXIikIARIlBhAcIEDf0aJaZU9bWVCd7T6zPbZoDp9Z+5w4qnurGAYVS85jICIrCAESBAgYJCAaISDJJKeGrIRSJj3EYotsdiXp6QNsqlzjMJuy4aELAnFvYiIrCAESBAo4SiAaISDcflhqTQQJl5EG2W37BWlPexWgUWXE0agE9ir+M5zA6SIsCAESBQxkjgEgGiEg4dZUUhewJTuJ2dNjKe7cJCKzJANcYVTprAPKkjQOtQciLQgBEgYOpgGaASAaISBRJQpR01RPTxIakznqcierctkEkx3Sp51sbw4+cAXnIQ==" - }, - { - "type": "ics23:simple", - "key": "c3Rha2luZw==", - "data": "Cq8BCgdzdGFraW5nEiAX2lqGKZJW473ICfGb3Wa2lotPFt1cTLN+R9aZJjs2xBoJCAEYASABKgEAIicIARIBARogOqsHULjzmZkig3Kxczq2JoCMuiq6iXWpKHea7ZB9gWAiJwgBEgEBGiBp76tKiIQVkrMiaBxiQMYu0e/01Saw7T/PjyEPDPlQbiIlCAESIQEmmrFm4aKKJReopSqK+rTjZSDTKuV0duBPSipjJxPzaA==" - } - ] - } - }, - { - "storage_prefix": "staking", - "key": "IRQE7KnWf7BcUyQTX/rb+q7XJL590w==", - "value": "CjVuZXV0cm9udmFsb3BlcjFxbmsybjRubGtwdzl4ZnFudGxhZGg3NHc2dWp0dWx3bnFzaGVweBJDCh0vY29zbW9zLmNyeXB0by5lZDI1NTE5LlB1YktleRIiCiA/t9hdbTKV91SkxZmBgg39qOod/0vO76wK5QW4V6ZyiyADKgo3MDAwMDAwMDAwMhw3MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwOgYKBHRlc3RKAFJLCjsKEjEwMDAwMDAwMDAwMDAwMDAwMBISMjAwMDAwMDAwMDAwMDAwMDAwGhExMDAwMDAwMDAwMDAwMDAwMBIMCIvg1pYGEMCl3pgBWgEx", - "Proof": { - "ops": [ - { - "type": "ics23:iavl", - "key": "IRQE7KnWf7BcUyQTX/rb+q7XJL590w==", - "data": "CuYEChYhFATsqdZ/sFxTJBNf+tv6rtckvn3TEoICCjVuZXV0cm9udmFsb3BlcjFxbmsybjRubGtwdzl4ZnFudGxhZGg3NHc2dWp0dWx3bnFzaGVweBJDCh0vY29zbW9zLmNyeXB0by5lZDI1NTE5LlB1YktleRIiCiA/t9hdbTKV91SkxZmBgg39qOod/0vO76wK5QW4V6ZyiyADKgo3MDAwMDAwMDAwMhw3MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwOgYKBHRlc3RKAFJLCjsKEjEwMDAwMDAwMDAwMDAwMDAwMBISMjAwMDAwMDAwMDAwMDAwMDAwGhExMDAwMDAwMDAwMDAwMDAwMBIMCIvg1pYGEMCl3pgBWgExGgsIARgBIAEqAwACAiIrCAESBAIEAiAaISAUEQIV7Mowp74roi0TppU27U2MG6vmxyfOJv0qCgfKqyIpCAESJQQIAiCCcJylC1/v/+M5ac1A5fvMcAA+5C+mG74CeoXjOScF1SAiKwgBEgQGEBwgGiEgD6ziA96HscsB249ulbBxQa4rSR8BzLzeJNkXjOakvjoiKwgBEgQIGCQgGiEgySSnhqyEUiY9xGKLbHYl6ekDbKpc4zCbsuGhCwJxb2IiKwgBEgQKOEogGiEg3H5Yak0ECZeRBtlt+wVpT3sVoFFlxNGoBPYq/jOcwOkiLAgBEgUMZI4BIBohIOHWVFIXsCU7idnTYynu3CQisyQDXGFU6awDypI0DrUHIi0IARIGDqYBmgEgGiEgUSUKUdNUT08SGpM56nInq3LZBJMd0qedbG8OPnAF5yE=" - }, - { - "type": "ics23:simple", - "key": "c3Rha2luZw==", - "data": "Cq8BCgdzdGFraW5nEiAX2lqGKZJW473ICfGb3Wa2lotPFt1cTLN+R9aZJjs2xBoJCAEYASABKgEAIicIARIBARogOqsHULjzmZkig3Kxczq2JoCMuiq6iXWpKHea7ZB9gWAiJwgBEgEBGiBp76tKiIQVkrMiaBxiQMYu0e/01Saw7T/PjyEPDPlQbiIlCAESIQEmmrFm4aKKJReopSqK+rTjZSDTKuV0duBPSipjJxPzaA==" - } - ] - } - } - ], - "height": 77, - "revision": 2 -} -``` -
- -## Queries - -In this section we describe the queries required on grpc server. - -```protobuf -// Query defines the gRPC querier service. -service Query { - // returns all the registered queries in the module with filtration by owner and/or connection id - rpc RegisteredQueries(QueryRegisteredQueriesRequest) - returns (QueryRegisteredQueriesResponse) { - option (google.api.http).get = - "/neutron/interchainqueries/interchainqueries/registered_queries"; - } - - // returns registered query by id - rpc RegisteredQuery(QueryRegisteredQueryRequest) - returns (QueryRegisteredQueryResponse) { - option (google.api.http).get = - "/neutron/interchainqueries/interchainqueries/registered_query"; - } - - // returns query result for a particular registered interchain query by id - rpc QueryResult(QueryRegisteredQueryResultRequest) returns (QueryRegisteredQueryResultResponse) { - option (google.api.http).get = "/neutron/interchainqueries/interchainqueries/query_result"; - } - - // returns last height about which Neutron knows for the particular remote chain - rpc LastRemoteHeight(QueryLastRemoteHeight) returns (QueryLastRemoteHeightResponse) { - option (google.api.http).get = "/neutron/interchainqueries/interchainqueries/remote_height"; - } -} -``` - -### registered-query - -Returns registered query by id. - -```bash -neutrond query interchainqueries registered-query [id] -``` - -
- Example - Returns info about registered query with id 1: - - ```shell - neutrond query interchainqueries registered-query 1 - ``` - -Output: - - ```shell - registered_query: - connection_id: connection-0 - id: "1" - owner: "neutron14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s5c2epq" - last_submitted_result_local_height: "0" - last_submitted_result_remote_height: "0" - transactions_filter: "{}" - keys: - - path: "staking" - key: "MRQE7KnWf7BcUyQTX/rb+q7XJL590xQE7KnWf7BcUyQTX/rb+q7XJL590w==" - query_type: kv - update_period: "1" - ``` - -
- -### registered-queries - -Returns all the registered queries in the module with filtration by owner and/or connection id. - -```bash -neutrond query interchainqueries registered-queries -``` - -
- Example - Returns all registered interchain queries in the module with connection id `connection-0` and owner `neutron14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s5c2epq`: - - ```shell - neutrond query interchainqueries registered-queries --connection-id connection-0 --owners neutron14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s5c2epq - ``` - -Output: - - ```shell - registered_queries: - - connection_id: connection-0 - id: "1" - owner: "neutron14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s5c2epq" - last_submitted_result_local_height: "206" - last_submitted_result_remote_height: "203" - transactions_filter: "{}" - keys: - - path: "staking" - key: "MRQE7KnWf7BcUyQTX/rb+q7XJL590xQE7KnWf7BcUyQTX/rb+q7XJL590w==" - query_type: kv - update_period: "1" - - connection_id: connection-0 - id: "2" - owner: "neutron14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s5c2epq" - last_submitted_result_local_height: "199" - last_submitted_result_remote_height: "188" - transactions_filter: '{"message.module": "bank"}' - query_type: tx - update_period: "5" - ``` - -
- -### query-result - -Returns KV-storage result for particular registered interchain query by id. - -```bash -neutrond query interchainqueries query-result [query-id] -``` - -
- Example - Returns KV-storage result for registered interchain query with id 1: - - ```shell - neutrond query interchainqueries query-result 1 - ``` - -Output: - - ```shell - result: - blocks: [] - height: "203" - kv_results: - - Proof: null - key: MRQE7KnWf7BcUyQTX/rb+q7XJL590xQE7KnWf7BcUyQTX/rb+q7XJL590w== - storage_prefix: staking - value: Ci5uZXV0cm9uMXFuazJuNG5sa3B3OXhmcW50bGFkaDc0dzZ1anR1bHduNmR3cTh6EjVuZXV0cm9udmFsb3BlcjFxbmsybjRubGtwdzl4ZnFudGxhZGg3NHc2dWp0dWx3bnFzaGVweBocNzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMA== - - Proof: null - key: IRQE7KnWf7BcUyQTX/rb+q7XJL590w== - storage_prefix: staking - value: CjVuZXV0cm9udmFsb3BlcjFxbmsybjRubGtwdzl4ZnFudGxhZGg3NHc2dWp0dWx3bnFzaGVweBJDCh0vY29zbW9zLmNyeXB0by5lZDI1NTE5LlB1YktleRIiCiCGVtQII4Ok0ieJqHiQcBkW42FKCSKPv+3poD5Me4zh1SADKgo3MDAwMDAwMDAwMhw3MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwOgYKBHRlc3RKAFJKCjsKEjEwMDAwMDAwMDAwMDAwMDAwMBISMjAwMDAwMDAwMDAwMDAwMDAwGhExMDAwMDAwMDAwMDAwMDAwMBILCKLo1pYGEKjc/G1aATE= - revision: "0" - ``` - -
- -### query-last-remote-height - -Returns last height about which Neutron knows for the particular remote chain by connection id. - -```bash -neutrond query interchainqueries query-last-remote-height [connection-id] -``` - -
- Example - Returns last height remote chain by connection id `connection-0`: - - ```shell - neutrond query interchainqueries query-last-remote-height connection-0 - ``` - -Output: - - ```shell - height: "29" - ``` - -
\ No newline at end of file diff --git a/docs/neutron/modules/interchain-queries/events.md b/docs/neutron/modules/interchain-queries/events.md deleted file mode 100644 index 5d0e580e6..000000000 --- a/docs/neutron/modules/interchain-queries/events.md +++ /dev/null @@ -1,17 +0,0 @@ -# Events - -There is one important event that exists in the ICQ module, which is emitted after any action that happened to a registered Interchain Query: -* `EventTypeNeutronMessage` - "neutron" - -### `EventTypeNeutronMessage` - -| Attribute Key | Attribute Value | -|---------------|-------------------------------------------------------------------------------| -| module | `interchainqueries` | -| action | action identifier: `query_updated` or `query_removed` | -| query_id | `{identifier_of_registered_query}` | -| connection_id | `{connection_id_for_query}` | -| owner | `{query_owner}` Note: is only presented in `query_updated` action | -| type | `{query_type}` Note: only presented in `query_updated` action | -| tx_filter | `{transactions_search_filter}` Note: only presented in `query_updated` action | -| kv_key | `{kv_keys}` Note: only presented in `query_updated` action | \ No newline at end of file diff --git a/docs/neutron/modules/interchain-queries/explanation.md b/docs/neutron/modules/interchain-queries/explanation.md new file mode 100644 index 000000000..456b803b6 --- /dev/null +++ b/docs/neutron/modules/interchain-queries/explanation.md @@ -0,0 +1,96 @@ +# Explanation + +## How do KV-typed Interchain Queries work? + +The meaning of a KV Interchain Query is to get a secured access to a remote chain's storage from a smart contract. Such a secured access is based on: +- [IAVL tree](https://github.com/cosmos/iavl) which is used as data storage in Cosmos-SDK based blockchains. Each piece of data (value) is a leaf node in the tree having its unique data path (key); +- [abci_query](https://docs.cometbft.com/v0.38/spec/rpc/#abciquery) RPC that exposes the storage (`IAVL tree`) read operations by a given path. + +A typical flow of KV-typed Interchain Queries usage is as follows: +1. A smart contract developer realises that their interchain protocol depends on state of a remote chain, and figures out what info exactly they need to read from the chain; +2. Given the required data set, the developer composes a list of paths in the storage that contain the required data; +3. The developer writes and deploys a smart contract that contains Interchain Query registration logic and a callback for handling the query results; +4. The smart contract registers a KV-typed Interchain Query with the set of keys to read. The registered Interchain Query is stored in the `interchainqueries` module's state; +5. An Interchain Query relayer reads the `interchainqueries` module's state, finds the registered query and its parameters, and does the `abci_query` RPC. The result of the call is a set of key-value pairs with proofs coming from the `IAVL tree`; +6. The Interchain Query relayer provides the key-value pairs and proofs to the `interchainqueries` module. This is as KV Interchain Query result submission operation. The module does the result verification against the proofs and passes the result to the smart contract; +7. The smart contract does arbitrary handling of the result; +8. Steps 5-7 are repeated periodically until the query is removed. + +**Might be interesting:** +- [How to register an Interchain Query using neutron-sdk](/neutron/modules/interchain-queries/how-to#how-to-register-an-interchain-query-using-neutron-sdk) +- [How to register a KV-typed Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-kv-typed-interchain-query-with-custom-keys) +- [What is an Interchain Query relayer?](/neutron/modules/interchain-queries/explanation#what-is-an-interchain-query-relayer) + +## How do TX-typed Interchain Queries work? + +The meaning of a TX Interchain Query is to get a secured subscription on transactions happening on a remote chain from a smart contract. Such a secured access is based on: +- transaction execution [events](https://docs.cosmos.network/v0.50/learn/advanced/events) emission. In a word, events are structured logs of actions that take place within the blockchain; +- [tx_search](https://docs.cometbft.com/v0.38/app-dev/indexing-transactions#querying-transactions-events) RPC. This RPC allows to search for transactions based on events they emit. + +A typical flow of TX-typed Interchain Queries usage is as follows: +1. A smart contract developer realises that their interchain protocol depends on actions happening on a remote chain, and figures out what actions exactly they need to react on; +2. Given the requirements, the developer composes a list of filtering conditions that identify the needed transactions by the events they emit; +3. The developer writes and deploys a smart contract that contains Interchain Query registration logic and a callback for handling the query results; +4. The smart contract registers a TX-typed Interchain Query with the set of transaction filters to apply. The registered Interchain Query is stored in the `interchainqueries` module's state; +5. An Interchain Query relayer reads the `interchainqueries` module's state, finds the registered query and its parameters, and does the `tx_search` RPC. The result of the call is a list of transactions successfully processed on the remote chain; +6. The Interchain Query relayer provides the list of transactions a couple of headers for each transaction needed to verify the result to the `interchainqueries` module. This is a TX Interchain Query result submission operation. The module does the result verification against the headers and passes the result to the smart contract; +7. The smart contract does arbitrary handling of the result; +8. Steps 5-7 are repeated periodically until the query is removed. + +**Might be interesting:** +- [How to register an Interchain Query using neutron-sdk](/neutron/modules/interchain-queries/how-to#how-to-register-an-interchain-query-using-neutron-sdk) +- [How to register a TX-typed Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-tx-typed-interchain-query-with-custom-keys) +- [What is an Interchain Query relayer?](/neutron/modules/interchain-queries/explanation#what-is-an-interchain-query-relayer) + +## What is an Interchain Query relayer? + +An Interchain Query relayer is an off-chain application that serves the needs of `interchainqueries` module users. It is an intermediary between two chains, and in this regard it is similar to an IBC relayer. The responsibilities of an Interchain Query relayer are: +- Monitoring of the registered Interchain Queries: retrieval of Interchain Queries that are needed to be processed from the `interchainqueries` module's state; +- Interchain Queries execution: reading of remote chain's state based on the parameters defined in the Interchain Query being executed, fidning proofs for the read data; +- Query results submission: passing of the retrieved data and proofs to the `interchainqueries` module and, through that, to respective smart contracts. + +## Why is there a query creation deposit? + +In order to clean up ledger from not used, outdated queries, a special deposit mechanism is used. [RegisterInterchainQuery](/neutron/modules/interchain-queries/api#registerinterchainquery) message contains the `deposit` field which is used to collect escrow payment for query creation. In order to return escrow payment, a [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery) message should be issued. + +The required amount of coins to deposit is defined by the `query_deposit` [module parameter](/neutron/modules/interchain-queries/api#params). + +In other words, it is expected that the query owner will remove their queries when they are no longer needed. If a query hasn't been used for the `query_submit_timeout` period and the owner hasn't removed it, all network users are granted the opportunity to clean up the chain (to remove the unused query) and earn the deposited assets for doing so. + +**Might be interesting:** +- [What are the rules for creation deposit refund?](/neutron/modules/interchain-queries/explanation#what-are-the-rules-for-creation-deposit-refund) + +## What are the rules for creation deposit refund? + +The query creation deposit is paid when the Interchain Query is removed. It is done by issuing a [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery) message. The issuer may be either the query owner or anyone under specific circumstances. Briefly, if a query was registered recently or has been continuously updated (i.e. is within a so to say `query service period`), the query would seem to be valuable for its owner and only the owner can get rid of it and get the deposit back. If a query was registered a long time ago and hasn't been updated for a long time (i.e. is beyond the `query service period`), the query has most likely been forgotten, is not in use and therefore can be removed from the chain's state by anyone for a reward in the amount of the creation deposit. You can see a more detailed permission evaluation policy below. + +There are three arguments defining the removal permissions for an Interchain Query: +1. `query_submit_timeout` — a [registered query's property](/neutron/modules/interchain-queries/api#registeredquery) which defines the span in blocks of the query's renewable `query service period`. The period is granted when a query is registered and gets renewed each time a query is updated. A `query_submit_timeout` value is assigned to the query based on the [module's parameters](/neutron/modules/interchain-queries/api#params) at the time of query registration; +2. `last_submitted_result_local_height` — a [registered query's property](/neutron/modules/interchain-queries/api#registeredquery) representing the home chain's height the query was last time updated at; +3. `registered_at_height` — a [registered query's property](/neutron/modules/interchain-queries/api#registeredquery) representing the home chain's height the query was registered at. + +The permissions to execute [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery) are as follows: + +- Within the `query service period` only the query's owner is permissioned to remove it. A query is within the `query service period` if there **hasn't been** `params.query_submit_timeout` blocks yet since the query registration height **or** the last query update height: + + `within_service_period = current_height <= query.last_submitted_result_local_height + params.query_submit_timeout || current_height <= query.registered_at_height + params.query_submit_timeout` + +- Beyond the `query service period` anyone can remove the query and take the deposit as a reward for keeping the network tidy. A query is beyond the `query service period` if there **has been** `params.query_submit_timeout` blocks since the query registration height **and** the last query update height: + + `beyond_service_period = current_height > query.last_submitted_result_local_height + params.query_submit_timeout && current_height > query.registered_at_height + params.query_submit_timeout` + +## Why is the Proof field nullified in QueryResult RPC response? + +The `interchainqueries` module only needs KV proofs during the submission process to verify the values being submitted against the proofs. If save them afterwards, they'll just increase chain's space without any reasonable further usage. The KV results saved on chain can be trusted as cryptographically proved because they are verified at the very beginning — by the module at the submission step. + +The reason the `Proof` field is presented but empty is that the [QueryResult](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryResult) type is used for both query result submission and query result preservation in the module's storage. More designated types are likely to be introduced in the future to mitigate confusion around this. + +## Why doesn't interchainqueries module store TX-typed query results? + +If compare to the KV-typed Interchain Queries which have the last result stored on chain and available to be read, the TX-typed Interchain Queries are not about the last result, but about a possible list of results (transactions matched the filter). Storing the whole list of results may be cumbersome for the chain in terms of required space. So, instead of storing results on chain and requiring smart contracts to read them (as for KV queries), the `interchainqueries` module passes the whole tx results directly to smart contracts, ending the life of the results right after a successful [TxQueryResult](/neutron/modules/interchain-queries/api#messagetxqueryresult) sudo call. The only things that the module stores on chain regarding TX-typed Interchain Queries are: +- hashes of transactions that have been successfully processed by the owner smart contract to avoid multiple processing of the same transactions, and +- [failures appeared during sudo calls](#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails). + +## What happens if a sudo callback to a smart contract owning an Interchain Query fails? + +In this case, the `interchainqueries` module will store the failure in the [contractmanager](/neutron/modules/contract-manager/overview) module with all information about the query and a redacted (shortened to codespace and error code) error message. A full error message is emitted as an [event](https://docs.cosmos.network/v0.50/learn/advanced/events) on a failure (see the [message events emission](/neutron/modules/interchain-queries/api#sudo) for details). Note that the `out of gas` errors are stored as failures, too. Failed query result submissions can be read from the `contractmanager` module and resubmitted to the `interchainqueries` module. More info about the read and resubmit operations by the link to the [contractmanager](/neutron/modules/contract-manager/overview) module documentation. diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md new file mode 100644 index 000000000..3d7103bba --- /dev/null +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -0,0 +1,193 @@ +# How To + +## How to register an Interchain Query using neutron-sdk + +1. Find the register Interchain Query helper function that your needs require in the [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) repository. For this particular example, let's choose the [new_register_balances_query_msg](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/fn.new_register_balances_query_msg.html) function. + +2. From your contract, broadcast the message created by the helper function as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/): +```rust +use cosmwasm_std::{ + Binary, CosmosMsg, Response, SubMsg, ReplyOn, +}; +use neutron_sdk::{ + bindings::{ + msg::NeutronMsg, + }, + interchain_queries::v045::new_register_balances_query_msg, + NeutronResult, +} + +/// Reply ID used to tell this kind of reply call apart. +const REGISTER_BALANCES_ICQ_REPLY_ID: u64 = 1; + +/// Registers a balances ICQ for a given address. +pub fn register_balances_icq( + connection_id: String, + addr: String, + denoms: Vec, + update_period: u64, +) -> NeutronResult> { + ... + // Construct an ICQ registration message + let msg = + new_register_balances_query_msg(connection_id, addr, denoms, update_period)?; + + // Send the ICQ registration message as a submessage to receive a reply callback + Ok(Response::new().add_submessage(SubMsg { + id: REGISTER_BALANCES_ICQ_REPLY_ID, + payload: Binary::default(), + msg: CosmosMsg::Custom(msg), + gas_limit: None, + reply_on: ReplyOn::Success, + })) + ... +} +``` + +3. In the reply handler, decode the submessage result as a [MsgRegisterInterchainQueryResponse](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/bindings/msg/struct.MsgRegisterInterchainQueryResponse.html) to get access to the assigned Interchain Query ID. +```rust +use cosmwasm_std::{ + entry_point, DepsMut, Env, Reply, Response, StdError, +}; +use neutron_sdk::{ + bindings::msg::MsgRegisterInterchainQueryResponse, + NeutronResult, +}; + +/// Reply ID used to tell this kind of reply call apart. +const REGISTER_BALANCES_ICQ_REPLY_ID: u64 = 1; + +#[entry_point] +pub fn reply(_deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { + match msg.id { + REGISTER_BALANCES_ICQ_REPLY_ID => { + let resp: MsgRegisterInterchainQueryResponse = serde_json_wasm::from_slice( + &msg.result + .into_result() + .map_err(StdError::generic_err)? + .msg_responses[0] + .value + .to_vec(), + ) + .map_err(|e| StdError::generic_err(format!("failed to parse response: {:?}", e)))?; + + ... + } + + ... + } +} +``` + +## How to register a KV-typed Interchain Query with custom keys + +If your KV Interchain Query cannot be covered with the helpers from the [Interchain Queries related package](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) in the [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk), you will need to define the KVKeys for your query yourself and pass it to the [NeutronMsg::register_interchain_query](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/bindings/msg/enum.NeutronMsg.html#method.register_interchain_query) helper. For this particular example, let's register an [Account](https://github.com/cosmos/cosmos-sdk/blob/c29844f9e1ccc76ba68b8c0d931f3b0ad3885e13/proto/cosmos/auth/v1beta1/query.proto#L27-L31) Interchain Query to `cosmos-hub`. + +1. Figure out how the data path to the required data is constructed and what the data model is. This can be done by the module's code investigation. Start with finding the [respective auth module gRPC handler](https://github.com/cosmos/cosmos-sdk/blob/c29844f9e1ccc76ba68b8c0d931f3b0ad3885e13/x/auth/keeper/grpc_query.go#L69-L95) and then go deeper until you find what info exactly is written to the KVStore and at what path. + +For this example, the information we require from the module's code is: +- the store key for the module is [acc](https://github.com/cosmos/cosmos-sdk/blob/c29844f9e1ccc76ba68b8c0d931f3b0ad3885e13/x/auth/types/keys.go#L11-L12); +- the data path is constructed as [AddressStoreKeyPrefix](https://github.com/cosmos/cosmos-sdk/blob/c29844f9e1ccc76ba68b8c0d931f3b0ad3885e13/x/auth/types/keys.go#L22-L23) + [base64-encoded address](https://github.com/cosmos/cosmos-sdk/blob/c29844f9e1ccc76ba68b8c0d931f3b0ad3885e13/x/auth/types/keys.go#L34); +- the data model is [BaseAccount](https://github.com/cosmos/cosmos-sdk/blob/c29844f9e1ccc76ba68b8c0d931f3b0ad3885e13/x/auth/types/auth.pb.go#L29-L37). + +2. From your contract, broadcast the message created by the helper function as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/). Use the [decode_and_convert](https://docs.rs/neutron-sdk/0.8.0/neutron_sdk/interchain_queries/helpers/fn.decode_and_convert.html) helper function for bech32 address conversion. +```rust +use cosmwasm_std::{ + Binary, CosmosMsg, Response, SubMsg, ReplyOn, +}; +use neutron_sdk::{ + bindings::{ + msg::NeutronMsg, + types::KVKey, + }, + interchain_queries::helpers::decode_and_convert, + interchain_queries::types::QueryPayload, + NeutronResult, +} + +/// Name of the standard **auth** Cosmos-SDK module +const AUTH_STORE_KEY: &str = "acc"; +/// Storage prefix for account-by-address store +/// +const ADDRESS_STORE_PREFIX: u8 = 0x01; + +/// Reply ID used to tell this kind of reply call apart. +const REGISTER_ACCOUNT_ICQ_REPLY_ID: u64 = 1; + +/// Registers an account ICQ for a given address. +pub fn register_account_icq( + connection_id: String, + addr: String, + update_period: u64, +) -> NeutronResult> { + let mut key: Vec = vec![ADDRESS_STORE_PREFIX]; + key.extend_from_slice(&decode_and_convert(&addr)?); + // Construct an ICQ registration message + let msg = NeutronMsg::register_interchain_query( + QueryPayload::KV(vec![{ + KVKey { + path: AUTH_STORE_KEY.to_string(), + key: Binary::from(key), + } + }]), + connection_id, + update_period, + )?; + + // Send the ICQ registration message as a submessage to receive a reply callback + Ok(Response::new().add_submessage(SubMsg { + id: REGISTER_ACCOUNT_ICQ_REPLY_ID, + payload: Binary::default(), + msg: CosmosMsg::Custom(msg), + gas_limit: None, + reply_on: ReplyOn::Success, + })) +} +``` + +3. + +4. In the reply handler, decode the submessage result as a [MsgRegisterInterchainQueryResponse](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/bindings/msg/struct.MsgRegisterInterchainQueryResponse.html) to get access to the assigned Interchain Query ID. +```rust +use cosmwasm_std::{ + entry_point, DepsMut, Env, Reply, Response, StdError, +}; +use neutron_sdk::{ + bindings::msg::MsgRegisterInterchainQueryResponse, + NeutronResult, +}; + +/// Reply ID used to tell this kind of reply call apart. +const REGISTER_ACCOUNT_ICQ_REPLY_ID: u64 = 1; + +#[entry_point] +pub fn reply(_deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { + match msg.id { + REGISTER_ACCOUNT_ICQ_REPLY_ID => { + let resp: MsgRegisterInterchainQueryResponse = serde_json_wasm::from_slice( + &msg.result + .into_result() + .map_err(StdError::generic_err)? + .msg_responses[0] + .value + .to_vec(), + ) + .map_err(|e| StdError::generic_err(format!("failed to parse response: {:?}", e)))?; + + ... + } + + ... + } +} +``` + +5. Use the assigned Interchain Query ID to distinguish between different Interchain Queries in [QueryResult](/neutron/modules/interchain-queries/api#queryresult) calls and [SudoMsg::KVQueryResult](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/sudo/msg/enum.SudoMsg.html) callbacks. + +## How to register a TX-typed Interchain Query with custom keys + +TODO + +https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/bindings/msg/enum.NeutronMsg.html#method.register_interchain_query + +https://docs.cosmos.network/v0.50/build/modules/bank#events diff --git a/docs/neutron/modules/interchain-queries/known-bugs.md b/docs/neutron/modules/interchain-queries/known-bugs.md new file mode 100644 index 000000000..8a672f8c3 --- /dev/null +++ b/docs/neutron/modules/interchain-queries/known-bugs.md @@ -0,0 +1,5 @@ +# Known bugs + +### Impossibility to retrieve and prove KV data with nil values + +Due to a [bug](https://github.com/cosmos/ics23/issues/134) in ICS23 package, it's currently impossible to query an empty or `nil` value from a remote chain. Meaning if your KV-query is registered with key `K` and a value under this key is `nil` or empty, submission of such KV result will fail due to IAVL-proof verification error: `failed to verify proof: empty value in membership proof`. Moreover, due to [the nature of IAVL-proofs](https://github.com/cosmos/cosmos-sdk/blob/ae77f0080a724b159233bd9b289b2e91c0de21b5/docs/interfaces/lite/specification.md) (which is an underlying mechanism of verification of a validity of KV-queries results), it's also impossible to verify [IAVL-absence proof](https://github.com/cosmos/cosmos-sdk/blob/ae77f0080a724b159233bd9b289b2e91c0de21b5/docs/interfaces/lite/specification.md#iavl-absence-proof) if it contains IAVL-proof with `nil` or empty value: `failed to verify proof: could not verify absence of key. Please ensure that the path is correct.`. We are in contact with ics23 team to fix this issue ASAP, but in the meantime the only way to deal with the bug is to avoid querying keys with `nil` or empty values. diff --git a/docs/neutron/modules/interchain-queries/messages.md b/docs/neutron/modules/interchain-queries/messages.md deleted file mode 100644 index 397f515bb..000000000 --- a/docs/neutron/modules/interchain-queries/messages.md +++ /dev/null @@ -1,196 +0,0 @@ -# Messages - -### Register Interchain Query - -[`MsgRegisterInterchainQuery`](https://github.com/neutron-org/neutron/blob/v2.0.3/proto/interchainqueries/tx.proto#L23) can be submitted by smart-contract only via `MsgRegisterInterchainQuery` transaction: - -```protobuf -message MsgRegisterInterchainQuery { - // defines a query type: `kv` or `tx` now - string query_type = 1; - - // is used to define KV-storage keys for which we want to get values from remote chain - repeated KVKey keys = 2; - - // is used to define a filter for transaction search ICQ - string transactions_filter = 3; - - // is IBC connection ID for getting ConsensusState to verify proofs - string connection_id = 4; - - // is used to specify how often (in neutron blocks) the query must be updated - uint64 update_period = 5; - - // is the signer of the message - string sender = 6; -} - -message KVKey { - // Path (storage prefix) to the storage where you want to read value by key - // (usually name of cosmos-sdk module: 'staking', 'bank', etc.) - string path = 1; - // Key you want to read from the storage - bytes key = 2; -} -``` - -> **Note:** the maximum allowed number of KVKey values for a single InterchainQuery equals to 32. - -Currently `query_type` can take the following values: -* `kv` - query **values** from Cosmos-SDK KV-storage on remote chain which are stored under some **keys**. In this case `kv_keys` must be filled in. - -* `tx` - query to search for transactions on remote chain. `transactions_filter` describes a filter by which the [ICQ relayer](/relaying/icq-relayer) will perform the transactions search. [The transaction filter is described in more detail in the overview](/neutron/modules/interchain-queries/overview): - -`MsgRegisterInterchainQuery` returns [`MsgRegisterInterchainQueryResponse`](https://github.com/neutron-org/neutron/blob/v2.0.3/proto/interchainqueries/tx.proto#L44) where `id` is unique identifier of newly registered interchain query on success: -```protobuf -message MsgRegisterInterchainQueryResponse { - uint64 id = 1; -} -``` - -#### State modifications -* increments last registered query id; -* generates new [RegisteredQuery](https://github.com/neutron-org/neutron/blob/v2.0.3/proto/interchainqueries/genesis.proto#L11); -* save the record in storage under incremented query id; - -#### Events -Emits [`EventTypeNeutonMessage`](/neutron/modules/interchain-queries/events#eventtypeneutronmessage) with `action` equals `query_updated`. - -### Update Interchain Query - -> **Note:** as well as for query registration, for query updates the maximum allowed number of KVKey values for a single InterchainQuery equals to 32. - -[`MsgUpdateInterchainQueryRequest`](https://github.com/neutron-org/neutron/blob/v2.0.3/proto/interchainqueries/tx.proto#L114) can be submitted only by the owner of corresponding Interchain Query: -```protobuf -message MsgUpdateInterchainQueryRequest { - uint64 query_id = 1; - repeated KVKey new_keys = 2; - uint64 new_update_period = 3; - string new_transactions_filter = 4; - string sender = 5; // is the signer of the message and owner of the corresponding ICQ -} -``` - -Returns just an empty [`MsgUpdateInterchainQueryResponse`](https://github.com/neutron-org/neutron/blob/v2.0.3/proto/interchainqueries/tx.proto#L121) on success: -```protobuf -message MsgUpdateInterchainQueryResponse { -} -``` - -#### State modifications -* [Updates](https://github.com/neutron-org/neutron/blob/v2.0.3/x/interchainqueries/keeper/msg_server.go#L144) a corresponding `RegisteredQuery` structure. - -#### Events -Emits [`EventTypeNeutonMessage`](/neutron/modules/interchain-queries/events#eventtypeneutronmessage) with `action` equals `query_updated`. - - -### Remove Interchain Query - -[`MsgRemoveInterchainQueryRequest`](https://github.com/neutron-org/neutron/blob/v2.0.3/proto/interchainqueries/tx.proto#L108) can be submitted only by the owner of corresponding Interchain Query within the query's service period or by anyone beyond it. Read more about this message permissions [here](/neutron/modules/interchain-queries/overview#query-creation-deposit). -```protobuf -message MsgRemoveInterchainQueryRequest { - uint64 query_id = 1; - string sender = 2; // is the signer of the message and the owner of corresponding ICQ -} -``` - -Returns just an empty [`MsgRemoveInterchainQueryResponse`](https://github.com/neutron-org/neutron/blob/v2.0.3/proto/interchainqueries/tx.proto#L112) on success: -```protobuf -message MsgRemoveInterchainQueryResponse { -} -``` - -#### State modifications -* [Removes](https://github.com/neutron-org/neutron/blob/v2.0.3/x/interchainqueries/keeper/keeper.go#L140) a corresponding `RegisteredQuery` structure. -* Also removes the query results ([immediately](https://github.com/neutron-org/neutron/blob/v2.0.3/x/interchainqueries/keeper/keeper.go#L144) for a KV query, [deferred in the ICQ module EndBlock](https://github.com/neutron-org/neutron/blob/v2.0.3/x/interchainqueries/module.go#L176) for a TX query). - -#### Events -Emits [`EventTypeNeutonMessage`](/neutron/modules/interchain-queries/events#eventtypeneutronmessage) with `action` equals `query_removed`. - - -### Submit Query Result - -[`MsgSubmitQueryResult`](https://github.com/neutron-org/neutron/blob/v2.0.3/proto/interchainqueries/tx.proto#L46) can be submitted by any Neutron account via `MsgSubmitQueryResult` transaction: - -```protobuf -message MsgSubmitQueryResult { - uint64 query_id = 1; - string sender = 2; - - // is the IBC client ID for an IBC connection between Neutron chain and target chain (where the result was obtained from) - string client_id = 3; - QueryResult result = 4; -} - -message QueryResult { - repeated StorageValue kv_results = 1; - Block block = 2; - uint64 height = 3; - uint64 revision = 4; - bool allow_kv_callbacks = 5; -} - -message StorageValue { - // is the substore name (acc, staking, etc.) - string storage_prefix = 1; - - // is the key in IAVL store - bytes key = 2; - - // is the value in IAVL store - bytes value = 3; - - // is the Merkle Proof which proves existence of key-value pair in IAVL storage - tendermint.crypto.ProofOps Proof = 4; -} - -message Block { - // We need to know block X+1 to verify response of transaction for block X - // since LastResultsHash is root hash of all results from the txs from the previous block - google.protobuf.Any next_block_header = 1; - - // We need to know block X to verify inclusion of transaction for block X - google.protobuf.Any header = 2; - - TxValue tx = 3; -} - -message TxValue { - tendermint.abci.ResponseDeliverTx response = 1; - - // is the Merkle Proof which proves existence of response in block with height next_block_header.Height - tendermint.crypto.Proof delivery_proof = 2; - - // is the Merkle Proof which proves existence of data in block with height header.Height - tendermint.crypto.Proof inclusion_proof = 3; - - // is body of the transaction - bytes data = 4; -} -``` - -Returns just an empty [`MsgSubmitQueryResultResponse`](https://github.com/neutron-org/neutron/blob/v2.0.3/proto/interchainqueries/tx.proto#L106) on success: - -```protobuf -message MsgSubmitQueryResultResponse {} -``` - -#### State modifications -* get registered interchain query info by `MsgSubmitQueryResult.query_id`; -* for every `result` in `MsgSubmitQueryResult.result.kv_results`: - * read IBC connection consensus state from IBC keeper storage with `registered_query.ConnectionID`, `MsgSubmitQueryResult.result.revision`, `MsgSubmitQueryResult.result.height+1`; - * verify `result.Proof` with Merkle Root Hash from consensus state; -* save `MsgSubmitQueryResult.result.kv_results` to the storage: - * clear `MsgSubmitQueryResult.result` from the proofs, Neutron doesn't need them anymore; - * save cleared result to storage with key `registered_query.id`; - * set `registered_query.last_submitted_result_remote_height` to `result.height`; - * set `registered_query.last_submitted_result_local_height` to the current Neutron height; -* callback `MsgSubmitQueryResult.result.kv_results` to thr appropriate smart-contract if needed; -* for every `block` in `MsgSubmitQueryResult.result.blocks`: - * verify `block.next_block_header` and `block.header` by calling [`clientKeeper.UpdateClient(header)`](https://github.com/neutron-org/neutron/blob/v2.0.3/x/interchainqueries/keeper/process_block_results.go#L68); - * [verify](https://github.com/neutron-org/neutron/blob/v2.0.3/x/interchainqueries/keeper/process_block_results.go#L167) `block.txs` with verified headers; -* process every `transaction` in every `block` from `MsgSubmitQueryResult.result.blocks`: - * [check](https://github.com/neutron-org/neutron/blob/v1.0.4/x/interchainqueries/keeper/process_block_results.go#L134) transaction was not processed previously to avoid double submitting - * save generated record to the storage with composite key `bigEndianBytes(registered_query.id) + bigEndianBytes(last_submitted_transaction_id` prefixed by [`SubmittedTxKey`](https://github.com/neutron-org/neutron/blob/v1.0.4/x/interchainqueries/types/keys.go#L37); - * [callback](https://github.com/neutron-org/neutron/blob/v1.0.4/x/interchainqueries/keeper/process_block_results.go#L143) transaction to the appropriate smart-contract; - * [save](https://github.com/neutron-org/neutron/blob/v1.0.4/x/interchainqueries/keeper/process_block_results.go#L150) transaction's hash to the storage to approach double-submission preventing mechanics. diff --git a/docs/neutron/modules/interchain-queries/overview.md b/docs/neutron/modules/interchain-queries/overview.md index 1ece6eb91..63525a11d 100644 --- a/docs/neutron/modules/interchain-queries/overview.md +++ b/docs/neutron/modules/interchain-queries/overview.md @@ -1,167 +1,17 @@ # Overview -## Abstract +This document specifies the `interchainqueries` module for the Neutron network. -This document specifies the ICQ (**I**nter**C**hain **Q**ueries) module for the Neutron network. - -The ICQ module implements a mechanism to retrieve data from remote chains connected to Neutron via IBC. +Interchain Queries (ICQs) let developers retrieve verifiable data from distant blockchains — they’re crucial to building secure cross-chain applications. The implementation uses merkle proofs and IBC clients to verify data it retrieves directly from the target blockchain’s storage. It enables any smart-contract to register Interchain Queries and does not require any specific module on the target chain. ## Concepts -A smart-contract can register two types of Interchain Query for particular chain with some query payload and `update_period`: -* Key-Value query (KV-query) - to read **values** from Cosmos-SDK KV-storage on remote chain which are stored under a set of **keys**; -* Transactions query (TX-query) - find transactions on remote chain under by condition (transactions filter). - -> :warning: **IMPORTANT NOTE ABOUT KV-QUERIES** -> -> **Due to a [bug](https://github.com/cosmos/ics23/issues/134) in ICS23 package, it's currently impossible to query an empty or `nil` value from a remote chain.** -> -> **Meaning if your KV-query is registered with key `K` and a value under this key is `nil` or empty, submission of such** -> **KV result will fail due to IAVL-proof verification error: `failed to verify proof: empty value in membership proof`** -> -> **Moreover, due to [the nature of IAVL-proofs](https://github.com/cosmos/cosmos-sdk/blob/ae77f0080a724b159233bd9b289b2e91c0de21b5/docs/interfaces/lite/specification.md)** -> **(which is an underlying mechanism of verification of a validity of KV-queries results),** -> **it's also impossible to verify** -> **[IAVL-absence proof](https://github.com/cosmos/cosmos-sdk/blob/ae77f0080a724b159233bd9b289b2e91c0de21b5/docs/interfaces/lite/specification.md#iavl-absence-proof)** -> **if it contains IAVL-proof with `nil` or empty value: `failed to verify proof: could not verify absence of key. Please ensure that the path is correct.`** -> -> **We are in contact with ics23 team to fix this issue ASAP, but in the meantime the only way to deal with the bug - is to avoid querying keys with `nil` or empty values.** - - - -ICQ Relayer keeps track of registered Interchain Queries by querying all existed ICQs at the start of work and by subscribing on [Update](https://github.com/neutron-org/neutron/blob/v2.0.3/x/interchainqueries/keeper/msg_server.go#L305) and [Delete](https://github.com/neutron-org/neutron/blob/v2.0.3/x/interchainqueries/keeper/msg_server.go#L321) events which are emitted in corresponding Neutron handlers. When the ICQ Relayer sees that it's time to perform an interchain query, it makes a necessary RPC call to a remote chain and makes the results available for the Neutron's smart contracts by submitting the result to the module. Read more about it at the [Relayer's page](/relaying/icq-relayer#overview). - -Neutron verifies the data and processes the query result depending on the interchain query type: -* in case of a KV-query, the ICQ module saves the result into module's storage, and passed the query id to the contract's -[SudoKVQueryResult](https://github.com/neutron-org/neutron/blob/v2.0.3/x/contractmanager/keeper/sudo.go#L211) [handler](https://github.com/neutron-org/neutron-sdk/blob/v0.5.0/contracts/neutron_interchain_queries/src/contract.rs#L385); -* in case of a TX-query, the ICQ module **does not** save the result to the storage, finds the contract that registered the query, -and passes the full result to the contract's [SudoTXQueryResult](https://github.com/neutron-org/neutron/blob/v2.0.3/x/contractmanager/keeper/sudo.go#L173) [handler](https://github.com/neutron-org/neutron-sdk/blob/v0.5.0/contracts/neutron_interchain_queries/src/contract.rs#L267). - -## Query creation deposit -In order to clean up ledger from not used, outdated queries special deposit mechanism is used. [RegisteredQuery](https://github.com/neutron-org/neutron/blob/main/proto/interchainqueries/genesis.proto#L39) contains `deposit` field, this field is used to collect escrow payment for query creation. In order to return escrow payment a `RemoveInterchainQuery` message should be issued. - -Permission to perform `RemoveInterchainQuery` message is based on three parameters: -1. `query_submit_timeout` — a module parameter which can be thought of as query service period; -2. `last_submitted_result_local_height` — registered query's property representing the Neutron's height the query was updated last time at; -3. `registered_at_height` — registered query's property representing the Neutron's height the query was registered at. - -The permissions to execute `RemoveInterchainQuery` are as follows: -- within the service period (i.e. if `current_height <= last_submitted_result_local_height + query_submit_timeout && current_height <= registered_at_height + query_submit_timeout`) only the query's owner is permissioned to remove it; -- beyond the service period (i.e. if `current_height > last_submitted_result_local_height + query_submit_timeout || current_height > registered_at_height + query_submit_timeout`) anyone can remove the query and take the deposit as a reward. - -Amount of coins to deposit is defined via parameter (`query_deposit`) controlled by governance proposal. - -In other words, it is expected of the query owner to remove its queries when they are not needed anymore. If a query hasn't been in use for the `query_submit_timeout` and owner hasn't removed it, network users are granted with an opportunity to clean the chain up and raise assets for it. - -## Transaction filters - -Since events themselves are not part of the consensus and are not included in the transaction result, it's necessary to -[implement additional checks](https://github.com/neutron-org/neutron-sdk/blob/c197ceacc1c23d2f1283be91f8f90c2be1328db0/contracts/neutron_interchain_queries/src/contract.rs#L197) -in your `SudoTXQueryResult` handler to check that result transactions satisfies your transactions filter. For instance, you can check that messages in the transactions have proper types, payload, etc. -If your contract does not have such checks, malicious relayer can send a fully valid Tendermint transaction which does not satisfy your defined transactions filter, and your business-logic can be broken. - -> NOTE: when registering a TX-query, you write the transaction filters as filters for transaction events. When you check the submitted transaction in your contracts, though, you can only check the information that is stored on-chain (i.e., message fields for messages in a transaction). To put it another way, the set of values that you can use to filter transactions is the intersection of the values that are added to transaction events (used by the ICQ relayer to perform the search) and the values included directly to sdk.Msgs (can be used by your code to check whether the submitted transaction matches your query). - -You can see more info, examples and recommendations about proper transactions result handling [here](https://github.com/neutron-org/neutron-sdk/blob/v0.5.0/contracts/neutron_interchain_txs/src/contract.rs#L439). - - -```json -[{"field": "{eventType}.{attributeKey}", "val": "{attributeValue}", "op": "gte"}, ...] -``` - -Maximum allowed amount of filters is 32. Supplying more filters than allowed will return an error. - -Supported operators: -* `eq` -* `lt` -* `gt` -* `lte` -* `gte` - -The ICQ relayer can easily parse this format and compose it into usual [Tendermint syntax](https://docs.tendermint.com/v0.33/app-dev/indexing-transactions.html#querying-transactions) for searching transactions. - - -Suppose you want to search for transactions that meet specific conditions on a remote chain. You can build a query using various filters to narrow down the search. - -##### Finding Transfer Transactions with a Specific Amount - -```json -[{"field": "transfer.amount", "op": "eq", "val": 1000}] -``` - -This filter searches for all transfer transactions with an exact amount of 1000. The ICQ relayer converts it into the Tendermint search string: - -``` -"transfer.amount" = 1000 -``` - -##### Searching for Transactions within a Range of Dates - -```json -[{"field": "timestamp", "op": "gte", "val": "2023-01-01T00:00:00Z"}, {"field": "timestamp", "op": "lt", "val": "2023-02-01T00:00:00Z"}] -``` - -This filter queries for all transactions that were processed between January 1, 2023, and February 1, 2023. The corresponding Tendermint search string would be: - -``` -"timestamp" >= "2023-01-01T00:00:00Z" AND "timestamp" < "2023-02-01T00:00:00Z" -``` - -##### Combining Multiple Conditions - -```json -[{"field": "message.module", "op": "eq", "val": "bank"}, {"field": "transfer.sender", "op": "eq", "val": "neutron1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrstdxvff"}, {"field": "transfer.amount", "op": "gt", "val": 500}] -``` - -This example searches for bank transfer transactions sent by a specific address (`neutron1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrstdxvff`) and with an amount greater than 500. The search string would be: - -``` -"message.module" = "bank" AND "transfer.sender" = "neutron1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrstdxvff" AND "transfer.amount" > 500 -``` - -##### Effects of Filters - -The filters in the `transactions_filter` field allow for refined and targeted querying of transactions. Some effects of applying these filters are: - -- **Increased Efficiency**: By narrowing down the search criteria, the query can return results more quickly, reducing the computational resources required. -- **Improved Relevance**: Filters ensure that only transactions that meet specific criteria are returned, making the results more relevant to the user's needs. -- **Flexibility**: Users can combine different operators and fields to create complex queries that match their exact requirements. -- **Error Handling**: Providing incorrect or conflicting filters might result in an error, so the filter structure must be carefully constructed to avoid issues. - -By understanding the usage of the `transactions_filter` field, developers and users can leverage the power of targeted querying to interact with remote chains in a more effective and efficient manner. - -##### Having Fewer or More Filters - -###### Fewer Filters -**Pros:** -- **Broader Results**: Using fewer filters will generally lead to a larger result set, capturing more transactions that meet broad criteria. -- **Faster Execution**: With less complexity, the query may execute more quickly, as there are fewer conditions to evaluate. - -**Cons:** -- **Less Precision**: Fewer filters may lead to less relevant results if the query is too broad. - -###### More Filters -**Pros:** -- **More Specific Results**: More filters allow for more targeted and precise queries, narrowing down the result set to only the most relevant transactions. -- **Enhanced Control**: More filters offer greater control over the query, enabling more complex and nuanced searches. - -**Cons:** -- **Slower Execution**: More complex queries with multiple filters may take longer to execute, as each additional condition adds to the computational load. -- **Potential Overfitting**: Too many filters may lead to an overly narrow search, missing relevant transactions or even resulting in no results at all if the filters are too restrictive. - -##### Good Practices - -1. **Start with Core Criteria**: Identify the essential criteria for your query and start with those filters. It helps to focus on what you really need from the results. -2. **Incrementally Refine**: If needed, add additional filters incrementally to refine the results, testing at each stage to ensure relevance. -3. **Avoid Redundancy**: Ensure that each filter adds value to the query and that there are no redundant or conflicting filters. -4. **Test Performance**: Consider testing the query with different numbers of filters to gauge performance and result relevance, especially if using many filters. -5. **Use the Maximum Limit Wisely**: Note that the maximum allowed amount of 32 filters is a technical constraint. - -##### How Many Filters Do You Need? - -The optimal number of filters depends on the specific use case and the balance between precision and performance. Generally, it's best to use the minimum number of filters that provide the necessary specificity for your query. Using too few may yield irrelevant results, while using too many may overly narrow the search or impact performance. +A smart-contract can register an Interchain Query to periodically retrieve some data from remote chain's state and to process the retrieved data in arbitrary way. There are two types of Interchain Queries: +* Key-Value query (KV query) - to read values from Cosmos-SDK KV-storage on remote chain which are stored under a set of keys. It can be balances of accounts, governance proposals, different staking info, smart contracts' state, and literally anything from a remote chain's KV-storage. Read more about how KV queries work by the [link](/neutron/modules/interchain-queries/explanation#how-do-kv-typed-interchain-queries-work); +* Transactions query (TX query) - to find transactions on a remote chain by a list of parameters and equations (so called transactions filter) like transactions happened before some specific height, transactions sent to some specific recipient, or anything else that can be formed into a condition described by emitted events. Read more about how TX queries work by the [link](/neutron/modules/interchain-queries/explanation#how-do-tx-typed-interchain-queries-work). -##### Conclusion +Interchain Queries, similar to IBC, requires an intermediary infrastructure called an [Interchain Query relayer](/neutron/modules/interchain-queries/explanation#what-is-an-interchain-query-relayer) that serves smart contracts. It's supposed to gather info (and cryptographic proofs that the info is valid) defined in Interchain Query parameters from a remote chain's state, and pass it to the `interchainqueries` module and, through that, to smart contracts for handling. The gathering process is called Interchain Query execution, and the passing process is called Interchain Query result submission. The `interchainqueries` module has endpoints and events emission designated to facilitate relayer's work. -The number of filters in a query is a vital consideration, influencing both the relevance of the results and the performance of the query. Striking the right balance requires a thoughtful approach, considering the specific needs of the query, and adhering to good practices for constructing and refining filters. +An Interchain Query relayer should submit a query result via a specific [SubmitQueryResult](/neutron/modules/interchain-queries/api#submitqueryresult) endpoint of the `interchainqueries` module. In scope of this endpoint, the `interchainqueries` module does result verification and calls the designated [sudo handler](/neutron/modules/interchain-queries/api#sudo) of the smart contract that is the owner of the Interchain Query. During this handler the smart contract is supposed to process the query result, i.e. to react on the fresh data coming from the target chain. +One other similarity between the `interchainqueries` module and IBC is IBC clients usage. All Interchain Queries are about reading some data from a remote chain's storage, and the retrieved data is verified against ConsensusState of an IBC client to that chain. On result submission, the `interchainqueries` module verifies the storage values being submitted using the proofs being submitted against the home chain IBC client's ConsensusState, and therefore relies on the IBC protocol in terms of retrieved data authenticity. diff --git a/docs/neutron/modules/interchain-queries/state.md b/docs/neutron/modules/interchain-queries/state.md deleted file mode 100644 index 29a7d1dc4..000000000 --- a/docs/neutron/modules/interchain-queries/state.md +++ /dev/null @@ -1,7 +0,0 @@ -# State - -The ICQ module stores one [RegisteredQuery](https://github.com/neutron-org/neutron/blob/v2.0.3/proto/interchainqueries/genesis.proto#L11) per identifier. -`RegisteredQuery` contains all the necessary info for the ICQ relayer to perform a query on remote chain. `last_submitted_result_local_height`, `last_submitted_result_remote_height` are only used for KV-queries and are modified only when a relayer publishes result for a query. - -Results for interchain queries are stored as: -1. [QueryResult](https://github.com/neutron-org/neutron/blob/v2.0.3/proto/interchainqueries/tx.proto#L56) structure is stored under unique key containing identifier of `RegisteredQuery`; diff --git a/sidebars.js b/sidebars.js index 396f33b40..de55ae036 100644 --- a/sidebars.js +++ b/sidebars.js @@ -177,10 +177,10 @@ const sidebars = { type: 'category', items: [ 'neutron/modules/interchain-queries/overview', - 'neutron/modules/interchain-queries/messages', - 'neutron/modules/interchain-queries/client', - 'neutron/modules/interchain-queries/state', - 'neutron/modules/interchain-queries/events' + 'neutron/modules/interchain-queries/api', + 'neutron/modules/interchain-queries/explanation', + 'neutron/modules/interchain-queries/how-to', + 'neutron/modules/interchain-queries/known-bugs' ] }, { From 40cf0c33c21fbd8306de5b33ac76bfef84c67184 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Mon, 2 Sep 2024 18:14:24 +0300 Subject: [PATCH 02/32] remove target chain page --- docs/relaying/target-chain.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 docs/relaying/target-chain.md diff --git a/docs/relaying/target-chain.md b/docs/relaying/target-chain.md deleted file mode 100644 index 3d60dd37c..000000000 --- a/docs/relaying/target-chain.md +++ /dev/null @@ -1 +0,0 @@ -# Prepare target chain RPC node for Relayer's usage From cf493d9ba76dcfef14672104b41f810d21f646de Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Mon, 14 Oct 2024 17:27:37 +0300 Subject: [PATCH 03/32] add a HowTo for chosing of connection ID for ICQ --- .../modules/interchain-queries/how-to.md | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index 3d7103bba..31fe2213c 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -1,5 +1,60 @@ # How To +## How to chose the right IBC connection ID for an Interchain Query and verify it? + +Let's find an IBC connection between Neutron and CosmosHub. + +1. Go to [map of zones](https://mapofzones.com/zones/neutron-1/peers?columnKey=ibcVolumeIn&period=7d). There might be several connections between two chains, so pick one of them. For Neutron and CosmosHub, let's pick the `connection-0`. + +2. Go to [Neutron's chain registry page](https://github.com/cosmos/chain-registry/blob/master/neutron/chain.json), pick an RPC node from the `apis` section, and specify it in the following `neutrond` queries using the `--node` flag. + +3. Find out the IBC client ID and the counterparty IBC info for the `connection-0` IBC connection: + +``` +neutrond q ibc connection end connection-0 --node https://rpc-voidara.neutron-1.neutron.org + +connection: + client_id: 07-tendermint-0 + counterparty: + client_id: 07-tendermint-1119 + connection_id: connection-809 + ... +``` + +4. Check if the Neutron side IBC client's counterparty chain ID matches the ID of the chain you're up to point your Interchain Queries to: + +``` +neutrond q ibc client state 07-tendermint-0 --node https://rpc-voidara.neutron-1.neutron.org + +client_state: + ... + chain_id: cosmoshub-4 << matches the CosmosHub chain ID + ... +``` + +5. Go to [CosmosHub's chain registry page](https://github.com/cosmos/chain-registry/blob/master/cosmoshub/chain.json), pick an RPC node from the `apis` section, and specify it in the following `gaiad` queries using the `--node` flag. + +6. Using the counterparty IBC info retrieved at the third step of this HowTo, do the opposite side checks: check that the CosmosHub's side IBC connection and client's counterparty info corresponds to Neutron's side IBC connection and client's info: + +``` +gaiad q ibc connection end connection-809 --node https://cosmoshub.tendermintrpc.lava.build:443 + +connection: + client_id: 07-tendermint-1119 << matches the third step's connection.counterparty.client_id + counterparty: + client_id: 07-tendermint-0 << matches the third step's connection.client_id + connection_id: connection-0 << matches the third step's connection-id query parameter +``` + +``` +gaiad q ibc client state 07-tendermint-1119 --node https://cosmoshub.tendermintrpc.lava.build:443 + +client_state: + ... + chain_id: neutron-1 << matches the Neutron chain ID + ... +``` + ## How to register an Interchain Query using neutron-sdk 1. Find the register Interchain Query helper function that your needs require in the [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) repository. For this particular example, let's choose the [new_register_balances_query_msg](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/fn.new_register_balances_query_msg.html) function. From 11e0065866f7508b5e0ddc4e9523194454066d6b Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Mon, 14 Oct 2024 17:28:22 +0300 Subject: [PATCH 04/32] fix ICQs known bugs sidebar element path --- sidebars.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sidebars.js b/sidebars.js index 5a5f12d0e..bee8699b9 100644 --- a/sidebars.js +++ b/sidebars.js @@ -179,7 +179,7 @@ const sidebars = { "neutron/modules/interchain-queries/api", "neutron/modules/interchain-queries/explanation", "neutron/modules/interchain-queries/how-to", - "neutron/modules/interchain-queries/known-bug"' + "neutron/modules/interchain-queries/known-bugs", ], }, { From 4b29a300da286333b4eaaf79734695315ae53692 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Mon, 14 Oct 2024 17:59:59 +0300 Subject: [PATCH 05/32] add more explanations (IBC connection role, entry points, sudo calls, ICQ results removal, RPC node configuration) --- .../neutron/modules/interchain-queries/api.md | 2 ++ .../modules/interchain-queries/explanation.md | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/docs/neutron/modules/interchain-queries/api.md b/docs/neutron/modules/interchain-queries/api.md index 91fd70946..749fbd464 100644 --- a/docs/neutron/modules/interchain-queries/api.md +++ b/docs/neutron/modules/interchain-queries/api.md @@ -342,6 +342,7 @@ Events emission on failure: - attributes with the failure parameters: `_contract_address`, `failure_id`, `error`. **Might be interesting:** +- [What are entry points and sudo calls?](/neutron/modules/interchain-queries/explanation#what-are-entry-points-and-sudo-calls) - [What happens if a sudo callback to a smart contract owning an Interchain Query fails?](/neutron/modules/interchain-queries/explanation#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails) ### MessageKvQueryResult @@ -358,4 +359,5 @@ Events emission on failure: - attributes with the failure parameters: `_contract_address`, `failure_id`, `error`. **Might be interesting:** +- [What are entry points and sudo calls?](/neutron/modules/interchain-queries/explanation#what-are-entry-points-and-sudo-calls) - [What happens if a sudo callback to a smart contract owning an Interchain Query fails?](/neutron/modules/interchain-queries/explanation#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails) diff --git a/docs/neutron/modules/interchain-queries/explanation.md b/docs/neutron/modules/interchain-queries/explanation.md index 456b803b6..b5d75b7fb 100644 --- a/docs/neutron/modules/interchain-queries/explanation.md +++ b/docs/neutron/modules/interchain-queries/explanation.md @@ -49,6 +49,14 @@ An Interchain Query relayer is an off-chain application that serves the needs of - Interchain Queries execution: reading of remote chain's state based on the parameters defined in the Interchain Query being executed, fidning proofs for the read data; - Query results submission: passing of the retrieved data and proofs to the `interchainqueries` module and, through that, to respective smart contracts. +## What's the role of IBC connections in Interchain Queries and how to choose one? + +IBC [clients](https://ibc.cosmos.network/v8/ibc/overview/#clients) and [connections](https://ibc.cosmos.network/v8/ibc/overview/#connections) play significant role in Interchain Queries authenticity. It is the initialisation of an IBC connection that is responsible for IBC clients creation and verification that their states are correct for their respective counterparties, and it is the states of the IBC clients of an IBC connection that is responsible for Interchain Query results verification. One must choose the connection ID for their Interchain Queries wisely for it will define the trustworthiness of the whole Interchain Queries based application. + +There are two options how to find an IBC connection ID for one's needs: +- [Choose one of already existing IBC connections](/neutron/modules/interchain-queries/how-to#how-to-chose-the-right-ibc-connection-id-for-an-interchain-query-and-verify-it); +- Create an IBC connection between the chains yourself. For example, the [Hermes IBC relayer is capable of doing so](https://hermes.informal.systems/documentation/commands/path-setup/connections.html#establish-connection). + ## Why is there a query creation deposit? In order to clean up ledger from not used, outdated queries, a special deposit mechanism is used. [RegisterInterchainQuery](/neutron/modules/interchain-queries/api#registerinterchainquery) message contains the `deposit` field which is used to collect escrow payment for query creation. In order to return escrow payment, a [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery) message should be issued. @@ -91,6 +99,26 @@ If compare to the KV-typed Interchain Queries which have the last result stored - hashes of transactions that have been successfully processed by the owner smart contract to avoid multiple processing of the same transactions, and - [failures appeared during sudo calls](#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails). +## What are entry points and sudo calls? + +[Entry points](https://docs.cosmwasm.com/core/entrypoints) are where your contract can be called from the outside world. [Sudo](https://docs.cosmwasm.com/core/entrypoints/sudo) calls are messages issued by the chain itself. They are routed to a special `sudo` `entry_point` which can only be accessed by the chain. + +## Limited gas for sudo calls + +The `interchainqueries` module uses the [contractmanager](/neutron/modules/contract-manager/overview) module under the hood for `sudo` operations. The `contractmanager` module doesn't allow extensive `sudo` callbacks and [has a justified strict gas limitation for them](/neutron/modules/contract-manager/overview#gas-limitation). The limit is defined by the `sudo_call_gas_limit` `contractmanager` module's parameter. + +It is recommended by the `contractmanager` module to separate `sudo` callback and computations to different handlers in case the computations go beyond the allocated gas. For example, one can store `sudo` callback payload in the contract's state, and then read it and handle during an additional outer `execute` call to the contract. + ## What happens if a sudo callback to a smart contract owning an Interchain Query fails? In this case, the `interchainqueries` module will store the failure in the [contractmanager](/neutron/modules/contract-manager/overview) module with all information about the query and a redacted (shortened to codespace and error code) error message. A full error message is emitted as an [event](https://docs.cosmos.network/v0.50/learn/advanced/events) on a failure (see the [message events emission](/neutron/modules/interchain-queries/api#sudo) for details). Note that the `out of gas` errors are stored as failures, too. Failed query result submissions can be read from the `contractmanager` module and resubmitted to the `interchainqueries` module. More info about the read and resubmit operations by the link to the [contractmanager](/neutron/modules/contract-manager/overview) module documentation. + +## How Interchain Query results are removed? + +When someone successfully issues a [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery) message, the results of the respective Interchain Query stored on chain are removed depending on the type of the Interchain Query: +- KV query results are just single records in the store with a known removal gas consumption. So they are removed in the scope of the removal message handling; +- TX query results are hashes of remote chain transactions. Each of the hashes is a single record in the store, so the gas comsumption for the removal depends on the number of hashes to be removed. This uncertainty is the reason why the TX query results removal is placed at the EndBlock and distributed to small governance-controlled size batches. The removal message handling only marks the TX-typed Interchain Query as a one to be removed, and then in each EndBlock there's a number of its hashes removed. The number is defined by the `tx_query_removal_limit` [module parameter](/neutron/modules/interchain-queries/api#params). + +## Configuring your own remote chain RPC node for TX ICQ usage + +If running your own RPC node for the target chain, make sure to [configure](https://docs.cometbft.com/v0.38/core/configuration) its `indexer` parameter the way it is sufficient for the transactions filter you define for your queries. From d9bd882c679b385a7354fe3c524b2a0d5d05577f Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Mon, 14 Oct 2024 18:00:36 +0300 Subject: [PATCH 06/32] add missing keywords highlighting --- docs/neutron/modules/interchain-queries/api.md | 14 +++++++------- .../modules/interchain-queries/explanation.md | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/api.md b/docs/neutron/modules/interchain-queries/api.md index 749fbd464..cf7fdcda2 100644 --- a/docs/neutron/modules/interchain-queries/api.md +++ b/docs/neutron/modules/interchain-queries/api.md @@ -1,12 +1,12 @@ # API -This page contains the interchainqueries module's interface description: the endpoints the module exposes and the sudo messages the module issues. Each endpoint is explained in a dedicated section with links to request and response models, and an example of interaction with the module via the endpoint. The links to the request and response models also provide more information about request parameters and response values. +This page contains the `interchainqueries` module's interface description: the endpoints the module exposes and the `sudo` messages the module issues. Each endpoint is explained in a dedicated section with links to request and response models, and an example of interaction with the module via the endpoint. The links to the request and response models also provide more information about request parameters and response values. Please be aware that the examples do not necessarily reflect the current state on the chain; they are listed here only to visualize the request formation and response payload in a user-friendly way. **Endpoints** -This section lists piblic RPC API of the interchainqueries module. +This section lists piblic RPC API of the `interchainqueries` module. Queries: - [Params](#params); @@ -24,7 +24,7 @@ Messages: **Sudo** -This section lists sudo messages issued by the interchainqueries module to smart contracts owning Interchain Queries. +This section lists `sudo` messages issued by the `interchainqueries` module to smart contracts owning Interchain Queries. - [MessageTxQueryResult](#messagetxqueryresult) - [MessageKvQueryResult](#messagekvqueryresult) @@ -261,7 +261,7 @@ curl -X 'GET' \ ### RegisterInterchainQuery -Registers a new Interchain Query in the interchainqueries module. This message is supposed to be issues only by a smart contract. The caller contract is charged a query registration deposit automatically in the amount defined as the module's query deposit parameter. The deposit is paid back on the query removal. Make sure to have enough assets on the contract's account at the time of the message execution. +Registers a new Interchain Query in the `interchainqueries` module. This message is supposed to be issues only by a smart contract. The caller contract is charged a query registration deposit automatically in the amount defined as the module's query deposit parameter. The deposit is paid back on the query removal. Make sure to have enough assets on the contract's account at the time of the message execution. Returns an ID assigned to the registered query. Handle this message response via a reply handler in order to make use of the ID. @@ -332,7 +332,7 @@ Updates params of the interchainqueries module. Only callable by the module's au ### MessageTxQueryResult -MessageTxQueryResult is the model of the sudo message sent to a smart contract on a TX-typed Interchain Query result submission. The owner of a TX-typed Interchain Query must define a `sudo` entry_point for handling `tx_query_result` messages and place the needed logic there. The `tx_query_result` handler is treated by the interchainqueries module as a callback that is called each time a TX-typed query result is submitted. +MessageTxQueryResult is the model of the `sudo` message sent to a smart contract on a TX-typed Interchain Query result submission. The owner of a TX-typed Interchain Query must define a `sudo` entry_point for handling `tx_query_result` messages and place the needed logic there. The `tx_query_result` handler is treated by the `interchainqueries` module as a callback that is called each time a TX-typed query result is submitted. - [Message model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/contractmanager/types#MessageTxQueryResult) - [Message model in neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/sudo/msg/enum.SudoMsg.html#variant.TxQueryResult) @@ -347,9 +347,9 @@ Events emission on failure: ### MessageKvQueryResult -MessageKVQueryResult is the model of the sudo message sent to a smart contract on a KV-typed Interchain Query result submission. If the owner of a KV-typed Interchain Query wants to handle the query updates, it must define a `sudo` entry_point for handling `kv_query_result` messages and place the needed logic there. The `kv_query_result` handler is treated by the interchainqueries module as a callback that is called each time a KV-typed query result is submitted. +MessageKVQueryResult is the model of the `sudo` message sent to a smart contract on a KV-typed Interchain Query result submission. If the owner of a KV-typed Interchain Query wants to handle the query updates, it must define a `sudo` entry_point for handling `kv_query_result` messages and place the needed logic there. The `kv_query_result` handler is treated by the `interchainqueries` module as a callback that is called each time a KV-typed query result is submitted. -Note that there is no query result sent, only the query ID. In order to access the actual result, use the Query/QueryResult RPC of the interchainqueries module. +Note that there is no query result sent, only the query ID. In order to access the actual result, use the Query/QueryResult RPC of the `interchainqueries` module. - [Message model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/contractmanager/types#MessageKVQueryResult) - [Message model in neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/sudo/msg/enum.SudoMsg.html#variant.KVQueryResult) diff --git a/docs/neutron/modules/interchain-queries/explanation.md b/docs/neutron/modules/interchain-queries/explanation.md index b5d75b7fb..a8fa34fde 100644 --- a/docs/neutron/modules/interchain-queries/explanation.md +++ b/docs/neutron/modules/interchain-queries/explanation.md @@ -95,7 +95,7 @@ The reason the `Proof` field is presented but empty is that the [QueryResult](ht ## Why doesn't interchainqueries module store TX-typed query results? -If compare to the KV-typed Interchain Queries which have the last result stored on chain and available to be read, the TX-typed Interchain Queries are not about the last result, but about a possible list of results (transactions matched the filter). Storing the whole list of results may be cumbersome for the chain in terms of required space. So, instead of storing results on chain and requiring smart contracts to read them (as for KV queries), the `interchainqueries` module passes the whole tx results directly to smart contracts, ending the life of the results right after a successful [TxQueryResult](/neutron/modules/interchain-queries/api#messagetxqueryresult) sudo call. The only things that the module stores on chain regarding TX-typed Interchain Queries are: +If compare to the KV-typed Interchain Queries which have the last result stored on chain and available to be read, the TX-typed Interchain Queries are not about the last result, but about a possible list of results (transactions matched the filter). Storing the whole list of results may be cumbersome for the chain in terms of required space. So, instead of storing results on chain and requiring smart contracts to read them (as for KV queries), the `interchainqueries` module passes the whole tx results directly to smart contracts, ending the life of the results right after a successful [TxQueryResult](/neutron/modules/interchain-queries/api#messagetxqueryresult) `sudo` call. The only things that the module stores on chain regarding TX-typed Interchain Queries are: - hashes of transactions that have been successfully processed by the owner smart contract to avoid multiple processing of the same transactions, and - [failures appeared during sudo calls](#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails). From b39ce02f11631d64977ddd1dbc5d8ab855e48f70 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Wed, 16 Oct 2024 18:32:27 +0300 Subject: [PATCH 07/32] fix misprints --- docs/neutron/modules/interchain-queries/explanation.md | 4 ++-- docs/neutron/modules/interchain-queries/how-to.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/explanation.md b/docs/neutron/modules/interchain-queries/explanation.md index a8fa34fde..748364b66 100644 --- a/docs/neutron/modules/interchain-queries/explanation.md +++ b/docs/neutron/modules/interchain-queries/explanation.md @@ -23,7 +23,7 @@ A typical flow of KV-typed Interchain Queries usage is as follows: ## How do TX-typed Interchain Queries work? -The meaning of a TX Interchain Query is to get a secured subscription on transactions happening on a remote chain from a smart contract. Such a secured access is based on: +The meaning of a TX Interchain Query is to get a secured subscription on transactions happening on a remote chain from a smart contract. Such a subscription is based on: - transaction execution [events](https://docs.cosmos.network/v0.50/learn/advanced/events) emission. In a word, events are structured logs of actions that take place within the blockchain; - [tx_search](https://docs.cometbft.com/v0.38/app-dev/indexing-transactions#querying-transactions-events) RPC. This RPC allows to search for transactions based on events they emit. @@ -54,7 +54,7 @@ An Interchain Query relayer is an off-chain application that serves the needs of IBC [clients](https://ibc.cosmos.network/v8/ibc/overview/#clients) and [connections](https://ibc.cosmos.network/v8/ibc/overview/#connections) play significant role in Interchain Queries authenticity. It is the initialisation of an IBC connection that is responsible for IBC clients creation and verification that their states are correct for their respective counterparties, and it is the states of the IBC clients of an IBC connection that is responsible for Interchain Query results verification. One must choose the connection ID for their Interchain Queries wisely for it will define the trustworthiness of the whole Interchain Queries based application. There are two options how to find an IBC connection ID for one's needs: -- [Choose one of already existing IBC connections](/neutron/modules/interchain-queries/how-to#how-to-chose-the-right-ibc-connection-id-for-an-interchain-query-and-verify-it); +- [Choose one of already existing IBC connections](/neutron/modules/interchain-queries/how-to#how-to-choose-the-right-ibc-connection-id-for-an-interchain-query-and-verify-it); - Create an IBC connection between the chains yourself. For example, the [Hermes IBC relayer is capable of doing so](https://hermes.informal.systems/documentation/commands/path-setup/connections.html#establish-connection). ## Why is there a query creation deposit? diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index 31fe2213c..954fb975c 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -1,6 +1,6 @@ # How To -## How to chose the right IBC connection ID for an Interchain Query and verify it? +## How to choose the right IBC connection ID for an Interchain Query and verify it Let's find an IBC connection between Neutron and CosmosHub. From 0111af742ceedf8006a907955710e0c5e833c162 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Wed, 16 Oct 2024 18:33:41 +0300 Subject: [PATCH 08/32] add tx filter determination howto section, add pruning mention in private rpc node config guidelines --- .../modules/interchain-queries/explanation.md | 2 +- .../modules/interchain-queries/how-to.md | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/docs/neutron/modules/interchain-queries/explanation.md b/docs/neutron/modules/interchain-queries/explanation.md index 748364b66..a4acedc06 100644 --- a/docs/neutron/modules/interchain-queries/explanation.md +++ b/docs/neutron/modules/interchain-queries/explanation.md @@ -121,4 +121,4 @@ When someone successfully issues a [RemoveInterchainQuery](/neutron/modules/inte ## Configuring your own remote chain RPC node for TX ICQ usage -If running your own RPC node for the target chain, make sure to [configure](https://docs.cometbft.com/v0.38/core/configuration) its `indexer` parameter the way it is sufficient for the transactions filter you define for your queries. +If running your own RPC node for the target chain, make sure to configure its `pruning` parameter in the [app.toml](https://docs.cosmos.network/v0.50/learn/advanced/config) file and `indexer` parameter in the [config.toml](https://docs.cometbft.com/v0.38/core/configuration) file the way it is sufficient for the transactions filter you define for your queries. diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index 954fb975c..3f0441094 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -55,6 +55,49 @@ client_state: ... ``` +## How to find out what transaction filter to use + +Let's imagine that we need our Interchain Query based smart contract to know about undelegations done by `cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp` on CosmosHub. + +1. Find out what is the current version of the `staking` module (imported from `cosmos-sdk`) CosmosHub runs and go to the module's source code: + + 1.1. Find the git repository and currently running version of CosmosHub in the [chain registry](https://github.com/cosmos/chain-registry/blob/e346b6dbc0d901eec5e8704e0a7736bfdaa3dca9/cosmoshub/chain.json#L36-L37) (use the main branch to get the up-to-date info) — `v19.2.0`; + + 1.2. Find the [cosmos-sdk](https://github.com/cosmos/gaia/blob/v19.1.0/go.mod#L24) import in the `go.mod` file of the `gaia` repository of `v19.2.0` — `v0.50.9`; + + 1.3. Open the `staking` module's source code in [cosmos-sdk with tag v0.50.9](https://github.com/cosmos/cosmos-sdk/tree/v0.50.9/x/staking). + +2. Find the [Undelegate](https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L391-L392) entry point of the `staking` module's keeper. + +3. Find the [event emission part](https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L447-L455) of the Undelegate handler code. + +4. Pairing the emitted event type and required attributes, compose an exhaustive transaction filter. In this case, it's `unbond.delegator=cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp` (`types.EventTypeUnbond`.`types.AttributeKeyDelegator`=`cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp`). + +5. Try out the result query string in `gaiad q txs` query to make sure it works as expected: + +``` +gaiad q txs --query "unbond.delegator='cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp'" + +... +txs: +- code: 0 + ... + height: "22645909" + ... + body: + ... + messages: + - '@type': /cosmos.staking.v1beta1.MsgUndelegate + amount: + amount: "20045172" + denom: uatom + delegator_address: cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp + validator_address: cosmosvaloper1zqgheeawp7cmqk27dgyctd80rd8ryhqs6la9wc +``` + +**Might be interesting:** +- [Configuring your own remote chain RPC node for TX ICQ usage](/neutron/modules/interchain-queries/explanation#configuring-your-own-remote-chain-rpc-node-for-tx-icq-usage) + ## How to register an Interchain Query using neutron-sdk 1. Find the register Interchain Query helper function that your needs require in the [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) repository. For this particular example, let's choose the [new_register_balances_query_msg](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/fn.new_register_balances_query_msg.html) function. From 902e649e1bcf028ded245d7a1d546c008b069152 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Wed, 16 Oct 2024 18:44:59 +0300 Subject: [PATCH 09/32] make steps in howtos headers --- .../modules/interchain-queries/how-to.md | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index 3f0441094..be74a6e8c 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -4,11 +4,17 @@ Let's find an IBC connection between Neutron and CosmosHub. -1. Go to [map of zones](https://mapofzones.com/zones/neutron-1/peers?columnKey=ibcVolumeIn&period=7d). There might be several connections between two chains, so pick one of them. For Neutron and CosmosHub, let's pick the `connection-0`. +#### 1. Find an already existing IBC connection using an explorer -2. Go to [Neutron's chain registry page](https://github.com/cosmos/chain-registry/blob/master/neutron/chain.json), pick an RPC node from the `apis` section, and specify it in the following `neutrond` queries using the `--node` flag. +Go to [map of zones](https://mapofzones.com/zones/neutron-1/peers?columnKey=ibcVolumeIn&period=7d). There might be several connections between two chains, so pick one of them. For Neutron and CosmosHub, let's pick the `connection-0`. -3. Find out the IBC client ID and the counterparty IBC info for the `connection-0` IBC connection: +#### 2. Pick a neutron RPC node from the chain registry repo + +Go to [Neutron's chain registry page](https://github.com/cosmos/chain-registry/blob/master/neutron/chain.json), pick an RPC node from the `apis` section, and specify it in the following `neutrond` queries using the `--node` flag. + +#### 3. Gather neutron side info about the picket IBC connection + +Find out the IBC client ID and the counterparty IBC info for the `connection-0` IBC connection: ``` neutrond q ibc connection end connection-0 --node https://rpc-voidara.neutron-1.neutron.org @@ -21,7 +27,9 @@ connection: ... ``` -4. Check if the Neutron side IBC client's counterparty chain ID matches the ID of the chain you're up to point your Interchain Queries to: +#### 4. Check the IBC connection counterparty chain ID + +Check if the Neutron side IBC client's counterparty chain ID matches the ID of the chain you're up to point your Interchain Queries to: ``` neutrond q ibc client state 07-tendermint-0 --node https://rpc-voidara.neutron-1.neutron.org @@ -32,9 +40,13 @@ client_state: ... ``` -5. Go to [CosmosHub's chain registry page](https://github.com/cosmos/chain-registry/blob/master/cosmoshub/chain.json), pick an RPC node from the `apis` section, and specify it in the following `gaiad` queries using the `--node` flag. +#### 5. Pick a CosmosHub RPC node from the chain registry repo + +Go to [CosmosHub's chain registry page](https://github.com/cosmos/chain-registry/blob/master/cosmoshub/chain.json), pick an RPC node from the `apis` section, and specify it in the following `gaiad` queries using the `--node` flag. -6. Using the counterparty IBC info retrieved at the third step of this HowTo, do the opposite side checks: check that the CosmosHub's side IBC connection and client's counterparty info corresponds to Neutron's side IBC connection and client's info: +#### 6. Make sure the CosmosHub's side counterparty is Neutron + +Using the counterparty IBC info retrieved at the third step of this HowTo, do the opposite side checks: check that the CosmosHub's side IBC connection and client's counterparty info corresponds to Neutron's side IBC connection and client's info: ``` gaiad q ibc connection end connection-809 --node https://cosmoshub.tendermintrpc.lava.build:443 @@ -59,21 +71,29 @@ client_state: Let's imagine that we need our Interchain Query based smart contract to know about undelegations done by `cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp` on CosmosHub. -1. Find out what is the current version of the `staking` module (imported from `cosmos-sdk`) CosmosHub runs and go to the module's source code: +#### 1. Find the up-to-date source code of the staking module + +Find out what is the current version of the `staking` module (imported from `cosmos-sdk`) CosmosHub runs and go to the module's source code: + +1. Find the git repository and currently running version of CosmosHub in the [chain registry](https://github.com/cosmos/chain-registry/blob/e346b6dbc0d901eec5e8704e0a7736bfdaa3dca9/cosmoshub/chain.json#L36-L37) (use the main branch to get the up-to-date info) — `v19.2.0`; +2. Find the [cosmos-sdk](https://github.com/cosmos/gaia/blob/v19.1.0/go.mod#L24) import in the `go.mod` file of the `gaia` repository of `v19.2.0` — `v0.50.9`; +3. Open the `staking` module's source code in [cosmos-sdk with tag v0.50.9](https://github.com/cosmos/cosmos-sdk/tree/v0.50.9/x/staking). + +#### 2. Find the handler that manages undelegations - 1.1. Find the git repository and currently running version of CosmosHub in the [chain registry](https://github.com/cosmos/chain-registry/blob/e346b6dbc0d901eec5e8704e0a7736bfdaa3dca9/cosmoshub/chain.json#L36-L37) (use the main branch to get the up-to-date info) — `v19.2.0`; +Find the [Undelegate](https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L391-L392) entry point of the `staking` module's keeper. - 1.2. Find the [cosmos-sdk](https://github.com/cosmos/gaia/blob/v19.1.0/go.mod#L24) import in the `go.mod` file of the `gaia` repository of `v19.2.0` — `v0.50.9`; +#### 3. Find the events emitted on undelegations - 1.3. Open the `staking` module's source code in [cosmos-sdk with tag v0.50.9](https://github.com/cosmos/cosmos-sdk/tree/v0.50.9/x/staking). +Find the [event emission part](https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L447-L455) of the Undelegate handler code. -2. Find the [Undelegate](https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L391-L392) entry point of the `staking` module's keeper. +#### 4. Create a transactions query using the events -3. Find the [event emission part](https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L447-L455) of the Undelegate handler code. +Pairing the emitted event type and required attributes, compose an exhaustive transaction filter. In this case, it's `unbond.delegator=cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp` (`types.EventTypeUnbond`.`types.AttributeKeyDelegator`=`cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp`). -4. Pairing the emitted event type and required attributes, compose an exhaustive transaction filter. In this case, it's `unbond.delegator=cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp` (`types.EventTypeUnbond`.`types.AttributeKeyDelegator`=`cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp`). +#### 5. Try to get some results using the query -5. Try out the result query string in `gaiad q txs` query to make sure it works as expected: +Try out the result query string in `gaiad q txs` query to make sure it works as expected: ``` gaiad q txs --query "unbond.delegator='cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp'" From 5ddbce18ef6fb18a77cb581313b2de5ac25cdcf3 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Fri, 18 Oct 2024 13:17:54 +0400 Subject: [PATCH 10/32] add explanation section for TX query submitted results verification --- docs/neutron/modules/interchain-queries/explanation.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/neutron/modules/interchain-queries/explanation.md b/docs/neutron/modules/interchain-queries/explanation.md index a4acedc06..8bc77f1a4 100644 --- a/docs/neutron/modules/interchain-queries/explanation.md +++ b/docs/neutron/modules/interchain-queries/explanation.md @@ -87,6 +87,16 @@ The permissions to execute [RemoveInterchainQuery](/neutron/modules/interchain-q `beyond_service_period = current_height > query.last_submitted_result_local_height + params.query_submit_timeout && current_height > query.registered_at_height + params.query_submit_timeout` +## Why is it mandatory to do contract's side verification of submitted TX Interchain Query results? + +One important thing to keep in mind regarding Interchain Queries is that result submissions are permissionless. This means that anyone — not just your designated relayer — can submit the results of the Interchain Queries that your contract registered to the `interchainqueries` module. + +However, since events are not part of the consensus and are not included in the transaction result (and therefore not included in the TX-typed Interchain Queries result submission), the `interchainqueries` module cannot verify whether the submitted transactions actually match the criteria set by the Interchain Query’s transaction filters. + +Because of this limitation, it's essential to implement additional checks in your `SudoTXQueryResult` handler to ensure the submitted transactions meet your query's transaction filters criteria. You should at least verify that the messages in the transaction body have the correct message types and values. For example, if considering an Interchain Query that [gets Undelegate transactions issued by a concrete address](/neutron/modules/interchain-queries/how-to#how-to-find-out-what-transaction-filter-to-use), the verification will have to check that the message type is `/cosmos.staking.v1beta1.MsgUndelegate` and that the delegator address is `cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp`. The way to go is to have these two kinds of checks for each transaction filter in your query. + +Without these checks, a malicious relayer could submit a fully valid Tendermint transaction that doesn't meet your defined transaction filters, potentially compromising your business logic. For the example above, if you don't check the delegator address, anyone's Undelegate transactions will pass. + ## Why is the Proof field nullified in QueryResult RPC response? The `interchainqueries` module only needs KV proofs during the submission process to verify the values being submitted against the proofs. If save them afterwards, they'll just increase chain's space without any reasonable further usage. The KV results saved on chain can be trusted as cryptographically proved because they are verified at the very beginning — by the module at the submission step. From de05b732e44de993419529f18a183c6f173dcbc5 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Fri, 18 Oct 2024 13:18:19 +0400 Subject: [PATCH 11/32] rm interchainqueries TODO file --- .../modules/interchain-queries/TODO.md | 137 ------------------ 1 file changed, 137 deletions(-) delete mode 100644 docs/neutron/modules/interchain-queries/TODO.md diff --git a/docs/neutron/modules/interchain-queries/TODO.md b/docs/neutron/modules/interchain-queries/TODO.md deleted file mode 100644 index 4213a5af8..000000000 --- a/docs/neutron/modules/interchain-queries/TODO.md +++ /dev/null @@ -1,137 +0,0 @@ -# TODO - -## Explanation: How Interchain Query results are removed? - -- KV query results are removed immediately -- TX query results are removed in EndBlock in an amount based on the module's `tx_query_removal_limit` value - -## Explanation: Configuring your own remote chain RPC node for TX ICQ usage - -If running your own RPC node for the target chain, make sure to [configure](https://docs.cometbft.com/v0.38/core/configuration) it's `indexer` parameter the way it is sufficient for the transactions filter you define for your queries. - -... add something else probably - -## Explanation: What are sudo calls? - -## Explanation: Limited gas for sudo calls - -- reasoning -- what is the value and how to get the current value -- guidelines how to write sudo handlers (preserve sudo data, then process it in another outer call) - -## Explanation: How to find the right IBC connection ID for an Interchain Query? - -- explain clients and connections -- add links to IBC docs -- ICQs depend on IBC clients in terms of data authenticity and the client should be trustworthy (i.e. owned by the protocol) - -## Explanation: Guidelines on transactions_filter definition - -Since events themselves are not part of the consensus and are not included in the transaction result, it's necessary to -[implement additional checks](https://github.com/neutron-org/neutron-sdk/blob/c197ceacc1c23d2f1283be91f8f90c2be1328db0/contracts/neutron_interchain_queries/src/contract.rs#L197) -in your `SudoTXQueryResult` handler to check that result transactions satisfies your transactions filter. For instance, you can check that messages in the transactions have proper types, payload, etc. -If your contract does not have such checks, malicious relayer can send a fully valid Tendermint transaction which does not satisfy your defined transactions filter, and your business-logic can be broken. - -> NOTE: when registering a TX-query, you write the transaction filters as filters for transaction events. When you check the submitted transaction in your contracts, though, you can only check the information that is stored on-chain (i.e., message fields for messages in a transaction). To put it another way, the set of values that you can use to filter transactions is the intersection of the values that are added to transaction events (used by the ICQ relayer to perform the search) and the values included directly to sdk.Msgs (can be used by your code to check whether the submitted transaction matches your query). - -You can see more info, examples and recommendations about proper transactions result handling [here](https://github.com/neutron-org/neutron-sdk/blob/v0.5.0/contracts/neutron_interchain_txs/src/contract.rs#L439). - - -```json -[{"field": "{eventType}.{attributeKey}", "val": "{attributeValue}", "op": "gte"}, ...] -``` - -Maximum allowed amount of filters is 32. Supplying more filters than allowed will return an error. - -Supported operators: -* `eq` -* `lt` -* `gt` -* `lte` -* `gte` - -The ICQ relayer can easily parse this format and compose it into usual [Tendermint syntax](https://docs.tendermint.com/v0.33/app-dev/indexing-transactions.html#querying-transactions) for searching transactions. - -Suppose you want to search for transactions that meet specific conditions on a remote chain. You can build a query using various filters to narrow down the search. - -##### Finding Transfer Transactions with a Specific Amount - -```json -[{"field": "transfer.amount", "op": "eq", "val": 1000}] -``` - -This filter searches for all transfer transactions with an exact amount of 1000. The ICQ relayer converts it into the Tendermint search string: - -``` -"transfer.amount" = 1000 -``` - -##### Searching for Transactions within a Range of Dates - -```json -[{"field": "timestamp", "op": "gte", "val": "2023-01-01T00:00:00Z"}, {"field": "timestamp", "op": "lt", "val": "2023-02-01T00:00:00Z"}] -``` - -This filter queries for all transactions that were processed between January 1, 2023, and February 1, 2023. The corresponding Tendermint search string would be: - -``` -"timestamp" >= "2023-01-01T00:00:00Z" AND "timestamp" < "2023-02-01T00:00:00Z" -``` - -##### Combining Multiple Conditions - -```json -[{"field": "message.module", "op": "eq", "val": "bank"}, {"field": "transfer.sender", "op": "eq", "val": "neutron1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrstdxvff"}, {"field": "transfer.amount", "op": "gt", "val": 500}] -``` - -This example searches for bank transfer transactions sent by a specific address (`neutron1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrstdxvff`) and with an amount greater than 500. The search string would be: - -``` -"message.module" = "bank" AND "transfer.sender" = "neutron1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrstdxvff" AND "transfer.amount" > 500 -``` - -##### Effects of Filters - -The filters in the `transactions_filter` field allow for refined and targeted querying of transactions. Some effects of applying these filters are: - -- **Increased Efficiency**: By narrowing down the search criteria, the query can return results more quickly, reducing the computational resources required. -- **Improved Relevance**: Filters ensure that only transactions that meet specific criteria are returned, making the results more relevant to the user's needs. -- **Flexibility**: Users can combine different operators and fields to create complex queries that match their exact requirements. -- **Error Handling**: Providing incorrect or conflicting filters might result in an error, so the filter structure must be carefully constructed to avoid issues. - -By understanding the usage of the `transactions_filter` field, developers and users can leverage the power of targeted querying to interact with remote chains in a more effective and efficient manner. - -##### Having Fewer or More Filters - -###### Fewer Filters -**Pros:** -- **Broader Results**: Using fewer filters will generally lead to a larger result set, capturing more transactions that meet broad criteria. -- **Faster Execution**: With less complexity, the query may execute more quickly, as there are fewer conditions to evaluate. - -**Cons:** -- **Less Precision**: Fewer filters may lead to less relevant results if the query is too broad. - -###### More Filters -**Pros:** -- **More Specific Results**: More filters allow for more targeted and precise queries, narrowing down the result set to only the most relevant transactions. -- **Enhanced Control**: More filters offer greater control over the query, enabling more complex and nuanced searches. - -**Cons:** -- **Slower Execution**: More complex queries with multiple filters may take longer to execute, as each additional condition adds to the computational load. -- **Potential Overfitting**: Too many filters may lead to an overly narrow search, missing relevant transactions or even resulting in no results at all if the filters are too restrictive. - -##### Good Practices - -1. **Start with Core Criteria**: Identify the essential criteria for your query and start with those filters. It helps to focus on what you really need from the results. -2. **Incrementally Refine**: If needed, add additional filters incrementally to refine the results, testing at each stage to ensure relevance. -3. **Avoid Redundancy**: Ensure that each filter adds value to the query and that there are no redundant or conflicting filters. -4. **Test Performance**: Consider testing the query with different numbers of filters to gauge performance and result relevance, especially if using many filters. -5. **Use the Maximum Limit Wisely**: Note that the maximum allowed amount of 32 filters is a technical constraint. - -##### How Many Filters Do You Need? - -The optimal number of filters depends on the specific use case and the balance between precision and performance. Generally, it's best to use the minimum number of filters that provide the necessary specificity for your query. Using too few may yield irrelevant results, while using too many may overly narrow the search or impact performance. - -##### Conclusion - -The number of filters in a query is a vital consideration, influencing both the relevance of the results and the performance of the query. Striking the right balance requires a thoughtful approach, considering the specific needs of the query, and adhering to good practices for constructing and refining filters. From df5fc297f9aced3a812204bb3ce5edfb02a2ff1d Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Fri, 18 Oct 2024 15:11:06 +0400 Subject: [PATCH 12/32] remove -typed suffix for ICQ types --- .../neutron/modules/interchain-queries/api.md | 14 +++++------ .../modules/interchain-queries/explanation.md | 24 +++++++++---------- .../modules/interchain-queries/how-to.md | 4 ++-- .../modules/interchain-queries/overview.md | 4 ++-- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/api.md b/docs/neutron/modules/interchain-queries/api.md index cf7fdcda2..2a15f7a39 100644 --- a/docs/neutron/modules/interchain-queries/api.md +++ b/docs/neutron/modules/interchain-queries/api.md @@ -139,7 +139,7 @@ curl -X 'GET' \ **Might be interesting:** - [Why is the Proof field nullified in QueryResult RPC response?](/neutron/modules/interchain-queries/explanation#why-is-the-proof-field-nullified-in-queryresult-rpc-response) -- [Why doesn't interchainqueries module store TX-typed query results?](/neutron/modules/interchain-queries/explanation#why-doesnt-interchainqueries-module-store-tx-typed-query-results) +- [Why doesn't interchainqueries module store TX query results?](/neutron/modules/interchain-queries/explanation#why-doesnt-interchainqueries-module-store-tx-query-results) ### RegisteredQuery @@ -192,7 +192,7 @@ curl -X 'GET' \ **Might be interesting:** - [Why is the Proof field nullified in QueryResult RPC response?](/neutron/modules/interchain-queries/explanation#why-is-the-proof-field-nullified-in-queryresult-rpc-response) -- [Why doesn't interchainqueries module store TX-typed query results?](/neutron/modules/interchain-queries/explanation#why-doesnt-interchainqueries-module-store-tx-typed-query-results) +- [Why doesn't interchainqueries module store TX query results?](/neutron/modules/interchain-queries/explanation#why-doesnt-interchainqueries-module-store-tx-query-results) ### QueryResult @@ -232,7 +232,7 @@ curl -X 'GET' \ **Might be interesting:** - [Why is the Proof field nullified in QueryResult RPC response?](/neutron/modules/interchain-queries/explanation#why-is-the-proof-field-nullified-in-queryresult-rpc-response) -- [Why doesn't interchainqueries module store TX-typed query results?](/neutron/modules/interchain-queries/explanation#why-doesnt-interchainqueries-module-store-tx-typed-query-results) +- [Why doesn't interchainqueries module store TX query results?](/neutron/modules/interchain-queries/explanation#why-doesnt-interchainqueries-module-store-tx-query-results) ### LastRemoteHeight @@ -276,8 +276,8 @@ Events emission on success: **Might be interesting:** - [How to register an Interchain Query using neutron-sdk](/neutron/modules/interchain-queries/how-to#how-to-register-an-interchain-query-using-neutron-sdk) -- [How to register a KV-typed Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-kv-typed-interchain-query-with-custom-keys) -- [How to register a TX-typed Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-tx-typed-interchain-query-with-custom-keys) +- [How to register a KV Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-kv-interchain-query-with-custom-keys) +- [How to register a TX Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-tx-interchain-query-with-custom-keys) - [Why is there a query creation deposit?](/neutron/modules/interchain-queries/how-to#why-is-there-a-query-creation-deposit) - [Impossibility to retrieve and prove KV data with nil values](/neutron/modules/interchain-queries/known-bugs#impossibility-to-retrieve-and-prove-kv-data-with-nil-values) @@ -332,7 +332,7 @@ Updates params of the interchainqueries module. Only callable by the module's au ### MessageTxQueryResult -MessageTxQueryResult is the model of the `sudo` message sent to a smart contract on a TX-typed Interchain Query result submission. The owner of a TX-typed Interchain Query must define a `sudo` entry_point for handling `tx_query_result` messages and place the needed logic there. The `tx_query_result` handler is treated by the `interchainqueries` module as a callback that is called each time a TX-typed query result is submitted. +MessageTxQueryResult is the model of the `sudo` message sent to a smart contract on a TX Interchain Query result submission. The owner of a TX Interchain Query must define a `sudo` entry_point for handling `tx_query_result` messages and place the needed logic there. The `tx_query_result` handler is treated by the `interchainqueries` module as a callback that is called each time a TX query result is submitted. - [Message model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/contractmanager/types#MessageTxQueryResult) - [Message model in neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/sudo/msg/enum.SudoMsg.html#variant.TxQueryResult) @@ -347,7 +347,7 @@ Events emission on failure: ### MessageKvQueryResult -MessageKVQueryResult is the model of the `sudo` message sent to a smart contract on a KV-typed Interchain Query result submission. If the owner of a KV-typed Interchain Query wants to handle the query updates, it must define a `sudo` entry_point for handling `kv_query_result` messages and place the needed logic there. The `kv_query_result` handler is treated by the `interchainqueries` module as a callback that is called each time a KV-typed query result is submitted. +MessageKVQueryResult is the model of the `sudo` message sent to a smart contract on a KV Interchain Query result submission. If the owner of a KV Interchain Query wants to handle the query updates, it must define a `sudo` entry_point for handling `kv_query_result` messages and place the needed logic there. The `kv_query_result` handler is treated by the `interchainqueries` module as a callback that is called each time a KV query result is submitted. Note that there is no query result sent, only the query ID. In order to access the actual result, use the Query/QueryResult RPC of the `interchainqueries` module. diff --git a/docs/neutron/modules/interchain-queries/explanation.md b/docs/neutron/modules/interchain-queries/explanation.md index 8bc77f1a4..3642d8527 100644 --- a/docs/neutron/modules/interchain-queries/explanation.md +++ b/docs/neutron/modules/interchain-queries/explanation.md @@ -1,16 +1,16 @@ # Explanation -## How do KV-typed Interchain Queries work? +## How do KV Interchain Queries work? The meaning of a KV Interchain Query is to get a secured access to a remote chain's storage from a smart contract. Such a secured access is based on: - [IAVL tree](https://github.com/cosmos/iavl) which is used as data storage in Cosmos-SDK based blockchains. Each piece of data (value) is a leaf node in the tree having its unique data path (key); - [abci_query](https://docs.cometbft.com/v0.38/spec/rpc/#abciquery) RPC that exposes the storage (`IAVL tree`) read operations by a given path. -A typical flow of KV-typed Interchain Queries usage is as follows: +A typical flow of KV Interchain Queries usage is as follows: 1. A smart contract developer realises that their interchain protocol depends on state of a remote chain, and figures out what info exactly they need to read from the chain; 2. Given the required data set, the developer composes a list of paths in the storage that contain the required data; 3. The developer writes and deploys a smart contract that contains Interchain Query registration logic and a callback for handling the query results; -4. The smart contract registers a KV-typed Interchain Query with the set of keys to read. The registered Interchain Query is stored in the `interchainqueries` module's state; +4. The smart contract registers a KV Interchain Query with the set of keys to read. The registered Interchain Query is stored in the `interchainqueries` module's state; 5. An Interchain Query relayer reads the `interchainqueries` module's state, finds the registered query and its parameters, and does the `abci_query` RPC. The result of the call is a set of key-value pairs with proofs coming from the `IAVL tree`; 6. The Interchain Query relayer provides the key-value pairs and proofs to the `interchainqueries` module. This is as KV Interchain Query result submission operation. The module does the result verification against the proofs and passes the result to the smart contract; 7. The smart contract does arbitrary handling of the result; @@ -18,20 +18,20 @@ A typical flow of KV-typed Interchain Queries usage is as follows: **Might be interesting:** - [How to register an Interchain Query using neutron-sdk](/neutron/modules/interchain-queries/how-to#how-to-register-an-interchain-query-using-neutron-sdk) -- [How to register a KV-typed Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-kv-typed-interchain-query-with-custom-keys) +- [How to register a KV Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-kv-interchain-query-with-custom-keys) - [What is an Interchain Query relayer?](/neutron/modules/interchain-queries/explanation#what-is-an-interchain-query-relayer) -## How do TX-typed Interchain Queries work? +## How do TX Interchain Queries work? The meaning of a TX Interchain Query is to get a secured subscription on transactions happening on a remote chain from a smart contract. Such a subscription is based on: - transaction execution [events](https://docs.cosmos.network/v0.50/learn/advanced/events) emission. In a word, events are structured logs of actions that take place within the blockchain; - [tx_search](https://docs.cometbft.com/v0.38/app-dev/indexing-transactions#querying-transactions-events) RPC. This RPC allows to search for transactions based on events they emit. -A typical flow of TX-typed Interchain Queries usage is as follows: +A typical flow of TX Interchain Queries usage is as follows: 1. A smart contract developer realises that their interchain protocol depends on actions happening on a remote chain, and figures out what actions exactly they need to react on; 2. Given the requirements, the developer composes a list of filtering conditions that identify the needed transactions by the events they emit; 3. The developer writes and deploys a smart contract that contains Interchain Query registration logic and a callback for handling the query results; -4. The smart contract registers a TX-typed Interchain Query with the set of transaction filters to apply. The registered Interchain Query is stored in the `interchainqueries` module's state; +4. The smart contract registers a TX Interchain Query with the set of transaction filters to apply. The registered Interchain Query is stored in the `interchainqueries` module's state; 5. An Interchain Query relayer reads the `interchainqueries` module's state, finds the registered query and its parameters, and does the `tx_search` RPC. The result of the call is a list of transactions successfully processed on the remote chain; 6. The Interchain Query relayer provides the list of transactions a couple of headers for each transaction needed to verify the result to the `interchainqueries` module. This is a TX Interchain Query result submission operation. The module does the result verification against the headers and passes the result to the smart contract; 7. The smart contract does arbitrary handling of the result; @@ -39,7 +39,7 @@ A typical flow of TX-typed Interchain Queries usage is as follows: **Might be interesting:** - [How to register an Interchain Query using neutron-sdk](/neutron/modules/interchain-queries/how-to#how-to-register-an-interchain-query-using-neutron-sdk) -- [How to register a TX-typed Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-tx-typed-interchain-query-with-custom-keys) +- [How to register a TX Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-tx-interchain-query-with-custom-keys) - [What is an Interchain Query relayer?](/neutron/modules/interchain-queries/explanation#what-is-an-interchain-query-relayer) ## What is an Interchain Query relayer? @@ -91,7 +91,7 @@ The permissions to execute [RemoveInterchainQuery](/neutron/modules/interchain-q One important thing to keep in mind regarding Interchain Queries is that result submissions are permissionless. This means that anyone — not just your designated relayer — can submit the results of the Interchain Queries that your contract registered to the `interchainqueries` module. -However, since events are not part of the consensus and are not included in the transaction result (and therefore not included in the TX-typed Interchain Queries result submission), the `interchainqueries` module cannot verify whether the submitted transactions actually match the criteria set by the Interchain Query’s transaction filters. +However, since events are not part of the consensus and are not included in the transaction result (and therefore not included in the TX Interchain Queries result submission), the `interchainqueries` module cannot verify whether the submitted transactions actually match the criteria set by the Interchain Query’s transaction filters. Because of this limitation, it's essential to implement additional checks in your `SudoTXQueryResult` handler to ensure the submitted transactions meet your query's transaction filters criteria. You should at least verify that the messages in the transaction body have the correct message types and values. For example, if considering an Interchain Query that [gets Undelegate transactions issued by a concrete address](/neutron/modules/interchain-queries/how-to#how-to-find-out-what-transaction-filter-to-use), the verification will have to check that the message type is `/cosmos.staking.v1beta1.MsgUndelegate` and that the delegator address is `cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp`. The way to go is to have these two kinds of checks for each transaction filter in your query. @@ -103,9 +103,9 @@ The `interchainqueries` module only needs KV proofs during the submission proces The reason the `Proof` field is presented but empty is that the [QueryResult](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryResult) type is used for both query result submission and query result preservation in the module's storage. More designated types are likely to be introduced in the future to mitigate confusion around this. -## Why doesn't interchainqueries module store TX-typed query results? +## Why doesn't interchainqueries module store TX query results? -If compare to the KV-typed Interchain Queries which have the last result stored on chain and available to be read, the TX-typed Interchain Queries are not about the last result, but about a possible list of results (transactions matched the filter). Storing the whole list of results may be cumbersome for the chain in terms of required space. So, instead of storing results on chain and requiring smart contracts to read them (as for KV queries), the `interchainqueries` module passes the whole tx results directly to smart contracts, ending the life of the results right after a successful [TxQueryResult](/neutron/modules/interchain-queries/api#messagetxqueryresult) `sudo` call. The only things that the module stores on chain regarding TX-typed Interchain Queries are: +If compare to the KV Interchain Queries which have the last result stored on chain and available to be read, the TX Interchain Queries are not about the last result, but about a possible list of results (transactions matched the filter). Storing the whole list of results may be cumbersome for the chain in terms of required space. So, instead of storing results on chain and requiring smart contracts to read them (as for KV queries), the `interchainqueries` module passes the whole tx results directly to smart contracts, ending the life of the results right after a successful [TxQueryResult](/neutron/modules/interchain-queries/api#messagetxqueryresult) `sudo` call. The only things that the module stores on chain regarding TX Interchain Queries are: - hashes of transactions that have been successfully processed by the owner smart contract to avoid multiple processing of the same transactions, and - [failures appeared during sudo calls](#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails). @@ -127,7 +127,7 @@ In this case, the `interchainqueries` module will store the failure in the [cont When someone successfully issues a [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery) message, the results of the respective Interchain Query stored on chain are removed depending on the type of the Interchain Query: - KV query results are just single records in the store with a known removal gas consumption. So they are removed in the scope of the removal message handling; -- TX query results are hashes of remote chain transactions. Each of the hashes is a single record in the store, so the gas comsumption for the removal depends on the number of hashes to be removed. This uncertainty is the reason why the TX query results removal is placed at the EndBlock and distributed to small governance-controlled size batches. The removal message handling only marks the TX-typed Interchain Query as a one to be removed, and then in each EndBlock there's a number of its hashes removed. The number is defined by the `tx_query_removal_limit` [module parameter](/neutron/modules/interchain-queries/api#params). +- TX query results are hashes of remote chain transactions. Each of the hashes is a single record in the store, so the gas comsumption for the removal depends on the number of hashes to be removed. This uncertainty is the reason why the TX query results removal is placed at the EndBlock and distributed to small governance-controlled size batches. The removal message handling only marks the TX Interchain Query as a one to be removed, and then in each EndBlock there's a number of its hashes removed. The number is defined by the `tx_query_removal_limit` [module parameter](/neutron/modules/interchain-queries/api#params). ## Configuring your own remote chain RPC node for TX ICQ usage diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index be74a6e8c..0fc51b4ad 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -197,7 +197,7 @@ pub fn reply(_deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { } ``` -## How to register a KV-typed Interchain Query with custom keys +## How to register a KV Interchain Query with custom keys If your KV Interchain Query cannot be covered with the helpers from the [Interchain Queries related package](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) in the [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk), you will need to define the KVKeys for your query yourself and pass it to the [NeutronMsg::register_interchain_query](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/bindings/msg/enum.NeutronMsg.html#method.register_interchain_query) helper. For this particular example, let's register an [Account](https://github.com/cosmos/cosmos-sdk/blob/c29844f9e1ccc76ba68b8c0d931f3b0ad3885e13/proto/cosmos/auth/v1beta1/query.proto#L27-L31) Interchain Query to `cosmos-hub`. @@ -302,7 +302,7 @@ pub fn reply(_deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { 5. Use the assigned Interchain Query ID to distinguish between different Interchain Queries in [QueryResult](/neutron/modules/interchain-queries/api#queryresult) calls and [SudoMsg::KVQueryResult](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/sudo/msg/enum.SudoMsg.html) callbacks. -## How to register a TX-typed Interchain Query with custom keys +## How to register a TX Interchain Query with custom keys TODO diff --git a/docs/neutron/modules/interchain-queries/overview.md b/docs/neutron/modules/interchain-queries/overview.md index 63525a11d..e8bf7620b 100644 --- a/docs/neutron/modules/interchain-queries/overview.md +++ b/docs/neutron/modules/interchain-queries/overview.md @@ -7,8 +7,8 @@ Interchain Queries (ICQs) let developers retrieve verifiable data from distant b ## Concepts A smart-contract can register an Interchain Query to periodically retrieve some data from remote chain's state and to process the retrieved data in arbitrary way. There are two types of Interchain Queries: -* Key-Value query (KV query) - to read values from Cosmos-SDK KV-storage on remote chain which are stored under a set of keys. It can be balances of accounts, governance proposals, different staking info, smart contracts' state, and literally anything from a remote chain's KV-storage. Read more about how KV queries work by the [link](/neutron/modules/interchain-queries/explanation#how-do-kv-typed-interchain-queries-work); -* Transactions query (TX query) - to find transactions on a remote chain by a list of parameters and equations (so called transactions filter) like transactions happened before some specific height, transactions sent to some specific recipient, or anything else that can be formed into a condition described by emitted events. Read more about how TX queries work by the [link](/neutron/modules/interchain-queries/explanation#how-do-tx-typed-interchain-queries-work). +* Key-Value query (KV query) - to read values from Cosmos-SDK KV-storage on remote chain which are stored under a set of keys. It can be balances of accounts, governance proposals, different staking info, smart contracts' state, and literally anything from a remote chain's KV-storage. Read more about how KV queries work by the [link](/neutron/modules/interchain-queries/explanation#how-do-kv-interchain-queries-work); +* Transactions query (TX query) - to find transactions on a remote chain by a list of parameters and equations (so called transactions filter) like transactions happened before some specific height, transactions sent to some specific recipient, or anything else that can be formed into a condition described by emitted events. Read more about how TX queries work by the [link](/neutron/modules/interchain-queries/explanation#how-do-tx-interchain-queries-work). Interchain Queries, similar to IBC, requires an intermediary infrastructure called an [Interchain Query relayer](/neutron/modules/interchain-queries/explanation#what-is-an-interchain-query-relayer) that serves smart contracts. It's supposed to gather info (and cryptographic proofs that the info is valid) defined in Interchain Query parameters from a remote chain's state, and pass it to the `interchainqueries` module and, through that, to smart contracts for handling. The gathering process is called Interchain Query execution, and the passing process is called Interchain Query result submission. The `interchainqueries` module has endpoints and events emission designated to facilitate relayer's work. From cbfeb4241e5168f2970a19e8055a36541c06053b Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Wed, 30 Oct 2024 12:44:04 +0300 Subject: [PATCH 13/32] add a howto section for simple ICQ registration with contract code snippets --- .../modules/interchain-queries/how-to.md | 104 ++++++++++-------- 1 file changed, 59 insertions(+), 45 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index 0fc51b4ad..fb5e35006 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -120,82 +120,96 @@ txs: ## How to register an Interchain Query using neutron-sdk -1. Find the register Interchain Query helper function that your needs require in the [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) repository. For this particular example, let's choose the [new_register_balances_query_msg](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/fn.new_register_balances_query_msg.html) function. +#### 1. Find the appropriate helper function in Neutron SDK -2. From your contract, broadcast the message created by the helper function as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/): -```rust -use cosmwasm_std::{ - Binary, CosmosMsg, Response, SubMsg, ReplyOn, -}; -use neutron_sdk::{ - bindings::{ - msg::NeutronMsg, - }, - interchain_queries::v045::new_register_balances_query_msg, - NeutronResult, -} +Find the register Interchain Query helper function that your needs require in the [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) repository. For this particular example, let's choose the [new_register_balances_query_msg](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/fn.new_register_balances_query_msg.html) function. -/// Reply ID used to tell this kind of reply call apart. -const REGISTER_BALANCES_ICQ_REPLY_ID: u64 = 1; +#### 2. Use the helper to register an Interchain Query + +From your contract, broadcast the message created by the helper function as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/): -/// Registers a balances ICQ for a given address. -pub fn register_balances_icq( +```rust +pub fn register_balances_query( + env: Env, connection_id: String, addr: String, denoms: Vec, update_period: u64, -) -> NeutronResult> { - ... - // Construct an ICQ registration message - let msg = - new_register_balances_query_msg(connection_id, addr, denoms, update_period)?; +) -> NeutronResult> { + let msg = new_register_balances_query_msg( + env.contract.address, + connection_id, + addr.clone(), + denoms, + update_period, + )?; // Send the ICQ registration message as a submessage to receive a reply callback Ok(Response::new().add_submessage(SubMsg { id: REGISTER_BALANCES_ICQ_REPLY_ID, - payload: Binary::default(), + payload: to_json_binary(&addr)?, msg: CosmosMsg::Custom(msg), gas_limit: None, reply_on: ReplyOn::Success, })) - ... } ``` +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/cc29b8dd70db1bbc969c6f48350fdbaa4fb1bbaf/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L64-L87) -3. In the reply handler, decode the submessage result as a [MsgRegisterInterchainQueryResponse](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/bindings/msg/struct.MsgRegisterInterchainQueryResponse.html) to get access to the assigned Interchain Query ID. -```rust -use cosmwasm_std::{ - entry_point, DepsMut, Env, Reply, Response, StdError, -}; -use neutron_sdk::{ - bindings::msg::MsgRegisterInterchainQueryResponse, - NeutronResult, -}; - -/// Reply ID used to tell this kind of reply call apart. -const REGISTER_BALANCES_ICQ_REPLY_ID: u64 = 1; +#### 3. Define Interchain Query registration response handling +In the reply handler, decode the submessage result as a [MsgRegisterInterchainQueryResponse](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/bindings/msg/struct.MsgRegisterInterchainQueryResponse.html) (TODO: replace bindings link with neutron-sdk link) to get access to the assigned Interchain Query ID. +```rust #[entry_point] -pub fn reply(_deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { +pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { match msg.id { REGISTER_BALANCES_ICQ_REPLY_ID => { - let resp: MsgRegisterInterchainQueryResponse = serde_json_wasm::from_slice( - &msg.result + // decode the reply msg result as MsgRegisterInterchainQueryResponse + let resp = MsgRegisterInterchainQueryResponse::decode( + msg.result .into_result() .map_err(StdError::generic_err)? .msg_responses[0] + .clone() .value - .to_vec(), - ) - .map_err(|e| StdError::generic_err(format!("failed to parse response: {:?}", e)))?; + .to_vec() + .as_slice(), + )?; - ... - } + // memorize the address that corresponds to the query id to use it later in the + // SudoMsg::KVQueryResult handler. + let addr: String = from_json(&msg.payload)?; + ICQ_ID_TO_WATCHED_ADDR.save(deps.storage, resp.id, &addr)?; - ... + Ok(Response::default()) + } + _ => Err(NeutronError::InvalidReplyID(msg.id)), } } ``` +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/cc29b8dd70db1bbc969c6f48350fdbaa4fb1bbaf/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L113-L138) + +#### 4. Define Interchain Query results submission handling + +Get the submitted Interchain Query result from the `interchainqueries` module's storage by the query ID and handle it. + +```rust +/// The contract's callback for KV query results. Note that only the query id is provided, so you +/// need to read the query result from the state. +pub fn sudo_kv_query_result(deps: DepsMut, env: Env, query_id: u64) -> NeutronResult { + // Get the last submitted ICQ result from the Neutron ICQ module storage + let balance_resp = query_balance(deps.as_ref(), env.clone(), query_id)?; + // Get the address that was registered for the ICQ + let addr = ICQ_ID_TO_WATCHED_ADDR.load(deps.storage, query_id)?; + + // Put your business logic here + // For this example we just preserve the freshly fetched balances in the contract's state + REMOTE_BALANCES.save(deps.storage, addr, &balance_resp.balances)?; + + Ok(Response::default()) +} +``` +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/cc29b8dd70db1bbc969c6f48350fdbaa4fb1bbaf/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L140-L153) ## How to register a KV Interchain Query with custom keys From cbdc0fa0d61fac80266b63ac6d2b29aca75c8033 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Mon, 4 Nov 2024 17:08:29 +0300 Subject: [PATCH 14/32] refine KV ICQ registration howtos --- .../modules/interchain-queries/how-to.md | 251 +++++++++++++----- 1 file changed, 181 insertions(+), 70 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index fb5e35006..d149d9efa 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -120,22 +120,47 @@ txs: ## How to register an Interchain Query using neutron-sdk +This section contains a step-by-step guide on how to register an Interchain Query using the [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk) library and handle the query results in a smart contract. + #### 1. Find the appropriate helper function in Neutron SDK Find the register Interchain Query helper function that your needs require in the [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) repository. For this particular example, let's choose the [new_register_balances_query_msg](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/fn.new_register_balances_query_msg.html) function. -#### 2. Use the helper to register an Interchain Query +:::note Couldn't find the required helper function? +If there is no predefined helper function suitable for your needs in [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk), proceed to the [How to register a KV Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-kv-interchain-query-with-custom-keys) section. +::: + +#### 2. Define Interchain Query registration entry point -From your contract, broadcast the message created by the helper function as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/): +Implement an `execute` message handler in your contract that will process Interchain Query registration using the helper function as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/): ```rust +use neutron_sdk::interchain_queries::v047::register_queries::new_register_balances_query_msg; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + _deps: DepsMut, + env: Env, + _info: MessageInfo, + msg: ExecuteMsg, +) -> NeutronResult { + match msg { + ExecuteMsg::RegisterBalancesQuery { + connection_id, + addr, + denoms, + update_period, + } => register_balances_query(env, connection_id, addr, denoms, update_period), + } +} + pub fn register_balances_query( env: Env, connection_id: String, addr: String, denoms: Vec, update_period: u64, -) -> NeutronResult> { +) -> NeutronResult { let msg = new_register_balances_query_msg( env.contract.address, connection_id, @@ -148,18 +173,21 @@ pub fn register_balances_query( Ok(Response::new().add_submessage(SubMsg { id: REGISTER_BALANCES_ICQ_REPLY_ID, payload: to_json_binary(&addr)?, - msg: CosmosMsg::Custom(msg), + msg: msg, gas_limit: None, reply_on: ReplyOn::Success, })) } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/cc29b8dd70db1bbc969c6f48350fdbaa4fb1bbaf/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L64-L87) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L47-L87) #### 3. Define Interchain Query registration response handling -In the reply handler, decode the submessage result as a [MsgRegisterInterchainQueryResponse](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/bindings/msg/struct.MsgRegisterInterchainQueryResponse.html) (TODO: replace bindings link with neutron-sdk link) to get access to the assigned Interchain Query ID. +In the reply handler, decode the submessage result as a [MsgRegisterInterchainQueryResponse](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.MsgRegisterInterchainQueryResponse.html) to get access to the assigned Interchain Query ID. + ```rust +use neutron_std::types::neutron::interchainqueries::MsgRegisterInterchainQueryResponse; + #[entry_point] pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { match msg.id { @@ -187,13 +215,15 @@ pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { } } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/cc29b8dd70db1bbc969c6f48350fdbaa4fb1bbaf/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L113-L138) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L113-L138) #### 4. Define Interchain Query results submission handling -Get the submitted Interchain Query result from the `interchainqueries` module's storage by the query ID and handle it. +Get the submitted Interchain Query result from the `interchainqueries` module's storage using [query_balance](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v047/queries/fn.query_balance.html) helper function and handle it. ```rust +use neutron_sdk::interchain_queries::v047::queries::query_balance; + /// The contract's callback for KV query results. Note that only the query id is provided, so you /// need to read the query result from the state. pub fn sudo_kv_query_result(deps: DepsMut, env: Env, query_id: u64) -> NeutronResult { @@ -209,112 +239,193 @@ pub fn sudo_kv_query_result(deps: DepsMut, env: Env, query_id: u64) -> NeutronRe Ok(Response::default()) } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/cc29b8dd70db1bbc969c6f48350fdbaa4fb1bbaf/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L140-L153) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L140-L153) + +#### 5. Perform Interchain Query registration + +Broadcast a [ExecuteMsg::RegisterBalancesQuery](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_kv_icq/src/msg.rs#L10-L15) message to the contract with required parameters. ## How to register a KV Interchain Query with custom keys -If your KV Interchain Query cannot be covered with the helpers from the [Interchain Queries related package](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) in the [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk), you will need to define the KVKeys for your query yourself and pass it to the [NeutronMsg::register_interchain_query](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/bindings/msg/enum.NeutronMsg.html#method.register_interchain_query) helper. For this particular example, let's register an [Account](https://github.com/cosmos/cosmos-sdk/blob/c29844f9e1ccc76ba68b8c0d931f3b0ad3885e13/proto/cosmos/auth/v1beta1/query.proto#L27-L31) Interchain Query to `cosmos-hub`. +If your KV Interchain Query cannot be covered with the helpers from the [Interchain Queries related package](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) of [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk), you will need to define the KVKeys for your query yourself. For this particular example, let's register an [Account](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/proto/cosmos/auth/v1beta1/query.proto#L27-L31) Interchain Query to `cosmos-hub` `v21.0.0`. + +#### 1. Figure out the respective data path and model -1. Figure out how the data path to the required data is constructed and what the data model is. This can be done by the module's code investigation. Start with finding the [respective auth module gRPC handler](https://github.com/cosmos/cosmos-sdk/blob/c29844f9e1ccc76ba68b8c0d931f3b0ad3885e13/x/auth/keeper/grpc_query.go#L69-L95) and then go deeper until you find what info exactly is written to the KVStore and at what path. +Figure out how the data path to the required data is constructed and what the data model is. This can be done by the module's code investigation. Start with finding the [respective auth module gRPC handler](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/keeper/grpc_query.go#L62-L63) and then go deeper until you find what info exactly is written to the KVStore and at what path. For this example, the information we require from the module's code is: -- the store key for the module is [acc](https://github.com/cosmos/cosmos-sdk/blob/c29844f9e1ccc76ba68b8c0d931f3b0ad3885e13/x/auth/types/keys.go#L11-L12); -- the data path is constructed as [AddressStoreKeyPrefix](https://github.com/cosmos/cosmos-sdk/blob/c29844f9e1ccc76ba68b8c0d931f3b0ad3885e13/x/auth/types/keys.go#L22-L23) + [base64-encoded address](https://github.com/cosmos/cosmos-sdk/blob/c29844f9e1ccc76ba68b8c0d931f3b0ad3885e13/x/auth/types/keys.go#L34); -- the data model is [BaseAccount](https://github.com/cosmos/cosmos-sdk/blob/c29844f9e1ccc76ba68b8c0d931f3b0ad3885e13/x/auth/types/auth.pb.go#L29-L37). +- the store key used at [module's keeper initialisation](https://github.com/cosmos/gaia/blob/db2cc90315161d6730551d795558aaa7664aea6f/app/keepers/keepers.go#L207) is [acc](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/types/keys.go#L11-L12); +- the data path is constructed as [accounts store prefix](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/types/keys.go#L22-L23) + [hex address representation](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/keeper/grpc_query.go#L72-L76); +- the data model is [BaseAccount](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/types/auth.pb.go#L29-L37). + +#### 2. Define Interchain Query registration entry point + +Implement an `execute` message handler in your contract that will process Interchain Query registration by broadcasting a [MsgRegisterInterchainQuery](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.MsgRegisterInterchainQuery.html) message as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/). Use the data path info found at the previous step as the parameters of the message. -2. From your contract, broadcast the message created by the helper function as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/). Use the [decode_and_convert](https://docs.rs/neutron-sdk/0.8.0/neutron_sdk/interchain_queries/helpers/fn.decode_and_convert.html) helper function for bech32 address conversion. ```rust -use cosmwasm_std::{ - Binary, CosmosMsg, Response, SubMsg, ReplyOn, -}; -use neutron_sdk::{ - bindings::{ - msg::NeutronMsg, - types::KVKey, - }, - interchain_queries::helpers::decode_and_convert, - interchain_queries::types::QueryPayload, - NeutronResult, -} +use neutron_std::types::neutron::interchainqueries::MsgRegisterInterchainQuery; -/// Name of the standard **auth** Cosmos-SDK module -const AUTH_STORE_KEY: &str = "acc"; +/// Store key for standard **auth** Cosmos-SDK module +pub const AUTH_STORE_KEY: &str = "acc"; /// Storage prefix for account-by-address store -/// -const ADDRESS_STORE_PREFIX: u8 = 0x01; +/// +pub const ACCOUNTS_PREFIX: u8 = 0x01; -/// Reply ID used to tell this kind of reply call apart. -const REGISTER_ACCOUNT_ICQ_REPLY_ID: u64 = 1; +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + _deps: DepsMut, + env: Env, + _info: MessageInfo, + msg: ExecuteMsg, +) -> NeutronResult { + match msg { + ExecuteMsg::RegisterAccountQuery { + connection_id, + addr, + update_period, + } => register_account_query(env, connection_id, addr, update_period), + } +} -/// Registers an account ICQ for a given address. -pub fn register_account_icq( +pub fn register_account_query( + env: Env, connection_id: String, addr: String, update_period: u64, -) -> NeutronResult> { - let mut key: Vec = vec![ADDRESS_STORE_PREFIX]; - key.extend_from_slice(&decode_and_convert(&addr)?); - // Construct an ICQ registration message - let msg = NeutronMsg::register_interchain_query( - QueryPayload::KV(vec![{ - KVKey { - path: AUTH_STORE_KEY.to_string(), - key: Binary::from(key), - } - }]), +) -> NeutronResult { + // compose key as accounts store prefix + hex address representation + let mut key: Vec = vec![ACCOUNTS_PREFIX]; + key.extend_from_slice(decode_and_convert(&addr)?.as_slice()); + + let msg = MsgRegisterInterchainQuery { + query_type: QueryType::KV.into(), + keys: vec![KvKey { + path: AUTH_STORE_KEY.to_string(), + key: key, + }], + transactions_filter: String::default(), connection_id, update_period, - )?; + sender: env.contract.address.to_string(), + }; // Send the ICQ registration message as a submessage to receive a reply callback Ok(Response::new().add_submessage(SubMsg { id: REGISTER_ACCOUNT_ICQ_REPLY_ID, - payload: Binary::default(), - msg: CosmosMsg::Custom(msg), + payload: to_json_binary(&addr)?, + msg: msg.into(), gas_limit: None, reply_on: ReplyOn::Success, })) } ``` +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/contract.rs#L56-L102) + +#### 3. Define Interchain Query registration response handling -3. +In the reply handler, decode the submessage result as a [MsgRegisterInterchainQueryResponse](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.MsgRegisterInterchainQueryResponse.html) to get access to the assigned Interchain Query ID. -4. In the reply handler, decode the submessage result as a [MsgRegisterInterchainQueryResponse](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/bindings/msg/struct.MsgRegisterInterchainQueryResponse.html) to get access to the assigned Interchain Query ID. ```rust -use cosmwasm_std::{ - entry_point, DepsMut, Env, Reply, Response, StdError, -}; -use neutron_sdk::{ - bindings::msg::MsgRegisterInterchainQueryResponse, - NeutronResult, -}; - -/// Reply ID used to tell this kind of reply call apart. -const REGISTER_ACCOUNT_ICQ_REPLY_ID: u64 = 1; +use neutron_std::types::neutron::interchainqueries::MsgRegisterInterchainQueryResponse; #[entry_point] -pub fn reply(_deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { +pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { match msg.id { REGISTER_ACCOUNT_ICQ_REPLY_ID => { - let resp: MsgRegisterInterchainQueryResponse = serde_json_wasm::from_slice( - &msg.result + // decode the reply msg result as MsgRegisterInterchainQueryResponse + let resp = MsgRegisterInterchainQueryResponse::decode( + msg.result .into_result() .map_err(StdError::generic_err)? .msg_responses[0] + .clone() .value - .to_vec(), - ) - .map_err(|e| StdError::generic_err(format!("failed to parse response: {:?}", e)))?; + .to_vec() + .as_slice(), + )?; - ... + // memorize the address that corresponds to the query id to use it later in the + // SudoMsg::KVQueryResult handler. + let addr: String = from_json(&msg.payload)?; + ICQ_ID_TO_WATCHED_ADDR.save(deps.storage, resp.id, &addr)?; + + Ok(Response::default()) + } + _ => Err(NeutronError::InvalidReplyID(msg.id)), + } +} +``` +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/contract.rs#L128-L153) + +#### 4. Implement reconstruction of the query result + +Define how the query result should be reconstructed from [StorageValue](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.StorageValue.html) into a BaseAccount instance: + +```rust +use neutron_sdk::interchain_queries::types::KVReconstruct; +use neutron_std::types::neutron::interchainqueries::StorageValue; + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +/// A structure that can be reconstructed from **StorageValues**'s for the **Account Interchain Query**. +pub struct BaseAccount { + pub address: String, + pub account_number: String, + pub sequence: String, +} + +impl KVReconstruct for BaseAccount { + fn reconstruct(storage_values: &[StorageValue]) -> NeutronResult { + if storage_values.len() != 1 { + return Err(NeutronError::InvalidQueryResultFormat( + "storage_values length is not 1".into(), + )); } - ... + // first level value is Any as sdk.AccountI implementation: + // https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/types/account.go#L9-L32 + let any_value: Any = Any::decode(storage_values[0].value.as_slice())?; + // second level value is BaseAccount: + // https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/types/auth.pb.go#L29-L37 + let std_acc: StdBaseAccount = StdBaseAccount::decode(any_value.value.as_slice())?; + Ok(BaseAccount { + address: std_acc.address, + account_number: std_acc.account_number.to_string(), + sequence: std_acc.sequence.to_string(), + }) } } ``` +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/types.rs#L10-L38) + +#### 5. Define Interchain Query results submission handling + +Get the submitted Interchain Query result from the `interchainqueries` module's storage using [query_kv_result](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/queries/fn.query_kv_result.html) helper function and handle it. + +```rust +use neutron_sdk::interchain_queries::queries::query_kv_result; +use crate::types::BaseAccount; + +/// The contract's callback for KV query results. Note that only the query id is provided, so you +/// need to read the query result from the state. +pub fn sudo_kv_query_result(deps: DepsMut, query_id: u64) -> NeutronResult { + // Get the last submitted ICQ result from the Neutron ICQ module storage and decode it + // as BaseAccount using its KVReconstruct::reconstruct implementation. + let account_resp: BaseAccount = query_kv_result(deps.as_ref(), query_id)?; + // Get the address that was registered for the ICQ + let addr = ICQ_ID_TO_WATCHED_ADDR.load(deps.storage, query_id)?; + + // Put your business logic here + // For this example we just preserve the freshly fetched account in the contract's state + REMOTE_ACCOUNTS.save(deps.storage, addr, &account_resp)?; + + Ok(Response::default()) +} +``` +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/contract.rs#L155-L169) + +#### 6. Perform Interchain Query registration -5. Use the assigned Interchain Query ID to distinguish between different Interchain Queries in [QueryResult](/neutron/modules/interchain-queries/api#queryresult) calls and [SudoMsg::KVQueryResult](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/sudo/msg/enum.SudoMsg.html) callbacks. +Broadcast a [ExecuteMsg::RegisterAccountQuery](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/msg.rs#L10-L14) message to the contract with required parameters. ## How to register a TX Interchain Query with custom keys From c0b24e7f17b03361164d86378bb43074c7ec2edb Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Tue, 5 Nov 2024 11:57:58 +0300 Subject: [PATCH 15/32] move code snippets into details in interchainqueries howto --- .../modules/interchain-queries/how-to.md | 60 ++++++++++++++++--- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index d149d9efa..86c80e1ec 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -14,22 +14,29 @@ Go to [Neutron's chain registry page](https://github.com/cosmos/chain-registry/b #### 3. Gather neutron side info about the picket IBC connection -Find out the IBC client ID and the counterparty IBC info for the `connection-0` IBC connection: +Find out the IBC client ID and the counterparty IBC info for the `connection-0` IBC connection. + +
+ Show code ``` neutrond q ibc connection end connection-0 --node https://rpc-voidara.neutron-1.neutron.org connection: - client_id: 07-tendermint-0 - counterparty: +client_id: 07-tendermint-0 +counterparty: client_id: 07-tendermint-1119 connection_id: connection-809 ... ``` +
#### 4. Check the IBC connection counterparty chain ID -Check if the Neutron side IBC client's counterparty chain ID matches the ID of the chain you're up to point your Interchain Queries to: +Check if the Neutron side IBC client's counterparty chain ID matches the ID of the chain you're up to point your Interchain Queries to. + +
+ Show code ``` neutrond q ibc client state 07-tendermint-0 --node https://rpc-voidara.neutron-1.neutron.org @@ -39,6 +46,7 @@ client_state: chain_id: cosmoshub-4 << matches the CosmosHub chain ID ... ``` +
#### 5. Pick a CosmosHub RPC node from the chain registry repo @@ -46,7 +54,10 @@ Go to [CosmosHub's chain registry page](https://github.com/cosmos/chain-registry #### 6. Make sure the CosmosHub's side counterparty is Neutron -Using the counterparty IBC info retrieved at the third step of this HowTo, do the opposite side checks: check that the CosmosHub's side IBC connection and client's counterparty info corresponds to Neutron's side IBC connection and client's info: +Using the counterparty IBC info retrieved at the third step of this HowTo, do the opposite side checks: check that the CosmosHub's side IBC connection and client's counterparty info corresponds to Neutron's side IBC connection and client's info. + +
+ Show code ``` gaiad q ibc connection end connection-809 --node https://cosmoshub.tendermintrpc.lava.build:443 @@ -66,6 +77,7 @@ client_state: chain_id: neutron-1 << matches the Neutron chain ID ... ``` +
## How to find out what transaction filter to use @@ -93,7 +105,10 @@ Pairing the emitted event type and required attributes, compose an exhaustive tr #### 5. Try to get some results using the query -Try out the result query string in `gaiad q txs` query to make sure it works as expected: +Try out the result query string in `gaiad q txs` query to make sure it works as expected. + +
+ Show code ``` gaiad q txs --query "unbond.delegator='cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp'" @@ -114,6 +129,7 @@ txs: delegator_address: cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp validator_address: cosmosvaloper1zqgheeawp7cmqk27dgyctd80rd8ryhqs6la9wc ``` +
**Might be interesting:** - [Configuring your own remote chain RPC node for TX ICQ usage](/neutron/modules/interchain-queries/explanation#configuring-your-own-remote-chain-rpc-node-for-tx-icq-usage) @@ -132,7 +148,10 @@ If there is no predefined helper function suitable for your needs in [neutron-sd #### 2. Define Interchain Query registration entry point -Implement an `execute` message handler in your contract that will process Interchain Query registration using the helper function as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/): +Implement an `execute` message handler in your contract that will process Interchain Query registration using the helper function as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/). + +
+ Show code ```rust use neutron_sdk::interchain_queries::v047::register_queries::new_register_balances_query_msg; @@ -180,11 +199,15 @@ pub fn register_balances_query( } ``` [View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L47-L87) +
#### 3. Define Interchain Query registration response handling In the reply handler, decode the submessage result as a [MsgRegisterInterchainQueryResponse](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.MsgRegisterInterchainQueryResponse.html) to get access to the assigned Interchain Query ID. +
+ Show code + ```rust use neutron_std::types::neutron::interchainqueries::MsgRegisterInterchainQueryResponse; @@ -216,11 +239,15 @@ pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { } ``` [View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L113-L138) +
#### 4. Define Interchain Query results submission handling Get the submitted Interchain Query result from the `interchainqueries` module's storage using [query_balance](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v047/queries/fn.query_balance.html) helper function and handle it. +
+ Show code + ```rust use neutron_sdk::interchain_queries::v047::queries::query_balance; @@ -240,6 +267,7 @@ pub fn sudo_kv_query_result(deps: DepsMut, env: Env, query_id: u64) -> NeutronRe } ``` [View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L140-L153) +
#### 5. Perform Interchain Query registration @@ -262,6 +290,9 @@ For this example, the information we require from the module's code is: Implement an `execute` message handler in your contract that will process Interchain Query registration by broadcasting a [MsgRegisterInterchainQuery](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.MsgRegisterInterchainQuery.html) message as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/). Use the data path info found at the previous step as the parameters of the message. +
+ Show code + ```rust use neutron_std::types::neutron::interchainqueries::MsgRegisterInterchainQuery; @@ -320,11 +351,15 @@ pub fn register_account_query( } ``` [View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/contract.rs#L56-L102) +
#### 3. Define Interchain Query registration response handling In the reply handler, decode the submessage result as a [MsgRegisterInterchainQueryResponse](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.MsgRegisterInterchainQueryResponse.html) to get access to the assigned Interchain Query ID. +
+ Show code + ```rust use neutron_std::types::neutron::interchainqueries::MsgRegisterInterchainQueryResponse; @@ -356,10 +391,14 @@ pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { } ``` [View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/contract.rs#L128-L153) +
#### 4. Implement reconstruction of the query result -Define how the query result should be reconstructed from [StorageValue](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.StorageValue.html) into a BaseAccount instance: +Define how the query result should be reconstructed from [StorageValue](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.StorageValue.html) into a BaseAccount instance. + +
+ Show code ```rust use neutron_sdk::interchain_queries::types::KVReconstruct; @@ -396,11 +435,15 @@ impl KVReconstruct for BaseAccount { } ``` [View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/types.rs#L10-L38) +
#### 5. Define Interchain Query results submission handling Get the submitted Interchain Query result from the `interchainqueries` module's storage using [query_kv_result](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/queries/fn.query_kv_result.html) helper function and handle it. +
+ Show code + ```rust use neutron_sdk::interchain_queries::queries::query_kv_result; use crate::types::BaseAccount; @@ -422,6 +465,7 @@ pub fn sudo_kv_query_result(deps: DepsMut, query_id: u64) -> NeutronResult #### 6. Perform Interchain Query registration From c7666f607a5543938a85dca84ca66f8901ce8a7a Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Mon, 11 Nov 2024 17:47:26 +0300 Subject: [PATCH 16/32] add a how to section for TX ICQ --- .../modules/interchain-queries/how-to.md | 157 +++++++++++++++++- 1 file changed, 153 insertions(+), 4 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index 86c80e1ec..ded687211 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -471,10 +471,159 @@ pub fn sudo_kv_query_result(deps: DepsMut, query_id: u64) -> NeutronResult + Show code + +```rust +use neutron_std::types::neutron::interchainqueries::MsgRegisterInterchainQuery; + +/// Unbond delegator attribute key. +/// https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L447-L455 +const UNBOND_DELEGATOR_ATTR: &str = "unbond.delegator"; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + _deps: DepsMut, + env: Env, + _info: MessageInfo, + msg: ExecuteMsg, +) -> NeutronResult { + match msg { + ExecuteMsg::RegisterUndelegationsQuery { + connection_id, + addr, + update_period, + } => register_undelegations_query(env, connection_id, addr, update_period), + } +} + +pub fn register_undelegations_query( + env: Env, + connection_id: String, + addr: String, + update_period: u64, +) -> NeutronResult { + let msg = MsgRegisterInterchainQuery { + query_type: QueryType::TX.into(), + keys: vec![], + // the result filter is unbond.delegator=addr + transactions_filter: to_string(&vec![TransactionFilterItem { + field: UNBOND_DELEGATOR_ATTR.to_string(), + op: TransactionFilterOp::Eq, + value: TransactionFilterValue::String(addr.clone()), + }]) + .map_err(|e| StdError::generic_err(e.to_string()))?, + connection_id, + update_period, + sender: env.contract.address.to_string(), + }; + + Ok(Response::default().add_message(msg)) +} +``` +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_tx_icq/src/contract.rs#L55-L93) +
+ +#### 3. Define Interchain Query results submission handling + +Decode the transaction and its messages, implement the [contract's side verification of submitted TX Interchain Query results](/neutron/modules/interchain-queries/explanation#why-is-it-mandatory-to-do-contracts-side-verification-of-submitted-tx-interchain-query-results) and results handling. + +
+ Show code + +```rust +use neutron_sdk::sudo::msg::SudoMsg; +use cosmos_sdk_proto::cosmos::staking::v1beta1::MsgUndelegate; +use cosmos_sdk_proto::cosmos::tx::v1beta1::{TxBody, TxRaw}; + +const STAKING_UNDELEGATE_MSG_URL: &str = "/cosmos.staking.v1beta1.MsgUndelegate"; + +#[entry_point] +pub fn sudo(deps: DepsMut, env: Env, msg: SudoMsg) -> NeutronResult { + match msg { + SudoMsg::TxQueryResult { + query_id, + height, + data, + } => sudo_tx_query_result(deps, env, query_id, height, data), + _ => Ok(Response::default()), + } +} + +/// The contract's callback for TX query results. +pub fn sudo_tx_query_result( + deps: DepsMut, + _env: Env, + query_id: u64, + _height: Height, + data: Binary, +) -> NeutronResult { + // Decode the transaction data + let tx: TxRaw = TxRaw::decode(data.as_slice())?; + let body: TxBody = TxBody::decode(tx.body_bytes.as_slice())?; + + // Get the registered query by ID and retrieve the delegator address from query's transaction filter + let registered_query: RegisteredQuery = get_registered_query(deps.as_ref(), query_id)?; + let query_tx_filter: Vec = + serde_json_wasm::from_str(registered_query.transactions_filter.as_str())?; + let delegator = match &query_tx_filter[0].value { + TransactionFilterValue::String(s) => s.clone(), + _ => { + return Err(NeutronError::Std(StdError::generic_err( + "undelegations transaction filter value must be a String", + ))) + } + }; + + // the contract's side verification of submitted TX Interchain Query results part + let mut new_undelegations: Vec = vec![]; + for msg in body.messages.iter() { + // Narrow down the messages to only MsgUndelegate ones + if msg.type_url != STAKING_UNDELEGATE_MSG_URL { + continue; + } + // Narrow down the MsgUndelegate messages to only those that match the delegator address + let undelegate_msg = MsgUndelegate::decode(msg.value.as_slice())?; + if undelegate_msg.delegator_address != delegator { + continue; + } + + #[allow(clippy::unwrap_used)] + let undelegation_amount = undelegate_msg.amount.unwrap(); + new_undelegations.push(Coin { + denom: undelegation_amount.denom, + amount: Uint128::from_str(undelegation_amount.amount.as_str())?, + }); + } + + // Put your business logic here + // For this example we just preserve the new undelegations in the state + if !new_undelegations.is_empty() { + let mut undelegations = UNDELEGATED_AMOUNTS + .may_load(deps.storage, delegator.clone())? + .unwrap_or_default(); + undelegations.extend(new_undelegations); + UNDELEGATED_AMOUNTS.save(deps.storage, delegator, &undelegations)?; + } + + Ok(Response::default()) +} +``` +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_tx_icq/src/contract.rs#L115-L184) +
+ +#### 4. Perform Interchain Query registration + +Broadcast a [ExecuteMsg::RegisterUndelegationsQuery](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_tx_icq/src/msg.rs#L10-L14) message to the contract with required parameters. From a9995ab01bbebab77da3c60a5b8f50896baab25b Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Mon, 11 Nov 2024 18:41:43 +0300 Subject: [PATCH 17/32] update code links and polish KV and custom KV ICQ howtos --- .../modules/interchain-queries/how-to.md | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index ded687211..2e6b227c7 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -134,9 +134,9 @@ txs: **Might be interesting:** - [Configuring your own remote chain RPC node for TX ICQ usage](/neutron/modules/interchain-queries/explanation#configuring-your-own-remote-chain-rpc-node-for-tx-icq-usage) -## How to register an Interchain Query using neutron-sdk +## How to register and handle a KV Interchain Query -This section contains a step-by-step guide on how to register an Interchain Query using the [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk) library and handle the query results in a smart contract. +This section contains a brief guide on how to register a KV Interchain Query and handle the query results using [neutron-std](https://docs.rs/neutron-std/4.2.2-rc/neutron_std) and [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk) libraries in a smart contract. #### 1. Find the appropriate helper function in Neutron SDK @@ -198,7 +198,7 @@ pub fn register_balances_query( })) } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L47-L87) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L47-L87) #### 3. Define Interchain Query registration response handling @@ -238,7 +238,7 @@ pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { } } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L113-L138) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L100-L125) #### 4. Define Interchain Query results submission handling @@ -250,6 +250,15 @@ Get the submitted Interchain Query result from the `interchainqueries` module's ```rust use neutron_sdk::interchain_queries::v047::queries::query_balance; +use neutron_sdk::sudo::msg::SudoMsg; + +#[entry_point] +pub fn sudo(deps: DepsMut, env: Env, msg: SudoMsg) -> NeutronResult { + match msg { + SudoMsg::KVQueryResult { query_id } => sudo_kv_query_result(deps, env, query_id), + _ => Ok(Response::default()), + } +} /// The contract's callback for KV query results. Note that only the query id is provided, so you /// need to read the query result from the state. @@ -266,14 +275,14 @@ pub fn sudo_kv_query_result(deps: DepsMut, env: Env, query_id: u64) -> NeutronRe Ok(Response::default()) } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L140-L153) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L127-L148) #### 5. Perform Interchain Query registration -Broadcast a [ExecuteMsg::RegisterBalancesQuery](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_kv_icq/src/msg.rs#L10-L15) message to the contract with required parameters. +Broadcast a [ExecuteMsg::RegisterBalancesQuery](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_kv_icq/src/msg.rs#L10-L15) message to the contract with required parameters. -## How to register a KV Interchain Query with custom keys +## How to register and handle a KV Interchain Query with custom keys If your KV Interchain Query cannot be covered with the helpers from the [Interchain Queries related package](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) of [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk), you will need to define the KVKeys for your query yourself. For this particular example, let's register an [Account](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/proto/cosmos/auth/v1beta1/query.proto#L27-L31) Interchain Query to `cosmos-hub` `v21.0.0`. @@ -288,7 +297,7 @@ For this example, the information we require from the module's code is: #### 2. Define Interchain Query registration entry point -Implement an `execute` message handler in your contract that will process Interchain Query registration by broadcasting a [MsgRegisterInterchainQuery](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.MsgRegisterInterchainQuery.html) message as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/). Use the data path info found at the previous step as the parameters of the message. +Implement an `execute` message handler in your contract that will process Interchain Query registration by broadcasting a [MsgRegisterInterchainQuery](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.MsgRegisterInterchainQuery.html) message as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/). Use the data path info found at the previous step to parametrize the message.
Show code @@ -350,7 +359,7 @@ pub fn register_account_query( })) } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/contract.rs#L56-L102) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/contract.rs#L56-L102)
#### 3. Define Interchain Query registration response handling @@ -390,7 +399,7 @@ pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { } } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/contract.rs#L128-L153) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/contract.rs#L115-L140) #### 4. Implement reconstruction of the query result @@ -434,7 +443,7 @@ impl KVReconstruct for BaseAccount { } } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/types.rs#L10-L38) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/types.rs#L10-L38) #### 5. Define Interchain Query results submission handling @@ -445,9 +454,18 @@ Get the submitted Interchain Query result from the `interchainqueries` module's Show code ```rust +use neutron_sdk::sudo::msg::SudoMsg; use neutron_sdk::interchain_queries::queries::query_kv_result; use crate::types::BaseAccount; +#[entry_point] +pub fn sudo(deps: DepsMut, _env: Env, msg: SudoMsg) -> NeutronResult { + match msg { + SudoMsg::KVQueryResult { query_id } => sudo_kv_query_result(deps, query_id), + _ => Ok(Response::default()), + } +} + /// The contract's callback for KV query results. Note that only the query id is provided, so you /// need to read the query result from the state. pub fn sudo_kv_query_result(deps: DepsMut, query_id: u64) -> NeutronResult { @@ -464,12 +482,12 @@ pub fn sudo_kv_query_result(deps: DepsMut, query_id: u64) -> NeutronResult #### 6. Perform Interchain Query registration -Broadcast a [ExecuteMsg::RegisterAccountQuery](https://github.com/neutron-org/neutron-dev-contracts/blob/9918d0f03739af5acca954d80bb7bb468cd1b14c/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/msg.rs#L10-L14) message to the contract with required parameters. +Broadcast a [ExecuteMsg::RegisterAccountQuery](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/msg.rs#L10-L14) message to the contract with required parameters. ## How to register and handle a TX Interchain Query From 0dabdb713d72a5a6ebc28cc2936c5f31884d20fb Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Wed, 13 Nov 2024 12:52:39 +0300 Subject: [PATCH 18/32] add ToC and more Might be interesting links for ICQ docs --- .../neutron/modules/interchain-queries/api.md | 20 ++++++++--- .../modules/interchain-queries/explanation.md | 34 ++++++++++++++----- .../modules/interchain-queries/how-to.md | 20 +++++++++++ .../modules/interchain-queries/overview.md | 16 ++++++--- 4 files changed, 74 insertions(+), 16 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/api.md b/docs/neutron/modules/interchain-queries/api.md index 2a15f7a39..148efb18e 100644 --- a/docs/neutron/modules/interchain-queries/api.md +++ b/docs/neutron/modules/interchain-queries/api.md @@ -257,6 +257,9 @@ curl -X 'GET' \ ``` +**Might be interesting:** +-[What's the role of IBC connections in Interchain Queries and how to choose one?](/neutron/modules/interchain-queries/explanation#whats-the-role-of-ibc-connections-in-interchain-queries-and-how-to-choose-one) + ## Messages ### RegisterInterchainQuery @@ -275,10 +278,11 @@ Events emission on success: - other attributes with query parameters: `query_id`, `connection_id`, `owner`, `type`, `tx_filter`, `kv_key`. **Might be interesting:** -- [How to register an Interchain Query using neutron-sdk](/neutron/modules/interchain-queries/how-to#how-to-register-an-interchain-query-using-neutron-sdk) -- [How to register a KV Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-kv-interchain-query-with-custom-keys) -- [How to register a TX Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-tx-interchain-query-with-custom-keys) -- [Why is there a query creation deposit?](/neutron/modules/interchain-queries/how-to#why-is-there-a-query-creation-deposit) +- [How to choose the right IBC connection ID for an Interchain Query and verify it](/neutron/modules/interchain-queries/how-to#how-to-choose-the-right-ibc-connection-id-for-an-interchain-query-and-verify-it) +- [How to find out what transaction filter to use](/neutron/modules/interchain-queries/how-to#how-to-find-out-what-transaction-filter-to-use) +- [How to register and handle a KV Interchain Query](/neutron/modules/interchain-queries/how-to#how-to-register-and-handle-a-kv-interchain-query) +- [How to register and handle a TX Interchain Query](/neutron/modules/interchain-queries/how-to#how-to-register-and-handle-a-tx-interchain-query) +- [Why is there a query creation deposit?](/neutron/modules/interchain-queries/explanation#why-is-there-a-query-creation-deposit) - [Impossibility to retrieve and prove KV data with nil values](/neutron/modules/interchain-queries/known-bugs#impossibility-to-retrieve-and-prove-kv-data-with-nil-values) ### SubmitQueryResult @@ -289,6 +293,8 @@ Submits a result of an Interchain Query execution to the chain. This message han - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgSubmitQueryResultResponse) **Might be interesting:** +- [What are entry points and sudo calls?](/neutron/modules/interchain-queries/explanation#what-are-entry-points-and-sudo-calls) +- [Limited gas for sudo calls](/neutron/modules/interchain-queries/explanation#limited-gas-for-sudo-calls) - [What happens if a sudo callback to a smart contract owning an Interchain Query fails?](/neutron/modules/interchain-queries/explanation#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails) - [Impossibility to retrieve and prove KV data with nil values](/neutron/modules/interchain-queries/known-bugs#impossibility-to-retrieve-and-prove-kv-data-with-nil-values) @@ -307,6 +313,7 @@ Events emission on success: **Might be interesting:** - [What are the rules for creation deposit refund?](/neutron/modules/interchain-queries/explanation#what-are-the-rules-for-creation-deposit-refund) +- [How Interchain Query results are removed?](/neutron/modules/interchain-queries/explanation#how-interchain-query-results-are-removed) ### UpdateInterchainQuery @@ -343,7 +350,10 @@ Events emission on failure: **Might be interesting:** - [What are entry points and sudo calls?](/neutron/modules/interchain-queries/explanation#what-are-entry-points-and-sudo-calls) +- [Limited gas for sudo calls](/neutron/modules/interchain-queries/explanation#limited-gas-for-sudo-calls) - [What happens if a sudo callback to a smart contract owning an Interchain Query fails?](/neutron/modules/interchain-queries/explanation#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails) +- [Why is it mandatory to do contract's side verification of submitted TX Interchain Query results?](/neutron/modules/interchain-queries/explanation#why-is-it-mandatory-to-do-contracts-side-verification-of-submitted-tx-interchain-query-results) +- [Why doesn't interchainqueries module store TX query results?](/neutron/modules/interchain-queries/explanation#why-doesnt-interchainqueries-module-store-tx-query-results) ### MessageKvQueryResult @@ -360,4 +370,6 @@ Events emission on failure: **Might be interesting:** - [What are entry points and sudo calls?](/neutron/modules/interchain-queries/explanation#what-are-entry-points-and-sudo-calls) +- [Limited gas for sudo calls](/neutron/modules/interchain-queries/explanation#limited-gas-for-sudo-calls) - [What happens if a sudo callback to a smart contract owning an Interchain Query fails?](/neutron/modules/interchain-queries/explanation#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails) +- [Impossibility to retrieve and prove KV data with nil values](/neutron/modules/interchain-queries/known-bugs#impossibility-to-retrieve-and-prove-kv-data-with-nil-values) diff --git a/docs/neutron/modules/interchain-queries/explanation.md b/docs/neutron/modules/interchain-queries/explanation.md index 3642d8527..ecfe8d2b2 100644 --- a/docs/neutron/modules/interchain-queries/explanation.md +++ b/docs/neutron/modules/interchain-queries/explanation.md @@ -2,7 +2,7 @@ ## How do KV Interchain Queries work? -The meaning of a KV Interchain Query is to get a secured access to a remote chain's storage from a smart contract. Such a secured access is based on: +The meaning of a KV Interchain Query is to get a secure access to a remote chain's storage from a smart contract. Such a secure access is based on: - [IAVL tree](https://github.com/cosmos/iavl) which is used as data storage in Cosmos-SDK based blockchains. Each piece of data (value) is a leaf node in the tree having its unique data path (key); - [abci_query](https://docs.cometbft.com/v0.38/spec/rpc/#abciquery) RPC that exposes the storage (`IAVL tree`) read operations by a given path. @@ -12,18 +12,18 @@ A typical flow of KV Interchain Queries usage is as follows: 3. The developer writes and deploys a smart contract that contains Interchain Query registration logic and a callback for handling the query results; 4. The smart contract registers a KV Interchain Query with the set of keys to read. The registered Interchain Query is stored in the `interchainqueries` module's state; 5. An Interchain Query relayer reads the `interchainqueries` module's state, finds the registered query and its parameters, and does the `abci_query` RPC. The result of the call is a set of key-value pairs with proofs coming from the `IAVL tree`; -6. The Interchain Query relayer provides the key-value pairs and proofs to the `interchainqueries` module. This is as KV Interchain Query result submission operation. The module does the result verification against the proofs and passes the result to the smart contract; -7. The smart contract does arbitrary handling of the result; +6. The Interchain Query relayer provides the key-value pairs and proofs to the `interchainqueries` module. This is a KV Interchain Query result submission operation. The module does the result verification against the proofs, stores the result on chain, and notifies the owner smart contract about a fresh query result; +7. The smart contract reads the result from the module's storage and does arbitrary handling of the result; 8. Steps 5-7 are repeated periodically until the query is removed. **Might be interesting:** -- [How to register an Interchain Query using neutron-sdk](/neutron/modules/interchain-queries/how-to#how-to-register-an-interchain-query-using-neutron-sdk) -- [How to register a KV Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-kv-interchain-query-with-custom-keys) +- [How to register and handle a KV Interchain Query](/neutron/modules/interchain-queries/how-to#how-to-register-and-handle-a-kv-interchain-query) +- [How to register and handle a KV Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-and-handle-a-kv-interchain-query-with-custom-keys) - [What is an Interchain Query relayer?](/neutron/modules/interchain-queries/explanation#what-is-an-interchain-query-relayer) ## How do TX Interchain Queries work? -The meaning of a TX Interchain Query is to get a secured subscription on transactions happening on a remote chain from a smart contract. Such a subscription is based on: +The meaning of a TX Interchain Query is to get a secure subscription on transactions happening on a remote chain from a smart contract. Such a subscription is based on: - transaction execution [events](https://docs.cosmos.network/v0.50/learn/advanced/events) emission. In a word, events are structured logs of actions that take place within the blockchain; - [tx_search](https://docs.cometbft.com/v0.38/app-dev/indexing-transactions#querying-transactions-events) RPC. This RPC allows to search for transactions based on events they emit. @@ -38,8 +38,10 @@ A typical flow of TX Interchain Queries usage is as follows: 8. Steps 5-7 are repeated periodically until the query is removed. **Might be interesting:** -- [How to register an Interchain Query using neutron-sdk](/neutron/modules/interchain-queries/how-to#how-to-register-an-interchain-query-using-neutron-sdk) -- [How to register a TX Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-tx-interchain-query-with-custom-keys) +- [How to register and handle a TX Interchain Query](/neutron/modules/interchain-queries/how-to#how-to-register-and-handle-a-tx-interchain-query) +- [How to find out what transaction filter to use](/neutron/modules/interchain-queries/how-to#how-to-find-out-what-transaction-filter-to-use) +- [Why doesn't interchainqueries module store TX query results?](/neutron/modules/interchain-queries/explanation#why-doesnt-interchainqueries-module-store-tx-query-results) +- [Why is it mandatory to do contract's side verification of submitted TX Interchain Query results?](/neutron/modules/interchain-queries/explanation#why-is-it-mandatory-to-do-contracts-side-verification-of-submitted-tx-interchain-query-results) - [What is an Interchain Query relayer?](/neutron/modules/interchain-queries/explanation#what-is-an-interchain-query-relayer) ## What is an Interchain Query relayer? @@ -49,6 +51,9 @@ An Interchain Query relayer is an off-chain application that serves the needs of - Interchain Queries execution: reading of remote chain's state based on the parameters defined in the Interchain Query being executed, fidning proofs for the read data; - Query results submission: passing of the retrieved data and proofs to the `interchainqueries` module and, through that, to respective smart contracts. +**Might be interesting:** +- [Limited gas for sudo calls](/neutron/modules/interchain-queries/explanation#limited-gas-for-sudo-calls) + ## What's the role of IBC connections in Interchain Queries and how to choose one? IBC [clients](https://ibc.cosmos.network/v8/ibc/overview/#clients) and [connections](https://ibc.cosmos.network/v8/ibc/overview/#connections) play significant role in Interchain Queries authenticity. It is the initialisation of an IBC connection that is responsible for IBC clients creation and verification that their states are correct for their respective counterparties, and it is the states of the IBC clients of an IBC connection that is responsible for Interchain Query results verification. One must choose the connection ID for their Interchain Queries wisely for it will define the trustworthiness of the whole Interchain Queries based application. @@ -87,6 +92,9 @@ The permissions to execute [RemoveInterchainQuery](/neutron/modules/interchain-q `beyond_service_period = current_height > query.last_submitted_result_local_height + params.query_submit_timeout && current_height > query.registered_at_height + params.query_submit_timeout` +**Might be interesting:** +- [How Interchain Query results are removed?](/neutron/modules/interchain-queries/explanation#how-interchain-query-results-are-removed) + ## Why is it mandatory to do contract's side verification of submitted TX Interchain Query results? One important thing to keep in mind regarding Interchain Queries is that result submissions are permissionless. This means that anyone — not just your designated relayer — can submit the results of the Interchain Queries that your contract registered to the `interchainqueries` module. @@ -97,6 +105,10 @@ Because of this limitation, it's essential to implement additional checks in you Without these checks, a malicious relayer could submit a fully valid Tendermint transaction that doesn't meet your defined transaction filters, potentially compromising your business logic. For the example above, if you don't check the delegator address, anyone's Undelegate transactions will pass. +**Might be interesting:** +- [How to find out what transaction filter to use](/neutron/modules/interchain-queries/how-to#how-to-find-out-what-transaction-filter-to-use) +- [How to register and handle a TX Interchain Query](/neutron/modules/interchain-queries/how-to#how-to-register-and-handle-a-tx-interchain-query) + ## Why is the Proof field nullified in QueryResult RPC response? The `interchainqueries` module only needs KV proofs during the submission process to verify the values being submitted against the proofs. If save them afterwards, they'll just increase chain's space without any reasonable further usage. The KV results saved on chain can be trusted as cryptographically proved because they are verified at the very beginning — by the module at the submission step. @@ -109,6 +121,9 @@ If compare to the KV Interchain Queries which have the last result stored on cha - hashes of transactions that have been successfully processed by the owner smart contract to avoid multiple processing of the same transactions, and - [failures appeared during sudo calls](#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails). +**Might be interesting:** +- [How to register and handle a TX Interchain Query](/neutron/modules/interchain-queries/how-to#how-to-register-and-handle-a-tx-interchain-query) + ## What are entry points and sudo calls? [Entry points](https://docs.cosmwasm.com/core/entrypoints) are where your contract can be called from the outside world. [Sudo](https://docs.cosmwasm.com/core/entrypoints/sudo) calls are messages issued by the chain itself. They are routed to a special `sudo` `entry_point` which can only be accessed by the chain. @@ -119,6 +134,9 @@ The `interchainqueries` module uses the [contractmanager](/neutron/modules/contr It is recommended by the `contractmanager` module to separate `sudo` callback and computations to different handlers in case the computations go beyond the allocated gas. For example, one can store `sudo` callback payload in the contract's state, and then read it and handle during an additional outer `execute` call to the contract. +**Might be interesting:** +- [What are entry points and sudo calls?](/neutron/modules/interchain-queries/explanation#what-are-entry-points-and-sudo-calls) + ## What happens if a sudo callback to a smart contract owning an Interchain Query fails? In this case, the `interchainqueries` module will store the failure in the [contractmanager](/neutron/modules/contract-manager/overview) module with all information about the query and a redacted (shortened to codespace and error code) error message. A full error message is emitted as an [event](https://docs.cosmos.network/v0.50/learn/advanced/events) on a failure (see the [message events emission](/neutron/modules/interchain-queries/api#sudo) for details). Note that the `out of gas` errors are stored as failures, too. Failed query result submissions can be read from the `contractmanager` module and resubmitted to the `interchainqueries` module. More info about the read and resubmit operations by the link to the [contractmanager](/neutron/modules/contract-manager/overview) module documentation. diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index 2e6b227c7..a24047504 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -79,6 +79,9 @@ client_state: ``` +**Might be interesting:** +- [What's the role of IBC connections in Interchain Queries and how to choose one?](/neutron/modules/interchain-queries/explanation#whats-the-role-of-ibc-connections-in-interchain-queries-and-how-to-choose-one) + ## How to find out what transaction filter to use Let's imagine that we need our Interchain Query based smart contract to know about undelegations done by `cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp` on CosmosHub. @@ -132,6 +135,7 @@ txs: **Might be interesting:** +- [How do TX Interchain Queries work?](/neutron/modules/interchain-queries/explanation#how-do-tx-interchain-queries-work) - [Configuring your own remote chain RPC node for TX ICQ usage](/neutron/modules/interchain-queries/explanation#configuring-your-own-remote-chain-rpc-node-for-tx-icq-usage) ## How to register and handle a KV Interchain Query @@ -282,6 +286,11 @@ pub fn sudo_kv_query_result(deps: DepsMut, env: Env, query_id: u64) -> NeutronRe Broadcast a [ExecuteMsg::RegisterBalancesQuery](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_kv_icq/src/msg.rs#L10-L15) message to the contract with required parameters. +**Might be interesting:** +- [What are entry points and sudo calls?](/neutron/modules/interchain-queries/explanation#what-are-entry-points-and-sudo-calls) +- [Limited gas for sudo calls](/neutron/modules/interchain-queries/explanation#limited-gas-for-sudo-calls) +- [What happens if a sudo callback to a smart contract owning an Interchain Query fails?](/neutron/modules/interchain-queries/explanation#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails) + ## How to register and handle a KV Interchain Query with custom keys If your KV Interchain Query cannot be covered with the helpers from the [Interchain Queries related package](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) of [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk), you will need to define the KVKeys for your query yourself. For this particular example, let's register an [Account](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/proto/cosmos/auth/v1beta1/query.proto#L27-L31) Interchain Query to `cosmos-hub` `v21.0.0`. @@ -489,6 +498,11 @@ pub fn sudo_kv_query_result(deps: DepsMut, query_id: u64) -> NeutronResult Date: Wed, 13 Nov 2024 13:45:07 +0300 Subject: [PATCH 19/32] fox links to ICQ module --- docs/relaying/icq-relayer.md | 6 +++--- docs/tutorials/cosmwasm_icq.md | 7 +++---- .../neutron/modules/interchain-queries/messages.md | 8 ++++---- versioned_docs/version-1.0/relaying/icq-relayer.md | 8 ++++---- versioned_docs/version-1.0/tutorials/cosmwasm-icq.md | 6 +++--- .../neutron/modules/interchain-queries/messages.md | 10 +++++----- versioned_docs/version-2.0/relaying/icq-relayer.md | 8 ++++---- versioned_docs/version-2.0/tutorials/cosmwasm_icq.md | 6 +++--- .../neutron/modules/interchain-queries/messages.md | 10 +++++----- versioned_docs/version-3.0/relaying/icq-relayer.md | 8 ++++---- versioned_docs/version-3.0/tutorials/cosmwasm_icq.md | 6 +++--- 11 files changed, 41 insertions(+), 42 deletions(-) diff --git a/docs/relaying/icq-relayer.md b/docs/relaying/icq-relayer.md index 91bb56d6b..fb69ff953 100644 --- a/docs/relaying/icq-relayer.md +++ b/docs/relaying/icq-relayer.md @@ -8,11 +8,11 @@ If you are a smart contracts developer and up to develop your dApp on Neutron, y ### Queries gathering -All registered Interchain Queries and their parameters are stored in the eponymous module and available by its [query interface](/neutron/modules/interchain-queries/client#queries). The Relayer utilises the module's interface in order to initialise the performing list of queries. This is how the Relayer maintains the list of queries to be executed: +All registered Interchain Queries and their parameters are stored in the eponymous module and available by its [query interface](/neutron/modules/interchain-queries/api#registeredqueries). The Relayer utilises the module's interface in order to initialise the performing list of queries. This is how the Relayer maintains the list of queries to be executed: - on initialisation, the ICQ module `RegisteredQueries` query is executed with the `RELAYER_REGISTRY_ADDRESSES` parameter used for the `Owners` field; - then the parameter `RELAYER_REGISTRY_QUERY_IDS` will be used to filter out queries if it is not empty; -- during the rest of the run, the Relayer listens to the ICQ module's `query_update` and `query_removed` [events](/neutron/modules/interchain-queries/events) and modifies the queries list and parameters correspondingly. +- during the rest of the run, the Relayer listens to the ICQ module's events emitted on [RegisterInterchainQuery](/neutron/modules/interchain-queries/api#registerinterchainquery), [UpdateInterchainQuery](/neutron/modules/interchain-queries/api#updateinterchainquery), and [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery), and modifies the queries list and parameters correspondingly. The Relayer also listens to the Neutron's `NewBlockHeader` events that are used as a trigger for queries execution. Since each query has its own `update_period`, the Relayer tracks queries execution height and executes only the queries which update time has come. @@ -23,7 +23,7 @@ When the update time comes for a query, the Relayer runs the specified query on necessary KV-keys from the remote chain's storage with [Merkle Proofs](https://github.com/cosmos/cosmos-sdk/blob/ae77f0080a724b159233bd9b289b2e91c0de21b5/docs/interfaces/lite/specification.md). Neutron will need these proofs to [verify](https://github.com/neutron-org/neutron/blob/v4.2.4/x/interchainqueries/keeper/msg_server.go#L251) validity of KV-results on results submission; * in case of a TX-query, the Relayer makes a query to the target chain's [Tendermint RPC](https://docs.tendermint.com/v0.33/app-dev/indexing-transactions.html#querying-transactions) to search transactions by message types, events and attributes which were emitted during transactions execution and were -[indexed](https://docs.tendermint.com/v0.33/app-dev/indexing-transactions.html) by Tendermint. More about Tx query parameters syntax [in the dedicated section](/neutron/modules/interchain-queries/messages#register-interchain-query). When Relayer submits transactions search results to Neutron chain, it **DOES NOT** include events into result (even if events were used for the query), because [events are not deterministic](https://github.com/tendermint/tendermint/blob/bff63aec83a4cfbb3bba253cfa04737fb21dacb4/types/results.go#L47), therefore they can break blockchain consensus. One more important thing about TX queries is that the Relayer is made the way it only searches for and submits transactions within the trusting period of the Tendermint Light Client. Trusting period is usually calculated as `2/3 * unbonding_period`. Read more about Tendermint Light Client and trusted periods [at this post](https://blog.cosmos.network/light-clients-in-tendermint-consensus-1237cfbda104). +[indexed](https://docs.tendermint.com/v0.33/app-dev/indexing-transactions.html) by Tendermint. More about Tx query parameters syntax [in the dedicated section](/neutron/modules/interchain-queries/explanation#how-do-tx-interchain-queries-work). When Relayer submits transactions search results to Neutron chain, it **DOES NOT** include events into result (even if events were used for the query), because [events are not deterministic](https://github.com/tendermint/tendermint/blob/bff63aec83a4cfbb3bba253cfa04737fb21dacb4/types/results.go#L47), therefore they can break blockchain consensus. One more important thing about TX queries is that the Relayer is made the way it only searches for and submits transactions within the trusting period of the Tendermint Light Client. Trusting period is usually calculated as `2/3 * unbonding_period`. Read more about Tendermint Light Client and trusted periods [at this post](https://blog.cosmos.network/light-clients-in-tendermint-consensus-1237cfbda104). ### Results submission diff --git a/docs/tutorials/cosmwasm_icq.md b/docs/tutorials/cosmwasm_icq.md index dc010be27..19c5b66bb 100644 --- a/docs/tutorials/cosmwasm_icq.md +++ b/docs/tutorials/cosmwasm_icq.md @@ -15,7 +15,7 @@ We are going to learn how to: > contracts. You can check out CosmWasm [docs](https://docs.cosmwasm.com/docs) > and [blog posts](https://medium.com/cosmwasm/writing-a-cosmwasm-contract-8fb946c3a516) for entry-level tutorials. -> **Note:** before running any query creation transaction you need to top up your contract address. See [Interchain Queries Overview](../neutron/modules/interchain-queries/overview.md), "Query creation deposit" section. +> **Note:** before running any query creation transaction you need to top up your contract address in order to pay for the [query creation deposit](/neutron/modules/interchain-queries/explanation#why-is-there-a-query-creation-deposit). ## The complete example @@ -204,8 +204,7 @@ fn write_balance_query_id_to_reply_id(deps: DepsMut, reply: Reply) -> StdResult< } ``` -> **Note:** the ICQ module's `RegisterInterchainQueryMsg` message [returns](/neutron/modules/interchain-queries/messages#register-interchain-query) -> an identifier of newly registered Interchain Query in response. So in a real world scenario you should implement a `reply` handler in your contract +> **Note:** the ICQ module's [RegisterInterchainQueryMsg](/neutron/modules/interchain-queries/api#registerinterchainquery) message returns an identifier of newly registered Interchain Query in response. So in a real world scenario you should implement a `reply` handler in your contract > to catch the identifier after the registration, so you'll be able to work with the registered query later. In the snippet above, we create the `ExecuteMsg` enum that contains two `Register` messages for two different queries: @@ -575,7 +574,7 @@ pub fn remove_interchain_query(query_id: u64) -> NeutronResult contracts. You can check out CosmWasm [docs](https://docs.cosmwasm.com/docs) > and [blog posts](https://medium.com/cosmwasm/writing-a-cosmwasm-contract-8fb946c3a516) for entry-level tutorials. -> **Note:** before running any query creation transaction you need to top up your contract address. See [Interchain Queries Overview](../neutron/modules/interchain-queries/overview.md), "Query creation deposit" section. +> **Note:** before running any query creation transaction you need to top up your contract address. See [Interchain Queries Overview](/1.0/neutron/modules/interchain-queries/overview), "Query creation deposit" section. ## The complete example @@ -159,7 +159,7 @@ pub fn register_transfers_query( } ``` -> **Note:** the ICQ module's `RegisterInterchainQueryMsg` message [returns](/neutron/modules/interchain-queries/messages#register-interchain-query) +> **Note:** the ICQ module's `RegisterInterchainQueryMsg` message [returns](/1.0/neutron/modules/interchain-queries/messages#register-interchain-query) > an identifier of newly registered Interchain Query in response. So in a real world scenario you should implement a `reply` handler in your contract > to catch the identifier after the registration, so you'll be able to work with the registered query later. @@ -504,5 +504,5 @@ pub fn remove_interchain_query(query_id: u64) -> NeutronResult contracts. You can check out CosmWasm [docs](https://docs.cosmwasm.com/docs) > and [blog posts](https://medium.com/cosmwasm/writing-a-cosmwasm-contract-8fb946c3a516) for entry-level tutorials. -> **Note:** before running any query creation transaction you need to top up your contract address. See [Interchain Queries Overview](../neutron/modules/interchain-queries/overview.md), "Query creation deposit" section. +> **Note:** before running any query creation transaction you need to top up your contract address. See [Interchain Queries Overview](/2.0/neutron/modules/interchain-queries/overview), "Query creation deposit" section. ## The complete example @@ -204,7 +204,7 @@ fn write_balance_query_id_to_reply_id(deps: DepsMut, reply: Reply) -> StdResult< } ``` -> **Note:** the ICQ module's `RegisterInterchainQueryMsg` message [returns](/neutron/modules/interchain-queries/messages#register-interchain-query) +> **Note:** the ICQ module's `RegisterInterchainQueryMsg` message [returns](/2.0/neutron/modules/interchain-queries/messages#register-interchain-query) > an identifier of newly registered Interchain Query in response. So in a real world scenario you should implement a `reply` handler in your contract > to catch the identifier after the registration, so you'll be able to work with the registered query later. @@ -575,7 +575,7 @@ pub fn remove_interchain_query(query_id: u64) -> NeutronResult contracts. You can check out CosmWasm [docs](https://docs.cosmwasm.com/docs) > and [blog posts](https://medium.com/cosmwasm/writing-a-cosmwasm-contract-8fb946c3a516) for entry-level tutorials. -> **Note:** before running any query creation transaction you need to top up your contract address. See [Interchain Queries Overview](../neutron/modules/interchain-queries/overview.md), "Query creation deposit" section. +> **Note:** before running any query creation transaction you need to top up your contract address. See [Interchain Queries Overview](/3.0/neutron/modules/interchain-queries/overview), "Query creation deposit" section. ## The complete example @@ -204,7 +204,7 @@ fn write_balance_query_id_to_reply_id(deps: DepsMut, reply: Reply) -> StdResult< } ``` -> **Note:** the ICQ module's `RegisterInterchainQueryMsg` message [returns](/neutron/modules/interchain-queries/messages#register-interchain-query) +> **Note:** the ICQ module's `RegisterInterchainQueryMsg` message [returns](/3.0/neutron/modules/interchain-queries/messages#register-interchain-query) > an identifier of newly registered Interchain Query in response. So in a real world scenario you should implement a `reply` handler in your contract > to catch the identifier after the registration, so you'll be able to work with the registered query later. @@ -575,7 +575,7 @@ pub fn remove_interchain_query(query_id: u64) -> NeutronResult Date: Thu, 14 Nov 2024 13:28:42 +0300 Subject: [PATCH 20/32] update msg type names --- docs/neutron/modules/interchain-queries/api.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/api.md b/docs/neutron/modules/interchain-queries/api.md index 148efb18e..04f6d26b2 100644 --- a/docs/neutron/modules/interchain-queries/api.md +++ b/docs/neutron/modules/interchain-queries/api.md @@ -268,7 +268,7 @@ Registers a new Interchain Query in the `interchainqueries` module. This message Returns an ID assigned to the registered query. Handle this message response via a reply handler in order to make use of the ID. -- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgRegisterInterchainQueryRequest) +- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgRegisterInterchainQuery) - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgRegisterInterchainQueryResponse) Events emission on success: @@ -289,7 +289,7 @@ Events emission on success: Submits a result of an Interchain Query execution to the chain. This message handling may include passing of the result to the query's owner smart contract for processing which might be a pretty gas-consumable operation. -- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgSubmitQueryResultRequest) +- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgSubmitQueryResult) - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgSubmitQueryResultResponse) **Might be interesting:** @@ -302,7 +302,7 @@ Submits a result of an Interchain Query execution to the chain. This message han Removes a given Interchain Query and its results from the module. Can be removed only by the owner of the query during the query's submit timeout, and by anyone after the query has been timed out. The query deposit is returned to the caller on a success call. -- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgRemoveInterchainQueryRequest) +- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgRemoveInterchainQuery) - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgRemoveInterchainQueryResponse) Events emission on success: @@ -319,7 +319,7 @@ Events emission on success: Updates parameters of a registered Interchain Query. Only callable by the owner of the query. -- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgUpdateInterchainQueryRequest) +- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgUpdateInterchainQuery) - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgUpdateInterchainQueryResponse) Events emission on success: @@ -332,7 +332,7 @@ Events emission on success: Updates params of the interchainqueries module. Only callable by the module's authority. -- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgUpdateParamsRequest) +- [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgUpdateParams) - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgUpdateParamsResponse) ## Sudo From 0ec51b7369ce26010fc4195285ab07ad6baeeb2e Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Thu, 14 Nov 2024 14:07:46 +0300 Subject: [PATCH 21/32] update example of ICQ module params --- docs/neutron/modules/interchain-queries/api.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/neutron/modules/interchain-queries/api.md b/docs/neutron/modules/interchain-queries/api.md index 04f6d26b2..d495fc57a 100644 --- a/docs/neutron/modules/interchain-queries/api.md +++ b/docs/neutron/modules/interchain-queries/api.md @@ -57,7 +57,9 @@ curl -X 'GET' \ "amount": "1000000" } ], - "tx_query_removal_limit": "10000" + "tx_query_removal_limit": "10000", + "max_kv_query_keys_count": "32", + "max_transactions_filters": "32" } } ``` From 4cfc02696ef58a94856a51b32d6d8282c74caa4e Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Thu, 14 Nov 2024 14:08:19 +0300 Subject: [PATCH 22/32] minor fixes to ICQ module docs --- docs/neutron/modules/interchain-queries/explanation.md | 2 +- docs/neutron/modules/interchain-queries/how-to.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/explanation.md b/docs/neutron/modules/interchain-queries/explanation.md index ecfe8d2b2..033101133 100644 --- a/docs/neutron/modules/interchain-queries/explanation.md +++ b/docs/neutron/modules/interchain-queries/explanation.md @@ -64,7 +64,7 @@ There are two options how to find an IBC connection ID for one's needs: ## Why is there a query creation deposit? -In order to clean up ledger from not used, outdated queries, a special deposit mechanism is used. [RegisterInterchainQuery](/neutron/modules/interchain-queries/api#registerinterchainquery) message contains the `deposit` field which is used to collect escrow payment for query creation. In order to return escrow payment, a [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery) message should be issued. +In order to clean up ledger from not used, outdated queries, a special deposit mechanism is used. When a contract issues a [RegisterInterchainQuery](/neutron/modules/interchain-queries/api#registerinterchainquery) message, the deposit is charged from the contract's balance as escrow payment for query creation. In order to return escrow payment, the query should be removed by issuing a [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery) message. The required amount of coins to deposit is defined by the `query_deposit` [module parameter](/neutron/modules/interchain-queries/api#params). diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index a24047504..13dca7ebf 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -91,12 +91,12 @@ Let's imagine that we need our Interchain Query based smart contract to know abo Find out what is the current version of the `staking` module (imported from `cosmos-sdk`) CosmosHub runs and go to the module's source code: 1. Find the git repository and currently running version of CosmosHub in the [chain registry](https://github.com/cosmos/chain-registry/blob/e346b6dbc0d901eec5e8704e0a7736bfdaa3dca9/cosmoshub/chain.json#L36-L37) (use the main branch to get the up-to-date info) — `v19.2.0`; -2. Find the [cosmos-sdk](https://github.com/cosmos/gaia/blob/v19.1.0/go.mod#L24) import in the `go.mod` file of the `gaia` repository of `v19.2.0` — `v0.50.9`; +2. Find the [cosmos-sdk](https://github.com/cosmos/gaia/blob/v19.2.0/go.mod#L24) import in the `go.mod` file of the `gaia` repository of `v19.2.0` — `v0.50.9`; 3. Open the `staking` module's source code in [cosmos-sdk with tag v0.50.9](https://github.com/cosmos/cosmos-sdk/tree/v0.50.9/x/staking). #### 2. Find the handler that manages undelegations -Find the [Undelegate](https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L391-L392) entry point of the `staking` module's keeper. +Find the [Undelegate](https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L391-L392) handler of the `staking` module's keeper. #### 3. Find the events emitted on undelegations @@ -147,7 +147,7 @@ This section contains a brief guide on how to register a KV Interchain Query and Find the register Interchain Query helper function that your needs require in the [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) repository. For this particular example, let's choose the [new_register_balances_query_msg](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/fn.new_register_balances_query_msg.html) function. :::note Couldn't find the required helper function? -If there is no predefined helper function suitable for your needs in [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk), proceed to the [How to register a KV Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-a-kv-interchain-query-with-custom-keys) section. +If there is no predefined helper function suitable for your needs in [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk), proceed to the [How to register a KV Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-and-handle-a-kv-interchain-query-with-custom-keys) section. ::: #### 2. Define Interchain Query registration entry point @@ -509,7 +509,7 @@ This section contains a brief guide on how to register a TX Interchain Query and #### 1. Find out what transaction filter to use -Figure out the appropriate [tx_search](https://docs.cometbft.com/v0.38/app-dev/indexing-transactions#querying-transactions-events) query that would match transactions you need to process. This is described in the [How to find out what transaction filter to use](/neutron/modules/interchain-queries/how-to#how-to-find-out-what-transaction-filter-to-use) section. +Figure out the appropriate [tx_search](https://docs.cometbft.com/v0.38/app-dev/indexing-transactions#querying-transactions-events) query that would match transactions you need to process. This is described in the [How to find out what transaction filter to use](/neutron/modules/interchain-queries/how-to#how-to-find-out-what-transaction-filter-to-use) section. In this example we will use the same transaction filter as described by the link. #### 2. Define Interchain Query registration entry point From 9983744b1372b842840ce132270cf525cc66f3f2 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Thu, 14 Nov 2024 15:22:29 +0300 Subject: [PATCH 23/32] fix links to ICQ module for v4.0 --- .../neutron/modules/interchain-queries/messages.md | 10 +++++----- versioned_docs/version-4.0/relaying/icq-relayer.md | 8 ++++---- versioned_docs/version-4.0/tutorials/cosmwasm_icq.md | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/versioned_docs/version-4.0/neutron/modules/interchain-queries/messages.md b/versioned_docs/version-4.0/neutron/modules/interchain-queries/messages.md index 397f515bb..fb25ca329 100644 --- a/versioned_docs/version-4.0/neutron/modules/interchain-queries/messages.md +++ b/versioned_docs/version-4.0/neutron/modules/interchain-queries/messages.md @@ -39,7 +39,7 @@ message KVKey { Currently `query_type` can take the following values: * `kv` - query **values** from Cosmos-SDK KV-storage on remote chain which are stored under some **keys**. In this case `kv_keys` must be filled in. -* `tx` - query to search for transactions on remote chain. `transactions_filter` describes a filter by which the [ICQ relayer](/relaying/icq-relayer) will perform the transactions search. [The transaction filter is described in more detail in the overview](/neutron/modules/interchain-queries/overview): +* `tx` - query to search for transactions on remote chain. `transactions_filter` describes a filter by which the [ICQ relayer](/relaying/icq-relayer) will perform the transactions search. [The transaction filter is described in more detail in the overview](/4.0/neutron/modules/interchain-queries/overview): `MsgRegisterInterchainQuery` returns [`MsgRegisterInterchainQueryResponse`](https://github.com/neutron-org/neutron/blob/v2.0.3/proto/interchainqueries/tx.proto#L44) where `id` is unique identifier of newly registered interchain query on success: ```protobuf @@ -54,7 +54,7 @@ message MsgRegisterInterchainQueryResponse { * save the record in storage under incremented query id; #### Events -Emits [`EventTypeNeutonMessage`](/neutron/modules/interchain-queries/events#eventtypeneutronmessage) with `action` equals `query_updated`. +Emits [`EventTypeNeutonMessage`](/4.0/neutron/modules/interchain-queries/events#eventtypeneutronmessage) with `action` equals `query_updated`. ### Update Interchain Query @@ -81,12 +81,12 @@ message MsgUpdateInterchainQueryResponse { * [Updates](https://github.com/neutron-org/neutron/blob/v2.0.3/x/interchainqueries/keeper/msg_server.go#L144) a corresponding `RegisteredQuery` structure. #### Events -Emits [`EventTypeNeutonMessage`](/neutron/modules/interchain-queries/events#eventtypeneutronmessage) with `action` equals `query_updated`. +Emits [`EventTypeNeutonMessage`](/4.0/neutron/modules/interchain-queries/events#eventtypeneutronmessage) with `action` equals `query_updated`. ### Remove Interchain Query -[`MsgRemoveInterchainQueryRequest`](https://github.com/neutron-org/neutron/blob/v2.0.3/proto/interchainqueries/tx.proto#L108) can be submitted only by the owner of corresponding Interchain Query within the query's service period or by anyone beyond it. Read more about this message permissions [here](/neutron/modules/interchain-queries/overview#query-creation-deposit). +[`MsgRemoveInterchainQueryRequest`](https://github.com/neutron-org/neutron/blob/v2.0.3/proto/interchainqueries/tx.proto#L108) can be submitted only by the owner of corresponding Interchain Query within the query's service period or by anyone beyond it. Read more about this message permissions [here](/4.0/neutron/modules/interchain-queries/overview#query-creation-deposit). ```protobuf message MsgRemoveInterchainQueryRequest { uint64 query_id = 1; @@ -105,7 +105,7 @@ message MsgRemoveInterchainQueryResponse { * Also removes the query results ([immediately](https://github.com/neutron-org/neutron/blob/v2.0.3/x/interchainqueries/keeper/keeper.go#L144) for a KV query, [deferred in the ICQ module EndBlock](https://github.com/neutron-org/neutron/blob/v2.0.3/x/interchainqueries/module.go#L176) for a TX query). #### Events -Emits [`EventTypeNeutonMessage`](/neutron/modules/interchain-queries/events#eventtypeneutronmessage) with `action` equals `query_removed`. +Emits [`EventTypeNeutonMessage`](/4.0/neutron/modules/interchain-queries/events#eventtypeneutronmessage) with `action` equals `query_removed`. ### Submit Query Result diff --git a/versioned_docs/version-4.0/relaying/icq-relayer.md b/versioned_docs/version-4.0/relaying/icq-relayer.md index 7d8473f9e..bc49b429a 100644 --- a/versioned_docs/version-4.0/relaying/icq-relayer.md +++ b/versioned_docs/version-4.0/relaying/icq-relayer.md @@ -2,17 +2,17 @@ ## Overview -[Interchain Queries](/neutron/modules/interchain-queries/overview) allow smart contracts to make queries to a remote chain. An ICQ Relayer is a required component for making them possible. It acts as a facilitator between the Neutron chain and a querying chain, gathering queries that are needed to be performed from the Neutron, actually performing them, and eventually making the results available for the Neutron's smart contracts. These three main responsibilities are described in details below. +[Interchain Queries](/4.0/neutron/modules/interchain-queries/overview) allow smart contracts to make queries to a remote chain. An ICQ Relayer is a required component for making them possible. It acts as a facilitator between the Neutron chain and a querying chain, gathering queries that are needed to be performed from the Neutron, actually performing them, and eventually making the results available for the Neutron's smart contracts. These three main responsibilities are described in details below. If you are a smart contracts developer and up to develop your dApp on Neutron, you will most likely need your own ICQ Relayer to manage your Interchain Queries. ### Queries gathering -All registered Interchain Queries and their parameters are stored in the eponymous module and available by its [query interface](/neutron/modules/interchain-queries/client#queries). The Relayer utilises the module's interface in order to initialise the performing list of queries. This is how the Relayer maintains the list of queries to be executed: +All registered Interchain Queries and their parameters are stored in the eponymous module and available by its [query interface](/4.0/neutron/modules/interchain-queries/client#queries). The Relayer utilises the module's interface in order to initialise the performing list of queries. This is how the Relayer maintains the list of queries to be executed: - on initialisation, the ICQ module `RegisteredQueries` query is executed with the `RELAYER_REGISTRY_ADDRESSES` parameter used for the `Owners` field; - then the parameter `RELAYER_REGISTRY_QUERY_IDS` will be used to filter out queries if it is not empty; -- during the rest of the run, the Relayer listens to the ICQ module's `query_update` and `query_removed` [events](/neutron/modules/interchain-queries/events) and modifies the queries list and parameters correspondingly. +- during the rest of the run, the Relayer listens to the ICQ module's `query_update` and `query_removed` [events](/4.0/neutron/modules/interchain-queries/events) and modifies the queries list and parameters correspondingly. The Relayer also listens to the Neutron's `NewBlockHeader` events that are used as a trigger for queries execution. Since each query has its own `update_period`, the Relayer tracks queries execution height and executes only the queries which update time has come. @@ -23,7 +23,7 @@ When the update time comes for a query, the Relayer runs the specified query on necessary KV-keys from the remote chain's storage with [Merkle Proofs](https://github.com/cosmos/cosmos-sdk/blob/ae77f0080a724b159233bd9b289b2e91c0de21b5/docs/interfaces/lite/specification.md). Neutron will need these proofs to [verify](https://github.com/neutron-org/neutron/blob/v2.0.3/x/interchainqueries/keeper/msg_server.go#L228) validity of KV-results on results submission; * in case of a TX-query, the Relayer makes a query to the target chain's [Tendermint RPC](https://docs.tendermint.com/v0.33/app-dev/indexing-transactions.html#querying-transactions) to search transactions by message types, events and attributes which were emitted during transactions execution and were -[indexed](https://docs.tendermint.com/v0.33/app-dev/indexing-transactions.html) by Tendermint. More about Tx query parameters syntax [in the dedicated section](/neutron/modules/interchain-queries/messages#register-interchain-query). When Relayer submits transactions search results to Neutron chain, it **DOES NOT** include events into result (even if events were used for the query), because [events are not deterministic](https://github.com/tendermint/tendermint/blob/bff63aec83a4cfbb3bba253cfa04737fb21dacb4/types/results.go#L47), therefore they can break blockchain consensus. One more important thing about TX queries is that the Relayer is made the way it only searches for and submits transactions within the trusting period of the Tendermint Light Client. Trusting period is usually calculated as `2/3 * unbonding_period`. Read more about Tendermint Light Client and trusted periods [at this post](https://blog.cosmos.network/light-clients-in-tendermint-consensus-1237cfbda104). +[indexed](https://docs.tendermint.com/v0.33/app-dev/indexing-transactions.html) by Tendermint. More about Tx query parameters syntax [in the dedicated section](/4.0/neutron/modules/interchain-queries/messages#register-interchain-query). When Relayer submits transactions search results to Neutron chain, it **DOES NOT** include events into result (even if events were used for the query), because [events are not deterministic](https://github.com/tendermint/tendermint/blob/bff63aec83a4cfbb3bba253cfa04737fb21dacb4/types/results.go#L47), therefore they can break blockchain consensus. One more important thing about TX queries is that the Relayer is made the way it only searches for and submits transactions within the trusting period of the Tendermint Light Client. Trusting period is usually calculated as `2/3 * unbonding_period`. Read more about Tendermint Light Client and trusted periods [at this post](https://blog.cosmos.network/light-clients-in-tendermint-consensus-1237cfbda104). ### Results submission diff --git a/versioned_docs/version-4.0/tutorials/cosmwasm_icq.md b/versioned_docs/version-4.0/tutorials/cosmwasm_icq.md index dc010be27..cc19bbd76 100644 --- a/versioned_docs/version-4.0/tutorials/cosmwasm_icq.md +++ b/versioned_docs/version-4.0/tutorials/cosmwasm_icq.md @@ -15,7 +15,7 @@ We are going to learn how to: > contracts. You can check out CosmWasm [docs](https://docs.cosmwasm.com/docs) > and [blog posts](https://medium.com/cosmwasm/writing-a-cosmwasm-contract-8fb946c3a516) for entry-level tutorials. -> **Note:** before running any query creation transaction you need to top up your contract address. See [Interchain Queries Overview](../neutron/modules/interchain-queries/overview.md), "Query creation deposit" section. +> **Note:** before running any query creation transaction you need to top up your contract address. See [Interchain Queries Overview](/4.0/neutron/modules/interchain-queries/overview), "Query creation deposit" section. ## The complete example @@ -204,7 +204,7 @@ fn write_balance_query_id_to_reply_id(deps: DepsMut, reply: Reply) -> StdResult< } ``` -> **Note:** the ICQ module's `RegisterInterchainQueryMsg` message [returns](/neutron/modules/interchain-queries/messages#register-interchain-query) +> **Note:** the ICQ module's `RegisterInterchainQueryMsg` message [returns](/4.0/neutron/modules/interchain-queries/messages#register-interchain-query) > an identifier of newly registered Interchain Query in response. So in a real world scenario you should implement a `reply` handler in your contract > to catch the identifier after the registration, so you'll be able to work with the registered query later. @@ -575,7 +575,7 @@ pub fn remove_interchain_query(query_id: u64) -> NeutronResult Date: Fri, 15 Nov 2024 09:09:07 +0300 Subject: [PATCH 24/32] update ICQ howto contract links --- .../modules/interchain-queries/how-to.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index 13dca7ebf..93dd291d5 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -202,7 +202,7 @@ pub fn register_balances_query( })) } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L47-L87) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/07d0f1e6b4c36b8541e74530986a6baba2710cf1/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L47-L87) #### 3. Define Interchain Query registration response handling @@ -242,7 +242,7 @@ pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { } } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L100-L125) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/07d0f1e6b4c36b8541e74530986a6baba2710cf1/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L104-L129) #### 4. Define Interchain Query results submission handling @@ -279,7 +279,7 @@ pub fn sudo_kv_query_result(deps: DepsMut, env: Env, query_id: u64) -> NeutronRe Ok(Response::default()) } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L127-L148) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/07d0f1e6b4c36b8541e74530986a6baba2710cf1/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L131-L152) #### 5. Perform Interchain Query registration @@ -368,7 +368,7 @@ pub fn register_account_query( })) } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/contract.rs#L56-L102) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/07d0f1e6b4c36b8541e74530986a6baba2710cf1/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/contract.rs#L56-L102) #### 3. Define Interchain Query registration response handling @@ -408,7 +408,7 @@ pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { } } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/contract.rs#L115-L140) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/07d0f1e6b4c36b8541e74530986a6baba2710cf1/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/contract.rs#L119-L144) #### 4. Implement reconstruction of the query result @@ -452,7 +452,7 @@ impl KVReconstruct for BaseAccount { } } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/types.rs#L10-L38) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/07d0f1e6b4c36b8541e74530986a6baba2710cf1/contracts/docs/interchainqueries/howto/register_custom_kv_icq/src/types.rs#L10-L38) #### 5. Define Interchain Query results submission handling @@ -491,7 +491,7 @@ pub fn sudo_kv_query_result(deps: DepsMut, query_id: u64) -> NeutronResult #### 6. Perform Interchain Query registration @@ -565,7 +565,7 @@ pub fn register_undelegations_query( Ok(Response::default().add_message(msg)) } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_tx_icq/src/contract.rs#L55-L93) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/07d0f1e6b4c36b8541e74530986a6baba2710cf1/contracts/docs/interchainqueries/howto/register_tx_icq/src/contract.rs#L55-L93) #### 3. Define Interchain Query results submission handling @@ -653,7 +653,7 @@ pub fn sudo_tx_query_result( Ok(Response::default()) } ``` -[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_tx_icq/src/contract.rs#L115-L184) +[View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/07d0f1e6b4c36b8541e74530986a6baba2710cf1/contracts/docs/interchainqueries/howto/register_tx_icq/src/contract.rs#L115-L184) #### 4. Perform Interchain Query registration From 50d6f64dc8294081351a7592a627bd9a65bf939f Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Mon, 18 Nov 2024 19:04:01 +0300 Subject: [PATCH 25/32] move link to RPC node configuration to a note for better visibility --- docs/neutron/modules/interchain-queries/how-to.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index 93dd291d5..6ba6c3cc0 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -134,9 +134,12 @@ txs: ``` +:::note Sure that the query is correct but the result is empty? +That could happen if the RPC node is not configured properly. Read more about configuration [here](/neutron/modules/interchain-queries/explanation#configuring-your-own-remote-chain-rpc-node-for-tx-icq-usage). +::: + **Might be interesting:** - [How do TX Interchain Queries work?](/neutron/modules/interchain-queries/explanation#how-do-tx-interchain-queries-work) -- [Configuring your own remote chain RPC node for TX ICQ usage](/neutron/modules/interchain-queries/explanation#configuring-your-own-remote-chain-rpc-node-for-tx-icq-usage) ## How to register and handle a KV Interchain Query From 3b2e8ed645cba4780cb71e939cee4d3a12f62680 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Mon, 25 Nov 2024 15:38:24 +0300 Subject: [PATCH 26/32] apply ChatGPT for improving writing style and fixing grammar --- .../neutron/modules/interchain-queries/api.md | 36 ++-- .../modules/interchain-queries/explanation.md | 196 ++++++++++++------ .../modules/interchain-queries/how-to.md | 160 +++++++------- .../modules/interchain-queries/known-bugs.md | 14 +- .../modules/interchain-queries/overview.md | 30 +-- 5 files changed, 266 insertions(+), 170 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/api.md b/docs/neutron/modules/interchain-queries/api.md index d495fc57a..93f6cbdce 100644 --- a/docs/neutron/modules/interchain-queries/api.md +++ b/docs/neutron/modules/interchain-queries/api.md @@ -1,12 +1,12 @@ # API -This page contains the `interchainqueries` module's interface description: the endpoints the module exposes and the `sudo` messages the module issues. Each endpoint is explained in a dedicated section with links to request and response models, and an example of interaction with the module via the endpoint. The links to the request and response models also provide more information about request parameters and response values. +This page describes the interface of the `interchainqueries` module, including the endpoints it provides and the `sudo` messages it issues. Each endpoint is detailed in its own section, with links to the request and response models, as well as examples of how to interact with the module using the endpoint. The request and response model links also offer more details about the request parameters and response values. -Please be aware that the examples do not necessarily reflect the current state on the chain; they are listed here only to visualize the request formation and response payload in a user-friendly way. +Please note that the examples are for demonstration purposes only and may not reflect the current state of the chain. They are included to help visualize how requests are formed and what the response payloads look like. **Endpoints** -This section lists piblic RPC API of the `interchainqueries` module. +This section lists the public RPC API of the `interchainqueries` module. Queries: - [Params](#params); @@ -24,7 +24,7 @@ Messages: **Sudo** -This section lists `sudo` messages issued by the `interchainqueries` module to smart contracts owning Interchain Queries. +This section lists the `sudo` messages that the `interchainqueries` module sends to smart contracts that own Interchain Queries. - [MessageTxQueryResult](#messagetxqueryresult) - [MessageKvQueryResult](#messagekvqueryresult) @@ -33,7 +33,7 @@ This section lists `sudo` messages issued by the `interchainqueries` module to s ### Params -Queries the current parameters of the module. +Fetches the current parameters of the `interchainqueries` module. - [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryParamsRequest) - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryParamsResponse) @@ -67,7 +67,7 @@ curl -X 'GET' \ ### RegisteredQueries -Queries all the registered Interchain Queries in the module with filtration by owner and/or connection ID. +Retrieves all registered Interchain Queries in the module, with optional filtering by owner and/or connection ID. - [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryRegisteredQueriesRequest) - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryRegisteredQueriesResponse) @@ -145,7 +145,7 @@ curl -X 'GET' \ ### RegisteredQuery -Queries a registered Interchain Query by ID. +Fetches details of a registered Interchain Query using its ID. - [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryRegisteredQueryRequest) - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryRegisteredQueryResponse) @@ -198,7 +198,7 @@ curl -X 'GET' \ ### QueryResult -Queries the last successfully submitted result of an Interchain Query. +Retrieves the most recent successfully submitted result of an Interchain Query. This is only applicable for KV Interchain Queries. - [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryQueryResultRequest) - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryQueryResultResponse) @@ -238,7 +238,7 @@ curl -X 'GET' \ ### LastRemoteHeight -Queries the last height of a remote chain known to the IBC client behind a given connection ID. +Retrieves the most recent height of a remote chain as known by the IBC client associated with a given connection ID. - [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryLastRemoteHeightRequest) - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryLastRemoteHeightResponse) @@ -266,9 +266,9 @@ curl -X 'GET' \ ### RegisterInterchainQuery -Registers a new Interchain Query in the `interchainqueries` module. This message is supposed to be issues only by a smart contract. The caller contract is charged a query registration deposit automatically in the amount defined as the module's query deposit parameter. The deposit is paid back on the query removal. Make sure to have enough assets on the contract's account at the time of the message execution. +Registers a new Interchain Query in the `interchainqueries` module. This message should only be issued by a smart contract. The calling contract is automatically charged a query registration deposit, based on the module's query deposit parameter. The deposit is refunded when the query is removed. Ensure the contract's account has sufficient assets at the time of message execution. -Returns an ID assigned to the registered query. Handle this message response via a reply handler in order to make use of the ID. +The response includes the ID assigned to the registered query. Use a reply handler to process this response and utilize the query ID. - [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgRegisterInterchainQuery) - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgRegisterInterchainQueryResponse) @@ -289,7 +289,7 @@ Events emission on success: ### SubmitQueryResult -Submits a result of an Interchain Query execution to the chain. This message handling may include passing of the result to the query's owner smart contract for processing which might be a pretty gas-consumable operation. +Submits the result of an Interchain Query execution to the chain. Handling this message may involve forwarding the result to the smart contract that owns the query for processing, which could require significant gas usage. - [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgSubmitQueryResult) - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgSubmitQueryResultResponse) @@ -302,7 +302,7 @@ Submits a result of an Interchain Query execution to the chain. This message han ### RemoveInterchainQuery -Removes a given Interchain Query and its results from the module. Can be removed only by the owner of the query during the query's submit timeout, and by anyone after the query has been timed out. The query deposit is returned to the caller on a success call. +Removes a specific Interchain Query and its results from the module. The query can only be removed by its owner during the query's submit timeout. After the timeout, anyone can remove it. Upon successful removal, the query deposit is refunded to the caller. - [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgRemoveInterchainQuery) - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgRemoveInterchainQueryResponse) @@ -319,7 +319,7 @@ Events emission on success: ### UpdateInterchainQuery -Updates parameters of a registered Interchain Query. Only callable by the owner of the query. +Updates the parameters of a registered Interchain Query. This action can only be performed by the query's owner. - [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgUpdateInterchainQuery) - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgUpdateInterchainQueryResponse) @@ -332,7 +332,7 @@ Events emission on success: ### UpdateParams -Updates params of the interchainqueries module. Only callable by the module's authority. +Updates the parameters of the `interchainqueries` module. This action can only be performed by the module's authority. - [Request model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgUpdateParams) - [Response model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#MsgUpdateParamsResponse) @@ -341,7 +341,7 @@ Updates params of the interchainqueries module. Only callable by the module's au ### MessageTxQueryResult -MessageTxQueryResult is the model of the `sudo` message sent to a smart contract on a TX Interchain Query result submission. The owner of a TX Interchain Query must define a `sudo` entry_point for handling `tx_query_result` messages and place the needed logic there. The `tx_query_result` handler is treated by the `interchainqueries` module as a callback that is called each time a TX query result is submitted. +MessageTxQueryResult is the model of the `sudo` message sent to a smart contract when a TX Interchain Query result is submitted. The owner of a TX Interchain Query must implement a `sudo` entry point to handle `tx_query_result` messages and include the necessary logic in it. The `tx_query_result` handler functions as a callback, triggered by the `interchainqueries` module each time a TX query result is submitted. - [Message model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/contractmanager/types#MessageTxQueryResult) - [Message model in neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/sudo/msg/enum.SudoMsg.html#variant.TxQueryResult) @@ -359,9 +359,9 @@ Events emission on failure: ### MessageKvQueryResult -MessageKVQueryResult is the model of the `sudo` message sent to a smart contract on a KV Interchain Query result submission. If the owner of a KV Interchain Query wants to handle the query updates, it must define a `sudo` entry_point for handling `kv_query_result` messages and place the needed logic there. The `kv_query_result` handler is treated by the `interchainqueries` module as a callback that is called each time a KV query result is submitted. +MessageKvQueryResult is the model of the `sudo` message sent to a smart contract when a KV Interchain Query result is submitted. If the owner of a KV Interchain Query wants to handle updates, they must implement a `sudo` entry point to process `kv_query_result` messages and include the necessary logic in it. The `kv_query_result` handler acts as a callback, triggered by the `interchainqueries` module whenever a KV query result is submitted. -Note that there is no query result sent, only the query ID. In order to access the actual result, use the Query/QueryResult RPC of the `interchainqueries` module. +Note that the message does not include the actual query result, only the query ID. To access the result data, use the `Query/QueryResult` RPC of the `interchainqueries` module. - [Message model](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/contractmanager/types#MessageKVQueryResult) - [Message model in neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/sudo/msg/enum.SudoMsg.html#variant.KVQueryResult) diff --git a/docs/neutron/modules/interchain-queries/explanation.md b/docs/neutron/modules/interchain-queries/explanation.md index 033101133..fd3c3a064 100644 --- a/docs/neutron/modules/interchain-queries/explanation.md +++ b/docs/neutron/modules/interchain-queries/explanation.md @@ -2,18 +2,27 @@ ## How do KV Interchain Queries work? -The meaning of a KV Interchain Query is to get a secure access to a remote chain's storage from a smart contract. Such a secure access is based on: -- [IAVL tree](https://github.com/cosmos/iavl) which is used as data storage in Cosmos-SDK based blockchains. Each piece of data (value) is a leaf node in the tree having its unique data path (key); -- [abci_query](https://docs.cometbft.com/v0.38/spec/rpc/#abciquery) RPC that exposes the storage (`IAVL tree`) read operations by a given path. - -A typical flow of KV Interchain Queries usage is as follows: -1. A smart contract developer realises that their interchain protocol depends on state of a remote chain, and figures out what info exactly they need to read from the chain; -2. Given the required data set, the developer composes a list of paths in the storage that contain the required data; -3. The developer writes and deploys a smart contract that contains Interchain Query registration logic and a callback for handling the query results; -4. The smart contract registers a KV Interchain Query with the set of keys to read. The registered Interchain Query is stored in the `interchainqueries` module's state; -5. An Interchain Query relayer reads the `interchainqueries` module's state, finds the registered query and its parameters, and does the `abci_query` RPC. The result of the call is a set of key-value pairs with proofs coming from the `IAVL tree`; -6. The Interchain Query relayer provides the key-value pairs and proofs to the `interchainqueries` module. This is a KV Interchain Query result submission operation. The module does the result verification against the proofs, stores the result on chain, and notifies the owner smart contract about a fresh query result; -7. The smart contract reads the result from the module's storage and does arbitrary handling of the result; +A KV Interchain Query allows a smart contract to securely access the storage of a remote blockchain. This secure access relies on: + +- The [IAVL tree](https://github.com/cosmos/iavl), a data storage structure used in Cosmos-SDK-based blockchains. Each piece of data (value) is a leaf node in the tree, uniquely identified by its data path (key). +- The [abci_query](https://docs.cometbft.com/v0.38/spec/rpc/#abciquery) RPC, which provides access to the storage (`IAVL tree`) for reading operations using a specific path. + +Typical Flow of KV Interchain Queries Usage: + +1. A smart contract developer identifies that their interchain protocol requires access to the state of a remote chain and determines the specific data needed. + +2. The developer creates a list of storage paths that contain the required data. + +3. The developer writes and deploys a smart contract that includes logic for registering an Interchain Query and a callback to handle the query results. + +4. The smart contract registers a KV Interchain Query with the necessary set of keys. The registered query is saved in the `interchainqueries` module's state. + +5. An Interchain Query relayer reads the state of the `interchainqueries` module, finds the registered query and its parameters, and performs the `abci_query` RPC. This call returns a set of key-value pairs along with proofs from the `IAVL tree`. + +6. The relayer submits the key-value pairs and proofs to the `interchainqueries` module. This operation is called KV Interchain Query result submission. The module verifies the result using the proofs, stores it on-chain, and notifies the owning smart contract about the new result. + +7. The smart contract retrieves the result from the module's storage and processes it as needed. + 8. Steps 5-7 are repeated periodically until the query is removed. **Might be interesting:** @@ -23,18 +32,27 @@ A typical flow of KV Interchain Queries usage is as follows: ## How do TX Interchain Queries work? -The meaning of a TX Interchain Query is to get a secure subscription on transactions happening on a remote chain from a smart contract. Such a subscription is based on: -- transaction execution [events](https://docs.cosmos.network/v0.50/learn/advanced/events) emission. In a word, events are structured logs of actions that take place within the blockchain; -- [tx_search](https://docs.cometbft.com/v0.38/app-dev/indexing-transactions#querying-transactions-events) RPC. This RPC allows to search for transactions based on events they emit. - -A typical flow of TX Interchain Queries usage is as follows: -1. A smart contract developer realises that their interchain protocol depends on actions happening on a remote chain, and figures out what actions exactly they need to react on; -2. Given the requirements, the developer composes a list of filtering conditions that identify the needed transactions by the events they emit; -3. The developer writes and deploys a smart contract that contains Interchain Query registration logic and a callback for handling the query results; -4. The smart contract registers a TX Interchain Query with the set of transaction filters to apply. The registered Interchain Query is stored in the `interchainqueries` module's state; -5. An Interchain Query relayer reads the `interchainqueries` module's state, finds the registered query and its parameters, and does the `tx_search` RPC. The result of the call is a list of transactions successfully processed on the remote chain; -6. The Interchain Query relayer provides the list of transactions a couple of headers for each transaction needed to verify the result to the `interchainqueries` module. This is a TX Interchain Query result submission operation. The module does the result verification against the headers and passes the result to the smart contract; -7. The smart contract does arbitrary handling of the result; +A TX Interchain Query allows a smart contract to securely subscribe to and react to transactions occurring on a remote chain. This subscription relies on: + +- [Events](https://docs.cosmos.network/v0.50/learn/advanced/events) emitted during transaction execution. Events are structured logs of actions that occur within the blockchain. +- The [tx_search](https://docs.cometbft.com/v0.38/app-dev/indexing-transactions#querying-transactions-events) RPC, which enables searching for transactions based on the events they emit. + +Typical Flow of TX Interchain Queries Usage: + +1. A smart contract developer identifies that their interchain protocol requires responding to specific actions on a remote chain and determines the relevant actions. + +2. Based on these requirements, the developer defines a set of filtering conditions to identify the needed transactions based on their emitted events. + +3. The developer writes and deploys a smart contract that includes logic for registering an Interchain Query and a callback to handle the query results. + +4. The smart contract registers a TX Interchain Query with the specified set of transaction filters. The registered query is saved in the `interchainqueries` module's state. + +5. An Interchain Query relayer reads the state of the `interchainqueries` module, finds the registered query and its parameters, and performs the `tx_search` RPC. This call returns a list of transactions that match the filters and have been successfully processed on the remote chain. + +6. The relayer submits the list of transactions along with a few headers for each transaction (used to verify the result) to the `interchainqueries` module. This operation is called TX Interchain Query result submission. The module verifies the result using the headers and passes the data to the owning smart contract. + +7. The smart contract processes the result as needed. + 8. Steps 5-7 are repeated periodically until the query is removed. **Might be interesting:** @@ -46,64 +64,91 @@ A typical flow of TX Interchain Queries usage is as follows: ## What is an Interchain Query relayer? -An Interchain Query relayer is an off-chain application that serves the needs of `interchainqueries` module users. It is an intermediary between two chains, and in this regard it is similar to an IBC relayer. The responsibilities of an Interchain Query relayer are: -- Monitoring of the registered Interchain Queries: retrieval of Interchain Queries that are needed to be processed from the `interchainqueries` module's state; -- Interchain Queries execution: reading of remote chain's state based on the parameters defined in the Interchain Query being executed, fidning proofs for the read data; -- Query results submission: passing of the retrieved data and proofs to the `interchainqueries` module and, through that, to respective smart contracts. +An Interchain Query relayer is an off-chain application that facilitates the functionality of the `interchainqueries` module. Acting as an intermediary between two blockchains, it is similar in concept to an IBC relayer. The main responsibilities of an Interchain Query relayer are: + +- **Monitoring registered Interchain Queries**: Fetching the Interchain Queries that need processing from the `interchainqueries` module's state. + +- **Executing Interchain Queries**: Accessing the remote chain's state based on the parameters defined in the Interchain Query and obtaining proofs for the retrieved data. + +- **Submitting query results**: Delivering the retrieved data and its corresponding proofs to the `interchainqueries` module, which then forwards it to the relevant smart contracts. **Might be interesting:** - [Limited gas for sudo calls](/neutron/modules/interchain-queries/explanation#limited-gas-for-sudo-calls) ## What's the role of IBC connections in Interchain Queries and how to choose one? -IBC [clients](https://ibc.cosmos.network/v8/ibc/overview/#clients) and [connections](https://ibc.cosmos.network/v8/ibc/overview/#connections) play significant role in Interchain Queries authenticity. It is the initialisation of an IBC connection that is responsible for IBC clients creation and verification that their states are correct for their respective counterparties, and it is the states of the IBC clients of an IBC connection that is responsible for Interchain Query results verification. One must choose the connection ID for their Interchain Queries wisely for it will define the trustworthiness of the whole Interchain Queries based application. +IBC [clients](https://ibc.cosmos.network/v8/ibc/overview/#clients) and [connections](https://ibc.cosmos.network/v8/ibc/overview/#connections) play a crucial role in ensuring the authenticity of Interchain Queries. When an IBC connection is initialized, it creates IBC clients and verifies that their states are accurate for their respective counterparties. These client states are then used to verify the results of Interchain Queries. The chosen connection ID for an Interchain Query directly impacts the trustworthiness of the entire Interchain Queries-based application. + +There are two ways to find an appropriate IBC connection ID: -There are two options how to find an IBC connection ID for one's needs: -- [Choose one of already existing IBC connections](/neutron/modules/interchain-queries/how-to#how-to-choose-the-right-ibc-connection-id-for-an-interchain-query-and-verify-it); -- Create an IBC connection between the chains yourself. For example, the [Hermes IBC relayer is capable of doing so](https://hermes.informal.systems/documentation/commands/path-setup/connections.html#establish-connection). +- **[Use an existing IBC connection](/neutron/modules/interchain-queries/how-to#how-to-choose-the-right-ibc-connection-id-for-an-interchain-query-and-verify-it):** Select from connections that are already set up. + +- **Create a new IBC connection:** Establish a connection between the chains yourself. For instance, the [Hermes IBC relayer](https://hermes.informal.systems/documentation/commands/path-setup/connections.html#establish-connection) can be used to create IBC connections. ## Why is there a query creation deposit? -In order to clean up ledger from not used, outdated queries, a special deposit mechanism is used. When a contract issues a [RegisterInterchainQuery](/neutron/modules/interchain-queries/api#registerinterchainquery) message, the deposit is charged from the contract's balance as escrow payment for query creation. In order to return escrow payment, the query should be removed by issuing a [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery) message. +To ensure the ledger is kept clean of unused or outdated queries, a deposit mechanism is implemented. When a contract sends a [RegisterInterchainQuery](/neutron/modules/interchain-queries/api#registerinterchainquery) message, the required deposit is deducted from the contract's balance as an escrow payment for the query creation. This deposit is refunded when the query is removed by issuing a [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery) message. -The required amount of coins to deposit is defined by the `query_deposit` [module parameter](/neutron/modules/interchain-queries/api#params). +The amount required for the deposit is defined by the `query_deposit` [module parameter](/neutron/modules/interchain-queries/api#params). -In other words, it is expected that the query owner will remove their queries when they are no longer needed. If a query hasn't been used for the `query_submit_timeout` period and the owner hasn't removed it, all network users are granted the opportunity to clean up the chain (to remove the unused query) and earn the deposited assets for doing so. +In essence, query owners are expected to remove their queries once they are no longer needed. If a query is not used within the `query_submit_timeout` period and the owner does not remove it, any network user is allowed to clean up the chain by removing the unused query. As a reward, the deposited assets are transferred to the user who performs the cleanup. **Might be interesting:** - [What are the rules for creation deposit refund?](/neutron/modules/interchain-queries/explanation#what-are-the-rules-for-creation-deposit-refund) -## What are the rules for creation deposit refund? +## What are the rules for creation deposit refunds? + +The query creation deposit is refunded when an Interchain Query is removed by issuing a [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery) message. This message can be sent either by the query owner or, under certain conditions, by anyone. -The query creation deposit is paid when the Interchain Query is removed. It is done by issuing a [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery) message. The issuer may be either the query owner or anyone under specific circumstances. Briefly, if a query was registered recently or has been continuously updated (i.e. is within a so to say `query service period`), the query would seem to be valuable for its owner and only the owner can get rid of it and get the deposit back. If a query was registered a long time ago and hasn't been updated for a long time (i.e. is beyond the `query service period`), the query has most likely been forgotten, is not in use and therefore can be removed from the chain's state by anyone for a reward in the amount of the creation deposit. You can see a more detailed permission evaluation policy below. +If the query is within its active **query service period** (recently registered or continuously updated), it is considered valuable to its owner, and only the owner can remove it and reclaim the deposit. If the query has not been updated or used for a long time (beyond the **query service period**), it is likely abandoned. In this case, anyone can remove it and claim the deposit as a reward for cleaning up the chain's state. -There are three arguments defining the removal permissions for an Interchain Query: -1. `query_submit_timeout` — a [registered query's property](/neutron/modules/interchain-queries/api#registeredquery) which defines the span in blocks of the query's renewable `query service period`. The period is granted when a query is registered and gets renewed each time a query is updated. A `query_submit_timeout` value is assigned to the query based on the [module's parameters](/neutron/modules/interchain-queries/api#params) at the time of query registration; -2. `last_submitted_result_local_height` — a [registered query's property](/neutron/modules/interchain-queries/api#registeredquery) representing the home chain's height the query was last time updated at; -3. `registered_at_height` — a [registered query's property](/neutron/modules/interchain-queries/api#registeredquery) representing the home chain's height the query was registered at. +Parameters Defining Removal Permissions: -The permissions to execute [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery) are as follows: +1. **`query_submit_timeout`**: A [registered query property](/neutron/modules/interchain-queries/api#registeredquery) specifying the number of blocks that define the renewable **query service period**. This period starts when a query is registered and renews with each query update. The `query_submit_timeout` value is set based on the [module parameters](/neutron/modules/interchain-queries/api#params) at the time of query registration. -- Within the `query service period` only the query's owner is permissioned to remove it. A query is within the `query service period` if there **hasn't been** `params.query_submit_timeout` blocks yet since the query registration height **or** the last query update height: +2. **`last_submitted_result_local_height`**: A [registered query property](/neutron/modules/interchain-queries/api#registeredquery) indicating the block height on the home chain when the query was last updated. - `within_service_period = current_height <= query.last_submitted_result_local_height + params.query_submit_timeout || current_height <= query.registered_at_height + params.query_submit_timeout` +3. **`registered_at_height`**: A [registered query property](/neutron/modules/interchain-queries/api#registeredquery) indicating the block height on the home chain when the query was initially registered. -- Beyond the `query service period` anyone can remove the query and take the deposit as a reward for keeping the network tidy. A query is beyond the `query service period` if there **has been** `params.query_submit_timeout` blocks since the query registration height **and** the last query update height: +Removal Permissions: - `beyond_service_period = current_height > query.last_submitted_result_local_height + params.query_submit_timeout && current_height > query.registered_at_height + params.query_submit_timeout` +- **Within the Query Service Period** + Only the query owner can remove the query. A query is considered within the service period if the following condition is true: + ``` + within_service_period = + current_height <= query.last_submitted_result_local_height + params.query_submit_timeout || + current_height <= query.registered_at_height + params.query_submit_timeout + ``` +- **Beyond the Query Service Period** + Anyone can remove the query and claim the deposit as a reward. A query is beyond the service period if the following condition is true: + ``` + beyond_service_period = + current_height > query.last_submitted_result_local_height + params.query_submit_timeout && + current_height > query.registered_at_height + params.query_submit_timeout + ``` **Might be interesting:** - [How Interchain Query results are removed?](/neutron/modules/interchain-queries/explanation#how-interchain-query-results-are-removed) ## Why is it mandatory to do contract's side verification of submitted TX Interchain Query results? -One important thing to keep in mind regarding Interchain Queries is that result submissions are permissionless. This means that anyone — not just your designated relayer — can submit the results of the Interchain Queries that your contract registered to the `interchainqueries` module. +A crucial aspect of Interchain Queries is that result submissions are **permissionless**. This means that anyone — not just your designated relayer — can submit the results of TX Interchain Queries registered by your contract to the `interchainqueries` module. + +Since events are not part of the blockchain consensus and are not included in the transaction results (and thus not in TX Interchain Query result submissions), the `interchainqueries` module cannot ensure that the submitted transactions match the filters specified in your query. While the module can confirm that the submitted data comes from a valid transaction, it cannot determine whether the transaction satisfies your specific filtering criteria. -However, since events are not part of the consensus and are not included in the transaction result (and therefore not included in the TX Interchain Queries result submission), the `interchainqueries` module cannot verify whether the submitted transactions actually match the criteria set by the Interchain Query’s transaction filters. +To address this limitation, your contract's `SudoTXQueryResult` handler must include additional checks to verify that the submitted transactions meet the criteria defined in your query's transaction filters. At a minimum, you should confirm that: -Because of this limitation, it's essential to implement additional checks in your `SudoTXQueryResult` handler to ensure the submitted transactions meet your query's transaction filters criteria. You should at least verify that the messages in the transaction body have the correct message types and values. For example, if considering an Interchain Query that [gets Undelegate transactions issued by a concrete address](/neutron/modules/interchain-queries/how-to#how-to-find-out-what-transaction-filter-to-use), the verification will have to check that the message type is `/cosmos.staking.v1beta1.MsgUndelegate` and that the delegator address is `cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp`. The way to go is to have these two kinds of checks for each transaction filter in your query. +1. The messages in the transaction body have the correct message types. +2. The message values align with your filter conditions. -Without these checks, a malicious relayer could submit a fully valid Tendermint transaction that doesn't meet your defined transaction filters, potentially compromising your business logic. For the example above, if you don't check the delegator address, anyone's Undelegate transactions will pass. +Suppose you register a TX Interchain Query to track [Undelegate transactions issued by a specific address](/neutron/modules/interchain-queries/how-to#how-to-find-out-what-transaction-filter-to-use). Your contract should verify: + +- The message type is `/cosmos.staking.v1beta1.MsgUndelegate`. +- The `delegator_address` matches the specific address, e.g., `cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp`. + +These checks must be implemented for each transaction filter in your query. + +If you skip these checks, a malicious relayer could submit valid Tendermint transactions that don't meet your query's filters. This could disrupt your business logic. Using the above example, if you fail to verify the `delegator_address`, any valid Undelegate transaction — regardless of the sender — could pass through, potentially compromising your application's functionality. **Might be interesting:** - [How to find out what transaction filter to use](/neutron/modules/interchain-queries/how-to#how-to-find-out-what-transaction-filter-to-use) @@ -111,42 +156,65 @@ Without these checks, a malicious relayer could submit a fully valid Tendermint ## Why is the Proof field nullified in QueryResult RPC response? -The `interchainqueries` module only needs KV proofs during the submission process to verify the values being submitted against the proofs. If save them afterwards, they'll just increase chain's space without any reasonable further usage. The KV results saved on chain can be trusted as cryptographically proved because they are verified at the very beginning — by the module at the submission step. +The `interchainqueries` module requires KV proofs only during the submission process to verify that the submitted values match the provided proofs. Storing these proofs afterward would unnecessarily consume blockchain storage without serving any practical purpose. The KV results saved on-chain can be trusted because they are cryptographically verified during the submission step by the module. -The reason the `Proof` field is presented but empty is that the [QueryResult](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryResult) type is used for both query result submission and query result preservation in the module's storage. More designated types are likely to be introduced in the future to mitigate confusion around this. +The `Proof` field is present but empty because the [QueryResult](https://pkg.go.dev/github.com/neutron-org/neutron/v4@v4.0.1/x/interchainqueries/types#QueryResult) type is used both for query result submission and for storing query results in the module's state. This dual-purpose usage can cause confusion, but more specific types may be introduced in the future to address this issue. ## Why doesn't interchainqueries module store TX query results? -If compare to the KV Interchain Queries which have the last result stored on chain and available to be read, the TX Interchain Queries are not about the last result, but about a possible list of results (transactions matched the filter). Storing the whole list of results may be cumbersome for the chain in terms of required space. So, instead of storing results on chain and requiring smart contracts to read them (as for KV queries), the `interchainqueries` module passes the whole tx results directly to smart contracts, ending the life of the results right after a successful [TxQueryResult](/neutron/modules/interchain-queries/api#messagetxqueryresult) `sudo` call. The only things that the module stores on chain regarding TX Interchain Queries are: -- hashes of transactions that have been successfully processed by the owner smart contract to avoid multiple processing of the same transactions, and -- [failures appeared during sudo calls](#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails). +Unlike KV Interchain Queries, which store the latest result on-chain for retrieval, TX Interchain Queries involve a list of potential results (transactions that match the filter). Storing the entire list of results on-chain would require a significant amount of storage, which is impractical. + +Instead of saving results on-chain, the `interchainqueries` module directly sends the full TX results to the owning smart contracts during the [TxQueryResult](/neutron/modules/interchain-queries/api#messagetxqueryresult) `sudo` call. Once the `sudo` call is successfully completed, the results are discarded, minimizing storage use. + +The module stores only two things related to TX Interchain Queries: + +1. **Hashes of processed transactions**: This prevents the same transactions from being processed multiple times. +2. **[Failures appeared during sudo calls](#what-happens-if-a-sudo-callback-to-a-smart-contract-owning-an-interchain-query-fails)**. **Might be interesting:** - [How to register and handle a TX Interchain Query](/neutron/modules/interchain-queries/how-to#how-to-register-and-handle-a-tx-interchain-query) ## What are entry points and sudo calls? -[Entry points](https://docs.cosmwasm.com/core/entrypoints) are where your contract can be called from the outside world. [Sudo](https://docs.cosmwasm.com/core/entrypoints/sudo) calls are messages issued by the chain itself. They are routed to a special `sudo` `entry_point` which can only be accessed by the chain. +[Entry points](https://docs.cosmwasm.com/core/entrypoints) are functions in your smart contract that can be invoked by external entities. [Sudo](https://docs.cosmwasm.com/core/entrypoints/sudo) calls are special messages issued by the chain itself. These messages are routed to a dedicated `sudo` entry point, which is only accessible to the chain. ## Limited gas for sudo calls -The `interchainqueries` module uses the [contractmanager](/neutron/modules/contract-manager/overview) module under the hood for `sudo` operations. The `contractmanager` module doesn't allow extensive `sudo` callbacks and [has a justified strict gas limitation for them](/neutron/modules/contract-manager/overview#gas-limitation). The limit is defined by the `sudo_call_gas_limit` `contractmanager` module's parameter. +The `interchainqueries` module relies on the [contractmanager](/neutron/modules/contract-manager/overview) module to handle `sudo` operations. The `contractmanager` module [enforces strict gas limits](/neutron/modules/contract-manager/overview#gas-limitation) on `sudo` callbacks, defined by its `sudo_call_gas_limit` parameter, to prevent excessive gas usage. -It is recommended by the `contractmanager` module to separate `sudo` callback and computations to different handlers in case the computations go beyond the allocated gas. For example, one can store `sudo` callback payload in the contract's state, and then read it and handle during an additional outer `execute` call to the contract. +To manage cases where computations exceed the allocated gas, the `contractmanager` module recommends separating `sudo` callbacks from heavy computations. One approach is to store the `sudo` callback payload in the contract's state during the `sudo` call and then process it later in a separate external `execute` call. This method ensures that the gas limit for `sudo` calls is not exceeded, while still allowing complex logic to be executed when needed. **Might be interesting:** - [What are entry points and sudo calls?](/neutron/modules/interchain-queries/explanation#what-are-entry-points-and-sudo-calls) ## What happens if a sudo callback to a smart contract owning an Interchain Query fails? -In this case, the `interchainqueries` module will store the failure in the [contractmanager](/neutron/modules/contract-manager/overview) module with all information about the query and a redacted (shortened to codespace and error code) error message. A full error message is emitted as an [event](https://docs.cosmos.network/v0.50/learn/advanced/events) on a failure (see the [message events emission](/neutron/modules/interchain-queries/api#sudo) for details). Note that the `out of gas` errors are stored as failures, too. Failed query result submissions can be read from the `contractmanager` module and resubmitted to the `interchainqueries` module. More info about the read and resubmit operations by the link to the [contractmanager](/neutron/modules/contract-manager/overview) module documentation. +If a `sudo` callback fails, the `interchainqueries` module records the failure in the [contractmanager](/neutron/modules/contract-manager/overview) module. This record includes all relevant information about the query and a redacted error message (reduced to the codespace and error code). A full error message is emitted as an [event](https://docs.cosmos.network/v0.50/learn/advanced/events) to provide more context about the failure. For details, see the [message events emission](/neutron/modules/interchain-queries/api#sudo) section. + +Failures due to `out of gas` errors are also recorded. + +Failed query result submissions can be retrieved from the `contractmanager` module and resubmitted to the `interchainqueries` module. For more information about reading and resubmitting failed operations, refer to the [contractmanager documentation](/neutron/modules/contract-manager/overview). + +## How are Interchain Query results removed? + +When a [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery) message is successfully executed, the results of the respective Interchain Query are removed from the chain's storage. The removal process depends on the type of the Interchain Query: -## How Interchain Query results are removed? +- **KV Query Results**: + KV query results are single records in the store with a predictable gas consumption for removal. These records are removed immediately during the handling of the removal message. -When someone successfully issues a [RemoveInterchainQuery](/neutron/modules/interchain-queries/api#removeinterchainquery) message, the results of the respective Interchain Query stored on chain are removed depending on the type of the Interchain Query: -- KV query results are just single records in the store with a known removal gas consumption. So they are removed in the scope of the removal message handling; -- TX query results are hashes of remote chain transactions. Each of the hashes is a single record in the store, so the gas comsumption for the removal depends on the number of hashes to be removed. This uncertainty is the reason why the TX query results removal is placed at the EndBlock and distributed to small governance-controlled size batches. The removal message handling only marks the TX Interchain Query as a one to be removed, and then in each EndBlock there's a number of its hashes removed. The number is defined by the `tx_query_removal_limit` [module parameter](/neutron/modules/interchain-queries/api#params). +- **TX Query Results**: + TX query results consist of hashes of remote chain transactions, with each hash being a separate record in the store. The gas consumption for removal depends on the number of hashes, which introduces uncertainty. + + To handle this, TX query results are removed in batches during the `EndBlock` phase. When a removal message is processed, the TX Interchain Query is marked for removal. Subsequently, in each `EndBlock`, a small batch of hashes is removed. The batch size is controlled by the `tx_query_removal_limit` [module parameter](/neutron/modules/interchain-queries/api#params). + +This approach ensures that gas consumption remains manageable while removing large numbers of TX query results. ## Configuring your own remote chain RPC node for TX ICQ usage -If running your own RPC node for the target chain, make sure to configure its `pruning` parameter in the [app.toml](https://docs.cosmos.network/v0.50/learn/advanced/config) file and `indexer` parameter in the [config.toml](https://docs.cometbft.com/v0.38/core/configuration) file the way it is sufficient for the transactions filter you define for your queries. +If you are running your own RPC node for the target chain, ensure that its configuration supports the transaction filters defined in your TX Interchain Queries. Specifically, you need to adjust the following parameters: + +- **`pruning` parameter**: Configure this in the [app.toml](https://docs.cosmos.network/v0.50/learn/advanced/config) file to retain the required historical data for your queries. + +- **`indexer` parameter**: Set this in the [config.toml](https://docs.cometbft.com/v0.38/core/configuration) file to enable transaction indexing. + +Proper configuration of these parameters ensures that the node can provide the necessary data for your TX Interchain Queries. \ No newline at end of file diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index 6ba6c3cc0..c13adf414 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -2,22 +2,22 @@ ## How to choose the right IBC connection ID for an Interchain Query and verify it -Let's find an IBC connection between Neutron and CosmosHub. +This guide explains how to identify and verify an IBC connection between Neutron and CosmosHub. -#### 1. Find an already existing IBC connection using an explorer +#### 1. Find an existing IBC connection using an explorer -Go to [map of zones](https://mapofzones.com/zones/neutron-1/peers?columnKey=ibcVolumeIn&period=7d). There might be several connections between two chains, so pick one of them. For Neutron and CosmosHub, let's pick the `connection-0`. +Visit the [map of zones](https://mapofzones.com/zones/neutron-1/peers?columnKey=ibcVolumeIn&period=7d). You may find multiple connections between the two chains. For Neutron and CosmosHub, we’ll use `connection-0`. -#### 2. Pick a neutron RPC node from the chain registry repo +#### 2. Pick a Neutron RPC node from the chain registry -Go to [Neutron's chain registry page](https://github.com/cosmos/chain-registry/blob/master/neutron/chain.json), pick an RPC node from the `apis` section, and specify it in the following `neutrond` queries using the `--node` flag. +Go to [Neutron's chain registry page](https://github.com/cosmos/chain-registry/blob/master/neutron/chain.json), choose an RPC node from the `apis` section, and use it in subsequent `neutrond` queries with the `--node` flag. -#### 3. Gather neutron side info about the picket IBC connection +#### 3. Gather Neutron-side information about the chosen IBC connection -Find out the IBC client ID and the counterparty IBC info for the `connection-0` IBC connection. +Retrieve the IBC client ID and counterparty details for `connection-0`.
- Show code +Show code ``` neutrond q ibc connection end connection-0 --node https://rpc-voidara.neutron-1.neutron.org @@ -31,12 +31,12 @@ counterparty: ```
-#### 4. Check the IBC connection counterparty chain ID +#### 4. Check the counterparty chain ID for the Neutron-side IBC connection -Check if the Neutron side IBC client's counterparty chain ID matches the ID of the chain you're up to point your Interchain Queries to. +Ensure that the counterparty chain ID of the Neutron-side IBC client matches the CosmosHub chain ID.
- Show code +Show code ``` neutrond q ibc client state 07-tendermint-0 --node https://rpc-voidara.neutron-1.neutron.org @@ -48,16 +48,16 @@ client_state: ```
-#### 5. Pick a CosmosHub RPC node from the chain registry repo +#### 5. Pick a CosmosHub RPC node from the chain registry -Go to [CosmosHub's chain registry page](https://github.com/cosmos/chain-registry/blob/master/cosmoshub/chain.json), pick an RPC node from the `apis` section, and specify it in the following `gaiad` queries using the `--node` flag. +Visit [CosmosHub's chain registry page](https://github.com/cosmos/chain-registry/blob/master/cosmoshub/chain.json), select an RPC node from the `apis` section, and use it in `gaiad` queries with the `--node` flag. -#### 6. Make sure the CosmosHub's side counterparty is Neutron +#### 6. Verify that CosmosHub's counterparty corresponds to Neutron -Using the counterparty IBC info retrieved at the third step of this HowTo, do the opposite side checks: check that the CosmosHub's side IBC connection and client's counterparty info corresponds to Neutron's side IBC connection and client's info. +Using the counterparty information from Step 3, confirm that CosmosHub's IBC connection and client details match Neutron's information.
- Show code +Show code ``` gaiad q ibc connection end connection-809 --node https://cosmoshub.tendermintrpc.lava.build:443 @@ -79,39 +79,46 @@ client_state: ```
+By following these steps, you can ensure that the IBC connection ID you choose is valid and correctly corresponds to the intended chains. + **Might be interesting:** - [What's the role of IBC connections in Interchain Queries and how to choose one?](/neutron/modules/interchain-queries/explanation#whats-the-role-of-ibc-connections-in-interchain-queries-and-how-to-choose-one) ## How to find out what transaction filter to use -Let's imagine that we need our Interchain Query based smart contract to know about undelegations done by `cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp` on CosmosHub. +Imagine you need your Interchain Query-based smart contract to track undelegations made by `cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp` on CosmosHub. #### 1. Find the up-to-date source code of the staking module -Find out what is the current version of the `staking` module (imported from `cosmos-sdk`) CosmosHub runs and go to the module's source code: +1. Locate the current version of the `staking` module used by CosmosHub. Check the [chain registry](https://github.com/cosmos/chain-registry/blob/e346b6dbc0d901eec5e8704e0a7736bfdaa3dca9/cosmoshub/chain.json#L36-L37) to find the repository and version in use, e.g., `v19.2.0`. +2. In the `gaia` repository for `v19.2.0`, locate the [cosmos-sdk](https://github.com/cosmos/gaia/blob/v19.2.0/go.mod#L24) import in the `go.mod` file, e.g., `v0.50.9`. +3. Access the `staking` module's source code in the [cosmos-sdk with tag v0.50.9](https://github.com/cosmos/cosmos-sdk/tree/v0.50.9/x/staking). -1. Find the git repository and currently running version of CosmosHub in the [chain registry](https://github.com/cosmos/chain-registry/blob/e346b6dbc0d901eec5e8704e0a7736bfdaa3dca9/cosmoshub/chain.json#L36-L37) (use the main branch to get the up-to-date info) — `v19.2.0`; -2. Find the [cosmos-sdk](https://github.com/cosmos/gaia/blob/v19.2.0/go.mod#L24) import in the `go.mod` file of the `gaia` repository of `v19.2.0` — `v0.50.9`; -3. Open the `staking` module's source code in [cosmos-sdk with tag v0.50.9](https://github.com/cosmos/cosmos-sdk/tree/v0.50.9/x/staking). +:::note +Currently used versions might be different by the time you read this. +::: -#### 2. Find the handler that manages undelegations +#### 2. Find the handler managing undelegations -Find the [Undelegate](https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L391-L392) handler of the `staking` module's keeper. +Identify the [Undelegate handler](https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L391-L392) in the `staking` module's keeper. -#### 3. Find the events emitted on undelegations +#### 3. Locate the events emitted during undelegations -Find the [event emission part](https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L447-L455) of the Undelegate handler code. +Examine the [event emission section](https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L447-L455) of the Undelegate handler code. -#### 4. Create a transactions query using the events +#### 4. Create a transaction filter using the events -Pairing the emitted event type and required attributes, compose an exhaustive transaction filter. In this case, it's `unbond.delegator=cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp` (`types.EventTypeUnbond`.`types.AttributeKeyDelegator`=`cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp`). +Match the event type and attributes emitted. For this scenario, use the filter: +`unbond.delegator=cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp` +This corresponds to: +`types.EventTypeUnbond.types.AttributeKeyDelegator = cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp`. -#### 5. Try to get some results using the query +#### 5. Test the query filter -Try out the result query string in `gaiad q txs` query to make sure it works as expected. +Verify your filter by running the following `gaiad q txs` query to ensure it retrieves the expected results.
- Show code +Show code ``` gaiad q txs --query "unbond.delegator='cosmos17s3uhcvrwrsp2ldjvxp8rseyc3ulpchdry87hp'" @@ -135,7 +142,7 @@ txs:
:::note Sure that the query is correct but the result is empty? -That could happen if the RPC node is not configured properly. Read more about configuration [here](/neutron/modules/interchain-queries/explanation#configuring-your-own-remote-chain-rpc-node-for-tx-icq-usage). +If the query appears correct but no results are returned, it may indicate that the RPC node is not properly configured. For more information, refer to the [RPC node configuration guide](/neutron/modules/interchain-queries/explanation#configuring-your-own-remote-chain-rpc-node-for-tx-icq-usage). ::: **Might be interesting:** @@ -143,22 +150,22 @@ That could happen if the RPC node is not configured properly. Read more about co ## How to register and handle a KV Interchain Query -This section contains a brief guide on how to register a KV Interchain Query and handle the query results using [neutron-std](https://docs.rs/neutron-std/4.2.2-rc/neutron_std) and [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk) libraries in a smart contract. +This guide provides a brief guide to registering a KV Interchain Query and handling its results using the [neutron-std](https://docs.rs/neutron-std/4.2.2-rc/neutron_std) and [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk) libraries in a smart contract. #### 1. Find the appropriate helper function in Neutron SDK -Find the register Interchain Query helper function that your needs require in the [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) repository. For this particular example, let's choose the [new_register_balances_query_msg](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/fn.new_register_balances_query_msg.html) function. +Locate the helper function for registering an Interchain Query that suits your requirements in the [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html). For this example, we’ll use the [new_register_balances_query_msg](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/fn.new_register_balances_query_msg.html) function. :::note Couldn't find the required helper function? -If there is no predefined helper function suitable for your needs in [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk), proceed to the [How to register a KV Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-and-handle-a-kv-interchain-query-with-custom-keys) section. +If no predefined helper function meets your needs, refer to the [How to register a KV Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-and-handle-a-kv-interchain-query-with-custom-keys) section. ::: -#### 2. Define Interchain Query registration entry point +#### 2. Define the Interchain Query registration entry point -Implement an `execute` message handler in your contract that will process Interchain Query registration using the helper function as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/). +Create an `execute` message handler in your contract to register the Interchain Query using the helper function as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/). -
- Show code +
+Show code ```rust use neutron_sdk::interchain_queries::v047::register_queries::new_register_balances_query_msg; @@ -208,12 +215,12 @@ pub fn register_balances_query( [View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/07d0f1e6b4c36b8541e74530986a6baba2710cf1/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L47-L87)
-#### 3. Define Interchain Query registration response handling +#### 3. Define the Interchain Query registration response handler -In the reply handler, decode the submessage result as a [MsgRegisterInterchainQueryResponse](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.MsgRegisterInterchainQueryResponse.html) to get access to the assigned Interchain Query ID. +In the reply handler, decode the submessage result as a [MsgRegisterInterchainQueryResponse](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.MsgRegisterInterchainQueryResponse.html) to access the assigned Interchain Query ID. -
- Show code +
+Show code ```rust use neutron_std::types::neutron::interchainqueries::MsgRegisterInterchainQueryResponse; @@ -248,12 +255,12 @@ pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { [View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/07d0f1e6b4c36b8541e74530986a6baba2710cf1/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L104-L129)
-#### 4. Define Interchain Query results submission handling +#### 4. Define the Interchain Query results processing handler -Get the submitted Interchain Query result from the `interchainqueries` module's storage using [query_balance](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v047/queries/fn.query_balance.html) helper function and handle it. +Retrieve the query result from the `interchainqueries` module's storage using the [query_balance](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v047/queries/fn.query_balance.html) function and process it. -
- Show code +
+Show code ```rust use neutron_sdk::interchain_queries::v047::queries::query_balance; @@ -285,9 +292,9 @@ pub fn sudo_kv_query_result(deps: DepsMut, env: Env, query_id: u64) -> NeutronRe [View full code here](https://github.com/neutron-org/neutron-dev-contracts/blob/07d0f1e6b4c36b8541e74530986a6baba2710cf1/contracts/docs/interchainqueries/howto/register_kv_icq/src/contract.rs#L131-L152)
-#### 5. Perform Interchain Query registration +#### 5. Register the Interchain Query -Broadcast a [ExecuteMsg::RegisterBalancesQuery](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_kv_icq/src/msg.rs#L10-L15) message to the contract with required parameters. +Send a [ExecuteMsg::RegisterBalancesQuery](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_kv_icq/src/msg.rs#L10-L15) message to the contract with the required parameters. **Might be interesting:** - [What are entry points and sudo calls?](/neutron/modules/interchain-queries/explanation#what-are-entry-points-and-sudo-calls) @@ -296,23 +303,23 @@ Broadcast a [ExecuteMsg::RegisterBalancesQuery](https://github.com/neutron-org/n ## How to register and handle a KV Interchain Query with custom keys -If your KV Interchain Query cannot be covered with the helpers from the [Interchain Queries related package](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) of [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk), you will need to define the KVKeys for your query yourself. For this particular example, let's register an [Account](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/proto/cosmos/auth/v1beta1/query.proto#L27-L31) Interchain Query to `cosmos-hub` `v21.0.0`. +If your KV Interchain Query cannot be handled using the helpers from the [Interchain Queries related package](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/v045/register_queries/index.html) in [neutron-sdk](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk), you can define the `KVKeys` manually. This example demonstrates registering an [Account](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/proto/cosmos/auth/v1beta1/query.proto#L27-L31) Interchain Query for `cosmos-hub` `v21.0.0`. -#### 1. Figure out the respective data path and model +#### 1. Figure out the respective data path and model -Figure out how the data path to the required data is constructed and what the data model is. This can be done by the module's code investigation. Start with finding the [respective auth module gRPC handler](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/keeper/grpc_query.go#L62-L63) and then go deeper until you find what info exactly is written to the KVStore and at what path. +To determine how the data path is constructed and what the data model is, you need to investigate the module's code. Start by locating [the gRPC handler](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/keeper/grpc_query.go#L62-L63) in the module that corresponds to the data you're interested in. This handler provides a clue about where the data is stored and what the data model is. -For this example, the information we require from the module's code is: -- the store key used at [module's keeper initialisation](https://github.com/cosmos/gaia/blob/db2cc90315161d6730551d795558aaa7664aea6f/app/keepers/keepers.go#L207) is [acc](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/types/keys.go#L11-L12); -- the data path is constructed as [accounts store prefix](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/types/keys.go#L22-L23) + [hex address representation](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/keeper/grpc_query.go#L72-L76); -- the data model is [BaseAccount](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/types/auth.pb.go#L29-L37). +For this example: +- The store key used at [module's keeper initialisation](https://github.com/cosmos/gaia/blob/db2cc90315161d6730551d795558aaa7664aea6f/app/keepers/keepers.go#L207) is [`acc`](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/types/keys.go#L11-L12). +- The data path is the [accounts store prefix](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/types/keys.go#L22-L23) + [hex address representation](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/keeper/grpc_query.go#L72-L76). +- The data model is [`BaseAccount`](https://github.com/cosmos/cosmos-sdk/blob/853dbbf3e84900214137805d78e325ecd56fd68f/x/auth/types/auth.pb.go#L29-L37). #### 2. Define Interchain Query registration entry point -Implement an `execute` message handler in your contract that will process Interchain Query registration by broadcasting a [MsgRegisterInterchainQuery](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.MsgRegisterInterchainQuery.html) message as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/). Use the data path info found at the previous step to parametrize the message. +To enable Interchain Query registration, implement an `execute` message handler in your smart contract. This handler will broadcast a [MsgRegisterInterchainQuery](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.MsgRegisterInterchainQuery.html) message as a [submessage](https://docs.cosmwasm.com/docs/smart-contracts/message/submessage/). Use the data path information derived earlier to configure the message.
- Show code +Show code ```rust use neutron_std::types::neutron::interchainqueries::MsgRegisterInterchainQuery; @@ -376,10 +383,10 @@ pub fn register_account_query( #### 3. Define Interchain Query registration response handling -In the reply handler, decode the submessage result as a [MsgRegisterInterchainQueryResponse](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.MsgRegisterInterchainQueryResponse.html) to get access to the assigned Interchain Query ID. +In the reply handler, decode the submessage result as a [MsgRegisterInterchainQueryResponse](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.MsgRegisterInterchainQueryResponse.html) to retrieve the assigned Interchain Query ID. -
- Show code +
+Show code ```rust use neutron_std::types::neutron::interchainqueries::MsgRegisterInterchainQueryResponse; @@ -416,10 +423,10 @@ pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> NeutronResult { #### 4. Implement reconstruction of the query result -Define how the query result should be reconstructed from [StorageValue](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.StorageValue.html) into a BaseAccount instance. +Define how the query result should be reconstructed from [StorageValue](https://docs.rs/neutron-std/4.2.2-rc/neutron_std/types/neutron/interchainqueries/struct.StorageValue.html) into a `BaseAccount` instance. This involves decoding the stored values into the appropriate data structure. -
- Show code +
+Show code ```rust use neutron_sdk::interchain_queries::types::KVReconstruct; @@ -460,10 +467,10 @@ impl KVReconstruct for BaseAccount { #### 5. Define Interchain Query results submission handling -Get the submitted Interchain Query result from the `interchainqueries` module's storage using [query_kv_result](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/queries/fn.query_kv_result.html) helper function and handle it. +Retrieve the submitted Interchain Query result from the `interchainqueries` module's storage using the [query_kv_result](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/queries/fn.query_kv_result.html) helper function. Handle the result by decoding it and performing your contract's desired logic. -
- Show code +
+Show code ```rust use neutron_sdk::sudo::msg::SudoMsg; @@ -499,7 +506,7 @@ pub fn sudo_kv_query_result(deps: DepsMut, query_id: u64) -> NeutronResult - Show code +Show code ```rust use neutron_std::types::neutron::interchainqueries::MsgRegisterInterchainQuery; @@ -573,10 +582,13 @@ pub fn register_undelegations_query( #### 3. Define Interchain Query results submission handling -Decode the transaction and its messages, implement the [contract's side verification of submitted TX Interchain Query results](/neutron/modules/interchain-queries/explanation#why-is-it-mandatory-to-do-contracts-side-verification-of-submitted-tx-interchain-query-results) and results handling. +Implement a handler to process submitted TX Interchain Query results. This includes: +- Decoding the transaction and its messages. +- Performing [contract-side verification of submitted TX Interchain Query results](/neutron/modules/interchain-queries/explanation#why-is-it-mandatory-to-do-contracts-side-verification-of-submitted-tx-interchain-query-results). +- Handling the results in your business logic.
- Show code +Show code ```rust use neutron_sdk::sudo::msg::SudoMsg; @@ -661,7 +673,7 @@ pub fn sudo_tx_query_result( #### 4. Perform Interchain Query registration -Broadcast a [ExecuteMsg::RegisterUndelegationsQuery](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_tx_icq/src/msg.rs#L10-L14) message to the contract with required parameters. +Broadcast a [ExecuteMsg::RegisterUndelegationsQuery](https://github.com/neutron-org/neutron-dev-contracts/blob/9977666069741116cd95200ffb6ae05ab0834eae/contracts/docs/interchainqueries/howto/register_tx_icq/src/msg.rs#L10-L14) message to the contract with the required parameters. **Might be interesting:** - [Why is it mandatory to do contract's side verification of submitted TX Interchain Query results?](/neutron/modules/interchain-queries/explanation#why-is-it-mandatory-to-do-contracts-side-verification-of-submitted-tx-interchain-query-results) diff --git a/docs/neutron/modules/interchain-queries/known-bugs.md b/docs/neutron/modules/interchain-queries/known-bugs.md index 8a672f8c3..f0c25747d 100644 --- a/docs/neutron/modules/interchain-queries/known-bugs.md +++ b/docs/neutron/modules/interchain-queries/known-bugs.md @@ -2,4 +2,16 @@ ### Impossibility to retrieve and prove KV data with nil values -Due to a [bug](https://github.com/cosmos/ics23/issues/134) in ICS23 package, it's currently impossible to query an empty or `nil` value from a remote chain. Meaning if your KV-query is registered with key `K` and a value under this key is `nil` or empty, submission of such KV result will fail due to IAVL-proof verification error: `failed to verify proof: empty value in membership proof`. Moreover, due to [the nature of IAVL-proofs](https://github.com/cosmos/cosmos-sdk/blob/ae77f0080a724b159233bd9b289b2e91c0de21b5/docs/interfaces/lite/specification.md) (which is an underlying mechanism of verification of a validity of KV-queries results), it's also impossible to verify [IAVL-absence proof](https://github.com/cosmos/cosmos-sdk/blob/ae77f0080a724b159233bd9b289b2e91c0de21b5/docs/interfaces/lite/specification.md#iavl-absence-proof) if it contains IAVL-proof with `nil` or empty value: `failed to verify proof: could not verify absence of key. Please ensure that the path is correct.`. We are in contact with ics23 team to fix this issue ASAP, but in the meantime the only way to deal with the bug is to avoid querying keys with `nil` or empty values. +Due to a [bug](https://github.com/cosmos/ics23/issues/134) in the ICS23 package, it's currently not possible to query a `nil` or empty value from a remote chain. If your KV query is registered with a key `K` and the value under this key is `nil` or empty, the submission of such a KV result will fail due to an IAVL-proof verification error: + +``` +failed to verify proof: empty value in membership proof +``` + +Additionally, because of the [nature of IAVL proofs](https://github.com/cosmos/cosmos-sdk/blob/ae77f0080a724b159233bd9b289b2e91c0de21b5/docs/interfaces/lite/specification.md), which is the mechanism used for verifying KV query results, it's also impossible to verify an [IAVL absence proof](https://github.com/cosmos/cosmos-sdk/blob/ae77f0080a724b159233bd9b289b2e91c0de21b5/docs/interfaces/lite/specification.md#iavl-absence-proof) if the proof contains a `nil` or empty value. This results in the error: + +``` +failed to verify proof: could not verify absence of key. Please ensure that the path is correct. +``` + +We are in contact with the ICS23 team to resolve this issue as soon as possible. In the meantime, the only way to avoid this problem is to ensure that your queries do not target keys with `nil` or empty values. \ No newline at end of file diff --git a/docs/neutron/modules/interchain-queries/overview.md b/docs/neutron/modules/interchain-queries/overview.md index a935ba3aa..18f9e4029 100644 --- a/docs/neutron/modules/interchain-queries/overview.md +++ b/docs/neutron/modules/interchain-queries/overview.md @@ -1,25 +1,29 @@ # Overview -This document specifies the `interchainqueries` module for the Neutron network. +This document explains the `interchainqueries` module for the Neutron network. -Interchain Queries let developers retrieve verifiable data from distant blockchains — they’re crucial to building secure cross-chain applications. The implementation uses merkle proofs and IBC clients to verify data it retrieves directly from the target blockchain’s storage. It enables any smart-contract to register Interchain Queries and does not require any specific module on the target chain. +Interchain Queries allow developers to get verifiable data from other blockchains. This feature is essential for creating secure cross-chain applications. The module uses Merkle proofs and IBC clients to confirm the accuracy of the data retrieved directly from the storage of the target blockchain. It allows any smart contract to register Interchain Queries without needing any special module on the target blockchain. ## Table of contents -- [Overview](/neutron/modules/interchain-queries/overview) — high level description of the module; -- [API](/neutron/modules/interchain-queries/api) — description of the module's interface with endpoints, message models, emitted events; -- [Explanation](/neutron/modules/interchain-queries/explanation) — explanation of the module concepts and design resolution justifications; -- [How To](/neutron/modules/interchain-queries/how-to) — brief guides on how to do basic operations with the module; -- [Known Bugs](/neutron/modules/interchain-queries/known-bugs) — list of known bugs in the module. +- [Overview](/neutron/modules/interchain-queries/overview) — a high-level description of the module. +- [API](/neutron/modules/interchain-queries/api) — details about the module's interface, including endpoints, message models, and emitted events. +- [Explanation](/neutron/modules/interchain-queries/explanation) — an explanation of the module's concepts and the reasoning behind its design choices. +- [How To](/neutron/modules/interchain-queries/how-to) — short guides on performing basic operations with the module. +- [Known Bugs](/neutron/modules/interchain-queries/known-bugs) — a list of known issues in the module. ## Concepts -A smart-contract can register an Interchain Query to periodically retrieve some data from remote chain's state and to process the retrieved data in arbitrary way. There are two types of Interchain Queries: -* Key-Value query (KV query) - to read values from Cosmos-SDK KV-storage on remote chain which are stored under a set of keys. It can be balances of accounts, governance proposals, different staking info, smart contracts' state, and literally anything from a remote chain's KV-storage. Read more about how KV queries work by the [link](/neutron/modules/interchain-queries/explanation#how-do-kv-interchain-queries-work); -* Transactions query (TX query) - to find transactions on a remote chain by a list of parameters and equations (so called transactions filter) like transactions happened before some specific height, transactions sent to some specific recipient, or anything else that can be formed into a condition described by emitted events. Read more about how TX queries work by the [link](/neutron/modules/interchain-queries/explanation#how-do-tx-interchain-queries-work). +A smart contract can register an Interchain Query to regularly fetch data from a remote chain's state and process it in any way it needs. There are two types of Interchain Queries: -Interchain Queries, similar to IBC, requires an intermediary infrastructure called an [Interchain Query relayer](/neutron/modules/interchain-queries/explanation#what-is-an-interchain-query-relayer) that serves smart contracts. It's supposed to gather info (and cryptographic proofs that the info is valid) defined in Interchain Query parameters from a remote chain's state, and pass it to the `interchainqueries` module and, through that, to smart contracts for handling. The whole process is called Interchain Query execution, and the passing part is called Interchain Query result submission. The `interchainqueries` module has endpoints and events emission designated to facilitate relayer's work. Read more about the emitted events and endpoints in the [API section](/neutron/modules/interchain-queries/api). +- **Key-Value Query (KV Query)**: This type retrieves values from the Cosmos-SDK KV-storage on a remote chain, using a set of keys. It can be used to get account balances, governance proposals, staking information, smart contract states, or any other data stored in the remote chain's KV-storage. Learn more about how KV queries work [here](/neutron/modules/interchain-queries/explanation#how-do-kv-interchain-queries-work). -An Interchain Query relayer should submit a query result via the [SubmitQueryResult](/neutron/modules/interchain-queries/api#submitqueryresult) endpoint of the `interchainqueries` module. In scope of this endpoint, the `interchainqueries` module does result verification and calls the designated [sudo handler](/neutron/modules/interchain-queries/api#sudo) of the smart contract that is the owner of the Interchain Query. During this handler the smart contract is supposed to process the query result, i.e. to react on fresh data coming from the target chain. +- **Transactions Query (TX Query)**: This type finds transactions on a remote chain based on a set of parameters and conditions (called a transaction filter). For example, it can find transactions that happened before a specific block height, transactions sent to a certain recipient, or any other condition that can be defined using emitted events. Learn more about how TX queries work [here](/neutron/modules/interchain-queries/explanation#how-do-tx-interchain-queries-work). -One other similarity between the `interchainqueries` module and IBC is IBC clients usage. All Interchain Queries are about reading some data from a remote chain's storage, and the retrieved data is verified against ConsensusState of an IBC client to that chain. On result submission, the `interchainqueries` module verifies the storage values being submitted using the proofs being submitted against the Neutron side IBC client's ConsensusState, and therefore relies on the IBC protocol in terms of retrieved data authenticity. +Interchain Queries, like IBC, rely on an intermediary infrastructure called an [Interchain Query relayer](/neutron/modules/interchain-queries/explanation#what-is-an-interchain-query-relayer) to serve smart contracts. The relayer is responsible for collecting the requested information (along with cryptographic proofs to verify its validity) based on the parameters of the Interchain Query. It then delivers this data to the `interchainqueries` module, which forwards it to the smart contracts for processing. + +This entire process is called Interchain Query execution, and the step where the data is delivered is known as Interchain Query result submission. The `interchainqueries` module provides endpoints and emits specific events to make the relayer's job easier. You can find more details about these events and endpoints in the [API section](/neutron/modules/interchain-queries/api). + +An Interchain Query relayer submits a query result using the [SubmitQueryResult](/neutron/modules/interchain-queries/api#submitqueryresult) endpoint of the `interchainqueries` module. Through this endpoint, the `interchainqueries` module verifies the result and triggers the corresponding [sudo handler](/neutron/modules/interchain-queries/api#sudo) in the smart contract that owns the Interchain Query. The smart contract uses this handler to process the query result, reacting to the new data received from the target chain. + +Another similarity between the `interchainqueries` module and IBC is the use of IBC clients. All Interchain Queries involve reading data from a remote chain's storage, and this data is verified against the `ConsensusState` of an IBC client connected to that chain. During result submission, the `interchainqueries` module checks the submitted storage values using the provided proofs, comparing them against the `ConsensusState` of the IBC client on the Neutron side. This ensures that the authenticity of the retrieved data is guaranteed by the IBC protocol. From 70529f9ecc61e6f217c3b514e0aa48f1371f6138 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Mon, 25 Nov 2024 15:58:33 +0300 Subject: [PATCH 27/32] fix wording in ICS32 team mention --- docs/neutron/modules/interchain-queries/known-bugs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/neutron/modules/interchain-queries/known-bugs.md b/docs/neutron/modules/interchain-queries/known-bugs.md index f0c25747d..81f459d56 100644 --- a/docs/neutron/modules/interchain-queries/known-bugs.md +++ b/docs/neutron/modules/interchain-queries/known-bugs.md @@ -14,4 +14,4 @@ Additionally, because of the [nature of IAVL proofs](https://github.com/cosmos/c failed to verify proof: could not verify absence of key. Please ensure that the path is correct. ``` -We are in contact with the ICS23 team to resolve this issue as soon as possible. In the meantime, the only way to avoid this problem is to ensure that your queries do not target keys with `nil` or empty values. \ No newline at end of file +We are in contact with the team developing ICS32 to resolve this issue as soon as possible. In the meantime, the only way to avoid this problem is to ensure that your queries do not target keys with `nil` or empty values. \ No newline at end of file From 327d36a3a82abfa9e9ec65d4ca360593047d2802 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Mon, 25 Nov 2024 16:03:08 +0300 Subject: [PATCH 28/32] put link to ICQ relayer explanation in ICQs explanation sections instead of might be interesting --- docs/neutron/modules/interchain-queries/explanation.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/explanation.md b/docs/neutron/modules/interchain-queries/explanation.md index fd3c3a064..8a604c9b3 100644 --- a/docs/neutron/modules/interchain-queries/explanation.md +++ b/docs/neutron/modules/interchain-queries/explanation.md @@ -17,7 +17,7 @@ Typical Flow of KV Interchain Queries Usage: 4. The smart contract registers a KV Interchain Query with the necessary set of keys. The registered query is saved in the `interchainqueries` module's state. -5. An Interchain Query relayer reads the state of the `interchainqueries` module, finds the registered query and its parameters, and performs the `abci_query` RPC. This call returns a set of key-value pairs along with proofs from the `IAVL tree`. +5. An [Interchain Query relayer](/neutron/modules/interchain-queries/explanation#what-is-an-interchain-query-relayer) reads the state of the `interchainqueries` module, finds the registered query and its parameters, and performs the `abci_query` RPC. This call returns a set of key-value pairs along with proofs from the `IAVL tree`. 6. The relayer submits the key-value pairs and proofs to the `interchainqueries` module. This operation is called KV Interchain Query result submission. The module verifies the result using the proofs, stores it on-chain, and notifies the owning smart contract about the new result. @@ -28,7 +28,6 @@ Typical Flow of KV Interchain Queries Usage: **Might be interesting:** - [How to register and handle a KV Interchain Query](/neutron/modules/interchain-queries/how-to#how-to-register-and-handle-a-kv-interchain-query) - [How to register and handle a KV Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-and-handle-a-kv-interchain-query-with-custom-keys) -- [What is an Interchain Query relayer?](/neutron/modules/interchain-queries/explanation#what-is-an-interchain-query-relayer) ## How do TX Interchain Queries work? @@ -47,7 +46,7 @@ Typical Flow of TX Interchain Queries Usage: 4. The smart contract registers a TX Interchain Query with the specified set of transaction filters. The registered query is saved in the `interchainqueries` module's state. -5. An Interchain Query relayer reads the state of the `interchainqueries` module, finds the registered query and its parameters, and performs the `tx_search` RPC. This call returns a list of transactions that match the filters and have been successfully processed on the remote chain. +5. An [Interchain Query relayer](/neutron/modules/interchain-queries/explanation#what-is-an-interchain-query-relayer) reads the state of the `interchainqueries` module, finds the registered query and its parameters, and performs the `tx_search` RPC. This call returns a list of transactions that match the filters and have been successfully processed on the remote chain. 6. The relayer submits the list of transactions along with a few headers for each transaction (used to verify the result) to the `interchainqueries` module. This operation is called TX Interchain Query result submission. The module verifies the result using the headers and passes the data to the owning smart contract. @@ -60,7 +59,6 @@ Typical Flow of TX Interchain Queries Usage: - [How to find out what transaction filter to use](/neutron/modules/interchain-queries/how-to#how-to-find-out-what-transaction-filter-to-use) - [Why doesn't interchainqueries module store TX query results?](/neutron/modules/interchain-queries/explanation#why-doesnt-interchainqueries-module-store-tx-query-results) - [Why is it mandatory to do contract's side verification of submitted TX Interchain Query results?](/neutron/modules/interchain-queries/explanation#why-is-it-mandatory-to-do-contracts-side-verification-of-submitted-tx-interchain-query-results) -- [What is an Interchain Query relayer?](/neutron/modules/interchain-queries/explanation#what-is-an-interchain-query-relayer) ## What is an Interchain Query relayer? From 98d7214db43f2e1ba6fafb7e2db22e66ecd25b46 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Mon, 25 Nov 2024 16:13:22 +0300 Subject: [PATCH 29/32] add alternative way of finding events for transactions filter --- docs/neutron/modules/interchain-queries/how-to.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index c13adf414..84e249fa6 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -106,6 +106,10 @@ Identify the [Undelegate handler](https://github.com/cosmos/cosmos-sdk/blob/8bfc Examine the [event emission section](https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L447-L455) of the Undelegate handler code. +:::note +As an alternative for Steps 1-3, you can issue a transaction similar to the ones you want to capture using your transactions filter. After broadcasting the transaction, observe the emitted events list and use the event types and attributes to construct your query. +::: + #### 4. Create a transaction filter using the events Match the event type and attributes emitted. For this scenario, use the filter: From bbfa1690e4140a38f69c38ef6b14dcf2111cdbc4 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Mon, 25 Nov 2024 16:25:31 +0300 Subject: [PATCH 30/32] add links to neutron ICQ relayer implementation --- docs/neutron/modules/interchain-queries/explanation.md | 1 + docs/relaying/icq-relayer.md | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/neutron/modules/interchain-queries/explanation.md b/docs/neutron/modules/interchain-queries/explanation.md index 8a604c9b3..c4e9fe411 100644 --- a/docs/neutron/modules/interchain-queries/explanation.md +++ b/docs/neutron/modules/interchain-queries/explanation.md @@ -71,6 +71,7 @@ An Interchain Query relayer is an off-chain application that facilitates the fun - **Submitting query results**: Delivering the retrieved data and its corresponding proofs to the `interchainqueries` module, which then forwards it to the relevant smart contracts. **Might be interesting:** +- [Neutron implementation of an Interchain Query relayer](/relaying/icq-relayer) - [Limited gas for sudo calls](/neutron/modules/interchain-queries/explanation#limited-gas-for-sudo-calls) ## What's the role of IBC connections in Interchain Queries and how to choose one? diff --git a/docs/relaying/icq-relayer.md b/docs/relaying/icq-relayer.md index fb69ff953..535f65fa2 100644 --- a/docs/relaying/icq-relayer.md +++ b/docs/relaying/icq-relayer.md @@ -1,10 +1,14 @@ # ICQ Relayer +## Source code + +- Github: https://github.com/neutron-org/neutron-query-relayer + ## Overview [Interchain Queries](/neutron/modules/interchain-queries/overview) allow smart contracts to make queries to a remote chain. An ICQ Relayer is a required component for making them possible. It acts as a facilitator between the Neutron chain and a querying chain, gathering queries that are needed to be performed from the Neutron, actually performing them, and eventually making the results available for the Neutron's smart contracts. These three main responsibilities are described in details below. -If you are a smart contracts developer and up to develop your dApp on Neutron, you will most likely need your own ICQ Relayer to manage your Interchain Queries. +If you are a smart contracts developer and up to develop your dApp on Neutron, you will most likely need your own ICQ Relayer to manage your Interchain Queries. ### Queries gathering From ad236dc01efd9cfcc3be7d0f2829965e501ba54c Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Wed, 27 Nov 2024 10:51:30 +0300 Subject: [PATCH 31/32] refactor how to find tx filter for gaia v21.0.0 --- docs/neutron/modules/interchain-queries/how-to.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/neutron/modules/interchain-queries/how-to.md b/docs/neutron/modules/interchain-queries/how-to.md index 84e249fa6..ffb0f1efa 100644 --- a/docs/neutron/modules/interchain-queries/how-to.md +++ b/docs/neutron/modules/interchain-queries/how-to.md @@ -90,9 +90,9 @@ Imagine you need your Interchain Query-based smart contract to track undelegatio #### 1. Find the up-to-date source code of the staking module -1. Locate the current version of the `staking` module used by CosmosHub. Check the [chain registry](https://github.com/cosmos/chain-registry/blob/e346b6dbc0d901eec5e8704e0a7736bfdaa3dca9/cosmoshub/chain.json#L36-L37) to find the repository and version in use, e.g., `v19.2.0`. -2. In the `gaia` repository for `v19.2.0`, locate the [cosmos-sdk](https://github.com/cosmos/gaia/blob/v19.2.0/go.mod#L24) import in the `go.mod` file, e.g., `v0.50.9`. -3. Access the `staking` module's source code in the [cosmos-sdk with tag v0.50.9](https://github.com/cosmos/cosmos-sdk/tree/v0.50.9/x/staking). +1. Locate the current version of the `staking` module used by CosmosHub. Check the [chain registry](https://github.com/cosmos/chain-registry/blob/5e684932c8421a59cebe0b4cc5a2fde2d0633b44/cosmoshub/chain.json#L36-L37) to find the repository and version in use, e.g., `v21.0.0`. +2. In the `gaia` repository for `v21.0.0`, locate the [cosmos-sdk](https://github.com/cosmos/gaia/blob/v21.0.0/go.mod#L24) import in the `go.mod` file, e.g., `v0.50.9`. In this case, the `cosmos-sdk` version is replaced with a special release [v0.50.9-lsm](https://github.com/cosmos/gaia/blob/v21.0.0/go.mod#L251-L252) +3. Access the `staking` module's source code in the [cosmos-sdk with tag v0.50.9-lsm](https://github.com/cosmos/cosmos-sdk/tree/v0.50.9-lsm/x/staking). :::note Currently used versions might be different by the time you read this. @@ -100,11 +100,11 @@ Currently used versions might be different by the time you read this. #### 2. Find the handler managing undelegations -Identify the [Undelegate handler](https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L391-L392) in the `staking` module's keeper. +Identify the [Undelegate handler](https://github.com/cosmos/cosmos-sdk/tree/v0.50.9-lsm/x/staking/keeper/msg_server.go#L455-L456) in the `staking` module's keeper. #### 3. Locate the events emitted during undelegations -Examine the [event emission section](https://github.com/cosmos/cosmos-sdk/blob/8bfcf554275c1efbb42666cc8510d2da139b67fa/x/staking/keeper/msg_server.go#L447-L455) of the Undelegate handler code. +Examine the [event emission section](https://github.com/cosmos/cosmos-sdk/tree/v0.50.9-lsm/x/staking/keeper/msg_server.go#L542-L550) of the Undelegate handler code. :::note As an alternative for Steps 1-3, you can issue a transaction similar to the ones you want to capture using your transactions filter. After broadcasting the transaction, observe the emitted events list and use the event types and attributes to construct your query. From a7e13b2f08169a6732edded60265d5f3689a3903 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Wed, 27 Nov 2024 16:35:35 +0300 Subject: [PATCH 32/32] add explanation section that highlights reliance of KV ICQ on target chain storage layout --- .../modules/interchain-queries/explanation.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/neutron/modules/interchain-queries/explanation.md b/docs/neutron/modules/interchain-queries/explanation.md index c4e9fe411..db0c7ddbe 100644 --- a/docs/neutron/modules/interchain-queries/explanation.md +++ b/docs/neutron/modules/interchain-queries/explanation.md @@ -26,6 +26,7 @@ Typical Flow of KV Interchain Queries Usage: 8. Steps 5-7 are repeated periodically until the query is removed. **Might be interesting:** +- [The dependency of KV Interchain Queries on remote chain storage layout](/neutron/modules/interchain-queries/explanation#the-dependency-of-kv-interchain-queries-on-remote-chain-storage-layout) - [How to register and handle a KV Interchain Query](/neutron/modules/interchain-queries/how-to#how-to-register-and-handle-a-kv-interchain-query) - [How to register and handle a KV Interchain Query with custom keys](/neutron/modules/interchain-queries/how-to#how-to-register-and-handle-a-kv-interchain-query-with-custom-keys) @@ -74,6 +75,29 @@ An Interchain Query relayer is an off-chain application that facilitates the fun - [Neutron implementation of an Interchain Query relayer](/relaying/icq-relayer) - [Limited gas for sudo calls](/neutron/modules/interchain-queries/explanation#limited-gas-for-sudo-calls) +## The dependency of KV Interchain Queries on remote chain storage layout + +KV Interchain Queries rely heavily on the storage layout of the remote chain, including the paths to IAVL leaf nodes and the data models used to represent the stored information. The accuracy and functionality of KV Interchain Queries depend entirely on the correctness of the paths and the consistency of the data models. This tight coupling introduces several considerations and potential challenges for dApp developers. The [neutron-sdk interchain queries related package](https://docs.rs/neutron-sdk/0.11.0/neutron_sdk/interchain_queries/index.html#) includes target chain version separation precisely for this reasoning. + +- Each KV Interchain Query requires the exact path to the desired entry in the IAVL tree of the remote chain. These paths are specific to the version and implementation of the modules on the remote chain. If a path is incorrect or becomes outdated, the query will fail. +- The structure of the data retrieved from the IAVL tree must match the expected model in the dApp. Changes in the data model due to updates or modifications in the remote chain's code can lead to errors in decoding or interpreting the retrieved data. + +Recomendations for dApp developers: + +1. **Follow and communicate**: + - Regularly monitor release notes, upgrade announcements, and repository updates of the target chains. + - Participate in the target chain’s community discussions to stay informed about upcoming changes. + - Work closely with remote chain developers to understand their module design and planned upgrades. + - Advocate for better documentation and tools that simplify storage layout discovery. + +2. **Secure with code**: + - Continuously run your dApp on the testnet of the target chain to catch breaking changes before they affect the mainnet. + - Set up automated integration tests that verify the correctness of KV Interchain Queries against the latest builds. + - Set up monitoring for target chain versions to detect changes proactively. + - Build fallback mechanisms to detect and handle query failures gracefully. + +In the event of an upcoming breaking change, update your codebase and prepare to upgrade your dApp on the mainnet once the remote chain is updated. + ## What's the role of IBC connections in Interchain Queries and how to choose one? IBC [clients](https://ibc.cosmos.network/v8/ibc/overview/#clients) and [connections](https://ibc.cosmos.network/v8/ibc/overview/#connections) play a crucial role in ensuring the authenticity of Interchain Queries. When an IBC connection is initialized, it creates IBC clients and verifies that their states are accurate for their respective counterparties. These client states are then used to verify the results of Interchain Queries. The chosen connection ID for an Interchain Query directly impacts the trustworthiness of the entire Interchain Queries-based application.