-
Notifications
You must be signed in to change notification settings - Fork 344
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
Define IBC interface #147
Comments
Generally, this makes sense to me - a few comments:
Just as a point of clarity, channels are necessarily associated with a single connection, but they aren't uniquely denoted by the pair of ports and a connection - they have individual identifiers - the unique tuple across the combined state of both chains is
Hmm. In general I agree, although I think we will also want "dynamic" WASM contracts - namely, contracts which can speak IBC protocols that may not be fixed prior to deployment of
This is possibly not necessary since the IBC message sequence is queryable by SDK application code & each channel will be associated with a unique contract, but it's fine if you need a separate identifier for some
Aye, exactly! |
Thank you for the detailed reply, and it all makes sense. As to protocol if we use the version field in the handshake, then that should be a way to dynamically inform the other side of the expected protocol.
A channel consists of a port and a connection, right? Can the same channelIdentifierA connect to multiple ports of chain A? And if not what is the use case for multiple channels between portA, connA and portB, connB? I can only think of a high priority and a low priority channel between a pair of contracts. But I am sure I am missing something |
Yes, and the other end can select a version it supports or reject the handshake if none are supported.
A channel is identified by a port identifier and a channel identifier, and is associated with one connection. A given channel & port identifier on chain A are associated with exactly one channel & port identifier on chain B. Multiple channels for the same connection can be used for regular multi-module communications (e.g. there are lots of contracts on chain A which want to talk to lots of contracts on chain B - there would be one connection but lots of channels, one per pair of contracts) - it's also possible to multiplex on a single channel, but the spec allows many channels-per-connection so it can be done at this layer. In the future connections could also have some sort of flow control or more complex ordering dependence - see https://github.com/cosmos/ics/issues/133, https://github.com/cosmos/ics/issues/131 (both "IBC 2.0" features). |
For reference (links behind Chris's explanations), look at ICS 4. In particular, it defines the interface Packet {
sequence: uint64
timeoutHeight: uint64
sourcePort: Identifier
sourceChannel: Identifier
destPort: Identifier
destChannel: Identifier
data: bytes
} ({dest,source}{Port,Channel} being the unique identifiers, sequence could serve as |
Versioning is defined here to be on a per-channel basis and can be used for protocol negotiation. I had assumed we could simplify the ICS potential for CosmWasm such that The channel state lifecycle diagram explains this process. What is unclear is where we have hooks that |
This comment does make it seem that interface ChannelProtocolRequest {
desiredProtocol string
supportedProtocols string[]
}
type ChannelProtocolResponse = ChannelProtocolMatch | ChannelProtocolError;
interface ChannelProtocolMatch {
acceptedProtocol: string
}
interface ChannelProtocolError {
error: "no compatible protocol
} If the first packet from the initiating side (that calls @cwgoes if you like this idea, I will make a proper Issue/PR on ICS (this is not CosmWasm-specific) |
See ICS 26 (module callback interface) for the list of hooks & their signatures. It may make sense to separate "IBC protocol" version negotiation and "application" version negotiation - however, I am not sure that the former is necessary at all in the channel handshake, it could happen earlier (e.g. with the connection or even with the client). |
After discussing offline, we agreed that ibc protocol level lives on a different level, and connection version is for application-protocol version. There will be a standardized ics20 protocol name: cosmos/ibc#381 as a starting point, and application developers can follow a similar convention set down by this core module. |
My characterization of dIBC is I think a simpler starting point. I was not proposing to add negotiation and versioning and such (though those are all valuable). Instead I was focused just on deploying new code on an existing chain to handle a new App protocol. I assume in this that the specific App protocol is known to both ends (based on the ports they are connecting to) rather than being a matter of negotiation. The "dynamic" is just about the ability to expand the App protocols processed by the chain by deploying support for it dynamically. I also think that the protocols defined this way ought to be understandable to e.g., Go modules that get deployed in a chain upgrade later. Thus, they should be amenable to a static deployment. Thus though we may want protocol negotiation, we should avoid implementing/encouraging protocols that put that in-band (if we can) unless they do so in a way that is compatible with e.g., a future implementation of those App packet types in Go or Rust. Since those cannot handle parsing payloads of types they weren't compiled with, that puts some constraints on the protocols we propose. |
Can this be considered done with #692 closed? |
The code is well-done. I should add a usage doc. Thanks for reminding me. Also, I should check with the ICS spec. If they will eventually allow contracts/modules to participate in version negotiation (rather than asking the relayer to set that), then we may need to expose some other return values. Also, see CosmWasm/wasmd#398 for the documentation work |
Whatever changes are necessary to enable this, if any, shouldn't be controversial I think. |
With a stable IBC approaching (and the spec being finalized), it is a good time to begin specifying how contracts work with IBC. The idea is to make a design that is compatible with the full spec, with all security guarantees, but makes a number of assumptions in
x/wasm
to provide a simple but useful interface for the contracts.The basic ideas from IBC include
Client
andConnection
which are established between 2 blockchains -x/wasm
doesn't touch these, it can only reuse existing connections, assuming a client passes in the relevant id.There is the concept of
Port
, which a module must bind to be able to send/receive messages. These are arbitrary strings on a first come, first serve basis. To avoid spamming by contracts,x/wasm
will check if the contract is IBC-enabled (it exports a few extra functions), and if so, will bind a port for that contract when it is instantiated of the formwasm:cosmos1q4djygw...
.Then there is the concept of a
Channel
. A channel is established between one module on one chain and another on another chain. It consists basically ofA: (port, connection) <-> B: (port, connection)
. Creating a channel involves a 3 step handshake. We need to allow cosmwasm contracts to establish channels, but ideally with one message/call (and letx/wasm
handle the handshake for them).Once a channel is established, it can be referenced inside the contract as
(remote port, remote connection_id)
which is the universal id of the counterparty. If this differs than the normal representation, thenx/wasm
can maintain a lookup table from channel id to this tuple.In general, IBC is a remote function call. Imagine some method on the remote side,
f(Caller, T) -> Result<U>
. WhereT
andU
are some serializable data structures, which depend on the protocol being used. (Same asHandleMsg
,QueryMsg
, etc).To send: we add another type to
CosmosMsg
as a valid return value:I think we should define the expected
protocol
somewhere. In order to properly parse the payload, we must ensure that both sides are speaking the same language. I do not need some complex two-way protocol negotiation, but some way to mark which protocol we expect them to speak (eg. ICS20) and if they do not know the string, they can reject the connection (rather than possibly parsing the payload incorrectly).msg_id
is an arbitrary unique string set by the cosmwasm contract that is not sent, but used byx/wasm
when it receives the response (to allow the contract to maintain a lookup table of pending responses without worrying about the internal ibc numbering system).The contract must then export two other functions that will be called at various steps in the lifetime of the packet.
ibc_receive(Extern, Params, IBCCall<IBCMsg>) -> Result<IBCResponse>
This is called on the receiving end of the call, after a relayed brings a proof of the committed
IBCCall
message.IBCMsg
is the contract-specific struct to deserialize the binary payload, just likeHandleMsg
, etc.ibc_ack(Extern, Params, msg_id, Result<IBCResponse>) -> Result<()>
After the message has been properly processed on the receiving side, an acknowledgement is returned to the server containing either a success message (in a protocol-specific format) or an error, along with the
msg_id
from the original call. This allows the contract to update it's cache of "pending transactions" and fully commit or revert the transaction.The text was updated successfully, but these errors were encountered: