Skip to content

Commit

Permalink
Channel close tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Lior Bondarevski committed Aug 28, 2022
1 parent 4c43604 commit 4058c9e
Show file tree
Hide file tree
Showing 2 changed files with 240 additions and 37 deletions.
179 changes: 176 additions & 3 deletions x/compute/internal/keeper/ibc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func ibcChannelCloseHelper(
t *testing.T, keeper Keeper, ctx sdk.Context,
contractAddr sdk.AccAddress, creatorPrivKey crypto.PrivKey,
gas uint64, shouldSendCloseConfirn bool, channel v1types.IBCChannel,
) cosmwasm.StdError {
) (sdk.Context, []ContractEvent, cosmwasm.StdError) {
// create new ctx with the same storage and a gas limit
// this is to reset the event manager, so we won't get
// events from past calls
Expand Down Expand Up @@ -147,10 +147,13 @@ func ibcChannelCloseHelper(
require.NotZero(t, gasMeter.GetWasmCounter(), err)

if err != nil {
return cosmwasm.StdError{GenericErr: &cosmwasm.GenericErr{Msg: err.Error()}}
return ctx, nil, cosmwasm.StdError{GenericErr: &cosmwasm.GenericErr{Msg: err.Error()}}
}

return cosmwasm.StdError{}
// wasmEvents comes from all the callbacks as well
wasmEvents := tryDecryptWasmEvents(ctx, []byte{}, true)

return ctx, wasmEvents, cosmwasm.StdError{}
}

func createIBCEndpoint(port string, channel string) v1types.IBCEndpoint {
Expand Down Expand Up @@ -514,3 +517,173 @@ func TestIBCChannelConnect(t *testing.T) {
})
}
}

func TestIBCChannelConnectOpenAck(t *testing.T) {
ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/ibc/contract.wasm", sdk.NewCoins())

_, _, contractAddress, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"init":{}}`, true, true, defaultGasForTests)
require.Empty(t, err)

ibcChannel := v1types.IBCChannel{
Endpoint: createIBCEndpoint(PortIDForContract(contractAddress), "channel.0"),
CounterpartyEndpoint: createIBCEndpoint(PortIDForContract(contractAddress), "channel.1"),
Order: v1types.Unordered,
Version: "1",
ConnectionID: "1",
}

ctx, _, err = ibcChannelConnectHelper(t, keeper, ctx, contractAddress, privKeyA, defaultGasForTests, true, ibcChannel)
require.Empty(t, err)

queryRes, err := queryHelper(t, keeper, ctx, contractAddress, `{"q":{}}`, true, true, math.MaxUint64)
require.Empty(t, err)

require.Equal(t, "3", queryRes)
}

func TestIBCChannelClose(t *testing.T) {
ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/ibc/contract.wasm", sdk.NewCoins())

_, _, contractAddress, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"init":{}}`, true, true, defaultGasForTests)
require.Empty(t, err)

for _, test := range []struct {
description string
connectionID string
output string
isSuccess bool
hasAttributes bool
hasEvents bool
}{
{
description: "Default",
connectionID: "0",
output: "6",
isSuccess: true,
hasAttributes: false,
hasEvents: false,
},
{
description: "SubmessageNoReply",
connectionID: "1",
output: "12",
isSuccess: true,
hasAttributes: false,
hasEvents: false,
},
{
description: "SubmessageWithReply",
connectionID: "2",
output: "19",
isSuccess: true,
hasAttributes: false,
hasEvents: false,
},
{
description: "Attributes",
connectionID: "3",
output: "9",
isSuccess: true,
hasAttributes: true,
hasEvents: false,
},
{
description: "Events",
connectionID: "4",
output: "10",
isSuccess: true,
hasAttributes: false,
hasEvents: true,
},
{
description: "Error",
connectionID: "5",
output: "",
isSuccess: false,
hasAttributes: false,
hasEvents: false,
},
} {
t.Run(test.description, func(t *testing.T) {
ibcChannel := v1types.IBCChannel{
Endpoint: createIBCEndpoint(PortIDForContract(contractAddress), "channel.0"),
CounterpartyEndpoint: createIBCEndpoint(PortIDForContract(contractAddress), "channel.1"),
Order: v1types.Unordered,
Version: "1",
ConnectionID: test.connectionID,
}

ctx, events, err := ibcChannelCloseHelper(t, keeper, ctx, contractAddress, privKeyA, defaultGasForTests, true, ibcChannel)

if !test.isSuccess {
require.Contains(t, fmt.Sprintf("%+v", err), "Intentional")
} else {
require.Empty(t, err)
if test.hasAttributes {
require.Equal(t,
[]ContractEvent{
{
{Key: "contract_address", Value: contractAddress.String()},
{Key: "attr1", Value: "😗"},
},
},
events,
)
}

if test.hasEvents {
hadCyber1 := false
evts := ctx.EventManager().Events()
for _, e := range evts {
if e.Type == "wasm-cyber1" {
require.False(t, hadCyber1)
attrs, err := parseAndDecryptAttributes(e.Attributes, []byte{}, false)
require.Empty(t, err)

require.Equal(t,
[]v010cosmwasm.LogAttribute{
{Key: "contract_address", Value: contractAddress.String()},
{Key: "attr1", Value: "🤯"},
},
attrs,
)

hadCyber1 = true
}
}

require.True(t, hadCyber1)
}

queryRes, err := queryHelper(t, keeper, ctx, contractAddress, `{"q":{}}`, true, true, math.MaxUint64)

require.Empty(t, err)

require.Equal(t, test.output, queryRes)
}
})
}
}

func TestIBCChannelCloseInit(t *testing.T) {
ctx, keeper, codeID, _, walletA, privKeyA, _, _ := setupTest(t, "./testdata/ibc/contract.wasm", sdk.NewCoins())

_, _, contractAddress, _, err := initHelper(t, keeper, ctx, codeID, walletA, privKeyA, `{"init":{}}`, true, true, defaultGasForTests)
require.Empty(t, err)

ibcChannel := v1types.IBCChannel{
Endpoint: createIBCEndpoint(PortIDForContract(contractAddress), "channel.0"),
CounterpartyEndpoint: createIBCEndpoint(PortIDForContract(contractAddress), "channel.1"),
Order: v1types.Unordered,
Version: "1",
ConnectionID: "1",
}

ctx, _, err = ibcChannelCloseHelper(t, keeper, ctx, contractAddress, privKeyA, defaultGasForTests, false, ibcChannel)
require.Empty(t, err)

queryRes, err := queryHelper(t, keeper, ctx, contractAddress, `{"q":{}}`, true, true, math.MaxUint64)
require.Empty(t, err)

require.Equal(t, "5", queryRes)
}
98 changes: 64 additions & 34 deletions x/compute/internal/keeper/testdata/ibc/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
use crate::state::{count, count_read};
use cosmwasm_std::{
entry_point, to_binary, Binary, CosmosMsg, Deps, DepsMut, Env, Event, Ibc3ChannelOpenResponse,
IbcBasicResponse, IbcChannelConnectMsg, IbcChannelOpenMsg, IbcChannelOpenResponse, MessageInfo,
Reply, ReplyOn, Response, StdError, StdResult, SubMsg, SubMsgResult, WasmMsg,
IbcBasicResponse, IbcChannelCloseMsg, IbcChannelConnectMsg, IbcChannelOpenMsg,
IbcChannelOpenResponse, MessageInfo, Reply, ReplyOn, Response, StdError, StdResult, SubMsg,
SubMsgResult, WasmMsg,
};

pub const IBC_APP_VERSION: &str = "ibc-v1";
Expand Down Expand Up @@ -78,6 +79,41 @@ pub fn increment(deps: DepsMut, c: u64) -> StdResult<Response> {
Ok(resp)
}

pub fn get_resp_based_on_num(env: Env, num: u64) -> StdResult<IbcBasicResponse> {
match num {
0 => Ok(IbcBasicResponse::default()),
1 => Ok(IbcBasicResponse::new().add_submessage(SubMsg {
id: 1,
msg: CosmosMsg::Wasm(WasmMsg::Execute {
code_hash: env.contract.code_hash,
contract_addr: env.contract.address.into_string(),
msg: Binary::from("{\"increment\":{\"addition\":5}}".as_bytes().to_vec()),
funds: vec![],
})
.into(),
reply_on: ReplyOn::Never,
gas_limit: None,
})),
2 => Ok(IbcBasicResponse::new().add_submessage(SubMsg {
id: 1,
msg: CosmosMsg::Wasm(WasmMsg::Execute {
code_hash: env.contract.code_hash,
contract_addr: env.contract.address.into_string(),
msg: Binary::from("{\"increment\":{\"addition\":5}}".as_bytes().to_vec()),
funds: vec![],
})
.into(),
reply_on: ReplyOn::Always,
gas_limit: None,
})),
3 => Ok(IbcBasicResponse::new().add_attribute("attr1", "😗")),
4 => Ok(IbcBasicResponse::new()
.add_event(Event::new("cyber1".to_string()).add_attribute("attr1", "🤯"))),
5 => Err(StdError::generic_err("Intentional")),
_ => Err(StdError::generic_err("Unsupported channel connect type")),
}
}

#[entry_point]
pub fn ibc_channel_connect(
deps: DepsMut,
Expand All @@ -99,39 +135,33 @@ pub fn ibc_channel_connect(

count(deps.storage).save(&(num + 4))?;

match num {
0 => Ok(IbcBasicResponse::default()),
1 => Ok(IbcBasicResponse::new().add_submessage(SubMsg {
id: 1,
msg: CosmosMsg::Wasm(WasmMsg::Execute {
code_hash: env.contract.code_hash,
contract_addr: env.contract.address.into_string(),
msg: Binary::from("{\"increment\":{\"addition\":5}}".as_bytes().to_vec()),
funds: vec![],
})
.into(),
reply_on: ReplyOn::Never,
gas_limit: None,
})),
2 => Ok(IbcBasicResponse::new().add_submessage(SubMsg {
id: 1,
msg: CosmosMsg::Wasm(WasmMsg::Execute {
code_hash: env.contract.code_hash,
contract_addr: env.contract.address.into_string(),
msg: Binary::from("{\"increment\":{\"addition\":5}}".as_bytes().to_vec()),
funds: vec![],
})
.into(),
reply_on: ReplyOn::Always,
gas_limit: None,
})),
3 => Ok(IbcBasicResponse::new().add_attribute("attr1", "😗")),
4 => Ok(IbcBasicResponse::new()
.add_event(Event::new("cyber1".to_string()).add_attribute("attr1", "🤯"))),
5 => Err(StdError::generic_err("Intentional")),
_ => Err(StdError::generic_err("Unsupported channel connect type")),
}
get_resp_based_on_num(env, num)
}
_ => Err(StdError::generic_err("Unsupported channel connect")),
}
}

#[entry_point]
/// On closed channel, we take all tokens from reflect contract to this contract.
/// We also delete the channel entry from accounts.
pub fn ibc_channel_close(
deps: DepsMut,
env: Env,
msg: IbcChannelCloseMsg,
) -> StdResult<IbcBasicResponse> {
match msg {
IbcChannelCloseMsg::CloseInit { channel: _ } => {
count(deps.storage).save(&5)?;
Ok(IbcBasicResponse::default())
}
IbcChannelCloseMsg::CloseConfirm { channel } => {
let num: u64 = channel.connection_id.parse::<u64>().map_err(|err| {
StdError::generic_err(format!("Got an error from parsing: {:?}", err))
})?;

count(deps.storage).save(&(num + 6))?;
get_resp_based_on_num(env, num)
}
_ => Err(StdError::generic_err("Unsupported channel close")),
}
}

0 comments on commit 4058c9e

Please sign in to comment.