Skip to content

Commit

Permalink
feat: query wasm contract state
Browse files Browse the repository at this point in the history
  • Loading branch information
foxpy committed Jun 6, 2023
1 parent 3841c59 commit 45ef7ce
Show file tree
Hide file tree
Showing 15 changed files with 427 additions and 8 deletions.
34 changes: 34 additions & 0 deletions contracts/neutron_interchain_queries/schema/execute_msg.json
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,40 @@
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"register_wasm_contract_state_query"
],
"properties": {
"register_wasm_contract_state_query": {
"type": "object",
"required": [
"connection_id",
"contract_address",
"storage_key",
"update_period"
],
"properties": {
"connection_id": {
"type": "string"
},
"contract_address": {
"type": "string"
},
"storage_key": {
"type": "string"
},
"update_period": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
}
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
Expand Down
22 changes: 22 additions & 0 deletions contracts/neutron_interchain_queries/schema/query_msg.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,28 @@
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"get_wasm_contract_state"
],
"properties": {
"get_wasm_contract_state": {
"type": "object",
"required": [
"query_id"
],
"properties": {
"query_id": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
}
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
Expand Down
35 changes: 33 additions & 2 deletions contracts/neutron_interchain_queries/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,22 @@ use neutron_sdk::bindings::types::{Height, KVKey};
use neutron_sdk::interchain_queries::get_registered_query;
use neutron_sdk::interchain_queries::v045::queries::{
query_balance, query_bank_total, query_delegations, query_distribution_fee_pool,
query_government_proposals, query_staking_validators,
query_government_proposals, query_staking_validators, query_wasm_contract_state,
};
use neutron_sdk::interchain_queries::v045::{
new_register_balance_query_msg, new_register_bank_total_supply_query_msg,
new_register_delegator_delegations_query_msg, new_register_distribution_fee_pool_query_msg,
new_register_gov_proposal_query_msg, new_register_staking_validators_query_msg,
new_register_transfers_query_msg,
register_queries::new_register_wasm_contract_store_query_msg,
types::{COSMOS_SDK_TRANSFER_MSG_URL, RECIPIENT_FIELD},
};
use neutron_sdk::sudo::msg::SudoMsg;
use neutron_sdk::{NeutronError, NeutronResult};

use neutron_sdk::interchain_queries::types::{
TransactionFilterItem, TransactionFilterOp, TransactionFilterValue,
};
use neutron_sdk::interchain_queries::v045::types::{COSMOS_SDK_TRANSFER_MSG_URL, RECIPIENT_FIELD};
use serde_json_wasm;

/// defines the incoming transfers limit to make a case of failed callback possible.
Expand Down Expand Up @@ -95,6 +96,17 @@ pub fn execute(
update_period,
min_height,
} => register_transfers_query(connection_id, recipient, update_period, min_height),
ExecuteMsg::RegisterWasmContractStateQuery {
connection_id,
update_period,
contract_address,
storage_key,
} => register_wasm_contract_state_query(
connection_id,
update_period,
contract_address,
storage_key,
),
ExecuteMsg::UpdateInterchainQuery {
query_id,
new_keys,
Expand Down Expand Up @@ -183,6 +195,22 @@ pub fn register_transfers_query(
Ok(Response::new().add_message(msg))
}

pub fn register_wasm_contract_state_query(
connection_id: String,
update_period: u64,
contract_address: String,
storage_key: String,
) -> NeutronResult<Response<NeutronMsg>> {
let msg = new_register_wasm_contract_store_query_msg(
connection_id,
contract_address,
storage_key,
update_period,
)?;

Ok(Response::new().add_message(msg))
}

pub fn update_interchain_query(
query_id: u64,
new_keys: Option<Vec<KVKey>>,
Expand Down Expand Up @@ -227,6 +255,9 @@ pub fn query(deps: Deps<NeutronQuery>, env: Env, msg: QueryMsg) -> NeutronResult
QueryMsg::GetDelegations { query_id } => {
Ok(to_binary(&query_delegations(deps, env, query_id)?)?)
}
QueryMsg::GetWasmContractState { query_id } => {
query_wasm_contract_state(deps, env, query_id)
}
QueryMsg::GetRegisteredQuery { query_id } => {
Ok(to_binary(&get_registered_query(deps, query_id)?)?)
}
Expand Down
7 changes: 7 additions & 0 deletions contracts/neutron_interchain_queries/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ pub enum ExecuteMsg {
connection_id: String,
update_period: u64,
},
RegisterWasmContractStateQuery {
connection_id: String,
update_period: u64,
contract_address: String,
storage_key: String,
},
UpdateInterchainQuery {
query_id: u64,
new_keys: Option<Vec<KVKey>>,
Expand All @@ -66,6 +72,7 @@ pub enum QueryMsg {
StakingValidators { query_id: u64 },
GovernmentProposals { query_id: u64 },
GetDelegations { query_id: u64 },
GetWasmContractState { query_id: u64 },
GetRegisteredQuery { query_id: u64 },
GetRecipientTxs { recipient: String },
}
Expand Down
2 changes: 1 addition & 1 deletion packages/neutron-sdk/src/interchain_queries/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub fn query_kv_result<T: KVReconstruct>(
}

/// Queries interchain query result (raw KV storage values or transactions) from Interchain Queries Module
fn get_interchain_query_result(
pub fn get_interchain_query_result(
deps: Deps<NeutronQuery>,
interchain_query_id: u64,
) -> NeutronResult<QueryRegisteredQueryResultResponse> {
Expand Down
15 changes: 14 additions & 1 deletion packages/neutron-sdk/src/interchain_queries/v045/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::errors::error::NeutronResult;
use crate::interchain_queries::helpers::length_prefix;
use crate::interchain_queries::v045::types::{
BALANCES_PREFIX, DELEGATION_KEY, FEE_POOL_KEY, PARAMS_STORE_DELIMITER, PROPOSALS_KEY_PREFIX,
SUPPLY_PREFIX, VALIDATORS_KEY,
SUPPLY_PREFIX, VALIDATORS_KEY, WASM_CONTRACT_STORE_PREFIX,
};
use cosmos_sdk_proto::cosmos::staking::v1beta1::Commission as ValidatorCommission;
use cosmwasm_std::{Binary, Decimal, Uint128};
Expand Down Expand Up @@ -93,6 +93,19 @@ pub fn create_validator_key<AddrBytes: AsRef<[u8]>>(
Ok(key)
}

/// Creates Cosmos-SDK distribution key for fee pool
/// <https://github.com/cosmos/cosmos-sdk/blob/35ae2c4c72d4aeb33447d5a7af23ca47f786606e/x/distribution/types/keys.go#L46>
pub fn create_wasm_contract_store_key<AddrBytes: AsRef<[u8]>, Key: AsRef<[u8]>>(
contract_address: AddrBytes,
key: Key,
) -> NeutronResult<Vec<u8>> {
let mut prefix: Vec<u8> = vec![WASM_CONTRACT_STORE_PREFIX];
prefix.extend_from_slice(contract_address.as_ref());
prefix.extend_from_slice(key.as_ref());

Ok(prefix)
}

/// Creates Cosmos-SDK distribution key for fee pool
/// <https://github.com/cosmos/cosmos-sdk/blob/35ae2c4c72d4aeb33447d5a7af23ca47f786606e/x/distribution/types/keys.go#L46>
pub fn create_fee_pool_key() -> NeutronResult<Vec<u8>> {
Expand Down
27 changes: 25 additions & 2 deletions packages/neutron-sdk/src/interchain_queries/v045/queries.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use crate::bindings::query::NeutronQuery;
use crate::interchain_queries::queries::{check_query_type, get_registered_query, query_kv_result};
use crate::interchain_queries::queries::{
check_query_type, get_interchain_query_result, get_registered_query, query_kv_result,
};
use crate::interchain_queries::types::QueryType;
use crate::interchain_queries::v045::types::{
Balances, Delegations, FeePool, GovernmentProposal, StakingValidator, TotalSupply,
};
use crate::NeutronResult;
use cosmwasm_std::{Deps, Env};
use cosmwasm_std::{Binary, Deps, Env, StdError};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -176,3 +178,24 @@ pub fn query_delegations(
.last_submitted_result_local_height,
})
}

pub fn query_wasm_contract_state(
deps: Deps<NeutronQuery>,
_env: Env,
registered_query_id: u64,
) -> NeutronResult<Binary> {
let registered_query = get_registered_query(deps, registered_query_id)?;

check_query_type(registered_query.registered_query.query_type, QueryType::KV)?;

let mut response = get_interchain_query_result(deps, registered_query_id)?;

// we expect exactly one storage value
let result = response
.result
.kv_results
.pop()
.ok_or_else(|| StdError::generic_err("empty query result"))?;

Ok(result.value)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::interchain_queries::types::{
};
use crate::interchain_queries::v045::types::{
BANK_STORE_KEY, DISTRIBUTION_STORE_KEY, GOV_STORE_KEY, HEIGHT_FIELD, KEY_BOND_DENOM,
PARAMS_STORE_KEY, RECIPIENT_FIELD, STAKING_STORE_KEY,
PARAMS_STORE_KEY, RECIPIENT_FIELD, STAKING_STORE_KEY, WASM_STORE_KEY,
};
use crate::{
bindings::{msg::NeutronMsg, types::KVKey},
Expand All @@ -12,7 +12,7 @@ use crate::{
interchain_queries::v045::helpers::{
create_account_denom_balance_key, create_delegation_key, create_fee_pool_key,
create_gov_proposal_key, create_params_store_key, create_total_denom_key,
create_validator_key,
create_validator_key, create_wasm_contract_store_key,
},
};
use cosmwasm_std::Binary;
Expand Down Expand Up @@ -185,6 +185,33 @@ pub fn new_register_delegator_delegations_query_msg(
NeutronMsg::register_interchain_query(QueryPayload::KV(keys), connection_id, update_period)
}

/// Creates a message to register an Interchain Query to get wasm contract store on remote chain
/// from **wasm** module
///
/// * **connection_id** is an IBC connection identifier between Neutron and remote chain;
/// * **key** is a wasm contract store key
/// * **update_period** is used to say how often the query must be updated.
pub fn new_register_wasm_contract_store_query_msg(
connection_id: String,
contract_address: String,
key: String,
update_period: u64,
) -> NeutronResult<NeutronMsg> {
let converted_addr_bytes = decode_and_convert(contract_address.as_str())?;
let wasm_key = create_wasm_contract_store_key(converted_addr_bytes, key.as_bytes())?;

let kv_key = KVKey {
path: WASM_STORE_KEY.to_string(),
key: Binary(wasm_key),
};

NeutronMsg::register_interchain_query(
QueryPayload::KV(vec![kv_key]),
connection_id,
update_period,
)
}

/// Creates a message to register an Interchain Query to get transfer events to a recipient on a remote chain.
///
/// * **connection_id** is an IBC connection identifier between Neutron and remote chain;
Expand Down
7 changes: 7 additions & 0 deletions packages/neutron-sdk/src/interchain_queries/v045/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ pub const FEE_POOL_KEY: u8 = 0x00;
/// <https://github.com/cosmos/cosmos-sdk/blob/35ae2c4c72d4aeb33447d5a7af23ca47f786606e/x/gov/types/keys.go#L41>
pub const PROPOSALS_KEY_PREFIX: u8 = 0x00;

/// Key for Wasm Contract Store in the **wasm** module's storage
/// <https://github.com/CosmWasm/wasmd/blob/e6d451bf9dd96a555b10e72aa3c0f6b820d34684/x/wasm/types/keys.go#L28>
pub const WASM_CONTRACT_STORE_PREFIX: u8 = 0x03;

/// Name of the standard **bank** Cosmos-SDK module
pub const BANK_STORE_KEY: &str = "bank";

Expand All @@ -72,6 +76,9 @@ pub const PARAMS_STORE_KEY: &str = "params";
/// Default delimiter of **params** Cosmos-SDK module
pub const PARAMS_STORE_DELIMITER: &str = "/";

/// Name of the **wasm** Cosmos module
pub const WASM_STORE_KEY: &str = "wasm";

pub const RECIPIENT_FIELD: &str = "transfer.recipient";
pub const HEIGHT_FIELD: &str = "tx.height";

Expand Down
1 change: 1 addition & 0 deletions scripts/test_icq_wasm_juno_testnet/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
storage/
55 changes: 55 additions & 0 deletions scripts/test_icq_wasm_juno_testnet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Test ICQ wasm contract state using Juno testnet

## 1. Install dependencies

Read [instructions](https://docs.neutron.org/neutron/build-and-run/localnet)
and install:
- neutron
- hermes
- neutron query relayer

## 2. Launch neutron

Go to `neutron/` directory and run `make start`.
This will deploy Neutron localnet.
Please wait 20 to 30 seconds for chain to initialize before
proceeding to step 3.

## 3. Connect to Juno testnet

Open `create_juno_connection.sh` in your text editor of choice.
Navigate to `JUNO_MNEMONIC=""` and insert there your own testnet mnemonic.
Please make sure to have at least 0.01 JUNOX on uni-6 testnet, these funds
are needed to create a connection.

Run `./create_juno_connection.sh`. After it finishes, `connection-0` should
appear on Neutron localnet. You can use this snippet to query a list of
connections on Neutron's localnet:

```bash
neutrond query ibc connection connections --node tcp://0.0.0.0:26657 --output json | jq '.connections[] | {id, client_id, state, counterparty}'
```

If this is the first time you are running this script, you should only
see `connection-0`. Don't worry if you see `connection-1`, `connection-2`
and so on, simply use the last one you have created.

## 4. Deploy ICQ relayer

Open `icq.env` in your text editor of choice.
Navigate to `RELAYER_NEUTRON_CHAIN_CONNECTION_ID=` and insert there
connection ID you have just created.

```bash
rm -rf storage/; export $(xargs < icq.env) && neutron_query_relayer start
```

## 5. Prepare to run test

Open `test_wasm_query.sh` in your text editor of choice.
Navigate to `CONNECTION_ID=""` and insert there
connection ID you have just created.

## 6. Run test

Execute `./test_wasm_query.sh`.
Loading

0 comments on commit 45ef7ce

Please sign in to comment.