Skip to content

Commit

Permalink
imp: remove stargate query (#31)
Browse files Browse the repository at this point in the history
* imp: removed stargate query

* imp(e2e): fixed tests

* deps(e2e): ran 'go mod tidy'

* style: ran 'cargo fmt'

* test: fixed tests
  • Loading branch information
srdtrk authored Dec 11, 2023
1 parent 7acbc64 commit 7150af5
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 136 deletions.
5 changes: 2 additions & 3 deletions e2e/interchaintest/contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ func (s *ContractTestSuite) TestRecoveredIcaContractInstantiatedChannelHandshake
})

s.Run("TestChannelHandshakeSuccessAfterFail", func() {
err = s.Contract.ExecCreateChannel(ctx, wasmdUser.KeyName(), s.ChainAConnID, s.ChainBConnID, nil, nil, "--gas", "500000")
err = s.Contract.ExecCreateChannelWithOptions(ctx, wasmdUser.KeyName(), s.ChainAConnID, s.ChainBConnID, nil, nil, "--gas", "500000")
s.Require().NoError(err)

// Wait for the channel to get set up
Expand Down Expand Up @@ -555,8 +555,7 @@ func (s *ContractTestSuite) TestIcaContractTimeoutPacket() {

s.Run("TestChannelReopening", func() {
// Reopen the channel:
txEncoding := icatypes.EncodingProto3JSON
err := s.Contract.ExecCreateChannel(ctx, wasmdUser.KeyName(), s.ChainAConnID, s.ChainBConnID, nil, &txEncoding, "--gas", "500000")
err := s.Contract.ExecCreateChannel(ctx, wasmdUser.KeyName(), "--gas", "500000")
s.Require().NoError(err)

// Wait for the channel to get set up
Expand Down
2 changes: 1 addition & 1 deletion e2e/interchaintest/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ require (
github.com/strangelove-ventures/interchaintest/v7 v7.0.0-20231025163603-99ec15f2674d
github.com/stretchr/testify v1.8.4
go.uber.org/zap v1.26.0
google.golang.org/grpc v1.57.0
)

require (
Expand Down Expand Up @@ -212,7 +213,6 @@ require (
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
google.golang.org/grpc v1.57.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
Expand Down
8 changes: 8 additions & 0 deletions e2e/interchaintest/types/ica_contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ func StoreAndInstantiateNewIcaContract(
}

func (c *IcaContract) ExecCreateChannel(
ctx context.Context, callerKeyName string, extraExecTxArgs ...string,
) error {
msg := newEmptyCreateChannelMsg()
err := c.Execute(ctx, callerKeyName, msg, extraExecTxArgs...)
return err
}

func (c *IcaContract) ExecCreateChannelWithOptions(
ctx context.Context, callerKeyName string, connectionId string,
counterpartyConnectionId string, counterpartyPortId *string,
txEncoding *string, extraExecTxArgs ...string,
Expand Down
14 changes: 12 additions & 2 deletions e2e/interchaintest/types/ica_msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,20 @@ func NewInstantiateMsgWithChannelInitOptions(
return string(jsonBytes)
}

func newEmptyCreateChannelMsg() string {
return `{ "create_channel": {} }`
}

func newCreateChannelMsg(
connectionId string, counterpartyConnectionId string,
counterpartyPortId *string, txEncoding *string,
) string {
type ChannelCreateMsg struct {
ChannelOpenInitOptions *ChannelOpenInitOptions `json:"channel_open_init_options,omitempty"`
}

type ChannelCreateMsgWrapper struct {
CreateChannelMsg ChannelOpenInitOptions `json:"create_channel"`
CreateChannelMsg ChannelCreateMsg `json:"create_channel"`
}

channelOpenInitOptions := ChannelOpenInitOptions{
Expand All @@ -83,7 +91,9 @@ func newCreateChannelMsg(
}

msg := ChannelCreateMsgWrapper{
CreateChannelMsg: channelOpenInitOptions,
CreateChannelMsg: ChannelCreateMsg{
ChannelOpenInitOptions: &channelOpenInitOptions,
},
}

jsonBytes, err := json.Marshal(msg)
Expand Down
31 changes: 23 additions & 8 deletions src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use crate::ibc::types::stargate::channel::new_ica_channel_open_init_cosmos_msg;
use crate::types::keys::{CONTRACT_NAME, CONTRACT_VERSION};
use crate::types::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};
use crate::types::state::{
CallbackCounter, ChannelState, ContractState, CALLBACK_COUNTER, CHANNEL_STATE, STATE,
CallbackCounter, ChannelState, ContractState, CALLBACK_COUNTER, CHANNEL_OPEN_INIT_OPTIONS,
CHANNEL_STATE, STATE,
};
use crate::types::ContractError;

Expand Down Expand Up @@ -37,6 +38,8 @@ pub fn instantiate(

// If channel open init options are provided, open the channel.
if let Some(channel_open_init_options) = msg.channel_open_init_options {
CHANNEL_OPEN_INIT_OPTIONS.save(deps.storage, &channel_open_init_options)?;

let ica_channel_open_init_msg = new_ica_channel_open_init_cosmos_msg(
env.contract.address.to_string(),
channel_open_init_options.connection_id,
Expand All @@ -61,7 +64,9 @@ pub fn execute(
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
match msg {
ExecuteMsg::CreateChannel(options) => execute::create_channel(deps, env, info, options),
ExecuteMsg::CreateChannel {
channel_open_init_options,
} => execute::create_channel(deps, env, info, channel_open_init_options),
ExecuteMsg::SendCustomIcaMessages {
messages,
packet_memo,
Expand Down Expand Up @@ -112,13 +117,13 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result<Response, C
}

mod execute {
use cosmwasm_std::CosmosMsg;
use cosmwasm_std::{CosmosMsg, StdResult};

use crate::{ibc::types::packet::IcaPacketData, types::msg::options::ChannelOpenInitOptions};

use super::{
new_ica_channel_open_init_cosmos_msg, Binary, ContractError, DepsMut, Env, MessageInfo,
Response, STATE,
Response, CHANNEL_OPEN_INIT_OPTIONS, STATE,
};

/// Submits a stargate `MsgChannelOpenInit` to the chain.
Expand All @@ -127,13 +132,23 @@ mod execute {
deps: DepsMut,
env: Env,
info: MessageInfo,
options: ChannelOpenInitOptions,
options: Option<ChannelOpenInitOptions>,
) -> Result<Response, ContractError> {
cw_ownable::assert_owner(deps.storage, &info.sender)?;

let mut contract_state = STATE.load(deps.storage)?;
contract_state.enable_channel_open_init();
STATE.save(deps.storage, &contract_state)?;
STATE.update(deps.storage, |mut state| -> StdResult<_> {
state.enable_channel_open_init();
Ok(state)
})?;

let options = if let Some(new_options) = options {
CHANNEL_OPEN_INIT_OPTIONS.save(deps.storage, &new_options)?;
new_options
} else {
CHANNEL_OPEN_INIT_OPTIONS
.may_load(deps.storage)?
.ok_or(ContractError::NoChannelInitOptions)?
};

let ica_channel_open_init_msg = new_ica_channel_open_init_cosmos_msg(
env.contract.address.to_string(),
Expand Down
2 changes: 1 addition & 1 deletion src/ibc/handshake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ mod ibc_channel_open {
// serde::Deserialize the metadata
let metadata: IcaMetadata = if channel.version.is_empty() {
// if empty, use create new metadata.
IcaMetadata::from_channel(deps.as_ref(), &channel)
IcaMetadata::from_channel(deps.as_ref(), &channel)?
} else {
serde_json_wasm::from_str(&channel.version).map_err(|_| {
ContractError::UnknownDataType(
Expand Down
72 changes: 52 additions & 20 deletions src/ibc/types/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Deps, IbcChannel};

use crate::types::{state::CHANNEL_STATE, ContractError};
use crate::types::{
state::{CHANNEL_OPEN_INIT_OPTIONS, CHANNEL_STATE},
ContractError,
};

use super::keys::ICA_VERSION;

Expand Down Expand Up @@ -72,37 +75,40 @@ impl IcaMetadata {
/// This is a fallback option if the ICA controller is not provided with the
/// handshake version metadata by the relayer. It first tries to load the
/// previous version of the [`IcaMetadata`] from the store, and if it fails,
/// it uses a stargate query to get the counterparty connection id.
/// Stargate queries are not universally supported, so this is a fallback option.
#[must_use]
pub fn from_channel(deps: Deps, channel: &IbcChannel) -> Self {
/// it uses the [`CHANNEL_OPEN_INIT_OPTIONS`] to create a new [`IcaMetadata`].
///
/// # Errors
///
/// Returns an error if the previous version of the [`IcaMetadata`] cannot be loaded
/// from the store, and no [`CHANNEL_OPEN_INIT_OPTIONS`] are set in the store.
pub fn from_channel(deps: Deps, channel: &IbcChannel) -> Result<Self, ContractError> {
// If the the counterparty chain is using the fee middleware, and the this chain is not,
// and the previous handshake was initiated with an empty version string, then the
// previous version in the contract's channel state will be wrapped by the fee middleware,
// and the IcaMetadata will not be able to be deserialized.
if let Ok(channel_state) = CHANNEL_STATE.load(deps.storage) {
if let Ok(previous_metadata) = serde_json_wasm::from_str(&channel_state.channel.version)
{
return previous_metadata;
return Ok(previous_metadata);
}
}

let counterparty_connection_id = super::stargate::query::counterparty_connection_id(
&deps.querier,
channel.connection_id.clone(),
)
.unwrap_or_default();
Self {
let options = CHANNEL_OPEN_INIT_OPTIONS.load(deps.storage)?;
if options.connection_id != channel.connection_id {
return Err(ContractError::InvalidConnection);
}

Ok(Self {
version: ICA_VERSION.to_string(),
controller_connection_id: channel.connection_id.clone(),
encoding: options.tx_encoding(),
controller_connection_id: options.connection_id,
// counterparty connection_id is not exposed to the contract, so we
// use a stargate query to get it. Stargate queries are not universally
// supported, so this is a fallback option.
host_connection_id: counterparty_connection_id,
host_connection_id: options.counterparty_connection_id,
address: String::new(),
encoding: TxEncoding::Proto3Json,
tx_type: "sdk_multi_msg".to_string(),
}
})
}

/// Validates the [`IcaMetadata`]
Expand Down Expand Up @@ -179,6 +185,8 @@ fn validate_ica_address(address: &str) -> Result<(), ContractError> {
mod tests {
use cosmwasm_std::{testing::mock_dependencies, IbcEndpoint, IbcOrder};

use crate::types::msg::options::ChannelOpenInitOptions;

use super::*;

fn mock_channel(
Expand Down Expand Up @@ -220,7 +228,7 @@ mod tests {

#[test]
fn test_validate_success() {
let deps = mock_dependencies();
let mut deps = mock_dependencies();

let channel = mock_channel(
"ics27-1",
Expand All @@ -230,13 +238,25 @@ mod tests {
"channel-1",
"port-1",
);
let metadata = IcaMetadata::from_channel(deps.as_ref(), &channel);
let stored_init_options = ChannelOpenInitOptions {
connection_id: "connection-0".to_string(),
counterparty_connection_id: "connection-1".to_string(),
tx_encoding: None,
counterparty_port_id: Some(super::super::keys::HOST_PORT_ID.to_string()),
};

CHANNEL_OPEN_INIT_OPTIONS
.save(deps.as_mut().storage, &stored_init_options)
.unwrap();

let metadata = IcaMetadata::from_channel(deps.as_ref(), &channel).unwrap();

assert!(metadata.validate(&channel).is_ok());
}

#[test]
fn test_validate_fail() {
let deps = mock_dependencies();
let mut deps = mock_dependencies();

let channel_1 = mock_channel(
"ics27-1",
Expand All @@ -246,6 +266,18 @@ mod tests {
"channel-1",
"port-1",
);

let stored_init_options = ChannelOpenInitOptions {
connection_id: "connection-0".to_string(),
counterparty_connection_id: "connection-1".to_string(),
tx_encoding: None,
counterparty_port_id: Some(super::super::keys::HOST_PORT_ID.to_string()),
};

CHANNEL_OPEN_INIT_OPTIONS
.save(deps.as_mut().storage, &stored_init_options)
.unwrap();

let channel_2 = mock_channel(
"ics27-1",
"connection-1",
Expand All @@ -254,7 +286,7 @@ mod tests {
"channel-1",
"port-1",
);
let metadata = IcaMetadata::from_channel(deps.as_ref(), &channel_1);
let metadata = IcaMetadata::from_channel(deps.as_ref(), &channel_1).unwrap();
assert!(metadata.validate(&channel_2).is_err());
}

Expand Down
Loading

0 comments on commit 7150af5

Please sign in to comment.