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

Sort Flow EVM events received from Event Streaming API by their TransactionIndex & EventIndex fields in ascending order #622

Merged
merged 2 commits into from
Oct 25, 2024

Conversation

m-Peter
Copy link
Collaborator

@m-Peter m-Peter commented Oct 22, 2024

Closes: #621

Description

This is a prerequisite for incorporating the offchain package of flow-go, and build a local state index on EVM Gateway.


For contributor use:

  • Targeted PR against master branch
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Code follows the standards mentioned here.
  • Updated relevant documentation
  • Re-reviewed Files changed in the Github PR explorer
  • Added appropriate labels

Summary by CodeRabbit

  • New Features

    • Introduced a sorting mechanism for events to ensure they are processed in the correct order based on their indices.
    • Enhanced functionality in event handling with updated transaction index assignments.
  • Bug Fixes

    • Improved error handling in tests for missing transactions and discrepancies in transaction hashes.
  • Tests

    • Expanded test cases to verify the ordering of block and transaction events based on their event indices.
    • Refined logic for generating transactions and blocks to accommodate new index parameters.

Copy link
Contributor

coderabbitai bot commented Oct 22, 2024

Walkthrough

The changes in this pull request introduce a sorting mechanism for events in the NewCadenceEvents function within the models/events.go file. The sorting is achieved using the sort package to organize events based on their TransactionIndex and EventIndex. Additionally, the models/events_test.go file is updated to enhance the newTransaction function by adding a txIndex parameter and updating test cases to verify event ordering. Error handling in the tests is also improved, ensuring robust validation of event processing.

Changes

Files Change Summary
models/events.go Added sorting mechanism for events in NewCadenceEvents using sort based on TransactionIndex and EventIndex. Updated event type verification to use qualified identifiers. Introduced txEvent type for transaction and receipt pairs.
models/events_test.go Updated newTransaction function to include txIndex parameter; expanded test cases for event ordering and improved error handling.

Assessment against linked issues

Objective Addressed Explanation
Sort EVM related events by their EventIndex (#621)

Possibly related PRs

Suggested labels

Testing

Suggested reviewers

  • peterargue
  • zhangchiqing
  • ramtinms
  • janezpodhostnik

🐰 In the meadow, events align,
With sorting magic, oh so fine!
Each index clear, in perfect order,
A dance of data, across the border.
Let’s hop and cheer, for changes made,
In the world of code, our joy displayed! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (2)
models/events.go (1)

43-47: LGTM: Sorting mechanism implemented correctly.

The sorting of events by their EventIndex is implemented efficiently using sort.Slice. This change aligns well with the PR objective and ensures that events are processed in the correct order.

Consider adding a brief comment explaining why sorting is necessary:

// Sort events by EventIndex to ensure correct processing order
sort.Slice(events.Events, func(i, j int) bool {
    return events.Events[i].EventIndex < events.Events[j].EventIndex
})
models/events_test.go (1)

166-176: Clarify variable naming for better readability

Consider renaming the variable txIndex to eventIndex to better reflect its role as the reversed event index. This enhances code readability and reduces potential confusion with txIndex used elsewhere.

Apply this diff to implement the change:

 for i := 0; i < txCount; i++ {
 	tx, _, txEvent, err := newTransaction(uint64(i), uint16(i))
 	require.NoError(t, err)

 	// make the Flow events come in reversed order
-	txIndex := (txCount - 1) - i
-	txEvent.EventIndex = txIndex
+	eventIndex := (txCount - 1) - i
+	txEvent.EventIndex = eventIndex

-	hashes[txIndex] = tx.Hash()
+	hashes[eventIndex] = tx.Hash()
 	blockEvents.Events = append(blockEvents.Events, txEvent)
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between db833bc and f2298e4.

📒 Files selected for processing (2)
  • models/events.go (2 hunks)
  • models/events_test.go (6 hunks)
🧰 Additional context used
🔇 Additional comments (6)
models/events.go (2)

5-5: LGTM: Import statement added correctly.

The sort package import is appropriately added and aligns with the new sorting functionality introduced in the file.


43-48: Overall changes look good and align with PR objectives.

The introduction of the sorting mechanism at the beginning of NewCadenceEvents ensures that events are processed in the correct order, as required by the PR objectives and linked issue #621. This change:

  1. Maintains the existing structure and logic of the file.
  2. Improves the reliability of event processing by ensuring correct order.
  3. Sets a solid foundation for building a local state index on the EVM Gateway.

The implementation is efficient and does not introduce any apparent issues or side effects.

To ensure the changes don't have unintended consequences, please run the following verification script:

✅ Verification successful

Verification successful: No issues detected.

The introduced sorting in NewCadenceEvents does not adversely affect existing functionality or tests. No potential race conditions were identified.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the sorting doesn't break existing functionality

# Test: Check if there are any test files that might need updates
fd -e go -e test.go

# Test: Look for any usage of NewCadenceEvents that might be affected
rg -A 5 "NewCadenceEvents"

# Test: Check for any potential race conditions introduced by the sorting
rg -A 5 "go func|goroutine|chan|select"

Length of output: 53345

models/events_test.go (4)

72-75: Function call updated to match new signature

The call to newTransaction has been correctly updated to include the new txIndex parameter.


134-135: Function call updated to match new signature

The call to newTransaction includes the new txIndex parameter, aligning with the updated function signature.


220-223: Function call updated to match new signature

The call to newTransaction has been correctly updated to include the txIndex parameter.


Line range hint 273-301: Function updated to handle transaction index

The newTransaction function now accepts txIndex and correctly assigns it to the res.Index field, ensuring that transaction indices are accurately represented in the test data.

@bluesign
Copy link

bluesign commented Oct 22, 2024

@m-Peter

I have a code like this not sure about your use case but maybe also need to order for transactionIndex:

sort.Slice(cadenceEvents, func(i, j int) bool {
	if cadenceEvents[i].TransactionIndex != cadenceEvents[j].TransactionIndex {
		return cadenceEvents[i].TransactionIndex < cadenceEvents[j].TransactionIndex
	}
	return cadenceEvents[i].EventIndex < cadenceEvents[j].EventIndex
})

there were some problematic blocks.

@m-Peter
Copy link
Collaborator Author

m-Peter commented Oct 22, 2024

@m-Peter

I have a code like this not sure about your use case but maybe also need to order for transactionIndex:

sort.Slice(cadenceEvents, func(i, j int) bool {
	if cadenceEvents[i].TransactionIndex != cadenceEvents[j].TransactionIndex {
		return cadenceEvents[i].TransactionIndex < cadenceEvents[j].TransactionIndex
	}
	return cadenceEvents[i].EventIndex < cadenceEvents[j].EventIndex
})

there were some problematic blocks.

@bluesign I assume this applies only to EVM.TransactionExecuted events, right? Could you share any such blocks? So I can investigate what went wrong and how to mitigate that.

Update: I added such a fallback sorting in 8cbfa77, just to be on the safe side.

@bluesign
Copy link

@m-Peter m-Peter marked this pull request as draft October 22, 2024 14:55
@m-Peter m-Peter force-pushed the mpeter/sort-flow-events-by-event-index branch from 8cbfa77 to 55811d2 Compare October 22, 2024 15:58
@m-Peter m-Peter marked this pull request as ready for review October 22, 2024 15:58
@atlantis-for-onflow
Copy link

Error: This repo is not allowlisted for Atlantis.

@m-Peter m-Peter changed the title Sort Flow events received from Event Streaming API by their EventIndex field in ascending order Sort Flow EVM events received from Event Streaming API by their TransactionIndex & EventIndex fields in ascending order Oct 22, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (5)
models/events.go (2)

25-25: LGTM: Improved event type checking.

The use of exact qualified identifier matching with the new constants in isBlockExecutedEvent and isTransactionExecutedEvent functions enhances reliability and potentially improves performance.

Consider caching the result of event.EventType.QualifiedIdentifier in a variable before comparison to slightly improve readability:

eventTypeID := event.EventType.QualifiedIdentifier
return eventTypeID == BlockExecutedQualifiedIdentifier // or TransactionExecutedQualifiedIdentifier

Also applies to: 33-33


47-54: LGTM: Implemented event sorting as per PR objective.

The new sorting mechanism ensures that events are processed in the correct order, addressing the main objective of this PR. The implementation correctly sorts first by TransactionIndex and then by EventIndex, aligning with the suggestion made in the PR comments.

Consider extracting the comparison logic into a separate function for improved readability:

sort.Slice(events.Events, func(i, j int) bool {
    return compareEvents(events.Events[i], events.Events[j])
})

func compareEvents(e1, e2 flow.Event) bool {
    if e1.TransactionIndex != e2.TransactionIndex {
        return e1.TransactionIndex < e2.TransactionIndex
    }
    return e1.EventIndex < e2.EventIndex
}
models/events_test.go (3)

157-227: LGTM: Comprehensive test case for event ordering.

This new test case effectively verifies the sorting mechanism for EVM events based on both TransactionIndex and EventIndex. It covers various scenarios and includes assertions for both Flow events and EVM transactions/receipts ordering.

Consider adding a comment explaining the significance of the specific TransactionIndex and EventIndex values chosen for each transaction. This would enhance the test's readability and make it easier for other developers to understand the test scenarios.


Line range hint 299-327: LGTM: Updated newTransaction function with txIndex parameter.

The newTransaction function has been correctly updated to include the txIndex parameter, and the Index field of the types.Result struct is now properly set. This change supports the new event sorting mechanism based on transaction indices.

Consider adding a comment explaining the purpose of the txIndex parameter and its role in event sorting. This would improve the function's documentation and make it clearer for other developers.


Line range hint 1-391: Overall assessment: Changes align with PR objectives and improve test coverage.

The modifications in this file successfully implement and test the new event sorting mechanism based on TransactionIndex and EventIndex. The changes are consistent throughout the file, and the new test cases provide comprehensive coverage for the updated event processing logic. These updates effectively address the PR's objective of sorting Flow events received from the Event Streaming API.

To further enhance the robustness of the tests, consider adding edge cases such as:

  1. Events with identical TransactionIndex but different EventIndex values.
  2. A large number of events to test the sorting algorithm's performance.
  3. Events with very high TransactionIndex or EventIndex values to ensure proper handling of integer overflow.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 8cbfa77 and 55811d2.

📒 Files selected for processing (2)
  • models/events.go (3 hunks)
  • models/events_test.go (6 hunks)
🧰 Additional context used
🔇 Additional comments (6)
models/events.go (3)

5-5: LGTM: Import addition for sorting functionality.

The addition of the sort package import is appropriate for the new sorting functionality implemented in the NewCadenceEvents function.


15-18: LGTM: Addition of typed constants for event identifiers.

The introduction of BlockExecutedQualifiedIdentifier and TransactionExecutedQualifiedIdentifier constants enhances code clarity and type safety. These constants are well-defined and consistent with the events package.


Line range hint 1-254: Overall implementation looks good, consider adding tests.

The changes implemented in this file successfully address the main objectives of the PR:

  1. Sorting of Flow events by TransactionIndex and EventIndex.
  2. Improved event type checking using qualified identifiers.

The overall structure of the code and error handling remain robust.

To ensure the new sorting logic is working as expected, please verify that appropriate test cases have been added or updated in the corresponding test file. Run the following command to check for changes in the test file:

If no changes are found in the test file, consider adding test cases to verify the new sorting behavior.

models/events_test.go (3)

72-72: LGTM: Updated function call with transaction index.

The newTransaction function call has been correctly updated to include the transaction index as a parameter. This change aligns with the new sorting mechanism based on transaction indices.


Line range hint 134-156: LGTM: Test case updated correctly.

The "block with more transaction hashes" test case has been properly updated to use the new newTransaction function signature. The test still effectively verifies the scenario where a block references more transactions than it should.


246-246: LGTM: Updated function call in event decoding test.

The newTransaction function call in the Test_EventDecoding function has been correctly updated to include the transaction index. This change ensures consistency with the new function signature and supports the updated event processing logic.

@@ -39,6 +44,15 @@ type CadenceEvents struct {

// NewCadenceEvents decodes the events into evm types.
func NewCadenceEvents(events flow.BlockEvents) (*CadenceEvents, error) {
Copy link
Member

Choose a reason for hiding this comment

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

Why Event Streaming API returns a different order?

Can we mention what was the default order?

And have we thought about changing the order in the EventStreaming API?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's a good question. So the default order seems to be ascending, for the most part. I am not sure if the Event Streaming API does offer such a guarantee, on the received order of the events.

However, regardless of whatever fixes we chose to do on the Event Streaming API, there are blocks that have EVM-related events out-of-order, see: #622 (comment).

And some other cases:

FlowTxIndex: 0, FlowEventIndex: 15
[EVM]:  A.e467b9dd11fa00df.EVM.TransactionExecuted(hash: [...], index: 0, ...)
FlowTxIndex: 0, FlowEventIndex: 16
[EVM]:  A.e467b9dd11fa00df.EVM.TransactionExecuted(hash: [...], index: 1, ...)
FlowTxIndex: 1, FlowEventIndex: 15
[EVM]:  A.e467b9dd11fa00df.EVM.TransactionExecuted(hash: [...], index: 0, ...)

This case though seems to be a race, as the index field of EVM.TransactionExecuted is not strictly increasing in the scope of an EVM block.

In order to incorporate the offchain package from flow-go, and replay EVM blocks & transactions to build a local state index, it is a prerequisite that we supply the blocks & transactions in the correct order, otherwise there will be state mismatches.

So the change in this PR, is more of a safety check, to ensure that we can mitigate such cases, no matter how the 3rd party tools, such as Event Streaming API, behave.

@m-Peter m-Peter force-pushed the mpeter/sort-flow-events-by-event-index branch from 55811d2 to 3e05ef5 Compare October 24, 2024 09:13
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
models/events_test.go (1)

157-227: LGTM: Comprehensive event ordering test with room for enhancement

The test case effectively validates the event ordering requirements by:

  1. Testing mixed TransactionIndex and EventIndex values
  2. Verifying both transaction and receipt ordering
  3. Including block events in the verification

Consider enhancing the test coverage with:

  1. Edge cases (e.g., maximum uint16 values for indices)
  2. Additional assertions for event payload consistency

Would you like me to provide examples of additional test cases?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 55811d2 and 3e05ef5.

📒 Files selected for processing (2)
  • models/events.go (3 hunks)
  • models/events_test.go (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • models/events.go
🔇 Additional comments (2)
models/events_test.go (2)

Line range hint 299-327: LGTM: Well-structured transaction creation with index tracking

The updated newTransaction function correctly incorporates the transaction index parameter, which is essential for proper event ordering. The implementation maintains good error handling and properly sets the index in the Result structure.


72-72: LGTM: Test cases properly updated for new transaction indexing

The existing test cases have been correctly updated to accommodate the new txIndex parameter while maintaining their original validation purposes.

Also applies to: 246-246

@m-Peter m-Peter merged commit e95b413 into main Oct 25, 2024
2 checks passed
@m-Peter m-Peter deleted the mpeter/sort-flow-events-by-event-index branch October 25, 2024 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

Sort EVM related events by their EventIndex
5 participants