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

feat: introduce hook max gas #119

Merged
merged 2 commits into from
Nov 6, 2024
Merged

feat: introduce hook max gas #119

merged 2 commits into from
Nov 6, 2024

Conversation

beer-1
Copy link
Contributor

@beer-1 beer-1 commented Nov 6, 2024

Description

This pull request introduces a new parameter hook_max_gas for the MsgFinalizeTokenDeposit message and to prevent deposit tx rejection due to gas limit.


Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • included the correct type prefix in the PR title, you can find examples of the prefixes below:
  • confirmed ! in the type prefix if API or client breaking change
  • targeted the correct branch
  • provided a link to the relevant issue or specification
  • reviewed "Files changed" and left comments if necessary
  • included the necessary unit and integration tests
  • updated the relevant documentation or specification, including comments for documenting Go code
  • confirmed all CI checks have passed

Reviewers Checklist

All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.

I have...

  • confirmed the correct type prefix in the PR title
  • confirmed all author checklist items have been addressed
  • reviewed state machine logic, API design and naming, documentation is accurate, tests and test coverage

Summary by CodeRabbit

  • New Features

    • Introduced a new parameter hook_max_gas to specify maximum gas for hook execution.
    • Enhanced FinalizeTokenDeposit method to include gas handling for bridge hooks and improved event emission based on operation success.
    • Added a default value for hook_max_gas to streamline parameter setup.
  • Bug Fixes

    • Implemented tests to ensure proper handling of gas limit scenarios, verifying that operations fail gracefully when out of gas.
  • Tests

    • Added a new test for handling deposit failures due to insufficient gas allocation.

@beer-1 beer-1 self-assigned this Nov 6, 2024
@beer-1 beer-1 requested a review from a team as a code owner November 6, 2024 02:44
Copy link

coderabbitai bot commented Nov 6, 2024

Walkthrough

This pull request introduces several changes primarily focused on enhancing gas management for the execution of hooks within the token deposit process. A new field, hook_max_gas, is added to the Params message in the protocol definition, allowing for a configurable maximum gas limit. Corresponding updates are made to the handleBridgeHook and FinalizeTokenDeposit methods to incorporate this new parameter, ensuring that gas consumption is managed effectively during hook execution. Additionally, a new test case is introduced to validate behavior under low gas conditions.

Changes

File Change Summary
proto/opinit/opchild/v1/types.proto Added field uint64 hook_max_gas = 7 to Params message for maximum gas limit in hooks.
x/opchild/keeper/deposit.go Updated handleBridgeHook to accept hookMaxGas uint64, adjusting gas consumption logic accordingly.
x/opchild/keeper/msg_server.go Modified FinalizeTokenDeposit to use params.HookMaxGas when calling handleBridgeHook, enhancing event logic.
x/opchild/keeper/msg_server_test.go Added test Test_MsgServer_Deposit_HookFail_WithOutOfGas to validate behavior when gas limit is exceeded.
x/opchild/types/params.go Introduced DefaultHookMaxGas variable and updated NewParams method to include hookMaxGas parameter.

Possibly related PRs

  • fix: audit #107: The changes in x/opchild/keeper/msg_server.go related to the FinalizeTokenDeposit method are relevant as they involve modifications to the handling of bridge hooks, which is directly connected to the new hook_max_gas field introduced in the main PR.

Poem

🐇 In the meadow where the gas flows,
A hook now knows just how far it goes.
With limits set, no more to fear,
Each deposit's path is now quite clear.
So hop along, let the tokens play,
With gas in check, we'll save the day! 🌼


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

codecov bot commented Nov 6, 2024

Codecov Report

Attention: Patch coverage is 70.00000% with 6 lines in your changes missing coverage. Please review.

Project coverage is 49.37%. Comparing base (0ef48cf) to head (cbb75b7).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
x/opchild/keeper/deposit.go 75.00% 2 Missing and 1 partial ⚠️
x/opchild/keeper/msg_server.go 40.00% 2 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #119      +/-   ##
==========================================
+ Coverage   49.25%   49.37%   +0.12%     
==========================================
  Files          57       57              
  Lines        4233     4249      +16     
==========================================
+ Hits         2085     2098      +13     
- Misses       1719     1721       +2     
- Partials      429      430       +1     
Files with missing lines Coverage Δ
x/opchild/types/params.go 68.88% <100.00%> (+1.44%) ⬆️
x/opchild/keeper/deposit.go 68.35% <75.00%> (+5.11%) ⬆️
x/opchild/keeper/msg_server.go 57.86% <40.00%> (-0.43%) ⬇️

Copy link

@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 and nitpick comments (6)
x/opchild/types/params.go (2)

13-13: Add documentation for the DefaultHookMaxGas constant.

Please add a comment explaining why 1,000,000 was chosen as the default value for hook max gas. This helps future maintainers understand the reasoning behind this specific limit.


Line range hint 51-70: Add validation for HookMaxGas in the Validate method.

The Validate method should check if HookMaxGas is within acceptable bounds to prevent potential issues with hook execution.

Consider adding validation like this:

 func (p Params) Validate(ac address.Codec) error {
     if _, err := ac.StringToBytes(p.Admin); err != nil {
         return err
     }
     for _, be := range p.BridgeExecutors {
         if _, err := ac.StringToBytes(be); err != nil {
             return err
         }
     }

     if err := p.MinGasPrices.Validate(); err != nil {
         return err
     }

     if p.MaxValidators == 0 {
         return ErrZeroMaxValidators
     }

+    if p.HookMaxGas == 0 {
+        return fmt.Errorf("hook max gas cannot be zero")
+    }
+
     // Validate fee whitelist addresses
     for _, addr := range p.FeeWhitelist {
         if _, err := ac.StringToBytes(addr); err != nil {
             return err
         }
     }

     return nil
 }
proto/opinit/opchild/v1/types.proto (1)

50-51: Enhance the field documentation.

The current documentation could be more descriptive. Consider adding:

  • Default value
  • Acceptable range/constraints
  • Impact on hook execution
  • Relationship with system-wide gas limits

Example:

-  // Max gas for hook execution of `MsgFinalizeTokenDeposit`
+  // Maximum gas limit for hook execution during MsgFinalizeTokenDeposit processing.
+  // Must be positive and not exceed the block gas limit.
+  // Default: 1000000 gas units.
+  // Note: Hook execution will fail if gas consumption exceeds this limit.
x/opchild/keeper/msg_server_test.go (3)

563-618: LGTM! Comprehensive test coverage for out-of-gas scenario.

The test thoroughly validates the behavior when a hook fails due to insufficient gas by:

  1. Setting an extremely low gas limit (1)
  2. Verifying the failure event attributes
  3. Checking that no token transfers occurred
  4. Ensuring proper error handling

Consider adding a comment explaining why the gas limit is set to 1, as it might not be immediately obvious that this is intentionally set to an extremely low value to force the out-of-gas condition.

 params.HookMaxGas = 1
+// Set an extremely low gas limit to force an out-of-gas condition
 input.OPChildKeeper.SetParams(ctx, params)

595-597: Consider adding gas meter validation.

The test sets up a gas meter with 2,000,000 gas units but doesn't verify the gas consumption. Consider adding assertions to validate that the hook execution attempted to consume more gas than the 1-unit limit.


601-609: Enhance error message validation.

While the test verifies the presence of "panic:" in the error message, it would be more robust to validate the specific out-of-gas error message to ensure the failure is happening for the expected reason.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0ef48cf and 18e45a9.

⛔ Files ignored due to path filters (1)
  • x/opchild/types/types.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (5)
  • proto/opinit/opchild/v1/types.proto (1 hunks)
  • x/opchild/keeper/deposit.go (2 hunks)
  • x/opchild/keeper/msg_server.go (1 hunks)
  • x/opchild/keeper/msg_server_test.go (2 hunks)
  • x/opchild/types/params.go (2 hunks)
🧰 Additional context used
🪛 GitHub Check: codecov/patch
x/opchild/keeper/msg_server.go

[warning] 441-442: x/opchild/keeper/msg_server.go#L441-L442
Added lines #L441 - L442 were not covered by tests

🔇 Additional comments (8)
x/opchild/types/params.go (2)

25-25: LGTM!

The DefaultParams function correctly incorporates the new DefaultHookMaxGas parameter.


30-30: LGTM!

The NewParams function signature and struct initialization are properly updated to include the new HookMaxGas parameter.

Also applies to: 38-38

x/opchild/keeper/deposit.go (3)

7-9: LGTM: Required import added for gas meter functionality

The addition of storetypes import is necessary for the new gas management features.


13-19: LGTM: Gas limit management implementation

The implementation correctly:

  • Stores the original gas meter
  • Calculates available gas for hook execution
  • Caps the gas at hookMaxGas

30-30: Verify gas consumption behavior

The implementation replaces the gas meter and consumes gas in the deferred function. Let's verify this behavior:

  1. Gas consumption is properly tracked
  2. Original gas meter is correctly updated
  3. No gas leaks occur during hook execution

Also applies to: 33-34

✅ Verification successful

Let me gather more specific information about the gas consumption implementation and tests.


Based on the code analysis, I can now generate the final response:

Gas consumption implementation appears correct and well-structured

The implementation shows proper gas handling with safety measures in place:

  • Original gas meter is preserved and updated correctly in the deferred function
  • Gas limit is properly capped with hookMaxGas
  • New gas meter is created with controlled limit for hook execution
  • Gas consumption is accurately tracked and transferred back to the original meter
  • Panic recovery ensures gas is always properly accounted

While test coverage could be more comprehensive for gas-specific scenarios, the core implementation follows best practices for gas management.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for tests validating gas consumption behavior
rg -l "GasMeter|ConsumeGas" --type go

# Look for potential gas-related test cases
ast-grep --pattern 'func Test$_.*Gas.*\(.*testing\.T\).*{
  $$$
}'

Length of output: 172


Script:

#!/bin/bash
# Check the gas consumption implementation in deposit.go
rg -A 10 "GasMeter|ConsumeGas" x/opchild/keeper/deposit.go

# Check test implementations for gas-related scenarios
rg -A 10 "GasMeter|ConsumeGas" x/opchild/keeper/msg_server_test.go

# Look for any gas-related test setup or assertions
ast-grep --pattern 'func \($_\) Test.*\(t \*testing.T\) {
  $$$
  GasMeter
  $$$
}'

Length of output: 1680

proto/opinit/opchild/v1/types.proto (1)

51-51: LGTM! Field implementation looks correct.

The field implementation follows proper protobuf conventions:

  • Appropriate field number sequence
  • Suitable type (uint64) for gas limits
  • Consistent YAML tag format
x/opchild/keeper/msg_server.go (2)

Line range hint 447-456: LGTM! Verify hook execution with different gas limits.

The changes effectively implement gas management for hook execution and provide detailed event attributes for observability. The error handling and recovery logic is comprehensive.

#!/bin/bash
# Description: Verify hook execution implementation across the codebase
# Test: Search for all hook execution calls to ensure consistent gas limit usage

# Check hook execution implementation
echo "Checking hook execution implementation..."
ast-grep --pattern 'handleBridgeHook($ctx, $data, $gas)'

# Check test coverage for different gas scenarios
echo "Checking test coverage for gas scenarios..."
rg -A 10 "Test.*Hook.*Gas" 
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 441-442: x/opchild/keeper/msg_server.go#L441-L442
Added lines #L441 - L442 were not covered by tests


439-443: Add test coverage for params retrieval error handling.

The error handling for params retrieval is not covered by tests. Consider adding test cases to verify the behavior when params retrieval fails.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 441-442: x/opchild/keeper/msg_server.go#L441-L442
Added lines #L441 - L442 were not covered by tests

x/opchild/keeper/deposit.go Show resolved Hide resolved
Copy link

@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 (4)
x/opchild/keeper/deposit.go (4)

13-16: Enhance the error message for better debugging.

While the validation is good, consider making the error message more descriptive to aid in debugging.

-		return false, "hook max gas is zero"
+		return false, "invalid hook_max_gas: value must be greater than zero"

18-22: Consider adding minimum gas validation.

While the code correctly caps the maximum gas, it doesn't ensure there's enough gas for minimal hook execution. Consider adding a minimum gas threshold check.

 	if hookMaxGas == 0 {
 		return false, "hook max gas is zero"
 	}
+
+	// Ensure minimum gas for hook execution
+	const minHookGas uint64 = 20_000 // adjust based on minimal hook requirements
+	if hookMaxGas < minHookGas {
+		return false, fmt.Sprintf("hook_max_gas too low: minimum required is %d", minHookGas)
+	}

37-38: Enhance the comment for better context.

While the implementation is correct, consider making the comment more descriptive to explain the purpose of the gas meter replacement.

-	// use new gas meter with the hook max gas limit
+	// Replace gas meter to enforce hook_max_gas limit and prevent excessive gas consumption during hook execution

Line range hint 13-39: Consider monitoring and tuning gas parameters.

The gas management implementation is solid, but consider:

  1. Adding metrics to monitor hook gas usage in production
  2. Making the minimum gas requirement configurable via chain parameters
  3. Documenting recommended gas values in the chain documentation

This will help operators tune these parameters based on real-world usage patterns.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 18e45a9 and cbb75b7.

📒 Files selected for processing (1)
  • x/opchild/keeper/deposit.go (2 hunks)
🔇 Additional comments (2)
x/opchild/keeper/deposit.go (2)

7-9: LGTM: Import changes are appropriate.

The addition of storetypes import is necessary for the new gas management functionality.


33-34: LGTM: Gas consumption in defer block is handled correctly.

The implementation properly accounts for all gas consumed during hook execution and correctly attributes it to "bridge hook".

Copy link
Contributor

@sh-cha sh-cha left a comment

Choose a reason for hiding this comment

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

LGTM

@beer-1 beer-1 merged commit 9a81ba3 into main Nov 6, 2024
8 checks passed
@beer-1 beer-1 deleted the feat/hook-max-gas branch November 6, 2024 04:44
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.

2 participants