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

chore: allow ics27 to select and return default JSON encoded metadata #1550

Merged
merged 21 commits into from
Jun 23, 2022

Conversation

damiannolan
Copy link
Member

@damiannolan damiannolan commented Jun 16, 2022

Description

Allow interchain accounts to accept an empty channel version and select a default.

  • Adding version return to OnChanOpenInit cb handler in controller
  • Updating test cases

closes: #1551


Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.

  • Targeted PR against correct branch (see CONTRIBUTING.md)
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Code follows the module structure standards.
  • Wrote unit and integration tests
  • Updated relevant documentation (docs/) or specification (x/<module>/spec/)
  • Added relevant godoc comments.
  • Added a relevant changelog entry to the Unreleased section in CHANGELOG.md
  • Re-reviewed Files changed in the Github PR explorer
  • Review Codecov Report in the comment section below once CI passes

@codecov-commenter
Copy link

Codecov Report

Merging #1550 (bf866c8) into damian/1477-implement-payee-distribution (f8928f6) will decrease coverage by 0.10%.
The diff coverage is 41.93%.

Impacted file tree graph

@@                             Coverage Diff                              @@
##           damian/1477-implement-payee-distribution    #1550      +/-   ##
============================================================================
- Coverage                                     80.29%   80.19%   -0.11%     
============================================================================
  Files                                           166      166              
  Lines                                         12304    12322      +18     
============================================================================
+ Hits                                           9880     9882       +2     
- Misses                                         1959     1974      +15     
- Partials                                        465      466       +1     
Impacted Files Coverage Δ
...ules/apps/27-interchain-accounts/types/metadata.go 75.70% <0.00%> (-7.81%) ⬇️
...interchain-accounts/controller/keeper/handshake.go 78.78% <61.11%> (-7.66%) ⬇️
...7-interchain-accounts/controller/ibc_middleware.go 83.63% <100.00%> (+0.30%) ⬆️

Base automatically changed from damian/1477-implement-payee-distribution to main June 17, 2022 13:40
@damiannolan damiannolan marked this pull request as ready for review June 22, 2022 09:26
@damiannolan damiannolan changed the title [WIP] Allow ics27 to select and return default JSON encoded metadata Allow ics27 to select and return default JSON encoded metadata Jun 22, 2022
@damiannolan damiannolan changed the title Allow ics27 to select and return default JSON encoded metadata chore: allow ics27 to select and return default JSON encoded metadata Jun 22, 2022
Copy link
Contributor

@chatton chatton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Just had a few questions/comments 👍

}
}

return nil
return string(icatypes.ModuleCdc.MustMarshalJSON(&metadata)), nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just to make sure I understand, if this panics this is handled at the sdk level right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, its caught by the grpc recovery interceptor (essentially a middleware handler in grpc land)

@@ -28,26 +28,35 @@ func (k Keeper) OnChanOpenInit(
chanCap *capabilitytypes.Capability,
counterparty channeltypes.Counterparty,
version string,
) error {
) (string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the implication of changing an OnChanOpenInit signature like this? Are we free to do this without causing any issues?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this instance yes, the OnChanOpenInit callback was already updated to include a second version return arg. The calling func in controller/ibc_middleware.go already contains this function signature which is the entrypoint of the module handshake essentially.

In other situations we may need to more careful changing function sigs but this doesn't really cause any issues.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to add to that: in general, we would also update the ibc spec for changes to these fn sigs. But like @damiannolan said the calling func already has this signature.

@@ -50,7 +50,8 @@ func (im IBCMiddleware) OnChanOpenInit(
return "", types.ErrControllerSubModuleDisabled
}

if err := im.keeper.OnChanOpenInit(ctx, order, connectionHops, portID, channelID, chanCap, counterparty, version); err != nil {
version, err := im.keeper.OnChanOpenInit(ctx, order, connectionHops, portID, channelID, chanCap, counterparty, version)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice readability improvement 🥇

Comment on lines +52 to +53
} else {
if err := icatypes.ModuleCdc.UnmarshalJSON([]byte(version), &metadata); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] rather than having nested if/else clauses it might be cleaner to have a helper function to return the metadata (using early returns)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took a look at this and feel like there's not a massive difference making a helper function. You'd either need to return a new metadata type or take a pointer and a bunch of other args too... I'm pretty indifferent about it

Copy link
Contributor

@seantking seantking left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Nice work.

Should we test this out manually as well?

@damiannolan
Copy link
Member Author

LGTM! Nice work.

Should we test this out manually as well?

Yup, already tested this manually as part of #396 QA scenarios.

return sdkerrors.Wrapf(icatypes.ErrUnknownDataType, "cannot unmarshal ICS-27 interchain accounts metadata")
if strings.TrimSpace(version) == "" {
connection, err := k.channelKeeper.GetConnection(ctx, connectionHops[0])
if err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a super tiny nit but you have the err statement in the second else clause in the ; err != nil setup, would be nice if they were both like this or both the other way just as a tiny remark on style

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we need to use the connection below outside the scope of the returned error.
Generally we use the below for function return sigs with one single error return:

if err := invokeFunc(); err != nil {
    // handle err
}

If we use the following then we can't use the connection below, outside the scope of the conditional:

if connection, err := k.channelKeeper.GetConnection(ctx, connectionHops[0]); err != nil {
   // connection and err are only available at this level of scope
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yes, that makes sense 🙈

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should technically be able to if you put the usage in an else clause, but I personally prefer the way you have it now rather than adding additional else clauses!

if err := icatypes.ModuleCdc.UnmarshalJSON([]byte(version), &metadata); err != nil {
return sdkerrors.Wrapf(icatypes.ErrUnknownDataType, "cannot unmarshal ICS-27 interchain accounts metadata")
if strings.TrimSpace(version) == "" {
connection, err := k.channelKeeper.GetConnection(ctx, connectionHops[0])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is connectionHops hardcoded to the first value of the array?

Copy link
Contributor

@seantking seantking Jun 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first value is the source chain connection end AFAIK

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConnectionHops is an ordered list of connection ids, so using connectionHops[0] here takes the first connection hop through which packets travel. There's a bunch of defensive checks in ibc core ensuring that this is always of length one at the moment. So on source chain connectionHops will contain the connection ID of self, in this instance its the controller chain. And likewise, the counterparty handlers would have a connectionHops array containing the connection of themself (host). Obviously in future with multi hop the semantics will change and ibc core will have to adapt for it. But due to the ordering, we can safely assume that the 0 index element is self.

Channel spec says:

The connectionHops stores the list of connection identifiers, in order, along which packets sent on this channel will travel. At the moment this list must be of length 1. In the future multi-hop channels may be supported.

Copy link
Contributor

@crodriguezvega crodriguezvega left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work, @damiannolan!

I just left a suggestion to potentially remove some duplicate code...

ControllerConnectionId: controllerConnectionID,
HostConnectionId: hostConnectionID,
Encoding: EncodingProtobuf,
TxType: TxTypeSDKMultiMsg,
Version: Version,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you can replace now this whole object initialization with a call to the NewDefaultMetadata function above?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call!

@damiannolan damiannolan enabled auto-merge (squash) June 23, 2022 14:30
@damiannolan damiannolan merged commit 8ffa912 into main Jun 23, 2022
@damiannolan damiannolan deleted the damian/handle-ica-empty-version branch June 23, 2022 14:31
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.

Allow interchain accounts to select a default metadata version
6 participants