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

Local state index engine #537

Merged
merged 1 commit into from
Sep 16, 2024
Merged

Conversation

sideninja
Copy link
Member

@sideninja sideninja commented Sep 10, 2024

Description

Implementation of state engine and state index.

There are two components:

  • engine is a process that currently listens to new block events (this should be changed in the future to have it's own database source, because it will be more reliable) and upon receiving a new block it executes all the transactions using the state index. Upon receiving a receipt, we make sure the receipt matches expected already indexed receipt.
  • state index handles creation of an emulator instance and executes the transaction. It then produces the receipt.

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 state management engine for processing blockchain transactions.
    • Added new fields for request handling and state indexing in the Bootstrap struct.
    • Enhanced the emulator's configuration with a new option to skip transaction validation.
    • Launched a new method for state indexing management.
  • Bug Fixes

    • Corrected the allocation logic in the ledger's slab index management.
  • Tests

    • Implemented a comprehensive integration test for state execution of transfers in the Flow EVM Gateway.

@sideninja sideninja changed the title Gregor/local state/engine Local state index engine Sep 10, 2024
Copy link
Contributor

coderabbitai bot commented Sep 10, 2024

Walkthrough

The pull request introduces significant enhancements to the state management and transaction processing capabilities of the Flow EVM Gateway. Key modifications include the addition of new fields and methods for state indexing in the Bootstrap struct, a new state management engine, and improved configurations in the emulator. These changes enhance the handling of transactions and state inspections, enabling better integration with JSON RPC APIs and bolstering the overall functionality of the system.

Changes

Files Change Summary
bootstrap/bootstrap.go Added fields Requester, State, and Ledger to Bootstrap struct; changed visibility of several fields to public; updated methods to utilize new fields; introduced StartStateIndex and StopStateIndex methods.
models/transaction.go Modified formatting of NewReceipt function call for improved readability.
tests/helpers.go Enhanced startEmulator function with SkipTransactionValidation field; improved readability of evmSign function.
services/state/state.go Introduced State struct with methods for transaction execution and state management, including NewState and Execute.

Possibly related issues

  • State index #322: The changes in this PR address the need for better state management and inspection capabilities, which are critical for implementing JSON RPC APIs as outlined in the issue.

Possibly related PRs

  • Remote ledger #362: The changes in the bootstrap/bootstrap.go file involve modifications to the Bootstrap struct, specifically the addition of new fields and changes to existing field visibility, which enhances functionality related to state management.
  • Pending transaction event from pool #374: This PR modifies the bootstrap/bootstrap.go file, specifically the startIngestion and startServer functions, which are related to the overall management of transactions and state, aligning with the changes made in the main PR.
  • Reuse client for storage query #542: The changes in the bootstrap/bootstrap.go file regarding the client setup and its parameters are relevant as they enhance the functionality of the Bootstrap struct, which is a central focus of the main PR.

Poem

🐇 In the meadow where code does play,
New fields and methods brighten the day.
With state and ledger, we leap and bound,
In the world of EVM, joy is found!
So hop along, let’s dance and cheer,
For changes that bring us all good cheer! 🎉


Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 4eb1229 and 169c245.

Files selected for processing (3)
  • bootstrap/bootstrap.go (13 hunks)
  • models/transaction.go (1 hunks)
  • tests/helpers.go (2 hunks)
Files skipped from review as they are similar to previous changes (3)
  • bootstrap/bootstrap.go
  • models/transaction.go
  • tests/helpers.go

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 generate interesting stats about this repository and render them as a table.
    -- @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: 1

Outside diff range, codebase verification and nitpick comments (1)
models/receipt.go (1)

73-141: LGTM with a suggestion for improvement!

The EqualReceipts function is well-structured and follows a clear logic for comparing the receipts. It handles nil values appropriately, performs a comprehensive comparison of the receipts, and returns detailed information about any mismatches.

Some positive aspects of the function:

  • Checks for nil values and returns an error if either receipt is nil.
  • Compares the logs of both receipts, ensuring that the number of logs matches and that each log entry's properties are equivalent.
  • Compares various fields of the receipts, such as TxHash, GasUsed, CumulativeGasUsed, Type, ContractAddress, Status, and Bloom.
  • Returns a boolean indicating whether the receipts are equal and a slice of errors detailing any mismatches.

Suggestion for improvement:

Consider extracting the log comparison logic into a separate function for better readability and maintainability. This would make the EqualReceipts function more concise and easier to understand.

For example:

func compareLogs(gethLogs []*gethTypes.Log, logs []*gethTypes.Log) []error {
    // ... log comparison logic ...
}

func EqualReceipts(gethReceipt *gethTypes.Receipt, receipt *Receipt) (bool, []error) {
    // ... other comparison logic ...
    logErrs := compareLogs(gethReceipt.Logs, receipt.Logs)
    errs = append(errs, logErrs...)
    // ... remaining comparison logic ...
}

Overall, great work on implementing this comprehensive receipt comparison function!

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between dea4e39 and 9504e97.

Files selected for processing (8)
  • bootstrap/bootstrap.go (13 hunks)
  • models/receipt.go (2 hunks)
  • models/transaction.go (1 hunks)
  • services/state/engine.go (1 hunks)
  • services/state/state.go (1 hunks)
  • storage/pebble/ledger.go (1 hunks)
  • tests/helpers.go (2 hunks)
  • tests/state_integration_test.go (1 hunks)
Files skipped from review due to trivial changes (1)
  • models/transaction.go
Additional comments not posted (17)
storage/pebble/ledger.go (1)

104-104: LGTM!

The code change is approved.

Assigning the result of index.Next() to the index variable is necessary to update the index with the next value. This ensures that the subsequent operations use the correct slab index.

services/state/state.go (1)

1-93: LGTM!

The State struct and its methods provide a clean and modular implementation for managing the state and executing transactions. The code follows good practices and handles errors appropriately.

tests/state_integration_test.go (1)

23-124: LGTM!

The Test_StateExecution_Transfers function provides a comprehensive integration test for state execution and transfers. It properly sets up the necessary components, performs multiple transactions, and verifies the expected balance changes. The test uses appropriate assertions and waits for new block events to ensure the state is updated before making assertions.

services/state/engine.go (1)

1-193: LGTM!

The code changes in this new file are approved. The code is well-structured, follows good practices, and implements the state engine functionality as described.

Some positive aspects of the code:

  • Implements interfaces for the engine and subscriber, promoting modularity and testability.
  • Uses dependency injection for the engine's dependencies, making it easier to test and maintain.
  • Handles errors and panics appropriately, ensuring the engine's robustness.
  • Logs important events and errors, aiding in debugging and monitoring.
  • The code is well-structured and readable, making it easier for other developers to understand and maintain.

Keep up the good work!

tests/helpers.go (2)

85-93: Verify the purpose and potential impact of skipping transaction validation.

The new SkipTransactionValidation field added to the server's configuration allows the emulator to bypass transaction validation checks. In the startEmulator function, this field is set to true.

Please ensure that skipping transaction validation is intended for testing purposes only and won't be enabled in production environments. Skipping validation could potentially lead to unexpected behavior or inconsistencies if not used carefully.

Consider adding a comment to clarify the purpose of this field and any potential risks associated with skipping transaction validation.

For example:

SkipTransactionValidation: true, // Set to true only for testing purposes. Do not use in production.

Also, verify that skipping transaction validation does not affect the correctness of the tests and that the tests still cover the necessary validation scenarios.


330-331: LGTM!

The formatting change in the evmSign function's parameter list, where the closing parenthesis has been moved to a new line, improves readability and aligns with the Go coding style guidelines.

This change does not affect the functionality of the code.

bootstrap/bootstrap.go (11)

36-36: LGTM!

The addition of the Ledger field to the Storages struct is approved.


48-49: LGTM!

The changes to the Bootstrap struct are approved:

  • Renaming the client field to Client is valid if the field needs to be accessed from outside the package.
  • The addition of the Requester field is approved.

50-51: LGTM!

The changes to the Bootstrap struct are approved:

  • Renaming the storages field to Storages is valid if the field needs to be accessed from outside the package.
  • Renaming the publishers field to Publishers is valid if the field needs to be accessed from outside the package.

55-57: LGTM!

The changes to the Bootstrap struct are approved:

  • Renaming the events field to Events is valid if the field needs to be accessed from outside the package.
  • Renaming the traces field to Traces is valid if the field needs to be accessed from outside the package.
  • The addition of the State field is approved.

93-98: LGTM!

The changes to the StartEventIngestion method are approved. They correctly use the public Client and Storages fields, reflecting the renaming of the previously private fields.


128-136: LGTM!

The changes to the StartEventIngestion method are approved. They correctly use the public Storages, Publishers, and Events fields, reflecting the renaming of the previously private fields.


Line range hint 141-174: LGTM!

The changes to the following methods are approved:

  • StartEventIngestion: Correctly uses the public Events field, reflecting the renaming of the previously private events field.
  • StartTraceDownloader: Correctly uses the public Publishers, Storages, and Traces fields, reflecting the renaming of the previously private publishers, storages, and traces fields.
  • StopTraceDownloader: Correctly uses the public Traces field, reflecting the renaming of the previously private traces field.

178-183: LGTM!

The changes to the StopEventIngestion method are approved. They correctly use the public Events field, reflecting the renaming of the previously private events field.


185-208: LGTM!

The addition of the StartStateIndex and StopStateIndex methods is approved:

  • StartStateIndex: Correctly initializes the state indexing engine using the newly added State field and the public Storages and Publishers fields.
  • StopStateIndex: Correctly manages the lifecycle of the state indexing engine using the public State field.

Line range hint 214-474: LGTM!

The changes to the following methods and functions are approved:

  • StartAPIServer: Correctly uses the public Server, Storages, and Publishers fields, reflecting the renaming of the previously private server, storages, and publishers fields.
  • StopAPIServer: Correctly uses the public Server field, reflecting the renaming of the previously private server field.
  • setupStorage: Correctly returns a Ledger field as part of the Storages struct, consistent with the addition of the Ledger field to the Storages struct.

493-496: LGTM!

The change to the Run function is approved. It correctly calls the newly introduced StartStateIndex method to ensure that the state indexing engine is started as part of the boot process.

assert.Equal(t, amount.Uint64()+amount2.Uint64(), balance.Uint64())
}

// todo test historic heights
Copy link
Contributor

Choose a reason for hiding this comment

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

Reminder: Implement test case for historic heights.

The todo comment indicates that testing historic heights is pending. It's important to ensure the correctness of the state at different points in time.

Do you want me to generate the test case for historic heights or open a GitHub issue to track this task?

models/receipt.go Outdated Show resolved Hide resolved
if gethReceipt.CumulativeGasUsed != receipt.CumulativeGasUsed {
errs = append(errs, fmt.Errorf("receipt CumulativeGasUsed mismatch: %d != %d", gethReceipt.CumulativeGasUsed, receipt.CumulativeGasUsed))
}
if gethReceipt.Type != 0 && gethReceipt.Type != receipt.Type { // only compare if not direct call
Copy link
Collaborator

Choose a reason for hiding this comment

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

I am not sure if this is safe, because a type of 0 is basically for LegacyTx. We have simply given the same type to direct calls, but we might miss some cases like this.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Seems like for direct calls, the TxType is never set: https://github.com/onflow/flow-go/blob/master/fvm/evm/types/result.go#L148-L151. Which means that it gets the default value of 0.

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 understand, but not sure if we can do it any other way?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe we could temporarily assign it here: https://github.com/onflow/flow-evm-gateway/pull/537/files#diff-b22e4b9d0ee4fa7a9557969e2ce56c91237a67f6e94d1709730985317c8866c3R71. Is this receipt supposed to be saved, or not? Even if it is, that's ok I guess. Becase the type we return for direct calls, is taken from: https://github.com/onflow/flow-evm-gateway/blob/main/models/transaction.go#L98. Which is the same as for LegacyTx.

return err
}

ctx, err := e.blockContext(block, receipt, uint(i), gasUsed)
Copy link
Collaborator

Choose a reason for hiding this comment

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

uint(i) seems to be used for TxCountSoFar, so I am wondering whether this should be 0-based? I guess it should be starting from 1. What do you think?

Copy link
Member Author

Choose a reason for hiding this comment

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

it's passing tests, but will take a look into flow-go how it's indexed

services/state/state.go Outdated Show resolved Hide resolved
Copy link
Collaborator

@m-Peter m-Peter left a comment

Choose a reason for hiding this comment

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

LGTM! 🎉

@sideninja sideninja changed the base branch from main to feature/state September 16, 2024 14:21
@sideninja sideninja merged commit 2ba6449 into feature/state Sep 16, 2024
1 of 2 checks passed
@sideninja sideninja mentioned this pull request Sep 16, 2024
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

2 participants