-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
x/ibc: implement ADR 032 typed events #7762
Conversation
@jackzampolin |
} | ||
|
||
// EventOnTimeoutPacket is a typed event emitted on packet timeout | ||
message EventOnTimeoutPacket { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be in channel along with all the events above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Height
type shouldn't be changed to pointer (this is would also make this pr a breaking change). Is there a reason this was done? The Height
interface is only used to avoid circular dependencies but we intentionally constructed the code such that the concrete Height
type is the only one used. We should definitely not be treating the Height type as an Any.
re #7762 (comment), I explored the issue with @akhilkumarpilli a little bit. In old events, when we have an event with In new typed events, it seems that we want to put any type of value (strings, numbers, also arrays and structs??) inside I think |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Diffs look a lot better. New way of emitting events looks great. Do you think you could update or event spec docs as well? It's be under x/ibc/applications/transfer/spec
and x/ibc/core/spec
@@ -0,0 +1,23 @@ | |||
syntax = "proto3"; | |||
package ibc.applications.transfer.v1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super nit, but can we rename these proto files to events.proto
?
bytes trace_hash = 1 [ | ||
(gogoproto.casttype) = "github.com/tendermint/tendermint/libs/bytes.HexBytes", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, I'd just use string here
txEvents = "tm.event='Tx'" | ||
blEvents = "tm.event='NewBlock'" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure there are constants for this on Tendermint?
// Replace "." in event type with "-" to fix tm event query issue | ||
evtType := strings.ReplaceAll(proto.MessageName(tev), ".", "-") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this from tendermint? is there an issue that we can track there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the actual issue we have: #7762 (comment)
var txResult abci.TxResult | ||
txResBytes, err := json.Marshal(rev.Data) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if err := json.Unmarshal(txResBytes, &txResult); err != nil { | ||
return nil, fmt.Errorf("failed to unmarshall into abci.TxResult: %s", string(txResBytes)) | ||
} | ||
return txResult.Result.Events, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we use a private function for each of the cases? just for ease of readability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this feature will help a lot!
Though there does seem to be a lot of marshalling into JSON and then immediately unmarshalling back into some struct. I wonder how much of this is strictly necessary and how much can be simplified and done without any marshalling.
It seems like at least some of this code will be called for each typed event on each full node. So it is crucial to limit the amount of serialization/deserialization that we are forcing every node to do.
evtJSON, err := codec.ProtoMarshalJSON(tev, nil) | ||
if err != nil { | ||
return Event{}, err | ||
} | ||
|
||
var attrMap map[string]json.RawMessage | ||
var attrMap map[string]interface{} | ||
err = json.Unmarshal(evtJSON, &attrMap) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there something simpler we could do here rather than marshaling and then unmarshalling back again?
case string: | ||
valueBz = []byte(v) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this special case necessary? What's the harm in JSON marshalling everything and then JSON unmarshalling?
var value interface{} | ||
err := json.Unmarshal(attr.Value, &value) | ||
if err != nil { | ||
value = string(attr.Value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note it seems possible that a module could emit an event string and have it get unmarshalled in JSON.
Imagine that an end user had control over an event attribute. They could construct the string such that it is valid JSON. This function will then successfully unmarshal into interface
whatever the user wanted to create and store it into the attribute value.
I'm not sure there's an obviously exploitable issue here, but it depends on the application. So we should make sure to prevent this.
I recommend always JSON marshalling the attribute value in TypedEventToEvent
and always unmarshalling here. If the JSON unmarshal fails then we simply return the error.
@@ -137,6 +165,37 @@ func ParseTypedEvent(event abci.Event) (proto.Message, error) { | |||
return protoMsg, nil | |||
} | |||
|
|||
// ResultEventToABCIEvent takes the ctypes.ResultEvent and casts it to abci.TxResult, extracting the []abci.Event | |||
func ResultEventToABCIEvent(rev ctypes.ResultEvent) ([]abci.Event, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this also return some sort of boolean flag indicating whether the returned events are TxEvents
or BlockEvents
?
txResBytes, err := json.Marshal(rev.Data) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if err := json.Unmarshal(txResBytes, &txResult); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we doing this marshalling and unmarshalling?
Can't we just cast rev.Data
to tmtypes.EventDataTx
?
And then we can get the abci.TxResult
inside?
https://github.com/tendermint/tendermint/blob/master/rpc/core/types/responses.go#L233
https://github.com/tendermint/tendermint/blob/e13b4386ff1a46a5e8879e11bd653b62d4ca0992/types/events.go#L86
bl, err := json.Marshal(rev.Data) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if err := json.Unmarshal(bl, &blResult); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
) | ||
channel, _ := am.keeper.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) | ||
|
||
if err := ctx.EventManager().EmitTypedEvent( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto @colin-axner 's comment above
channel, _ := am.keeper.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) | ||
|
||
if err := ctx.EventManager().EmitTypedEvent( | ||
&channeltypes.EventChannelTimeoutPacket{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto @colin-axner's comment above
@@ -12,12 +12,19 @@ message EventTransfer { | |||
string receiver = 2; | |||
} | |||
|
|||
// EventAcknowledgementSuccess is a typed event emitted on packet acknowledgement success | |||
message EventAcknowledgementSuccess { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these can go in channel
. We have a acknowledgement success/error type defined in channel so other applications may want to use this event. It's usage would make it easier on relayers as well
), | ||
}) | ||
if err := ctx.EventManager().EmitTypedEvent( | ||
&types.EventTransfer{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be emitting the token denom and amount here too? This information is redundant since the packet data will always be emitted, but maybe it is useful for exchanges to be notified that a certain transfer occurred?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be useful yes, don't see a reason why it shouldn't be emitted
) | ||
if err := ctx.EventManager().EmitTypedEvent( | ||
&types.EventDenominationTrace{ | ||
TraceHash: traceHash.String(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should emit the amount and receiver here as well
ctx.EventManager().EmitEvent( | ||
sdk.NewEvent( | ||
types.EventTypePacket, | ||
sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We still want to emit this information (It isn't 04-channel
logic). Ideally we want to bundle this information with whether the ack was a success or failure. Is it possible to embed a event type into another event easily.
I'm thinking we have the ack success/fail event in channel
which also get added an event type applications (such as transfer) can embed their own custom event
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to create separate events. We can't embed one event into other.
sdk.NewEvent( | ||
types.EventTypeTimeout, | ||
sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), | ||
sdk.NewAttribute(types.AttributeKeyRefundReceiver, data.Sender), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto, we still need this
I also in favour of adding support to search by |
what's the status of this pr? |
Hello @colin-axner , we stuck at querying typed events. Because it's storing extra quotes |
@marbar3778 did you/anyone from tendermint team got a chance to look into this? |
We have not. I don't think there is an issue related to this in tendermint. Would you want to open one? |
thanks, created an issue tendermint/tendermint#5978 |
IBC is no longer in the SDK. It seems to me the path forward with this pr is to:
Closing this pr as it is stale and likely easier to open a fresh pr to address the concerns of 1. |
Description
ref: #7563
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.
docs/
) or specification (x/<module>/spec/
)godoc
comments.Unreleased
section inCHANGELOG.md
Files changed
in the Github PR explorerCodecov Report
in the comment section below once CI passes