Skip to content

Commit

Permalink
Implement all missing v1 QueryPlugins
Browse files Browse the repository at this point in the history
  • Loading branch information
assafmo committed Aug 22, 2022
1 parent 8755a43 commit 40c02fe
Show file tree
Hide file tree
Showing 8 changed files with 398 additions and 66 deletions.
42 changes: 42 additions & 0 deletions cosmwasm/enclaves/shared/cosmwasm-v010-types/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,33 @@ pub enum QueryRequest {
Dist(DistQuery),
Mint(MintQuery),
Gov(GovQuery),
Ibc(IbcQuery),
}

/// These are queries to the various IBC modules to see the state of the contract's
/// IBC connection. These will return errors if the contract is not "ibc enabled"
#[non_exhaustive]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum IbcQuery {
/// Gets the Port ID the current contract is bound to.
///
/// Returns a `PortIdResponse`.
PortId {},
/// Lists all channels that are bound to a given port.
/// If `port_id` is omitted, this list all channels bound to the contract's port.
///
/// Returns a `ListChannelsResponse`.
ListChannels { port_id: Option<String> },
/// Lists all information for a (portID, channelID) pair.
/// If port_id is omitted, it will default to the contract's own channel.
/// (To save a PortId{} call)
///
/// Returns a `ChannelResponse`.
Channel {
channel_id: String,
port_id: Option<String>,
},
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
Expand Down Expand Up @@ -97,6 +124,8 @@ pub enum WasmQuery {
/// Key is the raw key used in the contracts Storage
key: Binary,
},
/// returns a ContractInfoResponse with metadata on the contract from the runtime
ContractInfo { contract_addr: String },
}

impl From<GovQuery> for QueryRequest {
Expand Down Expand Up @@ -153,6 +182,19 @@ pub enum StakingQuery {
Validators {},
/// Returns all the unbonding delegations by the delegator
UnbondingDelegations { delegator: HumanAddr },

/// Returns all validators in the currently active validator set.
///
/// The query response type is `AllValidatorsResponse`.
AllValidators {},
/// Returns the validator at the given address. Returns None if the validator is
/// not part of the currently active validator set.
///
/// The query response type is `ValidatorResponse`.
Validator {
/// The validator's address (e.g. (e.g. cosmosvaloper1...))
address: String,
},
}

/// Delegation is basic (cheap to query) data about a delegation
Expand Down
181 changes: 178 additions & 3 deletions go-cosmwasm/types/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,27 @@ type StakingQuery struct {
Validators *ValidatorsQuery `json:"validators,omitempty"`
AllDelegations *AllDelegationsQuery `json:"all_delegations,omitempty"`
Delegation *DelegationQuery `json:"delegation,omitempty"`
UnBondingDelegations *UnbondingDeletionsQuery `json:"unbonding_delegations, omitempty"`
UnBondingDelegations *UnbondingDeletionsQuery `json:"unbonding_delegations,omitempty"`
BondedDenom *struct{} `json:"bonded_denom,omitempty"`
AllValidators *AllValidatorsQuery `json:"all_validators,omitempty"`
Validator *ValidatorQuery `json:"validator,omitempty"`
}

type AllValidatorsQuery struct{}

// AllValidatorsResponse is the expected response to AllValidatorsQuery
type AllValidatorsResponse struct {
Validators Validators `json:"validators"`
}

type ValidatorQuery struct {
/// Address is the validator's address (e.g. cosmosvaloper1...)
Address string `json:"address"`
}

// ValidatorResponse is the expected response to ValidatorQuery
type ValidatorResponse struct {
Validator *Validator `json:"validator"` // serializes to `null` when unset which matches Rust's Option::None serialization
}

type UnbondingDeletionsQuery struct {
Expand Down Expand Up @@ -219,22 +238,40 @@ type BondedDenomResponse struct {
}

type WasmQuery struct {
Smart *SmartQuery `json:"smart,omitempty"`
Raw *RawQuery `json:"raw,omitempty"`
Smart *SmartQuery `json:"smart,omitempty"`
Raw *RawQuery `json:"raw,omitempty"`
ContractInfo *ContractInfoQuery `json:"contract_info,omitempty"`
}

// SmartQuery respone is raw bytes ([]byte)
type SmartQuery struct {
// Bech32 encoded sdk.AccAddress of the contract
ContractAddr string `json:"contract_addr"`
Msg []byte `json:"msg"`
}

// RawQuery response is raw bytes ([]byte)
type RawQuery struct {
// Bech32 encoded sdk.AccAddress of the contract
ContractAddr string `json:"contract_addr"`
Key []byte `json:"key"`
}

type ContractInfoQuery struct {
// Bech32 encoded sdk.AccAddress of the contract
ContractAddr string `json:"contract_addr"`
}

type ContractInfoResponse struct {
CodeID uint64 `json:"code_id"`
Creator string `json:"creator"`
// Set to the admin who can migrate contract, if any
Admin string `json:"admin,omitempty"`
Pinned bool `json:"pinned"`
// Set if the contract is IBC enabled
IBCPort string `json:"ibc_port,omitempty"`
}

type DistQuery struct {
Rewards *RewardsQuery `json:"rewards,omitempty"`
}
Expand All @@ -255,6 +292,144 @@ type StargateQuery struct {
Data []byte `json:"data"`
}

// IBCQuery defines a query request from the contract into the chain.
// This is the counterpart of [IbcQuery](https://github.com/CosmWasm/cosmwasm/blob/v0.14.0-beta1/packages/std/src/ibc.rs#L61-L83).
type IBCQuery struct {
PortID *PortIDQuery `json:"port_id,omitempty"`
ListChannels *ListChannelsQuery `json:"list_channels,omitempty"`
Channel *ChannelQuery `json:"channel,omitempty"`
}

type PortIDQuery struct{}

type PortIDResponse struct {
PortID string `json:"port_id"`
}

// ListChannelsQuery is an IBCQuery that lists all channels that are bound to a given port.
// If `PortID` is unset, this list all channels bound to the contract's port.
// Returns a `ListChannelsResponse`.
// This is the counterpart of [IbcQuery::ListChannels](https://github.com/CosmWasm/cosmwasm/blob/v0.14.0-beta1/packages/std/src/ibc.rs#L70-L73).
type ListChannelsQuery struct {
// optional argument
PortID string `json:"port_id,omitempty"`
}

type ListChannelsResponse struct {
Channels IBCChannels `json:"channels"`
}

type IBCEndpoint struct {
PortID string `json:"port_id"`
ChannelID string `json:"channel_id"`
}

// TODO: test what the sdk Order.String() represents and how to parse back
// Proto files: https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/ibc/core/channel/v1/channel.proto#L69-L80
// Auto-gen code: https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/x/ibc/core/04-channel/types/channel.pb.go#L70-L101
type IBCOrder = string

// These are the only two valid values for IbcOrder
const Unordered = "ORDER_UNORDERED"
const Ordered = "ORDER_ORDERED"

type IBCChannel struct {
Endpoint IBCEndpoint `json:"endpoint"`
CounterpartyEndpoint IBCEndpoint `json:"counterparty_endpoint"`
Order IBCOrder `json:"order"`
Version string `json:"version"`
ConnectionID string `json:"connection_id"`
}

type IBCOpenInit struct {
Channel IBCChannel `json:"channel"`
}

func (m *IBCOpenInit) ToMsg() IBCChannelOpenMsg {
return IBCChannelOpenMsg{
OpenInit: m,
}
}

type IBCOpenTry struct {
Channel IBCChannel `json:"channel"`
CounterpartyVersion string `json:"counterparty_version"`
}

func (m *IBCOpenTry) ToMsg() IBCChannelOpenMsg {
return IBCChannelOpenMsg{
OpenTry: m,
}
}

type IBCChannelOpenMsg struct {
OpenInit *IBCOpenInit `json:"open_init,omitempty"`
OpenTry *IBCOpenTry `json:"open_try,omitempty"`
}

// IBCChannels must JSON encode empty array as [] (not null) for consistency with Rust parser
type IBCChannels []IBCChannel

// MarshalJSON ensures that we get [] for empty arrays
func (e IBCChannels) MarshalJSON() ([]byte, error) {
if len(e) == 0 {
return []byte("[]"), nil
}
var raw []IBCChannel = e
return json.Marshal(raw)
}

// UnmarshalJSON ensures that we get [] for empty arrays
func (e *IBCChannels) UnmarshalJSON(data []byte) error {
// make sure we deserialize [] back to null
if string(data) == "[]" || string(data) == "null" {
return nil
}
var raw []IBCChannel
if err := json.Unmarshal(data, &raw); err != nil {
return err
}
*e = raw
return nil
}

// IBCEndpoints must JSON encode empty array as [] (not null) for consistency with Rust parser
type IBCEndpoints []IBCEndpoint

// MarshalJSON ensures that we get [] for empty arrays
func (e IBCEndpoints) MarshalJSON() ([]byte, error) {
if len(e) == 0 {
return []byte("[]"), nil
}
var raw []IBCEndpoint = e
return json.Marshal(raw)
}

// UnmarshalJSON ensures that we get [] for empty arrays
func (e *IBCEndpoints) UnmarshalJSON(data []byte) error {
// make sure we deserialize [] back to null
if string(data) == "[]" || string(data) == "null" {
return nil
}
var raw []IBCEndpoint
if err := json.Unmarshal(data, &raw); err != nil {
return err
}
*e = raw
return nil
}

type ChannelQuery struct {
// optional argument
PortID string `json:"port_id,omitempty"`
ChannelID string `json:"channel_id"`
}

type ChannelResponse struct {
// may be empty if there is no matching channel
Channel *IBCChannel `json:"channel,omitempty"`
}

type MintQuery struct {
Inflation *MintingInflationQuery `json:"inflation,omitempty"`
BondedRatio *MintingBondedRatioQuery `json:"bonded_ratio,omitempty"`
Expand Down
14 changes: 11 additions & 3 deletions integration-tests/contract-v1/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use cosmwasm_std::{
entry_point, BankMsg, Binary, CosmosMsg, Deps, DepsMut, DistributionMsg, Env, GovMsg, IbcMsg,
MessageInfo, Response, StakingMsg, StdResult, WasmMsg,
MessageInfo, QueryRequest, Response, StakingMsg, StdResult, WasmMsg,
};

use crate::msg::{Msg, QueryMsg};
Expand Down Expand Up @@ -141,6 +141,14 @@ fn handle_msg(_deps: DepsMut, _env: Env, _info: MessageInfo, msg: Msg) -> StdRes
}

#[entry_point]
pub fn query(_deps: Deps, _env: Env, _msg: QueryMsg) -> StdResult<Binary> {
return Ok(Binary(vec![]));
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::StargateQuery { path, data } => {
let res = deps
.querier
.query::<Binary>(&QueryRequest::Stargate { path, data });
deps.api.debug(&format!("ASSAF {:?}", res));
return Ok(res?);
}
}
}
8 changes: 3 additions & 5 deletions integration-tests/contract-v1/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ pub enum Msg {

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryRes {}
pub enum QueryMsg {
StargateQuery { path: String, data: Binary },
}
27 changes: 24 additions & 3 deletions integration-tests/test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { SecretNetworkClient, toBase64, toHex, Wallet } from "secretjs";
import { MsgSend } from "secretjs/dist/protobuf_stuff/cosmos/bank/v1beta1/tx";
import {
QueryBalanceRequest,
QueryBalanceResponse,
} from "secretjs/dist/protobuf_stuff/cosmos/bank/v1beta1/query";
import { sha256 } from "@noble/hashes/sha256";
import * as fs from "fs";

Expand Down Expand Up @@ -117,7 +121,7 @@ async function waitForBlocks() {
}
}

describe("BankMsg::Send", () => {
describe("Bank::MsgSend", () => {
test("v1", async () => {
const tx = await accounts.a.tx.compute.executeContract(
{
Expand Down Expand Up @@ -241,8 +245,25 @@ describe("StargateMsg", () => {
]
);
});
});

test("v0.10", async () => {
// TODO
describe("StargateQuery", () => {
test("v1", async () => {
const result = await accounts.a.query.compute.queryContract({
contractAddress: v1Address,
codeHash: v1CodeHash,
query: {
stargate_query: {
path: "/cosmos.bank.v1beta1.Query.Balance",
data: toBase64(
QueryBalanceRequest.encode({
address: accounts.a.address,
denom: "uscrt",
}).finish()
),
},
},
});
console.log(result);
});
});
Loading

0 comments on commit 40c02fe

Please sign in to comment.