-
Notifications
You must be signed in to change notification settings - Fork 628
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
Abstract IBC exported interface types to separate api go module #2471
Comments
Some additional thoughts here, I think depending on an interface is always a good idea. In this particular case, if the main problem is the method signature on the interface functions, it should also be possible to accept a single argument in the interface functions, some sort of options type (this would of course be a breaking change for all existing versions of ibc-go) type OnChanOpenInitOpts struct {
Order channeltypes.Order,
ConnectionHops []string,
PortID string,
ChannelID string,
ChannelCap *capabilitytypes.Capability,
Counterparty channeltypes.Counterparty,
Version string,
}
// sample definition
OnChanOpenInit(ctx sdk.Context, opts OnChanOpenInitOpts) (string, error) As new fields are added to this struct, as long as the zero value is treated correctly, it should not be a problem for backwards compatibility. To aid in readability, the functional options pattern is a nice UX to deal with these options types. Having said this, these two solutions are not mutually exclusive, as the number of arguments in these functions grows, simplifying the method signature can be a great UX improvement. |
I like this idea a lot. An example usage that would benefit us is needing to modify API's that affect |
re: @chatton's suggestion, my only gripe is that the arguments provided aren't really options and I'm not sure how well it'd work to add a new field that is unknown to older ibc applications. The new field would require upgrading the whole stack to ensure it is propagated? The callback flow I think would benefit from knowing that the receiving caller will utilize the new field and/or pass on the set value, but I do like the function options pattern and naming it something like Edit: I think so long as the new field has a sane default value it should be fine. I still have a mild concern about adding fields which apps on older versions don't have a chance to verify, but it's hard to reason about this situation without an example of an additional field to the channel end, so I think it worth crossing that bridge when we get there. One can always introduce the additional field as an extra argument to ensure apps have a chance to add additional checks for it |
Here is a draft of how we can add a top level In addition, to ensure that the api module does not rely on core IBC, the interfaces for types such as |
So far so good, looks pretty sweet to me. Definitely in favour of removing the interfaces like The concrete type for As far apps I think similar could be done with types like the |
@damiannolan and I did a quick deep dive into an api module which would eventually hold the LightClientModule interface (and its associated types) as well as the IBCApp interface (and its associated types). We ran into potential concerns around proto version breakage and decided to pump the breaks and report our findings before going deeper. I think the ideal dependency graph looks at a high level something like this: The primary issue with dependency management is testing. To feel confident in your tests, you likely want to import everything. In this image we have 3 forms of testing:
Unit tests are easy to rely on the onion dependency graph (api module at the core). Integration tests are trickier since they require importing core IBC. I suspect the only option here is to create a separate go.mod within a ibc module to run e2e's and integration tests e2e's work great as currently written. When doing our deep dive to create the API module we ran into the following issues. When moving the When creating the API module in this way, we are doing the following:
As we can see, these benefits are nice to have at the current moment and not essential. It is possible other more signficant benefits arise (like being able to reuse a single ibc module with different ibc implementations, ibc lite for example), but without the existence of those use cases, it's not an immediate benefit. When looking at the current state of the IBCApp, we forsee the same difficulties we see in the light client module. While we believe it is possible to create the api module as proposed, some additional investigative work is needed which we don't see as high priority enough given the potential benefits. Unless we see slow adoption by ibc apps and light clients to update ibc-go, I recommend we wait to create the api module until our investigative questions are answered and the IBCApp module has solidified after the proposed changes to the IBC router. Instead I recommend we look at our dependency management problem like an onion. The API module, while nice for clarity, is difficult to draw immediate benefits from given that it is at the core of our onion. If we look at the outer layer, we see there are immediate benefits and dependencies which can be removed from the inner layers. Issues #4527 and #3968 are good examples of this. Currently the core ibc dependency graph includes the binary it uses for testing e2e's. Exceptions are made for the modules which have been pulled out of core ibc and thus maintain a duplicate simapp.
Following this, an issue similar to #4213, #4807, and #4808 would enable us to begin peeling light clients out of core IBC and the testing pkg (integration tests). While I consider it very low value to make the solomachine it's own go.mod, I believe it's a necessary step in solving the over arching dependency graph issue. I believe the approach working outside in will make creating the api module a natural step. I don't believe this entire body of work needs to be tackled immediately, but rather items we can chip off in order as we feel ready. As well begin peeling away the outer layers, we may find easier ways to remove additional direct dependencies such as cometbft. Investigative questions for api module:
@damiannolan please add any additional context I missed |
I would say no. Proto versioning isn't well specified nor is it enforced. It is simply as best practice, and as such, there tends to be missing details on certain situations. Our situation is more difficult than common usage as adding new fields can break expected encodings during interactions with counterparties. Thus I would define our proto versioning on breaking changes to the encoding, not what is generated into the go api According to the encoding specs:
This quite clearly states that the name and declared type for each field is not included into the encoding and is only determined when the counterparty declares which type they are decoding into. That would mean if we change the import path of a field, without changing any of the structure of that imported type, then encoding the top level type using the old import path will result in the same bytes as encoding the top level type using the new import path, which to me does not require a proto version bump in the package suffix. thanks @damiannolan for discussing/investigating this with me! |
Summary
Opening this issue to discuss and explore the idea of potentially abstracting out the interface types maintained under
modules/core/exported
to a separate Go module.Problem Definition
One issue we face in the cosmos ecosystem with respect to IBC is that IBC applications maintained in their own repositories must stay in lock step with
ibc-go
releases. That is, in order for an IBC application to be included in a chain distribution'sapp.go
it must depend on the same version ofibc-go
that the chain itself depends on.The same would be true for applications maintained inside of
ibc-go
if #614 was to be implemented. Applications must follow theibc-go
release cycle and release in tandem an appropriate application version that is compatible.The problem arises when wiring the IBC
Router
inapp.go
, specifically, compatibility issues arise betweenibc-go
versions for theIBCModule
interface when invokingAddRoute()
. The Go compiler breaks if anIBCModule
depends on a different version ofibc-go
due to the parameters defined in the various handshake callback methods and packet APIs of this interface.This includes both concrete types and interface types defined within
ibc-go
.Proposal
A potential solution could be to extract the existing interfaces defined in
modules/core/exported
as well as the various parameters defined in the handshake callbacks and packet APIs of theIBCModule
interface to a separate Go module.This would allow IBC applications that live in their own repositories to freely maintain their own release cycle and only update to newer versions of
ibc-go
when explicitly forced to do so.A spike or investigation into this as a potential solution could be carried out. This would help determine the pros and cons of the changes to be made and if it would be worth the effort in doing so.
For Admin Use
The text was updated successfully, but these errors were encountered: