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

Implement ICS-20 Callbacks #5984

Merged
merged 13 commits into from
Apr 15, 2020
Merged

Implement ICS-20 Callbacks #5984

merged 13 commits into from
Apr 15, 2020

Conversation

AdityaSripal
Copy link
Member

@AdityaSripal AdityaSripal commented Apr 10, 2020

Closes: #5923 and #5947

Description

  • Implement acknowledgements in ICS20 as described in updated spec
  • Disallow user-initiated channel closing in ICS20
  • Remove unnecessary indirection
  • Add event attributes for acknowledging packet

For contributor use:

  • 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

For admin use:

  • Added appropriate labels to PR (ex. WIP, R4R, docs, etc)
  • Reviewers assigned
  • Squashed all commits, uses message "Merge pull request #XYZ: [title]" (coding standards)

@codecov
Copy link

codecov bot commented Apr 10, 2020

Codecov Report

Merging #5984 into master will decrease coverage by 0.06%.
The diff coverage is 17.28%.

@@            Coverage Diff             @@
##           master    #5984      +/-   ##
==========================================
- Coverage   58.19%   58.12%   -0.07%     
==========================================
  Files         396      396              
  Lines       23669    23709      +40     
==========================================
+ Hits        13773    13780       +7     
- Misses       8933     8966      +33     
  Partials      963      963              

Error: "",
}
if err := am.keeper.OnRecvPacket(ctx, packet, data); err != nil {
acknowledgement = FungibleTokenPacketAcknowledgement{
Copy link
Member Author

Choose a reason for hiding this comment

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

Currently any error returned by keeper.OnRecvPacket will cause a failed acknowledgement to be committed rather than reverting the transaction. Is this the behavior we want?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, that is the behaviour we want. Reverting the transaction would mean that the sequence number (e.g. in an ordered channel) would never proceed, which we don't want - IBC packets always have to be executed.

@@ -22,7 +22,6 @@ type ChannelKeeper interface {
SendPacket(ctx sdk.Context, channelCap *capability.Capability, packet channelexported.PacketI) error
PacketExecuted(ctx sdk.Context, packet channelexported.PacketI, acknowledgement []byte) error
ChanCloseInit(ctx sdk.Context, portID, channelID string, chanCap *capability.Capability) error
TimeoutExecuted(ctx sdk.Context, packet channelexported.PacketI) error
Copy link
Member Author

Choose a reason for hiding this comment

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

OnTimeoutPacket no longer calls TimeoutExecuted. TimeoutExecuted is called by the ibc handler after running callback


return nil, err
}
err = k.ChannelKeeper.TimeoutExecuted(ctx, cap, msg.Packet)
Copy link
Member Author

Choose a reason for hiding this comment

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

NOTE: ibc handler now calls this function rather than callback

@AdityaSripal AdityaSripal added R4R and removed WIP labels Apr 11, 2020
Copy link
Collaborator

@fedekunze fedekunze left a comment

Choose a reason for hiding this comment

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

👍

// See spec for onAcknowledgePacket: https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#packet-relay
type AckDataTransfer struct{}
type FungibleTokenPacketAcknowledgement struct {
Success bool `json:"success" yaml:"success"`
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit, can we make these fields private and have getter functions for them? Just to prevent them from being reset.

type AckDataTransfer struct{}
type FungibleTokenPacketAcknowledgement struct {
Success bool `json:"success" yaml:"success"`
Error string `json:"error" yaml:"error"`
Copy link
Collaborator

Choose a reason for hiding this comment

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

q: why not an error type instead? then you can remove the success field and do:

if ack.Error() != nil {
    return ack.Error()
}
// success

Copy link
Member Author

Choose a reason for hiding this comment

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

Just went off the spec. Agreed this has the same behavior.

@cwgoes any danger in switching to the above?

Copy link
Contributor

Choose a reason for hiding this comment

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

No, no danger, it just needs to be serialised correctly.


ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
Copy link
Collaborator

Choose a reason for hiding this comment

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

This event type is only for msg handlers afaik. This should instead be something like EventTimeout

sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, AttributeValueCategory),
sdk.NewAttribute(AttributeKeyAckSuccess, fmt.Sprintf("%t", ack.Success)),
Copy link
Collaborator

Choose a reason for hiding this comment

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

use ack.Error() == nil

sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, AttributeValueCategory),
sdk.NewAttribute(AttributeKeyAckSuccess, fmt.Sprintf("%t", ack.Success)),
sdk.NewAttribute(AttributeKeyAckError, ack.Error),
Copy link
Collaborator

Choose a reason for hiding this comment

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

return error message if ack.Error() != nil

Copy link
Collaborator

Choose a reason for hiding this comment

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

ctx.EventManager().EmitEvent(
		sdk.NewEvent(
			EventTypePacket,
			sdk.NewAttribute(sdk.AttributeKeyModule, AttributeValueCategory),
			sdk.NewAttribute(AttributeKeyReceiver, data.Receiver.String()),
			sdk.NewAttribute(AttributeKeyValue, data.Amount.String()),
			sdk.NewAttribute(AttributeKeyAckSuccess, fmt.Sprintf("%t", ack.Success)),
		),
)

if ack.Error != "" {
	ctx.EventManager().EmitEvent(
		sdk.NewEvent(
			EventTypePacket,
			sdk.NewAttribute(AttributeKeyAckError, ack.Error),
		),
	)
}


ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
Copy link
Collaborator

Choose a reason for hiding this comment

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

ditto, this should be EventTypeChannelClosed


ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
Copy link
Collaborator

Choose a reason for hiding this comment

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

ditto event could be packet acknowledged and attributes should be packet type, and transfer details

Copy link
Contributor

@cwgoes cwgoes left a comment

Choose a reason for hiding this comment

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

Nice start; see comments.

Error: "",
}
if err := am.keeper.OnRecvPacket(ctx, packet, data); err != nil {
acknowledgement = FungibleTokenPacketAcknowledgement{
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, that is the behaviour we want. Reverting the transaction would mean that the sequence number (e.g. in an ordered channel) would never proceed, which we don't want - IBC packets always have to be executed.

// TODO: handle packet receipt that due to an error (specify)
// the receiving chain couldn't process the transfer

// source chain sent invalid packet, shutdown our channel end
Copy link
Contributor

Choose a reason for hiding this comment

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

We definitely don't want to do this, not sure when/where this was from, but invalid packets should not close the channel

@AdityaSripal AdityaSripal added WIP and removed R4R labels Apr 14, 2020
@AdityaSripal AdityaSripal requested a review from cwgoes April 14, 2020 04:08
Copy link
Collaborator

@fedekunze fedekunze left a comment

Choose a reason for hiding this comment

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

LGTM. Pending comments from @cwgoes and changes to FungibleTokenPacketAcknowledgement fields

sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, AttributeValueCategory),
sdk.NewAttribute(AttributeKeyAckSuccess, fmt.Sprintf("%t", ack.Success)),
sdk.NewAttribute(AttributeKeyAckError, ack.Error),
Copy link
Collaborator

Choose a reason for hiding this comment

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

ctx.EventManager().EmitEvent(
		sdk.NewEvent(
			EventTypePacket,
			sdk.NewAttribute(sdk.AttributeKeyModule, AttributeValueCategory),
			sdk.NewAttribute(AttributeKeyReceiver, data.Receiver.String()),
			sdk.NewAttribute(AttributeKeyValue, data.Amount.String()),
			sdk.NewAttribute(AttributeKeyAckSuccess, fmt.Sprintf("%t", ack.Success)),
		),
)

if ack.Error != "" {
	ctx.EventManager().EmitEvent(
		sdk.NewEvent(
			EventTypePacket,
			sdk.NewAttribute(AttributeKeyAckError, ack.Error),
		),
	)
}

Copy link
Contributor

@cwgoes cwgoes left a comment

Choose a reason for hiding this comment

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

utACK

type AckDataTransfer struct{}
type FungibleTokenPacketAcknowledgement struct {
Success bool `json:"success" yaml:"success"`
Error string `json:"error" yaml:"error"`
Copy link
Contributor

Choose a reason for hiding this comment

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

No, no danger, it just needs to be serialised correctly.

@AdityaSripal
Copy link
Member Author

Believe this should be merged as-is. Tried to change the Acknowledgement struct to have just an error, but ran into a serialization panic since the error interface isn't registered.

Seems like there isn't a native JSON marshalling of error interface. I'm sure there's a way around this, but figure it's probably not worth the complication of implementing some custom way to marshal an error

@AdityaSripal AdityaSripal requested a review from fedekunze April 14, 2020 19:37
@AdityaSripal AdityaSripal added R4R and removed WIP labels Apr 14, 2020
Copy link
Member

@jackzampolin jackzampolin left a comment

Choose a reason for hiding this comment

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

This looks ready to go. When should I start integrating this into the relayer?

@fedekunze fedekunze added the A:automerge Automatically merge PR once all prerequisites pass. label Apr 15, 2020
@mergify mergify bot merged commit ca26587 into master Apr 15, 2020
@mergify mergify bot deleted the aditya/ics20-callbacks branch April 15, 2020 23:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A:automerge Automatically merge PR once all prerequisites pass.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Acknowledgements in ICS 20
4 participants