-
Notifications
You must be signed in to change notification settings - Fork 42
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
IBC
implementation idea
#27
Comments
Any update on this issue? |
Still curious if this is something that will be added to cw-multi-test at somepoint |
I think a simple first step, is just to ignore any IBC messages returned. This won't allow testing IBC, but will at least allow testing some non-ibc related functionality in said contracts (as they usually become completely untestable as soon as they have IBC Messages) |
I am closing this issue, as IBC support will be implemented as in #184. |
Implementing entry points
The first step is to implement all IBC-related entry points for contracts. What has to be done to add them to
Contract
trait and update theContractWrapper
. I would prefer the #26 first, but technically ordering is less relevant. Entry points I have written down to add are:Creating IBC Keeper
The second step is to create an IBC Keeper. Its purpose is to handle IBC-related messages:
I feel like all the messages should behave similarly: there should be some internal queue in the keeper, which contains messages to be relayed. The message type would look like this:
Making the
App
intoRc<RefCell<App>>
I don't like solutions like
Rc<RefCell<T>>
, but at this point, most arguments against it don't apply (we are on testing env, and leaks or performance does not matter). The problem is that theapp
has to be continually passed all over the place while it could be just fixed into some types using it later. We already use this approach in theSylvia
framework, but here it is even more important - you will need to relay messages at some point, and you don't want to passapp
instances every time, as it puts you in the risk of messing up the order ofapp
in the relayer (the whole idea is to have singleapp
per chain simulated).The easiest way to go here is to make an
App
intoAppImpl
, and then create an additional thin wrapper:Having all the inner functions of
AppImpl
, but taking self always by the shared borrow. ThenApp
can be copied all over the place cheaply, and all the API are kept (as they got only more generic).Relayer
Next in the queue is the
IbcRelayer
type. It would be something like that (probably with more data I miss here). As we want to allow later maybe redefinition ofRelayer
for custom cases, I will start with defining the trait:Then we create a relayer type:
So relayer is just keeping some two chains for future use. We want to make it useful. First, let things about creation:
Here is a nice trick to use. What drives me crazy in ts-relayer is remembering which chain is which. Now I can do the following:
All the types of structures returned by the relayer would have a function like
fn chain(&self, ChainHandle) -> ChainSpecificData)
, so I pass the well-named handle here.Some essential functions to be callable on the relayer are, for example,
relay_all(&self)
- which relates messages until there is nothing to relay,relay_once(&self, ChainHandle)
, which relays all messages pending on the passed chain, or evenrelay_single(&self, ChainHandle)
- I am committing the return type as it is just a structure describing all events happened while relaying. Also,create_channel
would create a channel on a given port.One other thing I have in mind is to add function(s) like
relay_with(&self, impl Fn<(ChainHandle, IbcRelayable)> -> RelayMethod)
, which allows controlling the relayer with theRelayMethod
type:Access to the queue
We could expose the queue for everyone, delivering a function on an
App
:However, I wouldn't say I like it as it exposes some internals too easily. Instead, I want to provide a function like this:
Now in all the relaying function (like
relay_all
), the relayer will call the properapp.relay(self)
to get access to underlying functions. Another thing the relayer has to do is to execute the entry points, and it leads to...Updating WasmKeeper
I am not 100% about that, but it is how it feels natural to me.
WasmKeeper
is an entity which keeps the code of the contract. Therefore it is the best one to execute its entry points - including IBC ones. I will add flow to it, which is just likeexecute
, but it would be anexecute_ibc
, and instead ofWasmMsg
, it would take our newly crafted type like:Now, it should be possible to schedule those messages from
app
level, so there is an execution loop performed onWasm
.Built-in IBC capabilities
Note that the whole relayer works on the
RelayableApp
trait providing access to the relay queue. That means that theApp
itself could have some additional functionalities allowing it to perform some "building" actions - either on itsIbcT
module or by some other functions which enqueue messages (additionally do whatever they want to do). One can also create a customRelayableApp
, which he uses only to push IBC messages on the queue, without any bank or wasm capabilities.Timing out
Timing out should be handled without involving the relayer (so it is guaranteed to happen). The best would be to do it automatically when
update_block
is called. Unfortunately, it leads to an issue thatIbcT
is generic, so it might not contain the required functionality. We could trait-bound it, but it would be very backwards-incompatible, and I know there are chains already implementingIbcT
, so they would be strongly affected by this.Instead, I would add the
ibc_timeout
function onApp
, enabled (by trait-bounds) only when ourApp
implementsRelayableApp
. It would query IbcKeeper for timed-out packages waiting (it would immediately drop them), and thenApp
would send properIbcCallMsg::PacketTimeout { ... }
messages.Ports creation
The easiest thing here is to provide a function like
bind_ibc(port_id: &str, contract: &str)
, which binds the contract to the given port on the chain (creates a new port if it does not exist).Events, attributes, all the things
I think the most challenging part will be to emit all the events and attributes properly. On the one hand - it is not this relevant for testing purposes; on the other hand - one might find it suitable. It would require tedious work to ensure that the
IbcKeeper
andWasmKeeper
are emitting all the events specific to IBC-related messages.The text was updated successfully, but these errors were encountered: