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

fix(datarace): make failedBlocks to sync.Map for concurrent access #1549

Closed
wants to merge 6 commits into from

Conversation

htiennv
Copy link
Contributor

@htiennv htiennv commented Jun 20, 2024

I reopened the PR to fix the data race (#1472) with failedBlocks but I switched to using sync.Map to protect a map.

Summary by CodeRabbit

  • Refactor

    • Enhanced thread-safety by transitioning to a concurrent map for managing failed blocks, improving overall reliability and error handling in the deposit service.
  • Bug Fixes

    • Improved error handling and retry mechanisms for processing failed blocks, ensuring only valid block numbers are processed and enhancing logging for better monitoring and debugging.
  • Style

    • Streamlined function signatures across multiple contracts for improved readability without altering functionality.

Copy link
Contributor

coderabbitai bot commented Jun 20, 2024

Walkthrough

The recent update modifies the Service struct in the deposit package by replacing the failedBlocks map with a thread-safe sync.Map. This change enhances the management of failed blocks, ensuring safe concurrent access and improving error handling and retry mechanisms throughout the deposit service.

Changes

Files Change Summary
mod/execution/pkg/deposit/service.go, mod/execution/pkg/deposit/sync.go Replaced failedBlocks map with sync.Map in Service struct and updated relevant methods for thread-safe operations.
contracts/src/eip4788/BeaconVerifier.sol, contracts/src/eip4788/SSZ.sol, contracts/src/eip4788/Verifier.sol, contracts/src/eip4788/interfaces/IBeaconVerifier.sol, contracts/test/BeaconDepositContract.t.sol Reformatted function signatures to consolidate parameters into single lines for improved readability.

Poem

In the code where bunnies hop,
A sync map helps the errors stop.
With threads that dance in perfect time,
The deposits flow, all in their prime.
Hooray for changes, bright and neat,
In our code, we find our beat!
🐇✨ Code on, my friends, so sweet! ✨🐇


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>.
    • 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 show all the console.log statements in this repository.
    • @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

Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

Commits

Files that changed from the base of the PR and between 6385030 and 456b7e9.

Files selected for processing (2)
  • mod/execution/pkg/deposit/service.go (3 hunks)
  • mod/execution/pkg/deposit/sync.go (3 hunks)
Additional comments not posted (4)
mod/execution/pkg/deposit/sync.go (2)

72-81: The use of sync.Map in depositCatchupFetcher function is correctly implemented for concurrent access.


94-94: Correct implementation of sync.Map methods (Store and Delete) in fetchAndStoreDeposits enhances thread safety.

Also applies to: 107-107, 111-111

mod/execution/pkg/deposit/service.go (2)

66-66: The declaration of failedBlocks as sync.Map in the Service struct is appropriate for ensuring thread safety.


109-109: Proper initialization of failedBlocks as sync.Map in the NewService constructor ensures immediate readiness for thread-safe operations.

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: 2

Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

Commits

Files that changed from the base of the PR and between 456b7e9 and aec29ae.

Files selected for processing (1)
  • mod/execution/pkg/deposit/sync.go (3 hunks)
Additional comments not posted (1)
mod/execution/pkg/deposit/sync.go (1)

Line range hint 1-111: Well-structured error handling and logging.

The file demonstrates consistent and structured error handling and logging, which enhances maintainability and traceability of the deposit handling operations.

@htiennv htiennv requested a review from ocnc June 22, 2024 15:52
Copy link

codecov bot commented Jun 23, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 64.15%. Comparing base (a76e04b) to head (f7af52a).
Report is 51 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##             main    #1549       +/-   ##
===========================================
+ Coverage   52.83%   64.15%   +11.32%     
===========================================
  Files           7        7               
  Lines         106      106               
  Branches       21       21               
===========================================
+ Hits           56       68       +12     
+ Misses         49       38       -11     
+ Partials        1        0        -1     

see 4 files with indirect coverage changes

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: 2

Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

Commits

Files that changed from the base of the PR and between aec29ae and 4847e16.

Files selected for processing (2)
  • mod/execution/pkg/deposit/service.go (3 hunks)
  • mod/execution/pkg/deposit/sync.go (3 hunks)
Additional comments not posted (4)
mod/execution/pkg/deposit/sync.go (1)

102-102: Correct usage of sync.Map for deletion.

The deletion operation on sync.Map is correctly implemented. This ensures that the entries are properly removed from the map after successful handling, contributing to the prevention of memory leaks or stale data accumulation.

mod/execution/pkg/deposit/service.go (3)

25-25: Import of sync package.

The import of the sync package is necessary for the use of sync.Map. This is a straightforward change but essential for the modifications made in this file.


56-56: Declaration of failedBlocks as sync.Map.

The change from a regular map to sync.Map is aligned with the objective of enhancing thread safety. This is a critical update to ensure that the Service struct can safely handle concurrent operations without leading to race conditions.


93-93: Initialization of failedBlocks in NewService.

The initialization of failedBlocks as sync.Map{} in the constructor ensures that the map is ready to be used safely across different goroutines immediately upon the creation of the Service instance.

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: 2

Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

Commits

Files that changed from the base of the PR and between 4847e16 and 0714b86.

Files selected for processing (1)
  • mod/execution/pkg/deposit/sync.go (3 hunks)

mod/execution/pkg/deposit/sync.go Show resolved Hide resolved
mod/execution/pkg/deposit/sync.go Show resolved Hide resolved
@htiennv
Copy link
Contributor Author

htiennv commented Jun 26, 2024

@itsdevbear @ocnc please review it!

@itsdevbear itsdevbear enabled auto-merge (squash) August 20, 2024 15:19
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

Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

Commits

Files that changed from the base of the PR and between 0714b86 and ec305f6.

Files selected for processing (2)
  • mod/execution/pkg/deposit/service.go (3 hunks)
  • mod/execution/pkg/deposit/sync.go (3 hunks)
Additional comments not posted (5)
mod/execution/pkg/deposit/sync.go (3)

65-74: Refine iteration control in failedBlocks.Range for error handling.

The iteration over failedBlocks continues even after a key fails to parse, which might not be the intended behavior. It's essential to ensure that the system behaves predictably in error scenarios. Consider refining the control logic to either skip the iteration or log and continue based on the severity of the error.

-  return true
+  return ok  // Continue only if the key was successfully parsed.

85-85: Consistency issue in stored values in sync.Map.

The Store method is currently used to mark failedBlocks, but the value stored is an empty struct (struct{}{}). This is inconsistent with previous discussions to store true. Aligning this throughout the code will ensure consistency and clarity.

-  s.failedBlocks.Store(blockNum, struct{}{})
+  s.failedBlocks.Store(blockNum, true)

98-98: Consistency issue in stored values in sync.Map.

The Store method is currently used to mark failedBlocks, but the value stored is an empty struct (struct{}{}). This is inconsistent with previous discussions to store true. Aligning this throughout the code will ensure consistency and clarity.

-  s.failedBlocks.Store(blockNum, struct{}{})
+  s.failedBlocks.Store(blockNum, true)
mod/execution/pkg/deposit/service.go (2)

25-25: Import of sync package is appropriate.

The addition of the sync package import is necessary for using sync.Map and is correctly implemented.


53-54: Transition to sync.Map for failedBlocks is appropriate.

The change from a standard map to sync.Map ensures thread-safe access to failedBlocks, which is crucial in a concurrent environment. The initialization is correctly updated to reflect this change.

Also applies to: 85-85

auto-merge was automatically disabled September 2, 2024 09:37

Head branch was pushed to by a user without write access

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

Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

Commits

Files that changed from the base of the PR and between ec305f6 and 76c4d99.

Files selected for processing (2)
  • mod/execution/pkg/deposit/service.go (3 hunks)
  • mod/execution/pkg/deposit/sync.go (3 hunks)
Additional comments not posted (7)
mod/execution/pkg/deposit/sync.go (4)

56-65: Improved concurrency and error handling in depositCatchupFetcher.

The changes in this function address the data race issue mentioned in the PR objectives and improve error handling:

  1. Using s.failedBlocks.Range() suggests that failedBlocks is now a sync.Map, which is thread-safe for concurrent access.
  2. The addition of error handling for key type assertion enhances the robustness of the code.
  3. Improved logging provides better visibility into the retry process.

These changes are approved as they align with the PR objectives and improve the overall quality of the code.


76-76: Approved: Thread-safe storage of failed blocks.

The change to use s.failedBlocks.Store() is consistent with the move to sync.Map, addressing the data race issue.

Regarding the use of struct{}{} as the value:

  1. This is a common Go idiom for using a map as a set, as mentioned in a previous comment.
  2. It's memory-efficient as an empty struct occupies zero bytes.
  3. We're only interested in the keys (block numbers), not the values.

This implementation is correct and follows Go best practices for set-like behavior.


89-89: Approved: Consistent use of thread-safe operations.

The changes on lines 89 and 93 are consistent with the use of sync.Map:

  1. Line 89: Using s.failedBlocks.Store() ensures thread-safe addition of failed blocks.
  2. Line 93: Using s.failedBlocks.Delete() ensures thread-safe removal of successfully processed blocks.

These modifications are crucial for maintaining the integrity of the failedBlocks data structure in a concurrent environment, directly addressing the data race issue mentioned in the PR objectives.

Also applies to: 93-93


56-65: Summary: Effective implementation of thread-safe operations for failedBlocks.

The changes in this file consistently implement the use of sync.Map for failedBlocks, addressing the data race issue mentioned in the PR objectives. Key improvements include:

  1. Thread-safe iteration in depositCatchupFetcher using Range().
  2. Consistent use of Store() and Delete() methods for managing failed blocks.
  3. Improved error handling and logging for better debuggability.

These changes enhance the robustness and concurrency safety of the deposit handling process. The implementation aligns well with Go best practices for concurrent map usage.

Also applies to: 76-76, 89-89, 93-93

mod/execution/pkg/deposit/service.go (3)

25-25: LGTM: Import of "sync" package added.

The addition of the "sync" package import is correct and necessary for using sync.Map.


Line range hint 1-140: Summary: Changes effectively address the data race issue.

The modifications in this file successfully implement the use of sync.Map for failedBlocks, addressing the data race issue mentioned in the PR objectives. The changes are well-implemented and improve the thread-safety of the Service struct.

A few minor suggestions were made:

  1. Expanding the comment for failedBlocks to provide more context on the benefits of using sync.Map.
  2. Verifying the type consistency between math.U64 and math.Slot for failedBlocks.

Overall, these changes enhance the robustness of the code for concurrent operations.


87-87: LGTM: Correct initialization of sync.Map.

The change from make(map[math.Slot]struct{}) to sync.Map{} correctly initializes the failedBlocks field with an empty sync.Map.

I noticed a potential inconsistency in the types used. The struct definition uses math.U64, but the old initialization used math.Slot. Could you verify if this was intentional or if it needs to be addressed? Here's a script to check for any remaining occurrences of math.Slot in relation to failedBlocks:

Verification successful

No issues found with the transition to sync.Map for failedBlocks.

The change from make(map[math.Slot]struct{}) to sync.Map{} for failedBlocks is correct and does not affect other parts of the codebase that use math.Slot. The transition appears to be isolated and appropriate.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining occurrences of math.Slot in relation to failedBlocks

# Test: Search for math.Slot in relation to failedBlocks
rg --type go -A 5 $'failedBlocks.*math\.Slot'

Length of output: 46


Script:

#!/bin/bash
# Description: Search for any occurrences of math.Slot in the codebase

# Test: Search for math.Slot in the entire codebase
rg --type go 'math\.Slot'

Length of output: 16148

mod/execution/pkg/deposit/service.go Show resolved Hide resolved
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: 2

Outside diff range comments (4)
contracts/src/eip4788/SSZ.sol (3)

Line range hint 15-19: LGTM! Consider minor formatting adjustment for consistency.

The change to move the parameter to the same line as the function name improves code conciseness without affecting functionality.

For consistency with other functions in this file, consider moving the internal and view modifiers to the same line as well:

-    function validatorPubkeyHashTreeRoot(bytes memory pubkey)
-        internal
-        view
-        returns (bytes32 root)
+    function validatorPubkeyHashTreeRoot(bytes memory pubkey) internal view returns (bytes32 root)

Line range hint 35-39: LGTM! Consider minor formatting adjustment for consistency.

The change to move the parameter to the same line as the function name improves code conciseness without affecting functionality.

For consistency with other functions in this file, consider moving the internal and pure modifiers to the same line as well:

-    function addressHashTreeRoot(address v)
-        internal
-        pure
-        returns (bytes32 root)
+    function addressHashTreeRoot(address v) internal pure returns (bytes32 root)

Line range hint 1-119: Consider a security audit for this cryptographic library.

While the changes in this PR are purely cosmetic and don't affect functionality, this file contains complex cryptographic operations and low-level assembly code. Given its critical nature in handling validator public keys and Merkle proofs, it's advisable to have a thorough security audit performed on this library.

Consider engaging a third-party security firm specializing in smart contract audits to review this SSZ library, focusing on:

  1. Correctness of the cryptographic implementations
  2. Potential vulnerabilities in the assembly code
  3. Gas optimization without compromising security
  4. Proper error handling and edge case management
contracts/test/BeaconDepositContract.t.sol (1)

Line range hint 1-236: Overall feedback: Good formatting improvements with suggestions for enhancement

The changes made to this file are primarily formatting improvements that enhance readability without altering functionality. These changes are consistent with common Solidity style guidelines and are approved.

While the test suite appears comprehensive, consider the following suggestions to further improve the contract's test coverage and maintainability:

  1. Add more edge cases: Consider adding tests for extreme values, such as type(uint256).max for amounts.
  2. Test for revert reasons: Ensure all possible revert reasons are tested, including those from the BeaconDepositContract.
  3. Use constants for repeated values: Consider defining constants for frequently used values like 32 ether to improve maintainability.
  4. Add documentation: Consider adding NatSpec comments to describe the purpose of each test function.
  5. Gas optimization tests: If relevant, consider adding tests to ensure gas usage remains within expected bounds.

These suggestions aim to enhance the robustness and maintainability of your test suite.

Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

Commits

Files that changed from the base of the PR and between 76c4d99 and b5b6b58.

Files selected for processing (5)
  • contracts/src/eip4788/BeaconVerifier.sol (2 hunks)
  • contracts/src/eip4788/SSZ.sol (2 hunks)
  • contracts/src/eip4788/Verifier.sol (1 hunks)
  • contracts/src/eip4788/interfaces/IBeaconVerifier.sol (1 hunks)
  • contracts/test/BeaconDepositContract.t.sol (2 hunks)
Additional comments not posted (6)
contracts/src/eip4788/BeaconVerifier.sol (4)

52-57: LGTM: Function signature reformatting.

The function signature has been reformatted to a single line, improving readability without changing functionality.


Line range hint 60-65: LGTM: Function signature reformatting.

The function signature has been reformatted to a single line, improving readability without changing functionality.


Line range hint 83-88: LGTM: Function signature reformatting.

The function signature has been reformatted to a single line, improving readability without changing functionality.


Line range hint 52-88: Summary: Improved code readability through function signature reformatting.

The changes in this file are purely cosmetic, focusing on reformatting function signatures to single lines. This improves code readability without altering the contract's functionality. The affected functions are:

  1. setZeroValidatorPubkeyGIndex
  2. setExecutionNumberGIndex
  3. getParentBeaconBlockRootAt

These changes are consistent with good coding practices and do not introduce any functional modifications or security risks.

contracts/test/BeaconDepositContract.t.sol (2)

63-65: Approved: Improved function signature formatting

The consolidation of the function signature for testFuzz_DepositWrongCredentials into a single line improves readability and aligns with common Solidity style guidelines.


120-122: Approved: Improved function signature formatting with a minor suggestion

The consolidation of the function signature for testFuzz_DepositNativeWrongMinAmount into a single line improves readability and aligns with common Solidity style guidelines.

Consider using the uint256 type alias ether instead of multiplying by 1 gwei in the function body. This would make the code more idiomatic and potentially easier to read. Here's a suggested change:

-        uint256 amountInGwei = amountInEther * 1 gwei;
+        uint256 amountInGwei = amountInEther * 1 ether;

This change maintains the same functionality while using a more standard Solidity convention.

Likely invalid or redundant comment.

contracts/src/eip4788/Verifier.sol Outdated Show resolved Hide resolved
contracts/src/eip4788/interfaces/IBeaconVerifier.sol Outdated Show resolved Hide resolved
@htiennv
Copy link
Contributor Author

htiennv commented Sep 2, 2024

Other changes:

  • Run forge fmt for fixes lint

@htiennv
Copy link
Contributor Author

htiennv commented Sep 2, 2024

@itsdevbear Please check again sir!

@abi87
Copy link
Collaborator

abi87 commented Oct 17, 2024

Subsumed by c640dfd

@abi87 abi87 closed this Oct 17, 2024
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.

4 participants