Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove non_exhaustive from IBC message types. #1449

Merged
merged 2 commits into from
Oct 14, 2022
Merged

Conversation

0xekez
Copy link
Contributor

@0xekez 0xekez commented Oct 7, 2022

IBC message types being non exhaustive means that contract authors have to include a wildcard arm in any match expression deailing with them. IMO, this is actually quite undesirable. I my contract to fail to compile if a message is added!

@webmaster128
Copy link
Member

webmaster128 commented Oct 10, 2022

I my contract to fail to compile if a message is added!

That's a noble approach. Better safe than sorry. However, it would require a major version bump of cosmwasm-std just because a new enum case is added. This is what we want to avoid with all the non_exhaustives.

@0xekez
Copy link
Contributor Author

0xekez commented Oct 11, 2022

@webmaster128: However, it would require a major version bump of cosmwasm-std just because a new enum case is added.

I trust that you have more experience with this stuff than I do. :) I do wonder what the odds of a new message being added to the channel establishment or teardown process is? my guess is, that considered, the expected value of this may be positive. also, adding a new case would break all existing IBC contracts that are deployed. perhaps that is worth a major version bump?

if we do decide to not merge this it's not a big deal. just need to be very careful bumping CosmWasm versions in IBC contracts. :)

@webmaster128
Copy link
Member

@ethanfrey what do you think about removing non_exhaustive from those two places? Do we expect new cases here any time soon?

@ethanfrey
Copy link
Member

I agree completely with removing the non_exhaustive flags here. I think there was a bit over eager tagging.

I would also remove it here IbcChannelConnectMsg

That said, I think CosmosMsg::Ibc(IbcMsg) type will.need non exhaustive and is very likely to receive additional types in 1.x

@webmaster128
Copy link
Member

Good, thanks. Yeah, the issue with non_exhaustive are the cases where the value is coming from the environment and the contract dev has to process them. For all messages, the contract dev creates them and there is no reason to match them.

@0xekez I tried the change in an IBC contract it seems like this is non breaking as it would just create a compiler warning for the fallback matche arm:

warning: unreachable pattern
   --> contracts/nois-proxy/src/contract.rs:193:9
    |
193 |         _ => panic!("What should I do?"),
    |         ^
    |
    = note: `#[warn(unreachable_patterns)]` on by default

Out of curiosity, I wonder why you need the match at all. With msg.channel() you can get the channel and msg.counterparty_version() gives you the counterparty. Is the actual enum case important in your code? Do you have code to share?

@0xekez
Copy link
Contributor Author

0xekez commented Oct 13, 2022

Here's a specific example of where #[non_exhaustive] is trouble:

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn ibc_channel_close(
    _deps: DepsMut,
    _env: Env,
    msg: IbcChannelCloseMsg,
) -> Result<IbcBasicResponse, ContractError> {
    match msg {
        // Error any TX that would cause the channel to close that is
        // coming from the local chain.
        IbcChannelCloseMsg::CloseInit { channel: _ } => Err(ContractError::CantCloseChannel {}),
        // If the close is coming from the other chain, we must allow
        // the TX to pass. Otherwise, our chain will believe the
        // channel to be open, while our counterparty will believe the
        // channel to be closed.
        IbcChannelCloseMsg::CloseConfirm { channel: _ } => Ok(IbcBasicResponse::default()),
        _ => unreachable!("channel can not be closed"),
    }
}

We need to match on the close message type as the contract should do something different depending on if this is a "request to close" from the local chain, or a "statement that the channel has been closed" from the counterparty chain. Channel closing is a really dangerous part of these contracts because if you fail the TX which confirms the close on your side, the chains will be out of sync where one side believes the channel closed and the other does not.

Here's a test that explores some of the complexities of channels closing.

IBC message types being non exhaustive means that contract authors
have to include a wildcard arm in any match expression deailing with
them. IMO, this is actually quite undesirable. I my contract to fail
to compile if a message is added!
@0xekez
Copy link
Contributor Author

0xekez commented Oct 13, 2022

Rebased and removed #[non_exhaustive] from IbcChannelConnectMsg.

@webmaster128
Copy link
Member

Merci, thanks for sharing. Will merge next week.

@webmaster128 webmaster128 merged commit 2e215cf into CosmWasm:main Oct 14, 2022
@webmaster128
Copy link
Member

Shipped as part of 1.1.5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants