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

Oblackmon3/rebase polymer develop to match v0.0.25 #3

Conversation

OBlackmon3
Copy link

@OBlackmon3 OBlackmon3 commented Oct 21, 2024

What?

Rebasing our changes onto upstream changes.

Why?

New features and bug fixes have been released and we want to use them.

How?

Performed a rebase.

Testing?

Not yet.

Summary by CodeRabbit

  • New Features

    • Introduced a new GitHub Actions workflow for automated container image pruning.
    • Added a GetProjects method to the ERPC struct for retrieving all managed projects.
    • Enhanced the RateLimitAutoTuner with logging capabilities.
    • Added support for new networks in the AlchemyHttpJsonRpcClient.
    • Implemented a health check handler in the erpc package to assess service status.
    • Added a new method GetMetricsTracker in the UpstreamsRegistry for accessing the metrics tracker.
    • Introduced a RandomID function for generating unique JSON-RPC IDs.
    • Added a ReadAll function for reading from io.Reader with chunked processing.
  • Bug Fixes

    • Improved error handling and logging in various upstream and client methods.
    • Refined request processing logic in the SupportsNetwork methods.
    • Updated error handling in the GetVendorSpecificErrorIfAny method for clearer categorization.
  • Documentation

    • Updated configuration documentation with new sections on caching drivers and rate limiters.
    • Enhanced README with case studies demonstrating eRPC's effectiveness.
    • Clarified caching mechanism details and added examples in the documentation.
  • Tests

    • Expanded test coverage for upstream functionalities and error handling.
    • Improved robustness of HTTP server tests with new scenarios and error assertions.
    • Enhanced load testing configuration and error handling in test/k6/run.js.

aramalipoor and others added 30 commits September 8, 2024 12:03
)

* fix: checking param for blockHash or blockNumber obj

* fix: conditional logic for eth_call caching

* fix: conditional logic for eth__getProof and eth_getStorageAt caching

* fix: rm redundant len check for blockHash param

* fix: set error as nil for conditional checking of params

* fix: handle blockHash if param is string

* test: eth_call and eth_getProof blockHash/blockNumber object as param

* fix: NormalizeEvmHttpJsonRpc for eth_getStorageAt method to support blockNumber as obj
Copy link

coderabbitai bot commented Oct 21, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

The pull request introduces multiple changes across various files, primarily enhancing the functionality of GitHub Actions workflows, updating Docker and Go configurations, and refining error handling mechanisms. A new workflow for pruning container images is added, while existing workflows for releases and tests are modified to improve their execution based on conditions. Additionally, several utility functions are introduced or updated to enhance memory handling and JSON processing. Documentation updates provide clearer guidance on configuration options and operational details.

Changes

File Path Change Summary
.github/workflows/prune.yml New workflow added for automating container image pruning with triggers for manual dispatch, cron job, and pushes to main.
.github/workflows/release.yml Added trigger for push to main, updated job runner to large, added steps for generating short SHA, and modified Docker image build logic.
.github/workflows/test.yml Updated job runner to large and modified step to use args instead of token for Codecov.
.gitignore Added patterns for ignoring __debug* files.
.vscode/launch.json Added environment variables for Go package launching.
Dockerfile Updated linker flags in build commands for Go application.
Makefile Modified test command to increase test count from 3 to 5.
README.md Added new section "Case Studies" with links to specific case studies.
auth/http.go Updated string handling in NewPayloadFromHttp to use util.Mem2Str.
cmd/erpc/init_test.go New file added to set global logging level for tests.
cmd/erpc/main.go Replaced hardcoded version and commit SHA with references to common package constants.
cmd/erpc/main_test.go Removed unused import and modified response handling in tests.
common/config.go Added version and commit SHA variables, updated YAML unmarshalling methods, and introduced default failsafe configuration.
common/errors.go Updated error handling logic and added new error types and methods.
common/evm.go Added function to check for Ethereum write methods.
common/evm_block_ref.go Enhanced parameter handling and error reporting in block reference extraction methods.
common/evm_block_ref_test.go Added new test cases for eth_call and eth_getProof methods.
common/evm_json_rpc.go Modified JSON-RPC normalization function to improve error handling.
common/init_test.go New file added to disable logging during tests.
common/json_rpc.go Restructured JSON-RPC request and response handling for improved efficiency.
common/request.go Updated field types for thread-safe access and modified methods for concurrency.
common/response.go Changed body field type to io.ReadCloser and added expected size field.
common/sonic.go Introduced integration with the sonic library for JSON processing.
common/utils.go Added ContextKey type and updated hex parsing logic.
data/memory.go Removed Query method and enhanced Get and Delete methods for wildcard support.
data/mock_connector.go Introduced MockMemoryConnector with delay features.
data/value.go Deleted file containing DataRow struct.
docs/pages/config/database.mdx Enhanced documentation on evmJsonRpcCache database caching.
docs/pages/config/example.mdx Added maxTimeout configuration option in the server section.
docs/pages/config/rate-limiters.mdx Added new section on auto-tuner feature for rate limits.
docs/pages/deployment/railway.mdx Updated usage instructions for connecting to eRPC via a private network.
docs/pages/operation/batch.mdx Added callout on drawbacks of JSON-RPC batching for EVM.
docs/pages/operation/production.mdx New section on memory usage and Go's garbage collection.
docs/pages/operation/url.mdx Introduced new section for health check endpoint.
erpc/erpc.go Added GetProjects method to ERPC struct.
erpc/erpc_test.go Updated logging configuration and response handling in tests.
erpc/evm_json_rpc_cache.go Streamlined JSON handling and logging in EvmJsonRpcCache.
erpc/evm_json_rpc_cache_test.go Updated response handling in tests to use util.StringToReaderCloser.
erpc/healthcheck.go Introduced health check handler for HTTP server.
erpc/http_server.go Enhanced error handling, request processing, and server configuration.
erpc/http_server_test.go Expanded test coverage and refined error handling.
erpc/init.go Streamlined initialization of httpServer.
erpc/multiplexer.go Added once field to Multiplexer for thread-safe Close method.
erpc/networks.go Updated inFlightRequests to use sync.Map for concurrent access.
erpc/networks_registry.go Modified inFlightRequests to use sync.Map and removed inFlightMutex.
erpc/networks_test.go Enhanced test coverage for upstream functionalities.
erpc/projects.go Updated logging and simplified network initialization logic.
erpc/projects_registry.go Added GetAll method to retrieve all registered projects.
go.mod Updated dependency versions and added replacement directive.
test/cmd/main.go Updated server configurations and port numbers.
test/fake_server.go Enhanced handling of JSON-RPC requests, including batch requests.
test/init_test.go Introduced package-level initialization for tests.
test/k6/run.js Updated load testing configuration and error handling logic.
test/samples/evm-json-rpc.json Added new JSON-RPC request and response for transaction tracing.
upstream/alchemy_http_json_rpc_client.go Added support for new networks in alchemyNetworkSubdomains.
upstream/envio_http_json_rpc_client.go Modified SupportsNetwork method for improved chain ID handling.
upstream/evm_state_poller.go Streamlined error handling in block fetching methods.
upstream/failsafe.go Enhanced error handling and logging in policy creation functions.
upstream/http_json_json_client_test.go Adjusted endpoint configurations and response handling in tests.
upstream/http_json_rpc_client.go Improved batch request handling and error processing.
upstream/init_test.go New file added to disable logging for upstream tests.
upstream/pimlico_http_json_rpc_client.go Updated SupportsNetwork method for chain ID processing.
upstream/registry.go Added GetMetricsTracker method and refined logging in updateScoresAndSort.
upstream/registry_test.go Enhanced testing of upstream scoring functionalities.
upstream/request_test.go Modified test for invalid JSON request body formatting.
upstream/thirdweb_http_json_rpc_client.go Updated SupportsNetwork method for chain ID extraction.
upstream/upstream.go Enhanced error handling and logging, added initRateLimitAutoTuner method.
util/fastmem.go Introduced memory manipulation functions for efficient string conversion.
util/headers.go Updated header extraction function to work with http.Response.
util/json_rpc.go Added RandomID function for generating JSON-RPC IDs.
util/reader.go Introduced ReadAll function for buffered reading from io.Reader.
util/redact.go Modified endpoint hashing logic for improved processing.
vendors/drpc.go Simplified error handling logic in GetVendorSpecificErrorIfAny.
vendors/quicknode.go Updated error handling method for consistency.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant GitHub Actions
    participant Docker
    participant Go Application
    User->>GitHub Actions: Trigger Workflow
    GitHub Actions->>Docker: Build Image
    Docker->>Go Application: Deploy Application
    Go Application->>User: Respond to Request
Loading

🐰 In the meadow, changes bloom,
New workflows and tests resume.
With pruning tasks and logs so bright,
Our code is polished, shining light! ✨


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

@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.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

🛑 Comments failed to post (94)
.vscode/launch.json (1)

14-18: 💡 Codebase verification

Issues Found: Incorrect Compiler Paths and Missing Go Installation

  • The specified C compiler (/usr/bin/cc) and C++ compiler (/usr/bin/c++) are not found in the current environment.
  • Go is not installed or not available in the PATH, causing CGO_ENABLED to be ineffective.

Recommendations:

  1. Update Compiler Paths:

    • Verify the actual locations of the C and C++ compilers on your development machines.
    • Update the CC and CXX environment variables in .vscode/launch.json with the correct paths.
    • Alternatively, consider removing the hardcoded paths and rely on the system's PATH to locate the compilers.
  2. Install and Configure Go:

    • Ensure that Go is installed on all development environments where this configuration will be used.
    • Add Go to the system PATH to enable CGO_ENABLED to function correctly.
  3. Make Configuration Flexible:

    • Instead of hardcoding paths, use environment variables or relative paths to enhance portability across different systems.
  4. Documentation:

    • Document the setup requirements for development environments, including the necessary installations and configurations for C, C++, and Go.
🔗 Analysis chain

LGTM. Consider documenting and verifying these environment variables.

The addition of these environment variables looks good and may be necessary for building with C/C++ dependencies. However, I have a few suggestions:

  1. Consider adding a comment explaining why these environment variables are needed. This will help future developers understand the configuration.
  2. Verify that the compiler paths ("/usr/bin/cc" and "/usr/bin/c++") are correct across all development environments used by the team. These paths might need to be adjusted for different operating systems or setups.
  3. Be aware that enabling CGo (CGO_ENABLED=1) can impact build times and binary portability. Ensure this is necessary for your project's requirements.

To verify the compiler paths across different environments, you could add a step in your CI pipeline or create a simple script for developers to run. Here's a basic shell script to check:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify C and C++ compiler paths

echo "Checking C compiler..."
if [ -x "/usr/bin/cc" ]; then
    echo "C compiler found at /usr/bin/cc"
else
    echo "Warning: C compiler not found at /usr/bin/cc"
fi

echo "Checking C++ compiler..."
if [ -x "/usr/bin/c++" ]; then
    echo "C++ compiler found at /usr/bin/c++"
else
    echo "Warning: C++ compiler not found at /usr/bin/c++"
fi

echo "Checking CGo..."
if [ "$(go env CGO_ENABLED)" == "1" ]; then
    echo "CGo is enabled"
else
    echo "Warning: CGo is not enabled"
fi

Length of output: 585


Script:

#!/bin/bash
# Description: Locate C and C++ compiler paths and verify Go installation

echo "Locating C compiler..."
CC_PATH=$(command -v cc)
if [ -n "$CC_PATH" ]; then
    echo "C compiler found at $CC_PATH"
else
    echo "Warning: C compiler not found in PATH"
fi

echo "Locating C++ compiler..."
CXX_PATH=$(command -v c++)
if [ -n "$CXX_PATH" ]; then
    echo "C++ compiler found at $CXX_PATH"
else
    echo "Warning: C++ compiler not found in PATH"
fi

echo "Verifying Go installation..."
GO_PATH=$(command -v go)
if [ -n "$GO_PATH" ]; then
    echo "Go is installed at $GO_PATH"
    CGO_ENABLED_STATUS=$(go env CGO_ENABLED)
    echo "CGo Enabled: $CGO_ENABLED_STATUS"
else
    echo "Warning: Go is not installed or not found in PATH"
    echo "CGo cannot be enabled without Go installation"
fi

Length of output: 698

data/connector.go (1)

18-19: 💡 Codebase verification

Incomplete Implementations for SetTTL and HasTTL Methods

The SetTTL and HasTTL methods are declared in multiple connector implementations but lack meaningful logic. Please ensure that these methods are properly implemented to support TTL functionality as intended.

🔗 Analysis chain

Approve the addition of TTL methods to the Connector interface.

The new SetTTL and HasTTL methods are good additions to the Connector interface, allowing for TTL functionality across different connector types. This enhancement can be useful for caching or data expiration scenarios.

To ensure consistency across all connector implementations, please run the following script:

Consider adding documentation for these new methods to clarify their purpose and expected behavior. For example:

// SetTTL sets the Time-To-Live (TTL) for a specific method.
// The ttlStr parameter should be a valid duration string (e.g., "5m", "1h").
SetTTL(method string, ttlStr string) error

// HasTTL checks if a TTL is set for a specific method.
HasTTL(method string) bool
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation of SetTTL and HasTTL methods in all connector types.

# Test: Search for SetTTL and HasTTL implementations in all connector files.
echo "Checking SetTTL implementations:"
rg -p "func \(\w+\s+\*\w+Connector\)\s+SetTTL\(" data/
echo "Checking HasTTL implementations:"
rg -p "func \(\w+\s+\*\w+Connector\)\s+HasTTL\(" data/

Length of output: 1072


Script:

#!/bin/bash
# Description: Retrieve the implementations of SetTTL and HasTTL methods in all connector types.

echo "Retrieving SetTTL implementations:"
ast-grep --pattern 'func ($_ *Connector) SetTTL($_, $_) error { $$$ }' data/

echo "Retrieving HasTTL implementations:"
ast-grep --pattern 'func ($_ *Connector) HasTTL($_) bool { $$$ }' data/

Length of output: 310

erpc/erpc.go (1)

60-62: 💡 Codebase verification

Add unit tests for GetAll() in ProjectsRegistry.

The GetAll() method is implemented correctly in ProjectsRegistry, but no tests were found for it. It's essential to add unit tests to ensure its functionality and performance, especially when dealing with a large number of projects.

🔗 Analysis chain

Verify the implementation of GetAll() in ProjectsRegistry.

While the GetProjects method is correctly implemented, it's crucial to ensure that the GetAll() method in ProjectsRegistry is properly implemented and tested, especially considering potential performance implications for a large number of projects.

Let's verify the implementation of GetAll():


Further verification needed for GetAll() in ProjectsRegistry.

[/run_scripts]

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation of GetAll() in ProjectsRegistry

# Test: Check the implementation of GetAll() in ProjectsRegistry
ast-grep --pattern $'type ProjectsRegistry struct {
  $$$
}

func (r *ProjectsRegistry) GetAll() []*PreparedProject {
  $$$
}'

# Test: Check for any existing tests for GetAll()
rg -A 5 'func TestProjectsRegistry_GetAll'

Length of output: 172


Script:

#!/bin/bash
# Description: List all methods in ProjectsRegistry

# List all methods of ProjectsRegistry
ast-grep --pattern $'type ProjectsRegistry struct {
  $$$
}

func (r *ProjectsRegistry) $$$($_) $$$ {
  $$$
}'

Length of output: 111


Script:

#!/bin/bash
# Description: Search for methods returning []*PreparedProject in ProjectsRegistry

rg -A 5 'func \(r \*ProjectsRegistry\) [A-Za-z0-9_]+\([^)]*\) \[]\*PreparedProject'

Length of output: 469

Dockerfile (1)

32-35: ⚠️ Potential issue

Approve path change, but reconsider permissions.

Moving the binaries to /usr/bin/ is a good practice. However, setting permissions to 777 is overly permissive and could pose security risks.

Consider using more restrictive permissions. For most cases, 755 (rwxr-xr-x) should be sufficient:

RUN chmod 755 /usr/bin/erpc-server*

This allows the owner to read, write, and execute, while others can only read and execute, which is typically sufficient for binary executables.

common/sonic.go (1)

1-58: 💡 Codebase verification

Potential issues identified with SonicCfg configuration.

The SonicCfg configuration impacts multiple parts of the system. Please review the following areas to ensure compatibility:

  • upstream/upstream.go
  • upstream/http_json_rpc_client.go
  • erpc/networks_test.go
  • erpc/http_server.go
  • common/request.go
  • common/json_rpc.go
  • common/errors.go
  • common/response.go
  • common/config.go
  • common/sonic.go

Additionally:

  • Custom JSON marshaling/unmarshaling implementations may be affected.
  • Usage of the standard encoding/json package in several files might require updates to align with SonicCfg configuration.
🔗 Analysis chain

Verify the impact of Sonic JSON configuration on the system.

The Sonic JSON configuration in this file is optimized for performance, which is generally good. However, it's important to ensure that these optimizations don't introduce unexpected behavior in other parts of the system.

Please run the following script to check for any potential issues:

This script will help identify:

  1. Where SonicCfg is being used.
  2. Any custom JSON marshaling/unmarshaling that might be affected by the new configuration.
  3. Any uses of the standard encoding/json package that might need to be updated to use Sonic instead.

Please review the results to ensure that the new configuration is compatible with existing code and that all necessary updates have been made.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of SonicCfg and potential impacts

# Test 1: Check for uses of SonicCfg
echo "Checking uses of SonicCfg:"
rg "SonicCfg" --type go

# Test 2: Look for any custom JSON marshaling/unmarshaling that might be affected
echo "\nChecking for custom JSON marshaling/unmarshaling:"
rg "(MarshalJSON|UnmarshalJSON)" --type go

# Test 3: Check for any uses of the standard encoding/json package that might need to be updated
echo "\nChecking for uses of encoding/json:"
rg "encoding/json" --type go

Length of output: 4183

test/cmd/main.go (1)

23-25: 🛠️ Refactor suggestion

Consider scalability and diversity in additional server configurations

The addition of 102 new server configurations (ports 9084-9185) significantly increases the scale of the test environment. While this can provide more comprehensive testing, please consider:

  1. The impact on system resources when running tests with this many servers.
  2. Whether using fixed values for FailureRate (0.05) and LimitedRate (0.01) for all additional servers provides sufficient diversity in testing scenarios.
  3. The necessity of having such a large number of test servers and whether a smaller subset could achieve the same testing goals.

Consider parameterizing the number of additional servers and their configuration values. This would allow for more flexible testing setups. For example:

func generateAdditionalConfigs(startPort, endPort int, failureRate, limitedRate float64) []test.ServerConfig {
    var configs []test.ServerConfig
    for i := startPort; i <= endPort; i++ {
        configs = append(configs, test.ServerConfig{
            Port:        i,
            FailureRate: failureRate,
            LimitedRate: limitedRate,
            MinDelay:    30 * time.Millisecond,
            MaxDelay:    150 * time.Millisecond,
            SampleFile:  "test/samples/evm-json-rpc.json",
        })
    }
    return configs
}

// Usage
additionalConfigs := generateAdditionalConfigs(9084, 9185, 0.05, 0.01)
serverConfigs = append(serverConfigs, additionalConfigs...)

This approach would make it easier to adjust the number and properties of additional servers for different testing scenarios.

upstream/ratelimiter_registry.go (1)

73-73: 💡 Codebase verification

Inconsistent MaxCount Type Declarations

The common/config.go file contains conflicting declarations of MaxCount as both int and uint. Please update all instances to uint to maintain type consistency and ensure type safety across the codebase.

🔗 Analysis chain

LGTM! Verify consistency across the codebase.

The removal of the explicit uint conversion improves type safety and aligns with the reported change in common/config.go where MaxCount is now of type uint. This change enhances clarity and reduces the potential for type-related errors.

To ensure consistency, let's verify that all usages of MaxCount in the codebase have been updated accordingly:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining uint conversions of MaxCount and its usage
# Expected result: No instances of uint(MaxCount) and consistent uint typing for MaxCount

# Search for any remaining uint conversions of MaxCount
echo "Searching for remaining uint conversions of MaxCount:"
rg 'uint\(\s*MaxCount\s*\)' -g '!vendor/'

# Search for MaxCount declarations and usages
echo "Searching for MaxCount declarations and usages:"
rg 'MaxCount\s*[^)]' -g '!vendor/'

Length of output: 2090

.github/workflows/release.yml (1)

99-115: ⚠️ Potential issue

LGTM with suggestion: New steps for short SHA and main branch Docker build

These additions enhance the workflow's flexibility and provide better tagging for Docker images:

  1. The short SHA generation is useful for creating more manageable image tags.
  2. The conditional step to build and push a Docker image from the main branch allows for continuous updates of the 'main' tagged image, which is great for development and testing purposes.

There's a potential issue in the short SHA generation step. To prevent possible word splitting and globbing, it's recommended to use double quotes. Please update line 101 as follows:

- run: echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
+ run: echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"

This change ensures that the output is correctly captured, even if it contains spaces or special characters.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

      - name: Generate short SHA
        id: short_sha
        run: echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"

      - name: Build and push Docker image from main
        if: github.event.inputs.version_tag == ''
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          platforms: linux/amd64,linux/arm64
          build-args: |
            VERSION=main
            COMMIT_SHA=${{ steps.short_sha.outputs.SHORT_SHA }}
          tags: |
            ghcr.io/${{ steps.tag_param.outputs.repo }}:main
🧰 Tools
🪛 actionlint

101-101: shellcheck reported issue in this script: SC2086:info:1:51: Double quote to prevent globbing and word splitting

(shellcheck)

data/postgresql.go (1)

92-95: 🛠️ Refactor suggestion

Improve the SetTTL method implementation

While the placeholder implementation maintains consistency with other connectors, consider the following improvements:

  1. Use more specific parameter names (e.g., key and ttl) instead of underscores to improve readability.
  2. Enhance the debug message to include the attempted key and TTL values.
  3. Consider returning an error indicating that the feature is not implemented, rather than silently succeeding.

Here's a suggested implementation:

func (p *PostgreSQLConnector) SetTTL(key string, ttl string) error {
    p.logger.Debug().Msgf("SetTTL not implemented for PostgreSQLConnector. Attempted values - Key: %s, TTL: %s", key, ttl)
    return fmt.Errorf("SetTTL not implemented for PostgreSQLConnector")
}

This change would provide more informative logging and a clear indication to callers that the method is not supported.

data/dynamodb.go (1)

264-267: 🛠️ Refactor suggestion

Consider enhancing the SetTTL method implementation

While the method serves as a placeholder for future TTL implementation, consider the following improvements:

  1. Make the debug message more specific, e.g., "SetTTL method not implemented for DynamoDBConnector".
  2. Consider returning an error instead of nil to indicate that the operation is not supported. This would prevent silent failures if the method is called without checking HasTTL first.

Here's a suggested implementation:

 func (d *DynamoDBConnector) SetTTL(_ string, _ string) error {
-	d.logger.Debug().Msgf("Method TTLs not implemented for DynamoDBConnector")
-	return nil
+	d.logger.Debug().Msg("SetTTL method not implemented for DynamoDBConnector")
+	return fmt.Errorf("SetTTL is not supported for DynamoDBConnector")
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

func (d *DynamoDBConnector) SetTTL(_ string, _ string) error {
	d.logger.Debug().Msg("SetTTL method not implemented for DynamoDBConnector")
	return fmt.Errorf("SetTTL is not supported for DynamoDBConnector")
}
test/samples/evm-json-rpc.json (1)

1439-1451: ⚠️ Potential issue

debug_traceTransaction implementation needs improvement.

The addition of the debug_traceTransaction method is a good step towards enhanced debugging capabilities. However, the current implementation has some issues:

  1. The response contains a placeholder result "bigfake:50000000" instead of an actual transaction trace.
  2. This placeholder doesn't match the expected format for a debug_traceTransaction result, which should be a detailed trace of the transaction execution.

To improve this, consider the following:

  1. Implement actual transaction tracing logic to return a detailed execution trace.
  2. Ensure the response follows the standard format for debug_traceTransaction, which typically includes steps of execution, gas usage, memory operations, and stack changes.
  3. If this is intended as a mock or placeholder, use a more realistic mock data structure that mirrors the expected output format.

Example of a more realistic mock response:

{
  "jsonrpc": "2.0",
  "result": {
    "gas": 21000,
    "failed": false,
    "returnValue": "",
    "structLogs": [
      {
        "pc": 0,
        "op": "PUSH1",
        "gas": 21000,
        "gasCost": 3,
        "depth": 1,
        "stack": [],
        "memory": [],
        "storage": {}
      },
      // ... more steps ...
    ]
  }
}

This structure more closely resembles what would be expected from an actual debug_traceTransaction call.

util/fastmem.go (4)

21-25: ⚠️ Potential issue

Avoid unsafe conversion in Mem2Str function

The Mem2Str function uses unsafe pointer manipulation to convert a []byte to a string. This approach can lead to unexpected behavior, violates the immutability of strings in Go, and may introduce subtle bugs if the underlying byte slice is modified elsewhere.

Consider using safe conversion methods:

-func Mem2Str(v []byte) (s string) {
-    (*GoString)(unsafe.Pointer(&s)).Len = (*GoSlice)(unsafe.Pointer(&v)).Len // #nosec G103
-    (*GoString)(unsafe.Pointer(&s)).Ptr = (*GoSlice)(unsafe.Pointer(&v)).Ptr // #nosec G103
-    return
+func Mem2Str(v []byte) string {
+    return string(v)
 }

If performance is a critical concern and you're using Go 1.20 or later, you can use unsafe.String:

import "unsafe"

// ...

func Mem2Str(v []byte) string {
    return unsafe.String(&v[0], len(v))
}

Note: Ensure that v is not empty to avoid a panic when accessing v[0].


28-33: ⚠️ Potential issue

Avoid unsafe conversion in Str2Mem function

The Str2Mem function uses unsafe pointer manipulation to convert a string to a []byte. This is risky because strings in Go are immutable, and sharing the underlying data can lead to undefined behavior if the byte slice is modified.

For safe conversion, use:

-func Str2Mem(s string) (v []byte) {
-    (*GoSlice)(unsafe.Pointer(&v)).Cap = (*GoString)(unsafe.Pointer(&s)).Len // #nosec G103
-    (*GoSlice)(unsafe.Pointer(&v)).Len = (*GoString)(unsafe.Pointer(&s)).Len // #nosec G103
-    (*GoSlice)(unsafe.Pointer(&v)).Ptr = (*GoString)(unsafe.Pointer(&s)).Ptr // #nosec G103
-    return
+func Str2Mem(s string) []byte {
+    return []byte(s)
 }

If you need to avoid copying for performance reasons and are certain that the byte slice will not be modified, you can use unsafe.Slice in Go 1.20 or later:

import (
    "unsafe"
)

// ...

func Str2Mem(s string) []byte {
    strHeader := (*[2]uintptr)(unsafe.Pointer(&s))
    data := strHeader[0]
    length := strHeader[1]
    return unsafe.Slice((*byte)(unsafe.Pointer(data)), length)
}

However, exercise caution as this breaks the immutability contract of strings and can lead to undefined behavior if the byte slice is modified.


20-20: 🛠️ Refactor suggestion

Review necessity of //go:nosplit directives

The //go:nosplit directives prevent the Go scheduler from preempting the function, which can lead to stack overflows if the function needs to grow the stack. Unless there's a specific reason (e.g., the function is called in a context where stack splitting is unsafe), consider removing these directives to allow normal stack management.

Also applies to: 27-27


35-37: 🛠️ Refactor suggestion

Simplify StringToReaderCloser with safe conversion

The StringToReaderCloser function relies on Str2Mem for converting strings to byte slices. Given the issues with Str2Mem, it's advisable to handle string-to-byte conversion safely.

Simplify the function using bytes.NewBufferString, which creates a buffer directly from a string:

-func StringToReaderCloser(b string) io.ReadCloser {
-    return io.NopCloser(bytes.NewBuffer(Str2Mem(b)))
+func StringToReaderCloser(b string) io.ReadCloser {
+    return io.NopCloser(bytes.NewBufferString(b))
 }

This approach eliminates the need for unsafe conversions and ensures data integrity.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

func StringToReaderCloser(b string) io.ReadCloser {
	return io.NopCloser(bytes.NewBufferString(b))
}
test/k6/run.js (2)

8-17: 🛠️ Refactor suggestion

Review preAllocatedVUs and maxVUs settings for optimal resource usage

The current configuration sets both preAllocatedVUs and maxVUs to 1000 for a request rate of 500 requests per second. This may allocate more virtual users than necessary, leading to unnecessary resource consumption. Consider adjusting these values to better match the expected load.

You might reduce preAllocatedVUs and maxVUs to align with the rate:

       executor: 'constant-arrival-rate',
       rate: 500,
       timeUnit: '1s',
       duration: '30m',
-      preAllocatedVUs: 1000,
-      maxVUs: 1000,
+      preAllocatedVUs: 500,
+      maxVUs: 500,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  scenarios: {    
    constant_request_rate: {
      executor: 'constant-arrival-rate',
      rate: 500,
      timeUnit: '1s',
      duration: '30m',
      preAllocatedVUs: 500,
      maxVUs: 500,
    },
  },

55-61: ⚠️ Potential issue

Avoid logging the full response body to prevent exposing sensitive data

In the catch block (lines 58-61), the code logs the entire response body when a JSON parsing error occurs. Logging the full response may expose sensitive information. Consider logging only the error message or a sanitized version of the response.

Apply this diff to adjust the logging:

   } catch (e) {
-    console.log(`Unmarshal error: ${e} for body: ${r.body}`);
+    console.log(`JSON parse error: ${e.message}`);
     return false;
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

      try {
        const body = JSON.parse(r.body);
        return body && (body.error === undefined || body.error === null);
      } catch (e) {
        console.log(`JSON parse error: ${e.message}`);
        return false;
      }
common/evm_json_rpc.go (5)

9-10: ⚠️ Potential issue

Potential for deadlocks due to locking jrq

Introducing jrq.Lock() and defer jrq.Unlock() adds concurrency control to jrq. Ensure that there are no other parts of the code that might lock jrq and cause a deadlock when this function is called.

Consider reviewing the codebase for other locks on jrq to prevent deadlocks. If nested locking is necessary, ensure that the locking order is consistent throughout the code.


44-58: ⚠️ Potential issue

Inconsistent handling of block number formats

In the case blocks starting at line 44, there's handling for both string and map parameter types, but the normalization logic may not cover all possible block number representations.

Ensure that block numbers within maps and as separate parameters are consistently normalized, regardless of whether they are strings or numeric types. Consider adding checks for numeric types similar to earlier code.


80-91: 🛠️ Refactor suggestion

Combine similar code blocks to improve readability

The code for normalizing fromBlock and toBlock in the eth_getLogs case is similar. Consider extracting this logic into a helper function to reduce duplication and improve maintainability.

Example:

func normalizeBlockParam(paramsMap map[string]interface{}, key string) {
    if value, ok := paramsMap[key]; ok {
        b, err := NormalizeHex(value)
        if err == nil {
            paramsMap[key] = b
        }
    }
}

// Then, in your case block:
normalizeBlockParam(paramsMap, "fromBlock")
normalizeBlockParam(paramsMap, "toBlock")

24-25: ⚠️ Potential issue

Potential format issue when converting float to string

Using fmt.Sprintf("%f", bkf) may include decimal points and fractional parts, which might not be appropriate for block numbers expected to be integers.

Consider formatting the float without decimal places:

-bks = fmt.Sprintf("%f", bkf)
+bks = fmt.Sprintf("%.0f", bkf)

Or cast the float to an integer if safe:

-bks = fmt.Sprintf("%f", bkf)
+bks = fmt.Sprintf("%d", int64(bkf))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

					bks = fmt.Sprintf("%.0f", bkf)
					b, err := NormalizeHex(bks)

20-36: ⚠️ Potential issue

Uninitialized variable bks may cause runtime errors

The variable bks may not be initialized if jrq.Params[0] is neither a string nor a float64. However, bks is used later in strings.HasPrefix(bks, "0x"), which could lead to a nil pointer dereference.

Ensure bks is properly initialized before it's used:

 if len(jrq.Params) > 0 {
     bks, ok := jrq.Params[0].(string)
     if !ok {
         bkf, ok := jrq.Params[0].(float64)
         if ok {
             bks = fmt.Sprintf("%f", bkf)
             b, err := NormalizeHex(bks)
             if err == nil {
                 jrq.Params[0] = b
             }
         }
+    } else {
+        // Initialize bks to prevent nil usage
+        bks = ""
     }
     if strings.HasPrefix(bks, "0x") {
         b, err := NormalizeHex(bks)
         if err == nil {
             jrq.Params[0] = b
         }
     }
 }

Committable suggestion was skipped due to low confidence.

data/mock_connector.go (4)

83-86: ⚠️ Potential issue

Add synchronization to SetFakeDelay for thread safety.

If MockMemoryConnector is accessed concurrently, modifying fakeDelay without synchronization could lead to race conditions.

Introduce a mutex to protect fakeDelay:

import "sync"

type MockMemoryConnector struct {
	*MemoryConnector
	fakeDelay time.Duration
	mu        sync.RWMutex
}

func (m *MockMemoryConnector) SetFakeDelay(delay time.Duration) {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.fakeDelay = delay
}

func (m *MockMemoryConnector) getFakeDelay() time.Duration {
	m.mu.RLock()
	defer m.mu.RUnlock()
	return m.fakeDelay
}

Update the Set and Get methods to use getFakeDelay():

 func (m *MockMemoryConnector) Set(ctx context.Context, partitionKey, rangeKey, value string) error {
-	time.Sleep(m.fakeDelay)
+	time.Sleep(m.getFakeDelay())
 	return m.MemoryConnector.Set(ctx, partitionKey, rangeKey, value)
 }
 func (m *MockMemoryConnector) Get(ctx context.Context, index, partitionKey, rangeKey string) (string, error) {
-	time.Sleep(m.fakeDelay)
+	time.Sleep(m.getFakeDelay())
 	return m.MemoryConnector.Get(ctx, index, partitionKey, rangeKey)
 }

71-75: ⚠️ Potential issue

Use context-aware delay to respect context cancellation in Set.

time.Sleep does not consider context cancellation. To handle cancellation properly, use a context-aware delay.

Apply this diff to make the delay context-aware:

 func (m *MockMemoryConnector) Set(ctx context.Context, partitionKey, rangeKey, value string) error {
-	time.Sleep(m.fakeDelay)
+	select {
+	case <-time.After(m.fakeDelay):
+		// Proceed after delay
+	case <-ctx.Done():
+		return ctx.Err()
+	}
 	return m.MemoryConnector.Set(ctx, partitionKey, rangeKey, value)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

// Set overrides the base Set method to include a fake delay
func (m *MockMemoryConnector) Set(ctx context.Context, partitionKey, rangeKey, value string) error {
	select {
	case <-time.After(m.fakeDelay):
		// Proceed after delay
	case <-ctx.Done():
		return ctx.Err()
	}
	return m.MemoryConnector.Set(ctx, partitionKey, rangeKey, value)
}

52-56: 🛠️ Refactor suggestion

Consider embedding a pointer to MemoryConnector for efficiency.

Currently, MockMemoryConnector embeds MemoryConnector by value. Embedding by pointer avoids copying the entire struct and is more efficient, especially if MemoryConnector contains state.

Apply this diff to embed MemoryConnector by pointer:

 type MockMemoryConnector struct {
-	MemoryConnector
+	*MemoryConnector
 	fakeDelay time.Duration
 }

Update the constructor accordingly:

 return &MockMemoryConnector{
-	MemoryConnector: *baseConnector,
+	MemoryConnector: baseConnector,
 	fakeDelay:       fakeDelay,
 }, nil

Committable suggestion was skipped due to low confidence.


77-81: ⚠️ Potential issue

Use context-aware delay to respect context cancellation in Get.

Similar to Set, the Get method should handle context cancellation during the delay.

Apply this diff to make the delay context-aware:

 func (m *MockMemoryConnector) Get(ctx context.Context, index, partitionKey, rangeKey string) (string, error) {
-	time.Sleep(m.fakeDelay)
+	select {
+	case <-time.After(m.fakeDelay):
+		// Proceed after delay
+	case <-ctx.Done():
+		return "", ctx.Err()
+	}
 	return m.MemoryConnector.Get(ctx, index, partitionKey, rangeKey)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

// Get overrides the base Get method to include a fake delay
func (m *MockMemoryConnector) Get(ctx context.Context, index, partitionKey, rangeKey string) (string, error) {
	select {
	case <-time.After(m.fakeDelay):
		// Proceed after delay
	case <-ctx.Done():
		return "", ctx.Err()
	}
	return m.MemoryConnector.Get(ctx, index, partitionKey, rangeKey)
}
data/memory.go (1)

45-48: 🛠️ Refactor suggestion

Consider implementing TTL functionality or removing the methods

The SetTTL method currently logs that TTLs are not implemented and returns nil. If TTL functionality is not intended for the MemoryConnector, it might be clearer to remove the SetTTL method altogether or return an error indicating that the operation is not supported. This will prevent any confusion for users who might expect TTL functionality to be available.

Consider returning an error to explicitly indicate the method is unsupported:

 func (m *MemoryConnector) SetTTL(_ string, _ string) error {
-	m.logger.Debug().Msgf("Method TTLs not implemented for MemoryConnector")
-	return nil
+	return fmt.Errorf("SetTTL is not supported for MemoryConnector")
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

func (m *MemoryConnector) SetTTL(_ string, _ string) error {
	return fmt.Errorf("SetTTL is not supported for MemoryConnector")
}
data/redis.go (3)

27-27: ⚠️ Potential issue

Potential concurrency issue with ttls map access

The ttls map may be accessed concurrently by multiple goroutines, which can lead to race conditions since Go maps are not safe for concurrent read and write operations. Consider protecting the ttls map with a mutex or using a sync.Map to ensure thread safety.


93-93: ⚠️ Potential issue

Security concern with InsecureSkipVerify set to true

Setting InsecureSkipVerify to true disables SSL certificate verification, which can expose the connection to man-in-the-middle attacks. It's recommended to avoid disabling SSL verification unless absolutely necessary. If this is required for development or testing purposes, ensure that it is not enabled in production environments.


137-141: ⚠️ Potential issue

Validate the format of rangeKey before splitting

In the line method := strings.ToLower(strings.Split(rangeKey, ":")[0]), it is assumed that rangeKey contains a : character. If rangeKey does not contain :, the extracted method may not be correct. Consider adding validation to ensure rangeKey is in the expected format or handle cases where it does not contain :, to prevent potential logical errors.

erpc/projects.go (1)

79-80: ⚠️ Potential issue

Handle potential error from nq.Method()

At lines 79-80, the error returned by nq.Method() is being ignored by assigning it to _. If there's a chance that nq.Method() can return an error, it's important to handle it to prevent unexpected behavior.

Consider modifying the code to handle the error:

-method, _ := nq.Method()
+method, err := nq.Method()
+if err != nil {
+    lg.Error().Err(err).Msg("Failed to get method from request")
+    return nil, err
+}

Committable suggestion was skipped due to low confidence.

upstream/pimlico_http_json_rpc_client.go (2)

148-152: ⚠️ Potential issue

Specify the JSON path in PeekStringByPath()

The PeekStringByPath() function requires a path argument to correctly extract the desired value from the JSON response. Omitting the path may lead to incorrect results or runtime errors.

Apply this diff to fix the issue:

-    cids, err := jrr.PeekStringByPath()
+    cids, err := jrr.PeekStringByPath("result")
     if err != nil {
         return false, err
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	cids, err := jrr.PeekStringByPath("result")
	if err != nil {
		return false, err
	}


136-136: ⚠️ Potential issue

Consider using a cryptographically secure random number generator

The current code uses math/rand.Intn to generate a random ID, which is not suitable for security-sensitive operations. If the random ID is used in a context where unpredictability is important, consider using crypto/rand to generate a cryptographically secure random number.

Apply this diff to use crypto/rand:

-import (
-    "math/rand"
+import (
+    "crypto/rand"
+    "math/big"
 )

...

-    rid := rand.Intn(100_000_000) // #nosec G404
+    nBig, err := rand.Int(rand.Reader, big.NewInt(100_000_000))
+    if err != nil {
+        return false, err
+    }
+    rid := nBig.Int64()

Committable suggestion was skipped due to low confidence.

common/response.go (6)

4-14: ⚠️ Potential issue

Resolve merge conflict markers in imports.

The code contains unresolved merge conflict markers (<<<<<<<, =======, >>>>>>>) in the import section. These markers indicate that there are conflicts that need to be manually resolved to ensure the code compiles correctly.


20-29: ⚠️ Potential issue

Resolve merge conflict markers in NormalizedResponse struct definition.

Unresolved merge conflict markers are present in the declaration of the NormalizedResponse struct. Please resolve these conflicts to maintain the integrity of the struct's definition.


230-240: ⚠️ Potential issue

Resolve merge conflict markers in EvmBlockNumber method.

There are unresolved merge conflict markers within the EvmBlockNumber method. It's crucial to resolve these to ensure the method functions as intended.


261-267: ⚠️ Potential issue

Resolve merge conflict markers in EvmBlockNumber method implementation.

Additional merge conflict markers are present in the implementation of the EvmBlockNumber method. These need to be addressed to avoid compilation errors.


179-194: ⚠️ Potential issue

Check for potential nil pointer dereference in IsResultEmptyish method.

Ensure that the method handles cases where jrr might be nil after calling JsonRpcResponse(), to avoid potential runtime panics.


202-218: 🛠️ Refactor suggestion

Optimize locking in IsObjectNull method.

The method acquires multiple read locks (resultMu and errMu). Consider combining locks or reviewing the locking strategy to improve performance while maintaining thread safety.

test/fake_server.go (8)

191-203: 🛠️ Refactor suggestion

Improve rate limiting implementation for realistic simulation

Using rand.Float64() for rate limiting introduces randomness rather than enforcing a strict rate limit. Consider using a token bucket or leaky bucket algorithm to simulate rate limiting more accurately.

Would you like assistance in implementing a more precise rate limiting mechanism?


191-203: 🛠️ Refactor suggestion

Use HTTP status codes to indicate rate limiting

When simulating rate limiting, it's helpful to use appropriate HTTP status codes, such as 429 Too Many Requests, to indicate to clients that they are being rate limited.

Apply this diff to set the HTTP status code:

 if rand.Float64() < fs.LimitedRate {
     fs.mu.Lock()
     fs.requestsLimited++
     fs.mu.Unlock()
     if req.ID != nil {
+        w.WriteHeader(http.StatusTooManyRequests)
         return &JSONRPCResponse{
             Jsonrpc: "2.0",
             Error:   map[string]interface{}{"code": -32000, "message": "simulated capacity exceeded"},
             ID:      req.ID,
         }
     }
     return nil // Notification, no response
 }

Committable suggestion was skipped due to low confidence.


108-112: ⚠️ Potential issue

Limit the size of request bodies to prevent potential memory exhaustion

In handleRequest, reading the entire request body using io.ReadAll without size limitations can lead to memory exhaustion if a large request is sent. Consider setting a maximum allowable size for the request body.

Apply this diff to limit the request body size:

 func (fs *FakeServer) handleRequest(w http.ResponseWriter, r *http.Request) {
     fs.mu.Lock()
     fs.requestsHandled++
     fs.mu.Unlock()

+    // Limit the size of the request body to 1MB
+    r.Body = http.MaxBytesReader(w, r.Body, 1<<20) // 1MB
+
     // Read the request body
     body, err := io.ReadAll(r.Body)
     if err != nil {
         fs.sendErrorResponse(w, nil, -32700, "Parse error")
         return
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	// Limit the size of the request body to 1MB
	r.Body = http.MaxBytesReader(w, r.Body, 1<<20) // 1MB

	body, err := io.ReadAll(r.Body)
	if err != nil {
		fs.sendErrorResponse(w, nil, -32700, "Parse error")
		return
	}

125-131: ⚠️ Potential issue

Handle malformed JSON requests properly

When unmarshalling the request fails, the error response should conform to JSON-RPC specifications. Currently, the code returns an "Invalid Request" error, but according to the JSON-RPC 2.0 specification, a parse error (-32700) should be returned for invalid JSON.

Apply this diff to return the correct error code:

 // Try to unmarshal as a single request
 var singleReq JSONRPCRequest
 err = json.Unmarshal(body, &singleReq)
 if err == nil {
     // Handle single request
     fs.handleSingleRequest(w, singleReq)
     return
 }
 
-// Invalid JSON-RPC request
-fs.sendErrorResponse(w, nil, -32600, "Invalid Request")
+// Parse error
+fs.sendErrorResponse(w, nil, -32700, "Parse error")

Committable suggestion was skipped due to low confidence.


264-275: ⚠️ Potential issue

Prevent incomplete large data generation in sample responses

In findMatchingSample, when generating large fake responses, the byte slice is allocated but not populated, resulting in a slice of zero bytes. Fill the slice with actual data to simulate realistic payloads.

Apply this diff to populate the byte slice:

 if txt, ok := sample.Response.Result.(string); ok {
     if strings.HasPrefix(txt, "bigfake:") {
         size, err := strconv.Atoi(txt[len("bigfake:"):])
         fmt.Printf("Generating big response of size %d\n", size)
         if err != nil {
             return nil
         }
         // generate a random string with the size of the number
-        sample.Response.Result = make([]byte, size)
+        data := make([]byte, size)
+        rand.Read(data)
+        sample.Response.Result = data
     }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

			if txt, ok := sample.Response.Result.(string); ok {
				if strings.HasPrefix(txt, "bigfake:") {
					size, err := strconv.Atoi(txt[len("bigfake:"):])
					fmt.Printf("Generating big response of size %d\n", size)
					if err != nil {
						return nil
					}
					// generate a random string with the size of the number
					data := make([]byte, size)
					rand.Read(data)
					sample.Response.Result = data
				}
			}

145-150: ⚠️ Potential issue

Handle notifications correctly in batch requests

In handleBatchRequest, responses for notifications (requests with null ID) should not be included in the response array, according to the JSON-RPC 2.0 specification. Adjust the code to exclude responses for notifications.

Apply this diff to skip responses for notifications:

 for _, req := range batchReq {
     response := fs.processSingleRequest(req)
     if response != nil {
+        if response.ID == nil {
+            continue // Skip notifications
+        }
         response.ID = req.ID
         responses = append(responses, *response)
     }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		response := fs.processSingleRequest(req)
		if response != nil {
			if response.ID == nil {
				continue // Skip notifications
			}
			response.ID = req.ID
			responses = append(responses, *response)
		}
	}

54-58: ⚠️ Potential issue

Initialize samples field to prevent potential nil pointer dereference

In the NewFakeServer function, if loadSamples fails, fs.samples may remain nil, which could lead to a nil pointer dereference in findMatchingSample. Consider initializing fs.samples to an empty slice to avoid this issue.

Apply this diff to ensure fs.samples is initialized:

 func NewFakeServer(port int, failureRate float64, limitedRate float64, minDelay, maxDelay time.Duration, sampleFilePath string) (*FakeServer, error) {
     fs := &FakeServer{
         Port:        port,
         FailureRate: failureRate,
+        LimitedRate: limitedRate,
+        MinDelay:    minDelay,
+        MaxDelay:    maxDelay,
+        samples:     []RequestResponseSample{},
     }

     if err := fs.loadSamples(sampleFilePath); err != nil {
         return nil, fmt.Errorf("failed to load samples: %w", err)
     }

Committable suggestion was skipped due to low confidence.


175-185: ⚠️ Potential issue

Check for nil req.ID to handle notifications correctly

In processSingleRequest, when returning an error response for invalid requests, the ID should be null if it was not provided in the request, according to the JSON-RPC 2.0 specification. Ensure that the ID is set appropriately.

Apply this diff to set ID to nil when it is not provided:

     // Validate request
     if req.Jsonrpc != "2.0" || req.Method == "" {
         fs.mu.Lock()
         fs.requestsFailed++
         fs.mu.Unlock()
         return &JSONRPCResponse{
             Jsonrpc: "2.0",
             Error:   map[string]interface{}{"code": -32600, "message": "Invalid Request"},
-            ID:      req.ID,
+            ID:      req.ID, // This should be null if req.ID is missing
         }
     }

Committable suggestion was skipped due to low confidence.

erpc/evm_json_rpc_cache.go (1)

130-132: ⚠️ Potential issue

Fix Error Handling in Caching Decision

If shouldCache is false and err is nil, returning err (which is nil) could incorrectly indicate success. Adjust the error handling to return nil only when appropriate.

Apply this diff to correct the error handling:

 if !shouldCache || err != nil {
-  return err
+  if err != nil {
+    return err
+  }
+  return nil
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	shouldCache, err := shouldCacheResponse(lg, req, resp, rpcReq, rpcResp)
	if !shouldCache || err != nil {
		if err != nil {
			return err
		}
		return nil
	}
common/evm_block_ref.go (3)

50-52: 🛠️ Refactor suggestion

Refactor repeated block hash length checks into a helper function

The length check if len(bns) == 66 is used in multiple places to identify block hashes (which are 32 bytes, resulting in a 66-character string including the 0x prefix). Refactoring this logic into a helper function would reduce code duplication and enhance maintainability.

Create a helper function IsBlockHash:

+func IsBlockHash(s string) bool {
+    return strings.HasPrefix(s, "0x") && len(s) == 66
+}

Then update the repeated checks:

-if len(bns) == 66 {
+if IsBlockHash(bns) {
     return bns, 0, nil
 }

Also applies to: 90-92, 115-117, 191-193


254-255: ⚠️ Potential issue

Handle errors from PeekStringByPath to ensure robust parsing

In ExtractEvmBlockReferenceFromResponse, the errors returned by PeekStringByPath are currently ignored. While ignoring nil values might be acceptable, unexpected parsing errors could go unnoticed, potentially leading to incorrect behavior. It's prudent to handle these errors to improve the robustness of the code.

Modify the code to handle errors:

-blockRef, _ := rpcResp.PeekStringByPath("blockHash")
+blockRef, err := rpcResp.PeekStringByPath("blockHash")
+if err != nil {
+    return "", 0, err
+}

-blockNumberStr, _ := rpcResp.PeekStringByPath("blockNumber")
+blockNumberStr, err := rpcResp.PeekStringByPath("blockNumber")
+if err != nil {
+    return blockRef, 0, err
+}

Also applies to: 274-275


253-291: ⚠️ Potential issue

Check for nil Result to prevent potential panics

In ExtractEvmBlockReferenceFromResponse, the condition if len(rpcResp.Result) > 0 assumes that rpcResp.Result is not nil. If Result is nil, accessing it could cause a panic. Safely check for nil before evaluating its length.

Modify the condition:

-if len(rpcResp.Result) > 0 {
+if rpcResp.Result != nil && len(rpcResp.Result) > 0 {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		if rpcResp.Result != nil && len(rpcResp.Result) > 0 {
			blockRef, _ := rpcResp.PeekStringByPath("blockHash")
			blockNumberStr, _ := rpcResp.PeekStringByPath("blockNumber")

			var blockNumber int64
			if blockNumberStr != "" {
				bn, err := HexToInt64(blockNumberStr)
				if err != nil {
					return "", 0, err
				}
				blockNumber = bn
			}

			if blockRef == "" && blockNumber > 0 {
				blockRef = strconv.FormatInt(blockNumber, 10)
			}

			return blockRef, blockNumber, nil
		}
	case "eth_getBlockByNumber":
		if rpcResp.Result != nil && len(rpcResp.Result) > 0 {
			blockRef, _ := rpcResp.PeekStringByPath("hash")
			blockNumberStr, _ := rpcResp.PeekStringByPath("number")

			var blockNumber int64
			if blockNumberStr != "" {
				bn, err := HexToInt64(blockNumberStr)
				if err != nil {
					return "", 0, err
				}
				blockNumber = bn
			}

			if blockRef == "" && blockNumber > 0 {
				blockRef = strconv.FormatInt(blockNumber, 10)
			}

			return blockRef, blockNumber, nil
		}
upstream/evm_state_poller.go (2)

318-322: ⚠️ Potential issue

Handle missing 'number' field in block data

When calling PeekStringByPath("number"), if the number field is missing or nil, it could lead to unexpected errors. Ensure that the absence of the number field is gracefully handled, possibly by adding a check for nil before proceeding.

Apply this diff to handle the missing 'number' field:

 numberStr, err := jrr.PeekStringByPath("number")
 if err != nil {
 	return 0, &common.BaseError{
 		Code:    "ErrEvmStatePoller",
-		Message: "cannot get block number from block data",
+		Message: "block number field is missing in block data",
 		Details: map[string]interface{}{
 			"blockTag": blockTag,
 			"result":   jrr.Result,
 		},
 	}
 }

Committable suggestion was skipped due to low confidence.


356-368: ⚠️ Potential issue

Handle both boolean and object responses from eth_syncing

The eth_syncing method can return either false (a boolean) when the node is not syncing or an object with syncing details when the node is syncing. Unmarshalling directly into a boolean will fail when the result is an object. Modify the code to handle both scenarios appropriately.

Apply this diff to fix the issue:

 var syncing bool
-err = common.SonicCfg.Unmarshal(jrr.Result, &syncing)
+if string(jrr.Result) == "false" {
+    syncing = false
+} else {
+    syncing = true
+}
+if err != nil {
+    // Handle any potential errors here
+}
 return syncing, nil

Committable suggestion was skipped due to low confidence.

common/request.go (1)

43-47: ⚠️ Potential issue

Unresolved merge conflict markers detected throughout the code

Unresolved merge conflict markers (<<<<<<< HEAD, =======, >>>>>>>) are present at multiple locations in the file (lines 43-47, 58-64, 85-91, 99-107, 115-120, 128-133, 143-153, 159-172). This indicates that the merge conflicts have not been properly resolved. Please resolve these conflicts to ensure the code is correct and compilable.

Also applies to: 58-64, 85-91, 99-107, 115-120, 128-133, 143-153, 159-172

upstream/registry.go (2)

171-173: 🛠️ Refactor suggestion

Consider refactoring nested map initialization to reduce duplication

The initialization of nested maps for u.upstreamScores is repeated multiple times. Refactoring this into a helper function would improve maintainability and reduce code duplication.

Here's how you might refactor the code:

func (u *UpstreamsRegistry) ensureUpstreamScore(upid, networkId, method string) {
	if _, ok := u.upstreamScores[upid]; !ok {
		u.upstreamScores[upid] = make(map[string]map[string]float64)
	}
	if _, ok := u.upstreamScores[upid][networkId]; !ok {
		u.upstreamScores[upid][networkId] = make(map[string]float64)
	}
	if _, ok := u.upstreamScores[upid][networkId][method]; !ok {
		u.upstreamScores[upid][networkId][method] = 0
	}
}

Then, you can replace the repeated initialization code with a single function call:

u.ensureUpstreamScore(upid, networkId, method)

361-366: 🛠️ Refactor suggestion

Simplify logging and remove unnecessary log level check

You can simplify the logging by removing the explicit log level check. Zerolog handles log level checks internally, so the condition is redundant. Additionally, use the Strs method to log the slice of upstream IDs directly.

Apply this diff to refactor the code:

-if u.logger.GetLevel() >= zerolog.TraceLevel {
-	newSortStr := ""
-	for _, ups := range upsList {
-		newSortStr += fmt.Sprintf("%s ", ups.Config().Id)
-	}
-	u.logger.Trace().Str("projectId", u.prjId).Str("networkId", networkId).Str("method", method).Str("newSort", newSortStr).Msgf("sorted upstreams")
-}
+upsIDs := make([]string, len(upsList))
+for i, ups := range upsList {
+	upsIDs[i] = ups.Config().Id
+}
+u.logger.Trace().
+	Str("projectId", u.prjId).
+	Str("networkId", networkId).
+	Str("method", method).
+	Strs("newSort", upsIDs).
+	Msg("sorted upstreams")

This refactoring enhances readability and leverages zerolog's features for more efficient logging.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	upsIDs := make([]string, len(upsList))
	for i, ups := range upsList {
		upsIDs[i] = ups.Config().Id
	}
	u.logger.Trace().
		Str("projectId", u.prjId).
		Str("networkId", networkId).
		Str("method", method).
		Strs("newSort", upsIDs).
		Msg("sorted upstreams")
erpc/networks.go (4)

25-26: 🛠️ Refactor suggestion

Consider potential performance implications of sync.Map

Replacing the inFlightRequests map with a *sync.Map simplifies concurrency management. However, sync.Map is optimized for cases with high read-to-write ratios and may not perform well under heavy write contention. If inFlightRequests involves frequent writes or deletions, a standard map with a mutex might offer better performance.


85-86: ⚠️ Potential issue

Ensure safe type assertion to prevent panics

The type assertion vinf.(*Multiplexer) can cause a panic if vinf is not of type *Multiplexer. To avoid this, consider using the comma-ok idiom to safely assert the type:

if infCandidate, ok := vinf.(*Multiplexer); ok {
    inf = infCandidate
    // proceed with inf
} else {
    // handle the unexpected type
    lg.Error().Msgf("unexpected type in inFlightRequests")
    // possibly delete the entry or take corrective action
}

This approach prevents potential panics due to incorrect type assumptions.


366-369: 🛠️ Refactor suggestion

Review the necessity of nil checks on the receiver

The check for n == nil within the method EvmIsBlockFinalized might be unnecessary. Since this is a method on the Network type, and calling it on a nil receiver is uncommon, consider removing this check unless there is a specific use case where n can be nil.


414-423: ⚠️ Potential issue

Check for potential nil references in state poller enrichment

When accessing resp.Upstream().Config().Id, there is a risk of a nil reference if resp.Upstream() or resp.Upstream().Config() returns nil. Add nil checks to prevent possible panics:

if resp.Upstream() != nil && resp.Upstream().Config() != nil {
    poller, ok := n.evmStatePollers[resp.Upstream().Config().Id]
    // proceed with poller
}
common/json_rpc.go (7)

333-339: 🛠️ Refactor suggestion

Optimize MarshalJSON to prevent unnecessary memory allocations

The MarshalJSON method reads the entire JSON into memory, which can be inefficient for large responses. Since the comment mentions that MarshalJSON should not be used for most use cases, consider removing or deprecating this method to prevent misuse.

Alternatively, if the method must remain, add a warning in the documentation and consider ways to optimize it.


347-352: 🛠️ Refactor suggestion

⚠️ Potential issue

Ensure proper locking order to prevent potential deadlocks

In the GetReader method, locks are acquired for idMu, errMu, and resultMu without a consistent order. This inconsistent locking order can lead to deadlocks if other methods lock these mutexes in a different order.

Standardize the locking order across all methods. For example, always lock idMu first, then errMu, then resultMu:

r.idMu.RLock()
r.errMu.RLock()
r.resultMu.RLock()
defer r.idMu.RUnlock()
defer r.errMu.RUnlock()
defer r.resultMu.RUnlock()

Ensure that all methods accessing these mutexes follow the same locking order.


347-349: 🛠️ Refactor suggestion

Avoid redundant defer statements within loops

In the GetReader method, the use of defer within a loop can lead to deferred calls piling up, which might not be executed until the function returns. This can have unintended side effects on performance and resource utilization.

Consider restructuring the code to minimize the use of defer within loops or tight code sections. Locking can be handled without defer when the scope is clear.

r.idMu.RLock()
// operations using idMu
r.idMu.RUnlock()

// Similarly for errMu and resultMu

This makes the locking and unlocking explicit and can improve readability and performance.


209-274: 🛠️ Refactor suggestion

Simplify error parsing logic in ParseError method

The ParseError method contains complex logic with multiple special cases for parsing errors. This complexity can make the code harder to maintain and may introduce bugs. Consider refactoring the method to simplify error handling.

One way to simplify is to unmarshal into a generic map and check for the presence of "code" and "message" keys:

 func (r *JsonRpcResponse) ParseError(raw string) error {
 	r.errMu.Lock()
 	defer r.errMu.Unlock()

 	r.errBytes = nil

-	// Complex special case handling...
+	// Unmarshal into a generic map to check for "code" and "message"
+	var errMap map[string]interface{}
+	if err := SonicCfg.UnmarshalFromString(raw, &errMap); err != nil {
+		return err
+	}
+	if errorData, exists := errMap["error"].(map[string]interface{}); exists {
+		if code, ok := errorData["code"].(float64); ok {
+			if message, ok := errorData["message"].(string); ok {
+				r.Error = NewErrJsonRpcExceptionExternal(
+					int(code),
+					message,
+					"",
+				)
+				r.errBytes = util.Str2Mem(raw)
+				return nil
+			}
+		}
+	}
+
+	// If no error field or unable to parse, set a generic error
+	r.Error = NewErrJsonRpcExceptionExternal(
+		int(JsonRpcErrorServerSideException),
+		raw,
+		"",
+	)
+	return nil
 }

This refactoring reduces complexity and makes the error parsing more robust.

Committable suggestion was skipped due to low confidence.


404-410: 🛠️ Refactor suggestion

⚠️ Potential issue

Deep copy mutable fields in Clone method

The Clone method copies pointers of mutable fields like idBytes, errBytes, and Result. This can lead to shared references where changes to one instance affect the other. To prevent this, deep copy these byte slices.

Modify the Clone method to deep copy mutable fields:

 return &JsonRpcResponse{
 	id: r.id,
-	idBytes:    r.idBytes,
-	Error:      r.Error,
-	errBytes:   r.errBytes,
-	Result:     r.Result,
+	idBytes:    append([]byte{}, r.idBytes...),
+	Error:      r.Error, // Assuming Error is immutable or handle deep copy if necessary
+	errBytes:   append([]byte{}, r.errBytes...),
+	Result:     append([]byte{}, r.Result...),
 	cachedNode: r.cachedNode, // Consider deep copying if necessary
 }, nil

Review whether Error and cachedNode require deep copies based on their mutability.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		id:         r.id,
		idBytes:    append([]byte{}, r.idBytes...),
		Error:      r.Error, // Assuming Error is immutable or handle deep copy if necessary
		errBytes:   append([]byte{}, r.errBytes...),
		Result:     append([]byte{}, r.Result...),
		cachedNode: r.cachedNode, // Consider deep copying if necessary
	}, nil

419-419: ⚠️ Potential issue

Avoid embedding sync.RWMutex directly into structs

Embedding sync.RWMutex directly into the JsonRpcRequest struct can lead to unintended behavior, especially if the struct is copied after use. Mutexes should be used as named fields to prevent accidental copying and to make the code more maintainable.

Apply this diff to fix the issue:

-type JsonRpcRequest struct {
-	sync.RWMutex
+type JsonRpcRequest struct {
+	mu sync.RWMutex

Update the code to use r.mu.RLock(), r.mu.RUnlock(), r.mu.Lock(), and r.mu.Unlock() accordingly.

Committable suggestion was skipped due to low confidence.


427-473: 🛠️ Refactor suggestion

⚠️ Potential issue

Improve ID parsing in UnmarshalJSON method

In the UnmarshalJSON method of JsonRpcRequest, when the ID is a string, parsing it into a float64 and then converting to int64 can lead to precision loss or incorrect results for large integer IDs represented as strings. It's better to parse the string directly into an int64.

Apply this diff to handle string IDs correctly:

 			case string:
 				if v == "" {
 					r.ID = util.RandomID()
 				} else {
-					var parsedID float64
-					if err := SonicCfg.Unmarshal([]byte(v), &parsedID); err != nil {
+					parsedID, err := strconv.ParseInt(v, 10, 64)
+					if err != nil {
 						return err
 					}
-					r.ID = int64(parsedID)
+					r.ID = parsedID
 				}

This ensures that string IDs are parsed accurately without loss of precision.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

func (r *JsonRpcRequest) UnmarshalJSON(data []byte) error {
	type Alias JsonRpcRequest
	aux := &struct {
		*Alias
		ID json.RawMessage `json:"id,omitempty"`
	}{
		Alias: (*Alias)(r),
	}
	aux.JSONRPC = "2.0"

	if err := SonicCfg.Unmarshal(data, &aux); err != nil {
		return err
	}

	if aux.ID == nil {
		r.ID = util.RandomID()
	} else {
		var id interface{}
		if err := SonicCfg.Unmarshal(aux.ID, &id); err != nil {
			return err
		}

		switch v := id.(type) {
		case float64:
			r.ID = int64(v)
		case string:
			if v == "" {
				r.ID = util.RandomID()
			} else {
				parsedID, err := strconv.ParseInt(v, 10, 64)
				if err != nil {
					return err
				}
				r.ID = parsedID
			}
		case nil:
			r.ID = util.RandomID()
		default:
			r.ID = util.RandomID()
		}
	}

	if r.ID == 0 {
		r.ID = util.RandomID()
	}

	return nil
}
common/config.go (1)

86-86: ⚠️ Potential issue

Typo in struct tag: yamle should be yaml

There's a typo in the struct tag for the TTL field; it should be yaml:"ttl" instead of yamle:"ttl" to ensure proper YAML unmarshalling.

Apply this diff to fix the typo:

 type MethodCacheConfig struct {
     Method string `yaml:"method" json:"method"`
-    TTL    string `yamle:"ttl" json:"ttl"`
+    TTL    string `yaml:"ttl" json:"ttl"`
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	TTL    string `yaml:"ttl" json:"ttl"`
erpc/http_server.go (8)

84-85: ⚠️ Potential issue

Setting SetEscapeHTML(false) May Introduce XSS Vulnerabilities

Disabling HTML escaping can lead to cross-site scripting (XSS) attacks if the data being encoded includes untrusted input. Ensure all response data is properly sanitized.

If HTML escaping is intentionally disabled, verify that all inputs to the encoder are safe and cannot contain malicious content.


300-327: 🛠️ Refactor suggestion

Simplify and Validate URL Path Parsing Logic

The parseUrlPath function can be simplified for clarity and to reduce the potential for errors. Additionally, validate that the URL segments are correctly extracted and handle unexpected values gracefully.

Consider refactoring the conditional statements and using a switch-case for better readability:

func (s *HttpServer) parseUrlPath(fctx *fasthttp.RequestCtx) (projectId, architecture, chainId string, isAdmin, isHealthCheck bool, err error) {
  isPost := fctx.IsPost()
  ps := path.Clean(util.Mem2Str(fctx.Path()))
  segments := strings.Split(ps, "/")

  switch {
  case isPost && len(segments) == 4:
    projectId = segments[1]
    architecture = segments[2]
    chainId = segments[3]
  case isPost && len(segments) == 3 && segments[2] == "admin":
    projectId = segments[1]
    isAdmin = true
  case len(segments) == 2 && segments[1] == "healthcheck":
    isHealthCheck = true
  default:
    err = common.NewErrInvalidUrlPath(ps)
  }

  return projectId, architecture, chainId, isAdmin, isHealthCheck, err
}

385-406: 🛠️ Refactor suggestion

Clarify Error Handling Logic in setResponseHeaders

The error handling in the setResponseHeaders function is complex and may be difficult to maintain. Consider simplifying the type assertions and error checks for better readability.

Refactor the nested type checks and error unwrapping to make the code more maintainable.


549-552: ⚠️ Potential issue

Handle Errors When Closing IPv4 Listener Gracefully

In the Start method, when attempting to close the IPv4 listener due to an error with the IPv6 listener, ensure that any errors encountered while closing are properly handled.

Consider logging the error when closing the IPv4 listener fails and continue the shutdown process gracefully.


76-80: ⚠️ Potential issue

Avoid Exposing Internal Error Details to Clients

Returning detailed error messages including stack traces to clients can expose sensitive internal information and aid malicious actors. Instead, log the detailed error internally and send a generic error message to the client.

Apply this diff to send a generic message to the client:

- msg := fmt.Sprintf("unexpected server panic on top-level handler: %v -> %s", r, util.Mem2Str(debug.Stack()))
+ s.logger.Error().Msgf("unexpected server panic on top-level handler: %v -> %s", r, util.Mem2Str(debug.Stack()))
  fastCtx.SetStatusCode(fasthttp.StatusInternalServerError)
  fastCtx.Response.Header.Set("Content-Type", "application/json")
- fastCtx.SetBodyString(fmt.Sprintf(`{"jsonrpc":"2.0","error":{"code":-32603,"message":"%s"}}`, msg))
+ fastCtx.SetBodyString(`{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal server error"}}`)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

				s.logger.Error().Msgf("unexpected server panic on top-level handler: %v -> %s", r, util.Mem2Str(debug.Stack()))
				fastCtx.SetStatusCode(fasthttp.StatusInternalServerError)
				fastCtx.Response.Header.Set("Content-Type", "application/json")
				fastCtx.SetBodyString(`{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal server error"}}`)

517-525: ⚠️ Potential issue

Check for Encoding Errors Before Setting Headers

When encoding the error response in handleErrorResponse, ensure that you check for encoding errors before setting response headers to avoid sending incomplete or incorrect responses.

Apply this diff to adjust the error handling:

err = encoder.Encode(resp)
if err != nil {
  logger.Error().Err(err).Msgf("failed to encode error response")
  ctx.SetStatusCode(fasthttp.StatusInternalServerError)
  ctx.Response.Header.Set("Content-Type", "application/json")
  ctx.SetBodyString(fmt.Sprintf(`{"jsonrpc":"2.0","error":{"code":-32603,"message":"%s"}}`, err.Error()))
} else {
- ctx.Response.Header.Set("Content-Type", "application/json")
}

Committable suggestion was skipped due to low confidence.


279-295: ⚠️ Potential issue

Consistent Error Handling in Single Response Scenario

When handling a single response, ensure that errors during encoding are consistently managed, and appropriate status codes and messages are returned to the client.

Apply this diff to align error handling with the batch processing logic:

  if r, ok := res.(*common.NormalizedResponse); ok {
    rdr, err := r.GetReader()
    if err != nil {
      fastCtx.SetStatusCode(fasthttp.StatusInternalServerError)
      fastCtx.SetBodyString(fmt.Sprintf(`{"jsonrpc":"2.0","error":{"code":-32603,"message":"%s"}}`, err.Error()))
      return
    }
    fastCtx.Response.SetBodyStream(rdr, -1)
    r.Release()
  } else {
    err = encoder.Encode(res)
+   if err != nil {
+     fastCtx.SetStatusCode(fasthttp.StatusInternalServerError)
+     fastCtx.SetBodyString(fmt.Sprintf(`{"jsonrpc":"2.0","error":{"code":-32603,"message":"%s"}}`, err.Error()))
+     return
+   }
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

			if r, ok := res.(*common.NormalizedResponse); ok {
				rdr, err := r.GetReader()
				if err != nil {
					fastCtx.SetStatusCode(fasthttp.StatusInternalServerError)
					fastCtx.SetBodyString(fmt.Sprintf(`{"jsonrpc":"2.0","error":{"code":-32603,"message":"%s"}}`, err.Error()))
					return
				}
				fastCtx.Response.SetBodyStream(rdr, -1)
				r.Release()
			} else {
				err = encoder.Encode(res)
				if err != nil {
					fastCtx.SetStatusCode(fasthttp.StatusInternalServerError)
					fastCtx.SetBodyString(fmt.Sprintf(`{"jsonrpc":"2.0","error":{"code":-32603,"message":"%s"}}`, err.Error()))
					return
				}
			}

450-462: ⚠️ Potential issue

Avoid Holding Locks Longer Than Necessary

In processErrorBody, the read lock on nq is held during logging. To prevent potential performance bottlenecks, acquire the lock only when accessing shared data and release it promptly.

Apply this diff to minimize the lock duration:

if !common.IsNull(err) {
  if nq != nil {
-   nq.RLock()
  }
  if common.HasErrorCode(err, common.ErrCodeEndpointClientSideException) {
    logger.Debug().Err(err).Object("request", nq).Msgf("forward request errored with client-side exception")
  } else {
    if e, ok := err.(common.StandardError); ok {
      logger.Error().Err(err).Object("request", nq).Msgf("failed to forward request: %s", e.DeepestMessage())
    } else {
      logger.Error().Err(err).Object("request", nq).Msgf("failed to forward request: %s", err.Error())
    }
  }
- if nq != nil {
-   nq.RUnlock()
- }
}

Committable suggestion was skipped due to low confidence.

upstream/http_json_json_client_test.go (2)

200-202: ⚠️ Potential issue

Replace panic with t.Fatalf for better test failure reporting

Using panic in test code can abruptly terminate the test suite and doesn't provide as clear feedback as the testing framework's error handling. Consider replacing panic with t.Fatalf to report the error in a more informative and controlled manner.

Apply this diff to improve error handling:

 if resp1 == nil {
-	panic(fmt.Sprintf("SeparateBatchRequestsWithSameIDs: resp1 is nil err1: %v", err1))
+	t.Fatalf("SeparateBatchRequestsWithSameIDs: resp1 is nil, err: %v", err1)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

				if resp1 == nil {
					t.Fatalf("SeparateBatchRequestsWithSameIDs: resp1 is nil, err: %v", err1)
				}

609-610: ⚠️ Potential issue

Avoid tight timing assertions to prevent flaky tests

Asserting that the duration is within a narrow time window (740ms to 780ms) can lead to flaky tests due to timing variations in different environments. Consider loosening the bounds or focusing on the timeout error.

Apply this diff to adjust the assertions:

-	assert.Greater(t, dur, 740*time.Millisecond)
-	assert.Less(t, dur, 780*time.Millisecond)
+	assert.Greater(t, dur, 700*time.Millisecond)
+	assert.Less(t, dur, 800*time.Millisecond)

Alternatively, you can remove the duration assertions and focus on verifying that a timeout occurred:

-	assert.Greater(t, dur, 700*time.Millisecond)
-	assert.Less(t, dur, 800*time.Millisecond)
+	assert.Error(t, err)
+	assert.Contains(t, err.Error(), "remote endpoint request timeout")

Committable suggestion was skipped due to low confidence.

upstream/http_json_rpc_client.go (3)

310-313: 🛠️ Refactor suggestion

Reconsider disabling JSON validation when parsing responses

In the code, searcher.ValidateJSON is set to false, which disables JSON validation when parsing the upstream responses. This might lead to unexpected behavior if the response contains malformed JSON. Enabling JSON validation can help ensure that the JSON parsing is robust and can catch potential issues early.

Apply this diff to enable JSON validation:

 searcher := ast.NewSearcher(util.Mem2Str(bodyBytes))
 searcher.CopyReturn = false
 searcher.ConcurrentRead = false
-searcher.ValidateJSON = false
+searcher.ValidateJSON = true
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	searcher := ast.NewSearcher(util.Mem2Str(bodyBytes))
	searcher.CopyReturn = false
	searcher.ConcurrentRead = false
	searcher.ValidateJSON = true

696-713: ⚠️ Potential issue

Ensure safe type assertion to prevent panics

At line 697, the code performs a type assertion msg.(string) without checking if the assertion is valid. If msg is not of type string, this will cause a panic. It's safer to use the two-value form of the type assertion to handle the case where msg is not a string.

Apply this diff to fix the issue:

 if dt, ok := err.Data.(map[string]interface{}); ok {
     if msg, ok := dt["message"]; ok {
-        if strings.Contains(msg.(string), "validation errors in batch") {
+        if msgStr, ok := msg.(string); ok {
+            if strings.Contains(msgStr, "validation errors in batch") {
                 // Existing code
-        }
+            }
+        }
     }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

				if msg, ok := dt["message"]; ok {
					if msgStr, ok := msg.(string); ok {
						if strings.Contains(msgStr, "validation errors in batch") {
							// Intentionally return a server-side error for failed requests in a batch
							// so they are retried in a different batch.
							// TODO Should we split a batch instead on json-rpc client level?
							return common.NewErrEndpointServerSideException(
								common.NewErrJsonRpcExceptionInternal(
									int(code),
									common.JsonRpcErrorServerSideException,
									err.Message,
									nil,
									details,
								),
								nil,
							)
						}
					}
				}
			}

416-436: ⚠️ Potential issue

Fix potential nil pointer dereference in getJsonRpcResponseFromNode

In the getJsonRpcResponseFromNode function, jrResp is declared but not initialized before calling jrResp.SetIDBytes(...). This can lead to a nil pointer dereference and panic when both rawResultErr != nil and rawErrorErr != nil. To fix this issue, initialize jrResp before using it.

Apply this diff to fix the issue:

 func getJsonRpcResponseFromNode(rootNode ast.Node) (*common.JsonRpcResponse, error) {
     idNode := rootNode.GetByPath("id")
     rawID, _ := idNode.Raw()
     resultNode := rootNode.GetByPath("result")
     rawResult, rawResultErr := resultNode.Raw()
     errorNode := rootNode.GetByPath("error")
     rawError, rawErrorErr := errorNode.Raw()

     if rawResultErr != nil && rawErrorErr != nil {
-        var jrResp *common.JsonRpcResponse
+        jrResp := &common.JsonRpcResponse{}

         if rawID != "" {
             err := jrResp.SetIDBytes(util.Str2Mem(rawID))
             if err != nil {
                 return nil, err
             }
         }

         cause := fmt.Sprintf("cannot parse json rpc response from upstream, for result: %s, for error: %s", rawResult, rawError)

-        jrResp = &common.JsonRpcResponse{
+        jrResp.Result = util.Str2Mem(rawResult)
+        jrResp.Error = common.NewErrJsonRpcExceptionExternal(
             int(common.JsonRpcErrorParseException),
             cause,
             "",
         )
-        }

         return jrResp, nil
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	if rawResultErr != nil && rawErrorErr != nil {
		jrResp := &common.JsonRpcResponse{}

		if rawID != "" {
			err := jrResp.SetIDBytes(util.Str2Mem(rawID))
			if err != nil {
				return nil, err
			}
		}

		cause := fmt.Sprintf("cannot parse json rpc response from upstream, for result: %s, for error: %s", rawResult, rawError)
		jrResp.Result = util.Str2Mem(rawResult)
		jrResp.Error = common.NewErrJsonRpcExceptionExternal(
			int(common.JsonRpcErrorParseException),
			cause,
			"",
		)

		return jrResp, nil
erpc/http_server_test.go (3)

341-341: ⚠️ Potential issue

Remove unnecessary debug print statement

The fmt.Println(body) statement in the test InvalidJSON is likely a leftover from debugging and should be removed to keep the test output clean.

Apply this diff to remove the debug print statement:

341d340
- 		fmt.Println(body)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.



595-597: ⚠️ Potential issue

Fix incorrect conditional and error message in test

The conditional logic in the AutoAddIDWhen0IsProvided test is incorrect. The condition should check if id is not zero, and the error message should reflect the actual expectation.

Apply this diff to correct the conditional and error message:

595,597c595,597
- 			if id == 0 {
- 				t.Fatalf("Expected id to be 0, got %d from body: %s", id, bodyStr)
- 			}
+ 			if id != 0 {
+ 				t.Fatalf("Expected id to be 0, got %d from body: %s", id, bodyStr)
+ 			}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

					if id != 0 {
						t.Fatalf("Expected id to be 0, got %d from body: %s", id, bodyStr)
					}

779-787: ⚠️ Potential issue

Remove deferred call to gock.Off() to prevent mocks from being disabled prematurely

In the createServerTestFixtures function, the defer gock.Off() statement will execute when the function returns, potentially disabling the HTTP mocks before the tests complete.

Consider removing the defer gock.Off() from this function and managing the lifecycle of gock in the calling function to ensure that mocks remain active for the duration of the tests.

Apply this diff to remove the deferred call:

786,787d785
- 	defer gock.Off()
-
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	func(body string, headers map[string]string, queryParams map[string]string) (int, string),
	string,
) {
	gock.EnableNetworking()
	gock.NetworkingFilter(func(req *http.Request) bool {
		shouldMakeRealCall := strings.Split(req.URL.Host, ":")[0] == "localhost"
		return shouldMakeRealCall
	})
common/errors.go (5)

943-957: 🛠️ Refactor suggestion

Add ErrorStatusCode method to ErrUpstreamSyncing

For consistency with other error types, consider adding an ErrorStatusCode() method to ErrUpstreamSyncing to specify the appropriate HTTP status code.

For example:

func (e *ErrUpstreamSyncing) ErrorStatusCode() int {
    return http.StatusServiceUnavailable
}

959-971: 🛠️ Refactor suggestion

Add ErrorStatusCode method to ErrUpstreamNotAllowed

Adding an ErrorStatusCode() method to ErrUpstreamNotAllowed will ensure consistent error handling and allow you to specify the appropriate HTTP status code.

For example:

func (e *ErrUpstreamNotAllowed) ErrorStatusCode() int {
    return http.StatusForbidden
}

460-474: 🛠️ Refactor suggestion

Define error code as a constant in ErrNotImplemented

For consistency with other error types, consider defining the error code "ErrNotImplemented" as a constant.

Apply this diff to define the error code as a constant:

+const ErrCodeNotImplemented ErrorCode = "ErrNotImplemented"

 type ErrNotImplemented struct{ BaseError }

 var NewErrNotImplemented = func(msg string) error {
 	return &ErrNotImplemented{
 		BaseError{
-			Code:    "ErrNotImplemented",
+			Code:    ErrCodeNotImplemented,
 			Message: msg,
 		},
 	}
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

const ErrCodeNotImplemented ErrorCode = "ErrNotImplemented"

type ErrNotImplemented struct{ BaseError }

var NewErrNotImplemented = func(msg string) error {
	return &ErrNotImplemented{
		BaseError{
			Code:    ErrCodeNotImplemented,
			Message: msg,
		},
	}
}

func (e *ErrNotImplemented) ErrorStatusCode() int {
	return http.StatusNotImplemented
}

939-941: 🛠️ Refactor suggestion

Use appropriate HTTP status code in ErrUpstreamMethodIgnored

Returning http.StatusUnsupportedMediaType (415) may not accurately represent the error. Consider using http.StatusMethodNotAllowed (405) or http.StatusNotImplemented (501) to better reflect that the method is not allowed or not implemented by the upstream.

Apply this diff to change the status code:

 func (e *ErrUpstreamMethodIgnored) ErrorStatusCode() int {
-	return http.StatusUnsupportedMediaType
+	return http.StatusMethodNotAllowed
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

func (e *ErrUpstreamMethodIgnored) ErrorStatusCode() int {
	return http.StatusMethodNotAllowed
}

1015-1030: ⚠️ Potential issue

Ensure consistent error chaining in NewErrJsonRpcRequestUnmarshal

When cause is not nil, the Cause field should be set to maintain proper error chaining and improve error tracing.

Apply this diff to set the Cause field consistently:

 		} else if cause != nil {
 			return &ErrJsonRpcRequestUnmarshal{
 				BaseError{
 					Code:    ErrCodeJsonRpcRequestUnmarshal,
-					Message: fmt.Sprintf("%s", cause),
+					Message: "failed to unmarshal json-rpc request",
+					Cause:   cause,
 				},
 			}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	if _, ok := cause.(*BaseError); ok {
		return &ErrJsonRpcRequestUnmarshal{
			BaseError{
				Code:    ErrCodeJsonRpcRequestUnmarshal,
				Message: "failed to unmarshal json-rpc request",
				Cause:   cause,
			},
		}
	} else if cause != nil {
		return &ErrJsonRpcRequestUnmarshal{
			BaseError{
				Code:    ErrCodeJsonRpcRequestUnmarshal,
				Message: "failed to unmarshal json-rpc request",
				Cause:   cause,
			},
		}
	}
erpc/networks_test.go (2)

1236-1260: ⚠️ Potential issue

Validate memory usage assertion in test

In the test ForwardWithMinimumMemoryAllocation, the assertion compares memory usage after garbage collection with an expected value. However, garbage collection may not immediately reclaim all memory, leading to flaky tests. Consider using more reliable methods for measuring memory usage or adjusting thresholds.

Consider adjusting the test to account for potential discrepancies in memory measurement.


4316-4398: ⚠️ Potential issue

Improve error assertion in ForwardIgnoredMethod test

In the ForwardIgnoredMethod test, the error is checked using common.HasErrorCode, but if the error is nil, this will cause a nil pointer dereference. Ensure that you check for a non-nil error before asserting the error code.

Apply this diff to add error nil check:

+			if err == nil {
+				t.Fatalf("Expected non-nil error, got nil")
+			}
			if !common.HasErrorCode(err, common.ErrCodeUpstreamMethodIgnored) {
				t.Fatalf("Expected error code %v, got %v", common.ErrCodeUpstreamMethodIgnored, err)
			}

Committable suggestion was skipped due to low confidence.

erpc/healthcheck.go (3)

40-46: 🛠️ Refactor suggestion

Make the error rate threshold configurable

The error rate threshold of 0.99 is hardcoded. Making it configurable increases flexibility and allows adjustments without changing the code.

Define a constant or configuration parameter for the threshold:

const upstreamErrorRateThreshold = 0.99

Update the comparison:

 				sort.Float64s(allErrorRates)
-				if allErrorRates[0] > 0.99 {
+				if allErrorRates[0] > upstreamErrorRateThreshold {
 					handleErrorResponse(&logger, nil, fmt.Errorf("all upstreams are down: %+v", allErrorRates), ctx, encoder)
 					return
 				}

51-52: 🛠️ Refactor suggestion

Set the Content-Type header for the response

To ensure clients interpret the response correctly, explicitly set the Content-Type header.

Apply this diff to set the Content-Type header:

 	ctx.SetStatusCode(fasthttp.StatusOK)
+	ctx.Response.Header.Set("Content-Type", "text/plain; charset=utf-8")
 	ctx.SetBodyString("OK")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	ctx.SetStatusCode(fasthttp.StatusOK)
	ctx.Response.Header.Set("Content-Type", "text/plain; charset=utf-8")
	ctx.SetBodyString("OK")

22-28: 🛠️ Refactor suggestion

Consider handling individual project errors without aborting the health check

Currently, if project.gatherHealthInfo() returns an error for any project, the health check responds with an error and exits. To improve robustness, consider logging the error and continuing to check the health of the remaining projects.

Apply this diff to modify the error handling:

 		h, err := project.gatherHealthInfo()
-		if err != nil {
-			handleErrorResponse(&logger, nil, err, ctx, encoder)
-			return
-		}
+		if err != nil {
+			logger.Error().Err(err).Msgf("Failed to gather health info for project %v", project.Name)
+			continue
+		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	for _, project := range projects {
		h, err := project.gatherHealthInfo()
		if err != nil {
			logger.Error().Err(err).Msgf("Failed to gather health info for project %v", project.Name)
			continue
		}

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

🧹 Outside diff range and nitpick comments (59)
util/json_rpc.go (1)

8-8: Consider adding a security note to the function comment.

The current comment is informative, but it would be beneficial to add a note about the security implications of using math/rand.

Consider updating the comment to include a security note:

- // RandomID returns a value appropriate for a JSON-RPC ID field (i.e int64 type but with 32 bit range) to avoid overflow during conversions and reading/sending to upstreams
+ // RandomID returns a value appropriate for a JSON-RPC ID field (i.e int64 type but with 32 bit range) to avoid overflow during conversions and reading/sending to upstreams.
+ // Note: This function uses math/rand and is not suitable for cryptographic purposes.
erpc/multiplexer.go (2)

25-31: LGTM: Excellent use of sync.Once for thread-safe closing

The modification of the Close method to use once.Do() is an excellent improvement. It ensures that the closing operation is performed only once, even if the method is called multiple times concurrently. This change enhances the thread-safety and idempotency of the Close operation.

Consider adding a debug log or returning an error if Close is called more than once. This could help with debugging in complex scenarios:

func (inf *Multiplexer) Close(resp *common.NormalizedResponse, err error) error {
    var alreadyClosed bool
    inf.once.Do(func() {
        inf.mu.Lock()
        defer inf.mu.Unlock()
        inf.resp = resp
        inf.err = err
        close(inf.done)
    })
    if alreadyClosed {
        return errors.New("multiplexer already closed")
    }
    alreadyClosed = true
    return nil
}

Line range hint 1-31: Overall assessment: Excellent improvements to thread-safety

The changes made to this file significantly enhance the thread-safety of the Multiplexer struct, particularly in its Close method. The addition of sync.Once and its use in Close ensure that the closing operation is performed only once, even in concurrent scenarios. These modifications align well with Go's best practices for concurrent programming and contribute positively to the overall robustness of the codebase.

As the codebase evolves, consider applying similar patterns to other parts of the system that may benefit from guaranteed single execution in concurrent environments. This consistent approach to thread-safety will help maintain the reliability of the entire system.

common/evm.go (1)

12-21: LGTM! Consider minor improvements for clarity and potential future scalability.

The IsEvmWriteMethod function is well-implemented and serves its purpose effectively. It correctly identifies Ethereum JSON-RPC write methods, which is valuable for various use cases such as access control or logging.

To further enhance this function:

  1. Consider adding a comment explaining the function's purpose and the significance of these methods.
  2. If the list of methods is expected to grow significantly in the future, consider using a map or switch statement for potentially better performance.

Here's a suggested improvement with added comments:

// IsEvmWriteMethod checks if the given method is an Ethereum JSON-RPC write method.
// These methods modify the blockchain state and typically require special permissions.
func IsEvmWriteMethod(method string) bool {
    // List of Ethereum JSON-RPC write methods
    writeMethodsMap := map[string]bool{
        "eth_sendRawTransaction":             true,
        "eth_sendTransaction":                true,
        "eth_createAccessList":               true,
        "eth_submitTransaction":              true,
        "eth_submitWork":                     true,
        "eth_newFilter":                      true,
        "eth_newBlockFilter":                 true,
        "eth_newPendingTransactionFilter":    true,
    }
    
    return writeMethodsMap[method]
}

This implementation uses a map for potentially better performance with a larger number of methods and includes explanatory comments.

util/reader.go (3)

8-10: LGTM! Consider adding documentation.

The function signature and initial buffer setup look good. The use of bytes.Buffer with a default capacity is an efficient approach.

Consider adding a godoc comment to explain the purpose of the function and its parameters, especially the significance of chunkSize and expectedSize.


11-16: LGTM! Consider enhancing readability.

The buffer growth logic with a 50MB cap is a good security measure. The implementation is efficient, growing the buffer only when necessary.

Consider extracting the 50MB constant to a named variable at the package level for better readability and easier maintenance, e.g.:

const maxExpectedSize = 50 * 1024 * 1024 // 50MB

Then use maxExpectedSize in the condition on line 11.


18-29: LGTM! Consider handling partial reads explicitly.

The main reading loop is well-implemented, using io.CopyN efficiently and handling errors correctly.

Consider explicitly handling the case where n < chunkSize but not EOF. This could occur if the reader returns fewer bytes than requested without an error. You might want to add a comment explaining that this case is implicitly handled by continuing the loop.

erpc/erpc.go (1)

59-62: Overall impact: New functionality added without breaking changes

The addition of the GetProjects method enhances the ERPC struct's functionality by providing a way to retrieve all prepared projects. This change aligns with the PR objectives of incorporating new features from the upstream version. It's a non-breaking change that could be useful for operations requiring access to all projects.

Consider how this new method might be used in the broader context of the application. If there are use cases where bulk operations on all projects are needed, this method will be particularly useful. However, be mindful of potential performance implications if the number of projects becomes very large.

Dockerfile (1)

Line range hint 1-41: Consider adding a health check and verifying build arguments

The Dockerfile structure and practices are generally good, including the use of multi-stage builds and Alpine for the final stage. To further improve it, consider:

  1. Adding a health check to the container for better orchestration support.
  2. Verifying that VERSION and COMMIT_SHA build arguments are always provided, perhaps with a default value or error if missing.

Example health check (adjust the command as needed for your application):

HEALTHCHECK CMD curl -f http://localhost:8080/health || exit 1

For build args, you could add:

ARG VERSION
ARG COMMIT_SHA
RUN test -n "$VERSION" && test -n "$COMMIT_SHA"

These additions would enhance the robustness and observability of your containerized application.

common/utils.go (2)

13-14: Add documentation for the new ContextKey type.

While introducing a custom type for context keys is a good practice for type safety, it's important to provide documentation explaining its purpose and intended usage, especially for exported types.

Consider adding a comment above the type declaration, like this:

// ContextKey is a custom type for keys used in context values to ensure type safety.
type ContextKey string

36-40: Approve changes with a minor suggestion for error handling.

The modifications to HexToInt64 improve its robustness by using the NormalizeHex function, which handles both hexadecimal and decimal inputs. The error handling is also more comprehensive.

Consider wrapping the error returned by ParseInt to provide more context:

i, err := strconv.ParseInt(normalizedHex, 0, 64)
if err != nil {
    return 0, fmt.Errorf("failed to parse normalized hex '%s': %w", normalizedHex, err)
}
return i, nil
docs/pages/operation/url.mdx (1)

74-86: LGTM: Valuable addition of Healthcheck documentation

The new Healthcheck section is a valuable addition to the documentation. It clearly explains the purpose and usage of the /healthcheck endpoint, including a practical cURL example. The info callout provides important context about the current functionality.

Consider adding a brief explanation of what a "non-200 response" might be in the info callout, to provide more clarity for users who may not be familiar with HTTP status codes.

auth/http.go (6)

23-23: LGTM: Improved token handling with util.Mem2Str.

The use of util.Mem2Str for token conversion is a good improvement for memory efficiency and safety.

Consider adding error handling for the case where the "token" argument is not present:

if tokenBytes := args.Peek("token"); tokenBytes != nil {
    ap.Secret.Value = util.Mem2Str(tokenBytes)
} else {
    return nil, errors.New("token not provided")
}

31-31: LGTM: Improved Authorization header handling with util.Mem2Str.

The use of util.Mem2Str for converting the Authorization header value and decoded basic auth credentials is consistent with the improved memory handling approach.

Consider adding error handling for the case where the Authorization header is empty after trimming:

ath := strings.TrimSpace(util.Mem2Str(ath))
if ath == "" {
    return nil, errors.New("empty Authorization header")
}

Also applies to: 40-40


59-59: LGTM: Improved JWT token handling with util.Mem2Str.

The use of util.Mem2Str for converting the JWT token value is consistent with the improved memory handling approach.

Consider adding error handling for the case where the "jwt" argument is not present:

if jwtBytes := args.Peek("jwt"); jwtBytes != nil {
    ap.Jwt.Token = util.Mem2Str(jwtBytes)
} else {
    return nil, errors.New("JWT token not provided")
}

64-65: LGTM: Improved SIWE payload handling with util.Mem2Str.

The use of util.Mem2Str for converting both signature and message values in SIWE payload handling is consistent with the improved memory handling approach.

Consider adding error handling for the case where either the signature or message is empty:

signature := util.Mem2Str(args.Peek("signature"))
message := util.Mem2Str(args.Peek("message"))
if signature == "" || message == "" {
    return nil, errors.New("SIWE signature or message not provided")
}
ap.Siwe = &SiwePayload{
    Signature: signature,
    Message:   normalizeSiweMessage(message),
}

Also applies to: 71-72


81-82: LGTM: Improved network payload handling with util.Mem2Str.

The use of util.Mem2Str for converting X-Forwarded-For header values in network payload handling is consistent with the improved memory handling approach.

Consider handling the case where the X-Forwarded-For header is empty:

xForwardedFor := util.Mem2Str(headers.Peek("X-Forwarded-For"))
ap.Network = &NetworkPayload{
    Address:        xForwardedFor,
    ForwardProxies: strings.Split(xForwardedFor, ","),
}
if xForwardedFor == "" {
    ap.Network.Address = "unknown"
    ap.Network.ForwardProxies = []string{"unknown"}
}

Line range hint 1-95: Overall assessment: Improved memory handling with consistent use of util.Mem2Str.

The changes in this file consistently apply util.Mem2Str for string conversions, which aligns with the PR objectives and likely improves memory efficiency and safety. The overall structure and logic of the functions remain intact, maintaining existing functionality.

To further enhance the robustness of the code, consider the following suggestions:

  1. Implement more comprehensive error handling for cases where expected values are missing or empty.
  2. Add unit tests to verify the behavior of the NewPayloadFromHttp function with various input scenarios, including edge cases.
  3. Consider adding comments to explain the purpose and benefits of using util.Mem2Str for future maintainers.
docs/pages/deployment/railway.mdx (1)

33-49: Excellent addition of usage instructions for private network connections.

This new section provides valuable guidance on using private network connections for eRPC, which can help users reduce costs and overhead. The code example is clear and well-formatted.

Consider rewording the introductory sentence for better clarity:

-To reduce cost and overhead use private network (`.railway.internal`) to connect to eRPC, from your backend services (such as indexers or mev bots):
+To reduce cost and overhead, use the private network (`.railway.internal`) to connect to eRPC from your backend services (such as indexers or mev bots):
🧰 Tools
🪛 LanguageTool

[uncategorized] ~35-~35: Possible missing comma found.
Context: ...ge in your services To reduce cost and overhead use private network (`.railway.internal...

(AI_HYDRA_LEO_MISSING_COMMA)

erpc/erpc_test.go (2)

18-18: Approve logging change with a suggestion for conditional setup.

The change to disable logging entirely is consistent with other test files and can help reduce noise in test output. However, consider implementing a conditional logging setup to facilitate debugging when needed.

Consider implementing a conditional logging setup:

func init() {
    if os.Getenv("ERPC_TEST_DEBUG") == "true" {
        zerolog.SetGlobalLevel(zerolog.DebugLevel)
    } else {
        zerolog.SetGlobalLevel(zerolog.Disabled)
    }
}

This allows enabling debug logging by setting an environment variable, which can be useful for troubleshooting test issues.


87-87: Approve JSON success response changes with a suggestion.

The modifications from json.RawMessage to byte slices for both RPC1 and RPC2 success responses are improvements, consistent with earlier changes.

To enhance maintainability, consider defining these JSON responses as constants:

const (
    rpc1SuccessResponse = `{"result":{"hash":"0x123456789","fromHost":"rpc1"}}`
    rpc2SuccessResponse = `{"result":{"hash":"0x123456789","fromHost":"rpc2"}}`
)

// Then use these constants in the test:
r.JSON([]byte(rpc1SuccessResponse))
// and
JSON([]byte(rpc2SuccessResponse))

This approach would centralize these response definitions, making them easier to update and maintain.

Also applies to: 96-96

README.md (1)

28-32: Excellent addition of case studies!

The new "Case Studies" section is a valuable addition to the README. It provides concrete examples of eRPC's benefits, which can help attract potential users and demonstrate the project's real-world impact.

Consider adding a brief introductory sentence before the links to provide context, such as:

# Case Studies

Explore how eRPC has improved performance and reduced costs for our users:

[🚀 Moonwell: How eRPC slashed RPC calls by 67%](https://erpc.cloud/case-studies/moonwell)<br/>
[🚀 Chronicle: How eRPC reduced RPC cost by 45%](https://erpc.cloud/case-studies/chronicle)

This small addition would help frame the case studies and set expectations for readers.

docs/pages/operation/production.mdx (3)

7-7: Improve grammar and clarity in the Memory usage section

The content is informative, but there are a few grammatical issues to address:

  1. Replace "your" with "you" in "for example your might see"
  2. Correct the spelling of "occesional" to "occasional"
  3. Consider restructuring the sentence for better clarity

Here's a suggested revision:

- Biggest memory usage contributor in eRPC is size of responses of your requests. For example, for common requests such as `eth_getBlockByNumber` or `eth_getTransactionReceipt` the size (&lt;1MB) will be relatively smaller than `debug_traceTransaction` (which could potentially be up to 50MB). When using eRPC in Kubernetes for example your might see occesional `OOMKilled` errors which is most often because of high RPS of large request/responses.
+ The biggest contributor to memory usage in eRPC is the size of responses to your requests. For example, common requests such as `eth_getBlockByNumber` or `eth_getTransactionReceipt` have relatively small responses (&lt;1MB), while `debug_traceTransaction` responses could potentially be up to 50MB. When using eRPC in Kubernetes, you might see occasional `OOMKilled` errors, which are most often due to a high rate of large request/responses.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~7-~7: “your” (belonging to you) seems less likely than “you”.
Context: ...en using eRPC in Kubernetes for example your might see occesional OOMKilled errors...

(AI_HYDRA_LEO_CP_YOUR_YOU)


[uncategorized] ~7-~7: “of” seems less likely than “or” (‘either … or’).
Context: ...which is most often because of high RPS of large request/responses. In majority o...

(AI_HYDRA_LEO_CP_OF_OR)


9-9: Minor grammatical correction and clarity improvement

The content provides valuable guidance, but there's a small grammatical issue to address:

- In majority of use-cases eRPC uses around 256MB of memory (and 1vCPU). To find the ideal memory limit based on your use-case start with a high limit first (e.g. 16GB) and route your production traffic (either shadow or real) to see what is the usage based on your request patterns.
+ In the majority of use-cases, eRPC uses around 256MB of memory (and 1vCPU). To find the ideal memory limit based on your use-case, start with a high limit first (e.g., 16GB) and route your production traffic (either shadow or real) to observe the usage based on your request patterns.

This revision adds the missing article, improves punctuation, and slightly rephrases the last part for better clarity.

🧰 Tools
🪛 LanguageTool

[grammar] ~9-~9: An article may be missing.
Context: ...igh RPS of large request/responses. In majority of use-cases eRPC uses around 256MB of mem...

(BUNCH_OF)


[uncategorized] ~9-~9: Possible missing comma found.
Context: ... request/responses. In majority of use-cases eRPC uses around 256MB of memory (and 1...

(AI_HYDRA_LEO_MISSING_COMMA)


32-32: Approve note change and suggest minor correction

The change in the note improves readability and punctuation. However, there's a minor issue to address:

- [Hedge policy](/config/failsafe#hedge-policy) is **highly-recommended** if you prefer "fast response as soon as possible". For example setting `500ms` as "delay" will make sure if upstream A did not respond under 500 milliseconds, simultaneously another request to upstream B will be fired, and eRPC will respond back as soon as any of them comes back with result faster. Note: since more requests are sent, it might incur higher costs to achieve the "fast response" goal.
+ [Hedge policy](/config/failsafe#hedge-policy) is **highly recommended** if you prefer "fast response as soon as possible". For example, setting `500ms` as "delay" will make sure if upstream A did not respond under 500 milliseconds, simultaneously another request to upstream B will be fired, and eRPC will respond back as soon as any of them comes back with result faster. Note: since more requests are sent, it might incur higher costs to achieve the "fast response" goal.

This revision removes the redundant hyphen in "highly-recommended" and adds a comma after "For example" for better readability.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~32-~32: The hyphen in highly-recommended is redundant.
Context: ...cy](/config/failsafe#hedge-policy) is highly-recommended if you prefer "fast response as soon ...

(ADVERB_LY_HYPHEN_FIX)


[typographical] ~32-~32: After the expression ‘for example’ a comma is usually used.
Context: ...fast response as soon as possible". For example setting 500ms as "delay" will make su...

(COMMA_FOR_EXAMPLE)

vendors/quicknode.go (2)

54-56: Approve changes with a minor suggestion for consistency

The refactoring of the error handling looks good. The new NewErrEndpointRequestTooLarge function with the EvmBlockRangeTooLarge argument provides more flexibility and specificity in error reporting.

For consistency, consider updating the error message in the common.JsonRpcErrorEvmLogsLargeRange constant (if it exists) to reflect the more generic "request too large" terminology used in the new error type. This would ensure that the error messages are aligned throughout the codebase.


Line range hint 39-124: Consider refactoring error handling for improved maintainability

While the current implementation is functional, consider the following suggestions to improve maintainability and readability:

  1. Extract the error handling logic into a separate function or use a switch statement to reduce the complexity of the GetVendorSpecificErrorIfAny method.
  2. Consider using constants for error codes and creating a mapping between error codes and their corresponding error types. This would make it easier to maintain and update error handling in the future.

Here's a high-level example of how you might refactor this:

const (
    ErrCodeMissingData        = -32000
    ErrCodeCapacityExceeded   = -32009
    // ... other error codes ...
)

var errorCodeMap = map[int]func(code int, msg string, details map[string]interface{}) error{
    ErrCodeMissingData: func(code int, msg string, details map[string]interface{}) error {
        return common.NewErrEndpointMissingData(
            common.NewErrJsonRpcExceptionInternal(code, common.JsonRpcErrorMissingData, msg, nil, details),
        )
    },
    // ... other mappings ...
}

func (v *QuicknodeVendor) GetVendorSpecificErrorIfAny(resp *http.Response, jrr interface{}, details map[string]interface{}) error {
    // ... existing code ...

    if errHandler, ok := errorCodeMap[code]; ok {
        return errHandler(code, msg, details)
    }

    // Handle special cases that can't be mapped directly
    if code == -32602 && strings.Contains(msg, "eth_getLogs") && strings.Contains(msg, "limited") {
        return common.NewErrEndpointRequestTooLarge(
            common.NewErrJsonRpcExceptionInternal(code, common.JsonRpcErrorEvmLogsLargeRange, msg, nil, details),
            common.EvmBlockRangeTooLarge,
        )
    }

    // ... handle other special cases ...

    return nil
}

This approach would make the error handling more modular and easier to maintain.

.github/workflows/release.yml (2)

99-101: Minor improvement needed in shell script

The addition of a step to generate a short SHA is a good practice for more specific Docker image tagging. However, there's a minor shell scripting improvement that can be made.

To prevent potential word splitting issues, please modify the script as follows:

- run: echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
+ run: echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"

This change ensures that the $GITHUB_OUTPUT variable is properly quoted, preventing any potential issues with special characters or spaces.

🧰 Tools
🪛 actionlint

101-101: shellcheck reported issue in this script: SC2086:info:1:51: Double quote to prevent globbing and word splitting

(shellcheck)


103-128: LGTM with a minor suggestion: Improved Docker image build and push

The changes to the Docker image build and push steps are well-implemented:

  1. Splitting the steps based on the presence of a version tag improves flexibility.
  2. Using the short SHA in build arguments enhances traceability.
  3. Adding the 'latest' tag for versioned builds follows best practices.

These improvements align well with the PR objectives and enhance the workflow's functionality.

Consider adding a comment explaining the purpose of each build step to improve readability:

      - name: Build and push Docker image from main
        if: github.event.inputs.version_tag == ''
        # This step builds and pushes the image when triggered by a push to main
        uses: docker/build-push-action@v5
        ...

      - name: Build and push Docker image with tags
        if: github.event.inputs.version_tag != ''
        # This step builds and pushes the image when a version tag is provided
        uses: docker/build-push-action@v5
        ...
upstream/alchemy_http_json_rpc_client.go (1)

53-54: LGTM! Consider adding a comment for clarity.

The addition of Scroll Sepolia and Scroll Mainnet networks to the alchemyNetworkSubdomains map is correct and aligns with the PR objectives. These changes expand the supported networks for the Alchemy client without affecting existing functionality.

Consider adding a brief comment above these new entries to explain their significance, e.g.:

// Scroll L2 networks

This would improve code readability and provide context for future maintainers.

erpc/projects_registry.go (1)

136-142: LGTM! Consider thread safety and immutability.

The GetAll() method is implemented correctly and efficiently. It provides a way to retrieve all registered projects, which aligns with the PR objective of incorporating new features.

However, consider the following suggestions for improvement:

  1. If thread safety is a concern, consider adding synchronization to prevent potential race conditions during concurrent map access.
  2. To ensure immutability of the returned data, you might want to return a deep copy of the projects or document that the returned slice should not be modified by callers.
  3. If a consistent order of projects is important for your use case, consider sorting the slice before returning it.

Here's an example of how you could implement these suggestions:

import "sync"

type ProjectsRegistry struct {
    // ... other fields ...
    mu               sync.RWMutex
    preparedProjects map[string]*PreparedProject
}

func (r *ProjectsRegistry) GetAll() []*PreparedProject {
    r.mu.RLock()
    defer r.mu.RUnlock()
    
    projects := make([]*PreparedProject, 0, len(r.preparedProjects))
    for _, project := range r.preparedProjects {
        // Assuming PreparedProject has a Clone method for deep copying
        projects = append(projects, project.Clone())
    }
    
    // Optionally, sort the projects if order matters
    // sort.Slice(projects, func(i, j int) bool {
    //     return projects[i].Config.Id < projects[j].Config.Id
    // })
    
    return projects
}

This implementation adds thread safety, ensures immutability, and provides an option for consistent ordering.

docs/pages/config/rate-limiters.mdx (3)

64-70: Consider adding a brief explanation of rate limits.

The introduction to the auto-tuner feature is clear and concise. To enhance clarity for readers who might be new to the concept, consider adding a brief explanation of what "rate limits" are and why they're important. This context will help readers better understand the value of the auto-tuner feature.


71-90: LGTM! Consider adding units for time-based parameters.

The example configuration and explanations are clear and informative. The emphasis on setting minBudget to at least 1 is particularly valuable.

To further enhance clarity, consider specifying the units for time-based parameters. For example, clarify if adjustmentPeriod: "1m" refers to 1 minute.

🧰 Tools
🪛 LanguageTool

[grammar] ~71-~71: A noun may be missing here.
Context: ...e auto-tuner is enabled by default when an upstream has any rate limit budget defined. Here...

(DT_JJ_NO_NOUN)


91-106: LGTM! Consider adding guidance on adjusting default values.

The explanation of the auto-tuner's operation and the presentation of default values are clear and informative. This provides a solid foundation for users to understand and implement the feature.

To further assist users, consider adding brief guidelines on when and how to adjust these default values. For example, you could explain scenarios where a user might want to increase or decrease the errorRateThreshold or adjust the increaseFactor and decreaseFactor.

docs/pages/operation/batch.mdx (1)

7-14: Excellent addition of the Callout component!

The new Callout provides crucial information about the potential drawbacks of JSON-RPC batching for EVM. This addition significantly enhances the documentation by alerting users to important considerations before they implement batching.

Consider adding a link to the eRPC documentation or a brief explanation of how eRPC addresses these issues (if it does) to provide users with a complete picture of batching in the context of eRPC.

docs/pages/config/database.mdx (3)

96-101: Helpful Redis configuration example added.

The new Redis configuration example is a valuable addition, providing practical guidance on setting up Redis with an eviction policy. This will be particularly useful for users implementing caching with Redis.

Consider adding a brief comment explaining the allkeys-lru policy for users who might not be familiar with Redis eviction policies. For example:

 maxmemory 2000mb
-maxmemory-policy allkeys-lru
+maxmemory-policy allkeys-lru  # Evict least recently used keys first

Line range hint 1-101: Comprehensive improvements to database configuration documentation.

The changes to this file significantly enhance the documentation's completeness and clarity. The addition of a comprehensive list of cacheable methods and the updated explanation of the re-org mechanism provide valuable information for users. These changes align well with the broader updates mentioned in the PR objectives and complement the enhancements made to other components.

For future consideration, it might be beneficial to include a brief section on performance implications of different caching strategies or driver choices. This could help users make more informed decisions based on their specific use cases and expected load.

🧰 Tools
🪛 LanguageTool

[typographical] ~104-~104: Consider putting a comma before the abbreviation “i.e.”.
Context: ...o store cached data permanently without TTL i.e. forever. You d...

(IE_COMMA)


Inconsistencies Found Between Documentation and Codebase

  • Cacheable Methods: None of the methods listed in the documentation are implemented in the codebase.
  • Database Drivers: Only the memory driver is implemented. The redis, postgresql, and dynamodb drivers mentioned in the documentation are missing.
🔗 Analysis chain

Line range hint 1-101: Documentation updates align with PR objectives, testing reminder.

The changes to this documentation file effectively support the PR objective of rebasing to match v0.0.25. The updated content provides clear guidance on new features and configurations, which is crucial for users adopting the latest version.

As mentioned in the PR description, testing has not yet been conducted for these changes. Please ensure that comprehensive testing is performed to verify the accuracy of the documentation and the functionality of the described features, particularly the caching mechanisms and database configurations.

To assist with verification, you could run the following script to check for any inconsistencies between the documentation and the actual code:

This script will help ensure that the documented features are actually implemented in the code.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistency between documentation and code

# Check if the cacheable methods listed in the documentation are actually implemented
echo "Checking cacheable methods implementation:"
rg -i "func.*\b($(sed -n '/| Method Name/,/^$/p' docs/pages/config/database.mdx | tail -n +3 | cut -d'|' -f2 | sed 's/ //g' | tr '\n' '|' | sed 's/|$//')\b)" erpc/

# Verify if the database drivers mentioned in the documentation are implemented
echo "Checking database drivers implementation:"
rg -i "driver.*\b(memory|redis|postgresql|dynamodb)\b" erpc/

Length of output: 23117

🧰 Tools
🪛 LanguageTool

[typographical] ~104-~104: Consider putting a comma before the abbreviation “i.e.”.
Context: ...o store cached data permanently without TTL i.e. forever. You d...

(IE_COMMA)

upstream/evm_state_poller.go (2)

Line range hint 318-327: Improved error handling and result processing in fetchBlock.

The changes enhance the method's efficiency and error reporting. The use of PeekStringByPath is a good practice for JSON parsing.

Consider wrapping the HexToInt64 call in a separate error check to provide more specific error information:

 numberStr, err := jrr.PeekStringByPath("number")
 if err != nil {
     return 0, &common.BaseError{
         Code:    "ErrEvmStatePoller",
         Message: "cannot get block number from block data",
         Details: map[string]interface{}{
             "blockTag": blockTag,
             "result":   jrr.Result,
         },
     }
 }

-return common.HexToInt64(numberStr)
+blockNumber, err := common.HexToInt64(numberStr)
+if err != nil {
+    return 0, &common.BaseError{
+        Code:    "ErrEvmStatePoller",
+        Message: "invalid block number format",
+        Details: map[string]interface{}{
+            "blockTag": blockTag,
+            "numberStr": numberStr,
+        },
+    }
+}
+return blockNumber, nil

356-365: Improved error handling and result processing in fetchSyncingState.

The changes simplify the logic, improve type safety, and enhance error reporting. The use of common.SonicCfg.Unmarshal is consistent with the codebase's practices.

Consider adding a check for nil result before unmarshalling to prevent potential panics:

 var syncing bool
+if jrr.Result == nil {
+    return false, &common.BaseError{
+        Code:    "ErrEvmStatePoller",
+        Message: "syncing state result is nil",
+    }
+}
 err = common.SonicCfg.Unmarshal(jrr.Result, &syncing)
 if err != nil {
     return false, &common.BaseError{
         Code:    "ErrEvmStatePoller",
         Message: "cannot get syncing state result type (must be boolean)",
         Details: map[string]interface{}{
             "result": util.Mem2Str(jrr.Result),
         },
     }
 }
docs/pages/config/example.mdx (1)

77-77: Add explanation for the new maxTimeout option

The new maxTimeout option has been added to the server configuration, but there's no explanation of its purpose or implications. To improve clarity:

  1. Add a brief explanation of what maxTimeout does and when it should be used.
  2. Consider mentioning any default value if one exists.
  3. Update the "Minimal erpc.yaml" section to include this option if it's considered essential.
  4. If applicable, add a note in the "Roadmap" section about future enhancements related to this option.

Here's a suggested explanation to add after the new line:

  maxTimeout: 30s  # Maximum allowed duration for any request before it's terminated
upstream/registry.go (1)

464-466: New getter method for metricsTracker looks good.

The GetMetricsTracker method is a straightforward and correct implementation of a getter for the metricsTracker field. This addition enhances the API of the UpstreamsRegistry struct, allowing external components to access the metrics tracker when needed.

Consider the implications of exposing this internal field directly. Depending on your design goals, you might want to return a read-only interface or a copy of the tracker to maintain better encapsulation. If direct access is intentional and necessary, please ensure it's documented in the package documentation.

test/k6/run.js (1)

36-42: Remove commented-out code for a cleaner codebase

The block of commented-out code may clutter the file and cause confusion. If this alternative payload is no longer needed, consider removing it or documenting its purpose.

vendors/drpc.go (1)

Line range hint 57-66: Consider using error codes alongside error message checks for robust error handling.

Relying solely on error message strings can be fragile if messages change or are localized. If possible, consider using error codes in conjunction with message checks to make the error handling more reliable.

common/response.go (1)

269-283: Reset All Fields in Release() to Prevent Memory Leaks

The Release() method currently resets body and jsonRpcResponse, but other fields like err, expectedSize, and metadata fields remain unchanged. To prevent potential memory leaks or unintended reuse, consider resetting all fields to their zero values.

Apply this diff to reset additional fields:

func (r *NormalizedResponse) Release() {
	r.Lock()
	defer r.Unlock()

	// Close and reset body
	if r.body != nil {
		err := r.body.Close()
		if err != nil {
			log.Error().Err(err).Interface("response", r).Msg("failed to close response body")
		}
		r.body = nil
	}

	r.jsonRpcResponse.Store(nil)
+	r.err = nil
+	r.expectedSize = 0
+	r.fromCache = false
+	r.attempts = 0
+	r.retries = 0
+	r.hedges = 0
+	r.upstream = nil
+	r.evmBlockNumber.Store(0)
}
test/fake_server.go (2)

Line range hint 252-273: Safely perform type assertions to prevent runtime panics

In the findMatchingSample method, type assertions are used without checking if they succeed:

if len(sample.Request.Params.([]interface{})) == len(req.Params.([]interface{})) {
    // ...
}

If Params cannot be asserted to []interface{}, the program will panic.

Modify the code to safely handle type assertions:

+sampleParams, ok1 := sample.Request.Params.([]interface{})
+reqParams, ok2 := req.Params.([]interface{})
+if ok1 && ok2 {
+    if len(sampleParams) == len(reqParams) {
+        // Compare params one by one
+        for i, param := range sampleParams {
+            if param != reqParams[i] {
+                break
+            }
+        }
+    }
+} else {
+    // Handle cases where Params are not slices
+    if sample.Request.Params == req.Params {
+        // Params match
+    } else {
+        // Params do not match
+        continue
+    }
+}

This change checks if the type assertions succeed and adds logic to handle cases where Params are not slices.


165-171: Set the correct Content-Length header

In handleSingleRequest, the Content-Length header is set based on the length of the JSON-encoded response:

w.Header().Set("Content-Length", strconv.Itoa(len(buf.Bytes())))

However, if the response contains multibyte characters, len(buf.Bytes()) may not accurately represent the byte length of the encoded response.

Consider using buf.Len() instead of len(buf.Bytes()):

w.Header().Set("Content-Length", strconv.Itoa(buf.Len()))

This ensures that the content length is accurately set.

common/evm_block_ref.go (1)

50-52: Encapsulate block hash length as a constant for clarity

The length check len(bns) == 66 uses a magic number. Consider defining a constant (e.g., BlockHashHexLength) to improve readability and maintainability.

Apply this diff to define and use a constant:

+const BlockHashHexLength = 66

...

 if strings.HasPrefix(bns, "0x") {
-    if len(bns) == 66 {
+    if len(bns) == BlockHashHexLength {
         return bns, 0, nil
     }
upstream/failsafe.go (1)

150-150: Reminder: Implement the Prometheus Metric

There is a TODO comment to emit a custom Prometheus metric to track circuit breaker root causes. Implementing this will enhance observability and help diagnose issues more effectively.

Would you like assistance in implementing this metric or creating a GitHub issue to track this task?

erpc/networks.go (1)

367-369: Simplify the nil check for evmStatePollers

Since method receivers cannot be nil, checking n == nil is unnecessary. Simplify the condition to:

Apply this diff to streamline the condition:

- if n == nil || n.evmStatePollers == nil || len(n.evmStatePollers) == 0 {
+ if n.evmStatePollers == nil || len(n.evmStatePollers) == 0 {
    return false, nil
}
common/json_rpc.go (1)

355-363: Simplify Slice Allocation in GetReader Method

The GetReader method pre-calculates totalReaders and manually manages indices, which can be simplified by appending to the slice without specifying its initial length.

Simplify the code by declaring the slice without predefining its length:

-    totalReaders := 3
-    if r.Error != nil || len(r.errBytes) > 0 {
-        totalReaders += 2
-    }
-    if r.Result != nil || len(r.Result) > 0 {
-        totalReaders += 2
-    }
-
-    readers := make([]io.Reader, totalReaders)
-    idx := 0
+    var readers []io.Reader

     readers = append(readers, bytes.NewReader([]byte(`{"jsonrpc":"2.0","id":`)))
     readers = append(readers, bytes.NewReader(r.idBytes))

     if len(r.errBytes) > 0 {
         readers = append(readers, bytes.NewReader([]byte(`,"error":`)))
         readers = append(readers, bytes.NewReader(r.errBytes))
     } else if r.Error != nil {
         r.errBytes, err = SonicCfg.Marshal(r.Error)
         if err != nil {
             return nil, err
         }
         readers = append(readers, bytes.NewReader([]byte(`,"error":`)))
         readers = append(readers, bytes.NewReader(r.errBytes))
     }

     if len(r.Result) > 0 {
         readers = append(readers, bytes.NewReader([]byte(`,"result":`)))
         readers = append(readers, bytes.NewReader(r.Result))
     }

     readers = append(readers, bytes.NewReader([]byte{'}'}))
erpc/http_server.go (2)

Line range hint 152-156: Avoid exposing internal error details in client responses

Similar to the previous issue, the error message in this per-request handler includes panic details and stack traces. Exposing such information can leak sensitive data. It's advisable to return a generic error message to the client and log the detailed information internally.

Apply this diff to fix the issue:

if r := recover(); r != nil {
-	msg := fmt.Sprintf("unexpected server panic on per-request handler: %v -> %s", r, util.Mem2Str(debug.Stack()))
+	msg := "Internal server error"
	lg.Error().Msgf("unexpected server panic on per-request handler: %v -> %s", r, util.Mem2Str(debug.Stack()))
	fastCtx.SetStatusCode(fasthttp.StatusInternalServerError)
	fastCtx.Response.Header.Set("Content-Type", "application/json")
	fastCtx.SetBodyString(fmt.Sprintf(`{"jsonrpc":"2.0","error":{"code":-32603,"message":"%s"}}`, msg))
}

Line range hint 518-522: Avoid exposing internal error details when encoding fails

If an error occurs during encoding of the error response, the current implementation sends err.Error() back to the client. This can reveal internal error messages or stack traces. Consider returning a generic error message instead.

Apply this diff to fix the issue:

if err != nil {
	logger.Error().Err(err).Msgf("failed to encode error response")
	ctx.SetStatusCode(fasthttp.StatusInternalServerError)
	ctx.Response.Header.Set("Content-Type", "application/json")
-	ctx.SetBodyString(fmt.Sprintf(`{"jsonrpc":"2.0","error":{"code":-32603,"message":"%s"}}`, err.Error()))
+	ctx.SetBodyString(`{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal server error"}}`)
} else {
	ctx.Response.Header.Set("Content-Type", "application/json")
}
upstream/upstream.go (3)

375-376: Address the TODO for per-network and per-method policies

The TODO comment suggests extending the failsafe executor to handle per-network or per-method configurations. Implementing this would allow for more granular control over retry, circuit breaker, and integrity policies.

Would you like assistance in designing and implementing this feature?


439-439: Consider making ignore methods per-network

The TODO comment indicates a plan to make the IgnoreMethods functionality per-network rather than global, which would be beneficial for upstreams supporting multiple networks.

Do you need help in refactoring the configuration to support per-network IgnoreMethods?


Line range hint 462-480: Handle errors when initializing rate limit auto-tuner

In initRateLimitAutoTuner, the error returned by GetBudget is currently ignored. To prevent silent failures, consider handling the error appropriately, such as logging it or exiting the initialization.

Apply this diff to handle the error:

 budget, err := u.rateLimitersRegistry.GetBudget(u.config.RateLimitBudget)
-if err == nil {
+if err != nil {
+    u.Logger.Error().Err(err).Msgf("failed to get rate limit budget: %s", u.config.RateLimitBudget)
+    return
+}
 dur, err := time.ParseDuration(cfg.AdjustmentPeriod)
erpc/http_server_test.go (2)

341-341: Use t.Log instead of fmt.Println for test logging

Using t.Log provides better integration with the testing framework and allows for more controlled test output.

Apply this diff:

-   			fmt.Println(body)
+   			t.Log(body)

584-584: Use t.Log instead of fmt.Println for test logging

Using t.Log provides better integration with the testing framework and keeps the test output organized.

Apply this diff:

-    					fmt.Println(string(bodyBytes))
+    					t.Log(string(bodyBytes))
common/errors.go (1)

701-702: Rename variable client to userErrors for clarity

The variable client counts user-related errors and is later referenced as "user errors" in the summary. Renaming client to userErrors or clientErrors improves readability and maintains consistent terminology.

Also applies to: 731-734, 767-769

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 76d16ed and 572f721.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (75)
  • .github/workflows/prune.yml (1 hunks)
  • .github/workflows/release.yml (4 hunks)
  • .github/workflows/test.yml (2 hunks)
  • .gitignore (1 hunks)
  • .vscode/launch.json (1 hunks)
  • Dockerfile (1 hunks)
  • Makefile (1 hunks)
  • README.md (1 hunks)
  • auth/http.go (6 hunks)
  • cmd/erpc/init_test.go (1 hunks)
  • cmd/erpc/main.go (1 hunks)
  • cmd/erpc/main_test.go (1 hunks)
  • common/config.go (4 hunks)
  • common/errors.go (14 hunks)
  • common/evm.go (1 hunks)
  • common/evm_block_ref.go (5 hunks)
  • common/evm_block_ref_test.go (3 hunks)
  • common/evm_json_rpc.go (2 hunks)
  • common/init_test.go (1 hunks)
  • common/json_rpc.go (4 hunks)
  • common/request.go (12 hunks)
  • common/response.go (6 hunks)
  • common/sonic.go (1 hunks)
  • common/utils.go (3 hunks)
  • data/memory.go (0 hunks)
  • data/mock_connector.go (2 hunks)
  • data/value.go (0 hunks)
  • docs/pages/config/database.mdx (2 hunks)
  • docs/pages/config/example.mdx (1 hunks)
  • docs/pages/config/rate-limiters.mdx (1 hunks)
  • docs/pages/deployment/railway.mdx (1 hunks)
  • docs/pages/operation/batch.mdx (1 hunks)
  • docs/pages/operation/production.mdx (1 hunks)
  • docs/pages/operation/url.mdx (1 hunks)
  • erpc/erpc.go (1 hunks)
  • erpc/erpc_test.go (3 hunks)
  • erpc/evm_json_rpc_cache.go (7 hunks)
  • erpc/evm_json_rpc_cache_test.go (13 hunks)
  • erpc/healthcheck.go (1 hunks)
  • erpc/http_server.go (15 hunks)
  • erpc/http_server_test.go (7 hunks)
  • erpc/init.go (1 hunks)
  • erpc/init_test.go (1 hunks)
  • erpc/multiplexer.go (2 hunks)
  • erpc/networks.go (11 hunks)
  • erpc/networks_registry.go (1 hunks)
  • erpc/networks_test.go (80 hunks)
  • erpc/projects.go (3 hunks)
  • erpc/projects_registry.go (1 hunks)
  • go.mod (2 hunks)
  • test/cmd/main.go (1 hunks)
  • test/fake_server.go (4 hunks)
  • test/init_test.go (1 hunks)
  • test/k6/run.js (3 hunks)
  • test/samples/evm-json-rpc.json (1 hunks)
  • upstream/alchemy_http_json_rpc_client.go (1 hunks)
  • upstream/envio_http_json_rpc_client.go (1 hunks)
  • upstream/evm_state_poller.go (3 hunks)
  • upstream/failsafe.go (7 hunks)
  • upstream/http_json_json_client_test.go (5 hunks)
  • upstream/http_json_rpc_client.go (22 hunks)
  • upstream/init_test.go (1 hunks)
  • upstream/pimlico_http_json_rpc_client.go (1 hunks)
  • upstream/registry.go (2 hunks)
  • upstream/registry_test.go (0 hunks)
  • upstream/request_test.go (1 hunks)
  • upstream/thirdweb_http_json_rpc_client.go (1 hunks)
  • upstream/upstream.go (4 hunks)
  • util/fastmem.go (1 hunks)
  • util/headers.go (2 hunks)
  • util/json_rpc.go (1 hunks)
  • util/reader.go (1 hunks)
  • util/redact.go (1 hunks)
  • vendors/drpc.go (2 hunks)
  • vendors/quicknode.go (1 hunks)
💤 Files with no reviewable changes (3)
  • data/memory.go
  • data/value.go
  • upstream/registry_test.go
✅ Files skipped from review due to trivial changes (6)
  • cmd/erpc/init_test.go
  • common/init_test.go
  • erpc/init_test.go
  • test/init_test.go
  • upstream/init_test.go
  • upstream/request_test.go
🧰 Additional context used
🪛 actionlint
.github/workflows/prune.yml

25-25: shellcheck reported issue in this script: SC2086:info:2:36: Double quote to prevent globbing and word splitting

(shellcheck)

.github/workflows/release.yml

23-23: label "large" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-14.0", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-13.0", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "macos-12.0", "macos-11", "macos-11.0", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


101-101: shellcheck reported issue in this script: SC2086:info:1:51: Double quote to prevent globbing and word splitting

(shellcheck)

.github/workflows/test.yml

6-6: label "large" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-14.0", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-13.0", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "macos-12.0", "macos-11", "macos-11.0", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)

🪛 LanguageTool
docs/pages/config/rate-limiters.mdx

[grammar] ~71-~71: A noun may be missing here.
Context: ...e auto-tuner is enabled by default when an upstream has any rate limit budget defined. Here...

(DT_JJ_NO_NOUN)

docs/pages/deployment/railway.mdx

[uncategorized] ~35-~35: Possible missing comma found.
Context: ...ge in your services To reduce cost and overhead use private network (`.railway.internal...

(AI_HYDRA_LEO_MISSING_COMMA)

docs/pages/operation/production.mdx

[uncategorized] ~7-~7: “your” (belonging to you) seems less likely than “you”.
Context: ...en using eRPC in Kubernetes for example your might see occesional OOMKilled errors...

(AI_HYDRA_LEO_CP_YOUR_YOU)


[uncategorized] ~7-~7: “of” seems less likely than “or” (‘either … or’).
Context: ...which is most often because of high RPS of large request/responses. In majority o...

(AI_HYDRA_LEO_CP_OF_OR)


[grammar] ~9-~9: An article may be missing.
Context: ...igh RPS of large request/responses. In majority of use-cases eRPC uses around 256MB of mem...

(BUNCH_OF)


[uncategorized] ~9-~9: Possible missing comma found.
Context: ... request/responses. In majority of use-cases eRPC uses around 256MB of memory (and 1...

(AI_HYDRA_LEO_MISSING_COMMA)


[uncategorized] ~11-~11: Possible missing comma found.
Context: ...sed on your request patterns. For more control you can configure Go's garbage collecti...

(AI_HYDRA_LEO_MISSING_COMMA)


[uncategorized] ~30-~30: A comma may be missing after the conjunctive/linking adverb ‘Therefore’.
Context: ...might take up to 10 seconds to respond. Therefore a low timeout might ultimately always f...

(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)


[uncategorized] ~32-~32: The hyphen in highly-recommended is redundant.
Context: ...cy](/config/failsafe#hedge-policy) is highly-recommended if you prefer "fast response as soon ...

(ADVERB_LY_HYPHEN_FIX)


[typographical] ~32-~32: After the expression ‘for example’ a comma is usually used.
Context: ...fast response as soon as possible". For example setting 500ms as "delay" will make su...

(COMMA_FOR_EXAMPLE)


[uncategorized] ~36-~36: Possible missing article found.
Context: ...wards cache database issues, so even if database is completely down it will not impact t...

(AI_HYDRA_LEO_MISSING_THE)

🔇 Additional comments (124)
.gitignore (1)

13-14: Appropriate additions to .gitignore

The new entries in the .gitignore file are beneficial:

  1. .semrel/: This likely ignores a directory related to semantic versioning or releases, which is good for excluding temporary or generated files.
  2. __debug*: This pattern ignores debug-related files and directories, which is a standard practice to keep the repository clean.

These additions align well with the project's structure and the PR's objective of incorporating upstream changes.

util/json_rpc.go (3)

1-1: LGTM: Package declaration is appropriate.

The util package name is suitable for utility functions like RandomID.


3-6: LGTM: Imports are correct and well-organized.

The necessary packages are imported, and the import order follows Go conventions.


1-11: Overall, the implementation is sound but with room for minor improvements.

The RandomID function correctly implements a method to generate random JSON-RPC IDs within a 32-bit range. The code is well-structured and follows Go conventions. Consider the following suggestions for improvement:

  1. Add a security note to the function comment about the use of math/rand.
  2. Ensure that the random number generator is properly seeded elsewhere in the codebase.

These changes will enhance the documentation and potentially improve the randomness of the generated IDs.

util/headers.go (5)

5-6: LGTM: Import changes improve readability.

The addition of an empty line between imports and moving "net/http" import improves code organization and readability.


11-11: LGTM: Loop iteration updated to match new signature.

The change to iterate over r.Header is consistent with the new function signature and maintains the existing logic for header selection.


20-20: LGTM: Header value extraction updated correctly.

The change to use r.Header.Get(k) is appropriate for the new signature and provides a safer way to access header values.


Line range hint 9-24: Overall, the changes to ExtractUsefulHeaders are well-implemented and improve the function.

The function now works directly with *http.Response, which provides more flexibility and aligns with common Go practices. The implementation remains consistent in its logic for selecting and extracting headers. These changes should make the function more versatile and easier to use in various contexts within the application.

However, it's crucial to ensure that all existing calls to this function throughout the codebase are updated to pass a *http.Response instead of an http.Header. This may require changes in other files that weren't included in this review.

To ensure a smooth transition, run the following script to identify any potential usage of the old function signature:

#!/bin/bash
# Description: Find potential usages of the old ExtractUsefulHeaders signature

# Test: Search for function calls with http.Header argument. Expect: No results.
rg -A 5 $'ExtractUsefulHeaders\s*\(\s*[^*]'

9-9: Approve signature change, but verify usage across codebase.

The change from http.Header to *http.Response provides more flexibility and aligns with the PR objectives. However, ensure that all calls to this function are updated accordingly.

Run the following script to verify the function usage:

erpc/multiplexer.go (1)

14-14: LGTM: Good addition for ensuring thread-safety

The addition of sync.Once is a good practice to ensure that certain operations are performed only once, even in concurrent scenarios. This change aligns well with the existing thread-safety measures in the Multiplexer struct.

.vscode/launch.json (1)

14-18: LGTM! Consider verifying compiler paths and CGo implications.

The addition of environment variables for C and C++ compilers, along with enabling CGo, is appropriate for projects that interact with C/C++ code. This aligns well with the PR objective of incorporating upstream changes, which may include new dependencies or features requiring CGo.

However, please consider the following:

  1. Verify that the compiler paths ("/usr/bin/cc" and "/usr/bin/c++") are correct for all development environments. These paths might vary across different systems.
  2. Be aware that enabling CGo can affect build times and binary portability. Ensure this aligns with your project's requirements.
  3. Document the reason for these changes in the project's README or development setup guide to inform other contributors.

To ensure the compiler paths are correct, you can run the following script:

This script will help verify the compiler paths and CGo support in your development environment.

util/reader.go (2)

31-31: LGTM! Efficient return of buffer contents.

The use of buf.Bytes() is correct and efficient, returning a slice of the buffer's contents without unnecessary copying.


1-32: Great implementation! Consider adding unit tests.

The ReadAll function is well-implemented, providing an efficient and secure way to read data from an io.Reader in chunks. It aligns well with the PR objectives of incorporating new features and improving functionality.

To ensure the robustness of this new function, consider adding comprehensive unit tests. These tests should cover various scenarios including:

  1. Reading small amounts of data (less than default buffer size)
  2. Reading large amounts of data (greater than default buffer size)
  3. Reading data with different chunk sizes
  4. Handling of EOF
  5. Handling of other potential errors
  6. Edge cases around the 50MB cap

Would you like assistance in generating these unit tests?

cmd/erpc/main.go (3)

9-9: LGTM: Import statement addition is appropriate.

The addition of the common package import is necessary and aligns with the goal of centralizing version information.


Line range hint 1-38: Overall, the changes in this file are well-implemented and improve version management.

The modifications to centralize version information in the common package enhance maintainability and align well with the PR objectives. The removal of hardcoded version variables and the use of constants from the common package is a good practice. These changes contribute to a more robust and maintainable codebase.


19-19: LGTM: Version logging update improves maintainability.

The use of common.ErpcVersion and common.ErpcCommitSha centralizes version information, which is a good practice. This change aligns well with the PR objectives.

To ensure these constants are properly set during the build process, please run the following script:

This script will help verify that the version constants are properly defined and set during the build process.

.github/workflows/test.yml (1)

6-6: ⚠️ Potential issue

Verify the runs-on attribute change

The runs-on attribute has been changed from ubuntu-latest to large. This is not a standard GitHub-hosted runner label and may cause issues.

If this is intended for a self-hosted runner, please ensure that:

  1. The large label is correctly configured for your self-hosted runner.
  2. The runner has the necessary resources and permissions to execute this job.

If this is not intended for a self-hosted runner, consider reverting to a standard GitHub-hosted runner label like ubuntu-latest.

To verify the available runner labels in your repository, you can run the following GitHub CLI command:

Please review and adjust the runs-on attribute accordingly.

🧰 Tools
🪛 actionlint

6-6: label "large" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-14.0", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-13.0", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "macos-12.0", "macos-11", "macos-11.0", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)

.github/workflows/prune.yml (4)

1-10: LGTM: Well-structured workflow triggers

The workflow name is concise and descriptive. The combination of manual, scheduled, and push-based triggers provides good flexibility for running the pruning process.


11-15: LGTM: Appropriate job configuration

The job setup is simple and suitable for the pruning task. Using the latest Ubuntu ensures access to up-to-date tools.


16-21: LGTM: Secure login to GitHub Container Registry

The login step uses the latest version of the docker/login-action and securely authenticates using the GITHUB_TOKEN, following best practices.


29-38: Consider enabling actual pruning after testing

The retention policy is currently set to dry-run mode, which is good for testing but won't perform actual pruning.

Once you've verified that the dry run produces the expected results, consider disabling dry-run mode to perform actual pruning. You can do this by setting dry-run: false in the workflow.

Would you like assistance in implementing a conditional dry-run mode based on the triggering event (e.g., always dry-run for scheduled runs, but allow actual pruning for manual dispatch)?

erpc/erpc.go (2)

Line range hint 1-62: Final thoughts: Good addition, ready for merge

The changes to erpc/erpc.go are minimal, focused, and add useful functionality without introducing complexity. The new GetProjects method is well-integrated with the existing code structure. With the suggested documentation addition, this change is ready for merge.


60-62: LGTM! Consider adding documentation.

The new GetProjects method is a good addition, providing a way to retrieve all projects. It's consistent with the existing code style and structure.

Consider adding a documentation comment for this method to explain its purpose and return value. For example:

// GetProjects returns a slice of all prepared projects in the ERPC instance.
func (e *ERPC) GetProjects() []*PreparedProject {
	return e.projectsRegistry.GetAll()
}

Let's verify the implementation of the GetAll() method in the ProjectsRegistry:

✅ Verification successful

Verification Successful

The GetAll() method in ProjectsRegistry is correctly implemented and functions as intended.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation of GetAll() method in ProjectsRegistry

# Test: Search for the GetAll method in ProjectsRegistry
rg -A 5 'func \(r \*ProjectsRegistry\) GetAll\(\)'

Length of output: 436

Dockerfile (2)

20-20: Approved: Improved version information management

The update to use common.ErpcVersion and common.ErpcCommitSha in the linker flags is a good practice. It centralizes version information, making it easier to maintain and update across the application. This change aligns well with the PR objective of incorporating upstream changes and improving code organization.


23-23: Approved: Consistent versioning across builds

The identical update for the pprof-enabled build command ensures consistency in version information management across different build configurations. This change maintains parity between the standard and pprof-enabled versions, which is crucial for debugging and performance analysis.

Makefile (1)

45-45: Approved: Increased test count for improved reliability.

The change from -count 3 to -count 5 enhances the reliability of test results by running each test more times. This can help identify flaky tests and ensure the stability of the rebased changes.

However, consider the trade-off between increased reliability and longer test execution time. If the tests were already stable with 3 runs, the additional runs might not provide significant value.

To assess the impact on test execution time, you can run the following script:

This script will help you evaluate whether the increased test count significantly affects the overall test execution time.

common/utils.go (2)

Line range hint 1-72: Summary: Changes align well with PR objectives and improve code quality.

The modifications in this file successfully incorporate new features and bug fixes, aligning with the PR's objective of rebasing to match v0.0.25. The changes enhance the robustness and flexibility of utility functions, particularly in handling hexadecimal and decimal inputs. The introduction of the ContextKey type also improves type safety.

While the changes are generally positive, consider addressing the following points:

  1. Add documentation for the new ContextKey type.
  2. Enhance error handling in HexToInt64 for more informative error messages.
  3. Finalize the error handling strategy in NormalizeHex as discussed.

These improvements will further enhance the code quality and maintainability.


Line range hint 43-72: Approve changes and address the TODO comment.

The modifications to NormalizeHex significantly improve its flexibility and robustness. It now handles various input types and includes better error handling.

Regarding the TODO comment on line 60, it's important to decide on the error handling strategy. Here's a suggestion:

if bn, ok := value.(string); ok {
    // ... (existing code)
    value, err := strconv.ParseUint(bn, 0, 64)
    if err == nil && value > 0 {
        return fmt.Sprintf("0x%x", value), nil
    }
    return "", fmt.Errorf("invalid string input: %s", bn)
}

This change would return an error for invalid string inputs, maintaining consistency with the function's error handling approach.

To verify the impact of this change, run the following script:

This script will help identify all usages of NormalizeHex and their surrounding context, allowing you to assess the impact of changing the error handling strategy.

✅ Verification successful

Approve changes and mark the TODO as resolved.

The updates to NormalizeHex enhance its error handling, and all usages in the codebase appropriately handle potential errors.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for usages of NormalizeHex to ensure they handle potential errors

rg -n 'NormalizeHex\(' | while read -r line; do
    file=$(echo "$line" | cut -d':' -f1)
    linenum=$(echo "$line" | cut -d':' -f2)
    context=$(rg -n 'NormalizeHex\(' "$file" -C 5)
    echo "File: $file"
    echo "Line: $linenum"
    echo "Context:"
    echo "$context"
    echo "------------------------"
done

Length of output: 61436

test/cmd/main.go (3)

18-20: Verify the intention behind server configuration changes

The server configurations have been updated with new port numbers (9081-9083) and significantly reduced LimitedRate values. While these changes align with the PR objective of rebasing to match the upstream version, they may have a substantial impact on the behavior of the fake servers.

  • The first server's LimitedRate has been reduced from 0.9 to 0.005
  • The second server's LimitedRate has been reduced from 0.8 to 0.2
  • The third server's LimitedRate has been reduced from 0.9 to 0.01

Please confirm that these changes are intentional and explain the reasoning behind the significant reductions in LimitedRate values. How might these changes affect the testing scenarios or the overall system behavior?


23-25: Clarify the purpose and impact of adding 102 new servers

A new loop has been introduced to add 102 additional servers with ports ranging from 9084 to 9185. While this change aligns with the PR objective of rebasing to match the upstream version, it represents a significant increase in the number of fake servers being created.

  1. Could you explain the rationale behind adding such a large number of new servers?
  2. Have you considered the potential impact on system resources, especially in testing environments?
  3. Are there any specific test scenarios or use cases that necessitate this many servers?

Additionally, it might be beneficial to make the number of additional servers configurable, rather than hardcoding it. This would allow for more flexibility in different testing scenarios.


18-25: Consider performance optimizations and additional logging for new server configurations

The changes introduce a significant increase in the number of fake servers, which could impact the performance and resource usage of the test environment. While the core structure of the main function remains unchanged, there are a few considerations:

  1. Performance: With the addition of 102 new servers, the startup and shutdown times might increase substantially. Consider implementing parallel server startup and shutdown to mitigate this.

  2. Logging: It might be beneficial to add more granular logging for the new servers, especially if any issues arise during their operation.

  3. Error handling: With the increased number of servers, there's a higher chance of encountering errors. Consider implementing more robust error handling and recovery mechanisms.

Have these changes been tested in an environment similar to the intended deployment environment? Are there any performance benchmarks or metrics that can be shared to demonstrate the impact of these changes?

Would you like assistance in implementing any of these suggestions, such as parallel server startup or enhanced logging?

docs/pages/operation/url.mdx (2)

70-72: LGTM: Improved document structure

The elevation of the "Batch requests" section to a second-level heading (H2) improves the overall structure of the document, making it consistent with other main sections.


Line range hint 1-86: LGTM: Improved overall document structure and content

The changes to this document have significantly improved its structure and content. The main sections are now consistently at the H2 level, creating a more balanced and easy-to-navigate layout. The flow of information is logical, starting with basic usage and progressing to more advanced topics like batch requests and the new healthcheck feature.

These improvements enhance the document's readability and make it a more comprehensive guide for users of eRPC.

auth/http.go (3)

9-9: LGTM: Import statement for util package added.

The addition of the util package import is consistent with the subsequent usage of util.Mem2Str throughout the file, supporting improved memory handling.


28-28: LGTM: Improved X-ERPC-Secret-Token header handling.

The use of util.Mem2Str for converting the X-ERPC-Secret-Token header value is consistent with the improved memory handling approach.


95-95: LGTM: Improved SIWE message normalization with util.Mem2Str.

The use of util.Mem2Str for converting the decoded base64 string in the normalizeSiweMessage function is consistent with the improved memory handling approach.

docs/pages/deployment/railway.mdx (1)

55-55: Appropriate generalization of the example URL.

The change from a specific deployment URL to a placeholder (https://erpc-xxxxxxx.up.railway.app) is a good improvement. It makes the documentation more generic and applicable to all users, regardless of their specific deployment.

go.mod (4)

8-8: LGTM: Bytedance/sonic version update.

The update from v1.12.2 to v1.12.3 for github.com/bytedance/sonic is a minor version change, which typically includes bug fixes and small improvements. This aligns with the PR objective of rebasing to match v0.0.25 of the upstream project.

Please ensure that this update is compatible with your codebase and doesn't introduce any breaking changes. Consider running the project's test suite to verify compatibility.


30-30: LGTM: Bits-and-blooms/bitset version update.

The update from v1.13.0 to v1.14.2 for github.com/bits-and-blooms/bitset is a minor version change, which typically includes new features, bug fixes, and improvements. This aligns with the PR objective of rebasing to match v0.0.25 of the upstream project.

Please ensure that this update is compatible with your codebase and doesn't introduce any breaking changes. Consider running the project's test suite to verify compatibility and to take advantage of any new features or improvements.


25-26: Clarify the need for the failsafe-go package replacement.

The addition of a replace directive for github.com/failsafe-go/failsafe-go points to a fork (github.com/aramalipoor/failsafe-go) at a specific commit (v0.0.0-20241002125322-de01986d3951). While this may be necessary for your current needs, it's important to consider the following:

  1. Using a fork may prevent you from receiving updates from the original package.
  2. Using a specific commit instead of a released version could introduce incompatibilities or unexpected behavior.
  3. This approach might make it harder for other developers to understand and maintain the project.

Could you please clarify:

  1. Why is this replacement necessary?
  2. Is there a plan to contribute these changes back to the original repository?
  3. Have you considered alternatives, such as vendoring the package or creating a patch?

Additionally, please ensure that this change doesn't introduce any compatibility issues with the rest of the codebase.


Line range hint 1-74: Summary of go.mod changes

The changes in this file include:

  1. Updating github.com/bytedance/sonic from v1.12.2 to v1.12.3
  2. Updating github.com/bits-and-blooms/bitset from v1.13.0 to v1.14.2
  3. Adding a replace directive for github.com/failsafe-go/failsafe-go

The version updates are minor and align with the PR objective. However, the replace directive requires further clarification due to potential maintenance and compatibility concerns.

Please ensure that:

  1. The updated packages are compatible with your codebase.
  2. The project's test suite passes with these changes.
  3. The rationale for the replace directive is documented and understood by the team.
erpc/init.go (1)

72-72: Simplified httpServer initialization, but consider error handling

The direct initialization of httpServer simplifies the code and leverages type inference. This is a good change that reduces unnecessary variable declarations.

However, there are two points to consider:

  1. Error handling: Ensure that NewHttpServer doesn't return an error that needs to be handled.
  2. Variable scope: Verify that httpServer isn't used outside this if block, as its scope has been reduced.

To verify the NewHttpServer function signature and usage, run the following script:

✅ Verification successful

httpServer initialization is correct and scoped appropriately

After verification, the initialization of httpServer does not require additional error handling as NewHttpServer does not return an error. Additionally, the scope of httpServer is appropriately limited to its usage context.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check NewHttpServer function signature and usage

# Test 1: Check NewHttpServer function signature
echo "Checking NewHttpServer function signature:"
ast-grep --pattern 'func NewHttpServer($_) ($_) { $$$' 

# Test 2: Check for any other usages of httpServer variable
echo "Checking for other usages of httpServer variable:"
rg 'httpServer' --type go

Length of output: 1110

erpc/erpc_test.go (2)

84-84: Approve JSON error response change.

The modification from json.RawMessage to a byte slice is an improvement. It's more efficient and consistent with changes in other test files.

This change can lead to slightly better performance in tests by avoiding an extra parsing step.


Line range hint 1-146: Summary of changes in erpc_test.go

The modifications in this file primarily focus on:

  1. Disabling logging in tests
  2. Changing JSON response handling from json.RawMessage to byte slices

These changes align with modifications in other test files, improving consistency across the test suite. They may also lead to slight performance improvements in tests. While the changes are generally positive, consider the suggestions for conditional logging and response constant definitions to further enhance maintainability and debugging capabilities.

docs/pages/operation/production.mdx (3)

5-6: LGTM: New section on Memory usage

The addition of a "Memory usage" section is valuable for production guidelines. It provides crucial information for users managing eRPC in production environments.


11-21: LGTM: Excellent guidance on Go's garbage collection configuration

This section provides valuable information for advanced users on configuring Go's garbage collection. The code block is well-formatted, and the comments clearly explain the purpose of each environment variable. This addition will be particularly helpful for users facing OOM issues in Kubernetes environments.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~11-~11: Possible missing comma found.
Context: ...sed on your request patterns. For more control you can configure Go's garbage collecti...

(AI_HYDRA_LEO_MISSING_COMMA)


27-27: LGTM: Improved readability in Failsafe policies section

The change from "even when only 1 upstream" to "even when you only have 1 upstream" improves readability and directly addresses the reader. This minor improvement aligns with best practices in technical writing.

.github/workflows/release.yml (6)

13-15: LGTM: New trigger for main branch pushes

Adding a trigger for pushes to the main branch is a good practice. It ensures that the release workflow runs automatically when changes are merged, which aligns well with continuous integration and deployment practices.


26-26: LGTM: Conditional steps for version tagging

Adding conditions to the tagging steps based on the 'version_tag' input is a good improvement. This allows the workflow to be more flexible, running differently when triggered by a push to main versus when manually triggered with a version tag.

Also applies to: 33-33, 39-39


49-49: LGTM: Conditional steps for release process

The addition of conditions to the release steps based on the 'version_tag' input is consistent with the changes in the 'tag' job. This ensures that the release process only runs when explicitly triggered with a version tag, adding flexibility to the workflow.

Also applies to: 56-56, 62-62


78-78: LGTM: Flexible checkout for Docker image build

Modifying the checkout step to use 'main' as the default when no version tag is provided is a good improvement. This change allows the workflow to build Docker images from the latest main branch when triggered by a push, while still supporting versioned builds when a tag is provided.


Line range hint 1-128: Overall assessment: Well-implemented improvements to the release workflow

The changes in this file significantly enhance the flexibility and functionality of the release workflow:

  1. The new trigger for pushes to the main branch supports continuous integration.
  2. Conditional steps allow for different behavior in automated and manual release scenarios.
  3. The Docker image build process is more robust, with improved traceability and tagging.

These improvements align well with the PR objectives of rebasing and incorporating upstream changes. The workflow now efficiently handles both automated builds from the main branch and manual versioned releases.

A few minor suggestions have been made to further improve the workflow:

  1. Verify the 'large' runner label to ensure it's a valid option.
  2. Add quotes in the shell script for generating the short SHA.
  3. Consider adding comments to explain the purpose of each Docker build step.

Overall, great work on enhancing this workflow!

🧰 Tools
🪛 actionlint

23-23: label "large" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-14.0", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-13.0", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "macos-12.0", "macos-11", "macos-11.0", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


23-23: ⚠️ Potential issue

Verify the 'large' runner label

The runner has been changed from 'ubuntu-latest' to 'large'. However, 'large' is not a standard GitHub-hosted runner label. This might cause the workflow to fail.

Please verify if 'large' is a custom self-hosted runner label in your organization. If not, consider changing it back to a standard GitHub-hosted runner like 'ubuntu-latest'.

To check available runners, you can run:

Replace {owner} and {repo} with your repository details.

🧰 Tools
🪛 actionlint

23-23: label "large" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-14.0", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-13.0", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "macos-12.0", "macos-11", "macos-11.0", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)

docs/pages/config/rate-limiters.mdx (1)

63-106: Excellent addition of auto-tuner documentation!

The introduction of the auto-tuner feature is well-documented, providing clear explanations, useful examples, and default configurations. This addition significantly enhances the rate-limiting capabilities and user control over request management.

A few minor suggestions have been made to further improve clarity and user guidance, but overall, this is a valuable update to the documentation.

🧰 Tools
🪛 LanguageTool

[grammar] ~71-~71: A noun may be missing here.
Context: ...e auto-tuner is enabled by default when an upstream has any rate limit budget defined. Here...

(DT_JJ_NO_NOUN)

erpc/projects.go (2)

91-91: Improved logging type specificity

The change from Str("id", nq.Id()) to Int64("id", nq.Id()) enhances log consistency by using the correct type for the id field. This improvement facilitates better log parsing and analysis.


Line range hint 1-11: Verify import changes

The AI summary mentioned the removal of the math package import, but this change is not visible in the provided code. Please verify if this change was made in a different commit or if the AI summary is incorrect.

Run the following script to check for any recent changes to import statements:

If the math package import was indeed removed, please ensure that all references to math functions have been properly addressed throughout the file.

upstream/pimlico_http_json_rpc_client.go (1)

148-152: Improved chain ID extraction and error handling

The changes to the chain ID extraction process are well-implemented:

  1. Using jrr.PeekStringByPath() provides a more robust way to extract the chain ID from the JSON-RPC response.
  2. The error handling is now more granular, allowing for specific error reporting if the string extraction fails.
  3. This change aligns with similar modifications in other client implementations, contributing to codebase consistency.

These improvements enhance the robustness of the SupportsNetwork method while maintaining its overall logic and backwards compatibility.

docs/pages/config/database.mdx (1)

82-85: Improved clarity on Redis usage and features.

The updated description provides clearer guidance on when to use Redis for caching, emphasizing its eviction policy feature. This addition helps users better understand the advantages of using Redis in this context.

upstream/evm_state_poller.go (3)

32-32: Improved clarity in synced field documentation.

The updated comment provides a more precise explanation of the synced field's values, enhancing code readability and maintainability.


368-368: LGTM: Correct return statement in fetchSyncingState.

The return statement correctly provides the parsed syncing state.


Line range hint 1-368: Summary: Improvements align well with PR objectives.

The changes in this file successfully incorporate upstream improvements, particularly in error handling and result processing. These modifications enhance code clarity, maintainability, and robustness, which aligns well with the PR's objective of rebasing to match v0.0.25.

To ensure these changes don't introduce any regressions, please run the following verification script:

✅ Verification successful

Verification Successful: The changes in upstream/evm_state_poller.go have been verified and no regressions were introduced.

  • No TODOs or FIXMEs found.
  • Error handling patterns are consistent across the codebase.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the changes in evm_state_poller.go don't introduce regressions

# Test: Check for any TODOs or FIXMEs that might have been introduced
rg -i "TODO|FIXME" upstream/evm_state_poller.go

# Test: Ensure all error cases are properly handled
ast-grep --pattern $'if err != nil {
  $$$
  return $_, &common.BaseError{
    $$$
  }
}' upstream/evm_state_poller.go

# Test: Verify consistent use of error handling patterns
rg -A 5 "common\.BaseError" upstream/evm_state_poller.go

Length of output: 1770

docs/pages/config/example.mdx (1)

Line range hint 1-100: Overall documentation structure and content look good

The documentation provides a comprehensive overview of eRPC configuration options. The structure is clear, with separate sections for minimal and full configuration examples. The added maxTimeout option enhances the server configuration capabilities.

Consider periodically reviewing and updating this document to ensure it stays in sync with the latest features and best practices for eRPC configuration.

common/evm_block_ref_test.go (6)

182-200: LGTM: New test case for eth_call with blockHash object.

This test case enhances coverage by checking the behavior of eth_call when a block hash is provided as an object. The expected values are appropriate for this scenario.


201-219: LGTM: New test case for eth_call with blockNumber object.

This test case further enhances coverage by checking the behavior of eth_call when a block number is provided as an object. The expected values are consistent with the provided block number.


294-309: LGTM: New test case for eth_getProof with blockHash object.

This test case enhances coverage by checking the behavior of eth_getProof when a block hash is provided as an object. The expected values are appropriate for this scenario.


310-325: LGTM: New test case for eth_getProof with blockNumber object.

This test case further enhances coverage by checking the behavior of eth_getProof when a block number is provided as an object. The expected values are consistent with the provided block number.


346-346: LGTM: Updated Result field type in eth_getTransactionReceipt test case.

The change from json.RawMessage to []byte for the Result field aligns with the JsonRpcResponse struct definition and ensures type consistency.


Line range hint 182-325: Summary: Improved test coverage for block reference extraction.

The changes in this file significantly enhance the test suite for the ExtractBlockReference function:

  1. New test cases for eth_call and eth_getProof methods with block identifiers (hash and number) as objects have been added.
  2. The eth_getTransactionReceipt test case has been updated for type consistency.

These additions improve the robustness of the test suite by covering more scenarios, particularly for methods that can accept block identifiers as objects.

Also applies to: 346-346

erpc/evm_json_rpc_cache_test.go (8)

12-12: LGTM: Import added for util package

The addition of the util package import is necessary and consistent with the changes made in the test cases.


68-68: LGTM: Updated response body handling

The change to use util.StringToReaderCloser for the response body is consistent with the new approach for handling response data. The test logic remains intact.


81-81: LGTM: Consistent update to response body handling

The change to use util.StringToReaderCloser for the response body is consistent with the previous modifications. The test logic and assertions remain unchanged.


97-97: LGTM: Consistent update to response body handling

The change to use util.StringToReaderCloser for the response body maintains consistency with the previous modifications. The test logic and assertions remain intact.


112-112: LGTM: Consistent update to response body handling

The change to use util.StringToReaderCloser for the response body maintains consistency with the previous modifications. The test logic and assertions remain unchanged.


150-150: LGTM: Consistent update to response body handling in test cases

The change to use util.StringToReaderCloser for the response body in the test cases maintains consistency with the previous modifications. The test logic, including the test cases and assertions, remains intact.


170-170: LGTM: Consistent updates across all test cases

The changes to use util.StringToReaderCloser for response bodies are consistent across all remaining test cases. The test logic and assertions remain unchanged, maintaining the integrity of the tests.

Also applies to: 185-185, 199-199, 213-213, 227-227, 241-241, 255-255


Line range hint 1-300: Summary: Consistent improvements in response body handling

The changes in this file demonstrate a systematic approach to improving response body handling in the test cases for EvmJsonRpcCache. Key points:

  1. Consistent use of util.StringToReaderCloser for response bodies across all test cases.
  2. No alterations to test logic or assertions, preserving the integrity of the tests.
  3. Addition of the util package import to support these changes.

These modifications align with the broader changes in the codebase for JSON-RPC request and response handling, potentially improving memory management and streamlining the testing process.

upstream/registry.go (1)

361-366: Excellent optimization for trace-level logging!

The conditional check for the logger's trace level before constructing and logging the sorted upstreams string is a great optimization. This change prevents unnecessary string concatenation when trace logging is disabled, potentially improving performance in production environments where trace logging is typically turned off.

upstream/http_json_json_client_test.go (2)

200-208: Improved response handling and verification.

The changes in response handling are a significant improvement:

  1. It ensures that the entire response body is read and consumed.
  2. The content of the response is now explicitly verified against the expected result.
  3. This approach is more robust and can catch potential issues with response content that might have been missed before.

These modifications enhance the test's reliability and thoroughness.

Also applies to: 216-221


609-610: Broadened acceptable duration range for timeout test.

The adjustment of the acceptable duration range from 745-755 milliseconds to 740-780 milliseconds is a positive change:

  1. It allows for slightly more variation in test execution time, which can help reduce test flakiness.
  2. The broader range still effectively verifies the timeout behavior.
  3. This change makes the test more robust across different environments where exact timing might vary.

This modification improves the test's reliability without compromising its effectiveness.

test/samples/evm-json-rpc.json (1)

1439-1451: New debug_traceTransaction method added

A new JSON-RPC request-response pair for the debug_traceTransaction method has been added to the file. This addition enhances the test coverage for debugging capabilities. The structure is consistent with other entries in the file.

However, there are a couple of points to consider:

  1. The response "result": "bigfake:50000000" seems to be a placeholder or mock response. In a real scenario, we would expect a more detailed trace result.
  2. The indentation of the new entry is inconsistent with the rest of the file, which might affect readability.

Consider adjusting the indentation to match the rest of the file:

-  {
-    "request": {
-      "jsonrpc": "2.0",
-      "method": "debug_traceTransaction",
-      "params": [
-        "0xe6c2decd68012e0245599ddf93c232bf92884758393a502852cbf2f393e3d99c"
-      ]
-    },
-    "response": {
-      "jsonrpc": "2.0",
-      "result": "bigfake:50000000"
-    }
-  }
+{
+  "request": {
+    "jsonrpc": "2.0",
+    "method": "debug_traceTransaction",
+    "params": [
+      "0xe6c2decd68012e0245599ddf93c232bf92884758393a502852cbf2f393e3d99c"
+    ]
+  },
+  "response": {
+    "jsonrpc": "2.0",
+    "result": "bigfake:50000000"
+  }
+}

To ensure this transaction hash is consistent within the file, let's search for its occurrences:

This will help verify if the transaction hash is used consistently throughout the file.

✅ Verification successful

Transaction hash usage verified

The transaction hash "0xe6c2decd68012e0245599ddf93c232bf92884758393a502852cbf2f393e3d99c" is used consistently across the file, including in the newly added debug_traceTransaction entry. This confirms that the addition maintains consistency within the test cases.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
grep -n "0xe6c2decd68012e0245599ddf93c232bf92884758393a502852cbf2f393e3d99c" test/samples/evm-json-rpc.json

Length of output: 647

common/sonic.go (1)

48-57: Review security implications of Sonic configuration settings

The SonicCfg is set with options that disable certain validations and escaping mechanisms, such as EscapeHTML: false, NoValidateJSONMarshaler: true, and ValidateString: false. Please verify that these settings do not introduce security vulnerabilities, especially if the JSON output includes user-provided input or is used in contexts susceptible to injection attacks.

test/k6/run.js (1)

8-17: Change to 'constant-arrival-rate' executor is appropriate

Switching from stages to scenarios with a constant-arrival-rate executor effectively generates a steady request rate of 500 requests per second. This configuration is suitable for maintaining a consistent load during the test duration.

vendors/drpc.go (1)

67-82: Verify that all possible error message variations are adequately handled.

Ensure that the string checks for error messages cover all relevant variations that might be returned by the API, to prevent any unhandled exceptions.

Would you like assistance in creating a comprehensive list of error messages and handling them accordingly?

common/evm_json_rpc.go (2)

8-10: Ensure proper error handling after removing error return value.

The function NormalizeEvmHttpJsonRpc no longer returns an error. Confirm that all internal errors are managed appropriately within the function to prevent unintended behavior.


62-76: Verify parameter indexing for the eth_getStorageAt method.

Ensure that accessing jrq.Params[2] aligns with the expected parameter structure for eth_getStorageAt. Confirm that parameters are correctly indexed and normalized according to the method's specification.

common/response.go (1)

218-219: ⚠️ Potential issue

Remove Unmatched RUnlock() Call

In the EvmBlockNumber() method, there is an r.RUnlock() call without a preceding r.RLock(). This can cause a runtime error due to unlocking an unlocked mutex. Ensure that every unlock operation is matched with a corresponding lock.

Apply this diff to remove the unnecessary unlock:

func (r *NormalizedResponse) EvmBlockNumber() (int64, error) {
	if r == nil {
		return 0, nil
	}

	if n := r.evmBlockNumber.Load(); n != 0 {
		return n, nil
	}
-	r.RUnlock()

	if r.request == nil {
		return 0, nil
	}

	// Remaining code...
}

Likely invalid or redundant comment.

common/request.go (2)

253-253: Ensure SonicCfg is thread-safe

At line 253, SonicCfg.Unmarshal is used for unmarshalling JSON data. Confirm that SonicCfg is configured for thread-safe operations to prevent potential data races.


116-116: Changing the return type of Id() may break existing code

The method Id() has changed its return type from string to int64. This is a breaking change that could affect any code that relies on Id() returning a string.

Please ensure that all usages of Id() are updated accordingly throughout the codebase.

Run the following script to find all occurrences of Id() and verify their usage:

erpc/evm_json_rpc_cache.go (7)

11-11: Importing the util package is appropriate

The addition of "github.com/erpc/erpc/util" is necessary for utilizing the new utility functions such as Mem2Str and Str2Mem introduced in this file.


65-67: Appropriate use of read lock on rpcReq

Adding rpcReq.RLock() and defer rpcReq.RUnlock() ensures thread-safe access to rpcReq within the Get method. This is good practice if rpcReq is subject to concurrent reads.


104-108: Efficient handling of JSON-RPC response

Using util.Str2Mem(resultString) optimizes memory usage by avoiding unnecessary allocations when setting jrr.Result. Also, setting the ID with jrr.SetID(rpcReq.ID) ensures that the response ID matches the request ID, which is essential for correct client-server communication. Error handling is properly implemented.


130-130: Consistent renaming to shouldCacheResponse

Renaming the function to shouldCacheResponse improves clarity by explicitly indicating that it determines whether the response should be cached. Ensure that all references to this function are updated throughout the codebase to prevent any inconsistencies.


192-192: Proper conversion before caching the response

Converting rpcResp.Result to a string using util.Mem2Str before caching ensures that the data is stored in a consistent format. This is important for reliable retrieval and use of cached responses.


Line range hint 195-249: Improved function naming and consistency in shouldCacheResponse

The renaming of shouldCache to shouldCacheResponse enhances readability and clarity of the codebase, making it explicit that the function determines caching based on the response. The logic within the function remains consistent and aligns with the caching strategy.


268-268: Simplification of shouldCacheForBlock function

The shouldCacheForBlock function now directly returns the result of c.network.EvmIsBlockFinalized(blockNumber), simplifying the code by removing unnecessary error handling. Ensure that any potential errors from EvmIsBlockFinalized are appropriately handled by the calling functions to prevent unintended behavior.

To verify error handling at call sites, you can run:

✅ Verification successful

Error Handling Verified in shouldCacheForBlock Callers

All callers of shouldCacheForBlock properly handle potential errors, ensuring no unintended behavior arises from the removal of error handling within the function.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that callers of `shouldCacheForBlock` handle errors appropriately.

# Find all calls to `shouldCacheForBlock` and display their context.

rg -A 3 -B 1 'shouldCacheForBlock\('

Length of output: 823

common/evm_block_ref.go (4)

90-92: Reuse the block hash length constant for consistency

To maintain consistency, use the previously defined BlockHashHexLength constant here as well.


115-117: Use the block hash length constant instead of magic number

Replace 66 with BlockHashHexLength to enhance code clarity and prevent potential errors if the block hash length changes.


187-193: Replace magic number with block hash length constant

For consistency and maintainability, use the BlockHashHexLength constant instead of 66 when checking block hash lengths.


266-267: Ensure block reference derivation is reliable

When blockRef is empty but blockNumber is available, the code assigns blockRef = strconv.FormatInt(blockNumber, 10). Confirm that representing the block reference as a decimal string of the block number aligns with the expected format elsewhere in the system.

Run the following script to identify usages of blockRef and ensure they're compatible with decimal block numbers:

upstream/failsafe.go (4)

Line range hint 69-74: Approved: Addition of Hedge Policy

The inclusion of the hedge policy in the CreateFailSafePolicies function is correctly implemented. The error handling and policy appending are properly handled.


Line range hint 190-217: Approved: Implementation of Hedge Policy Function

The createHedgePolicy function is well-implemented, including proper parsing of configuration values and error handling. The use of builder.OnHedge provides valuable control over hedging behavior.


269-271: Approved: Correct Handling of Client Errors

The retry policy correctly avoids retrying on client-side errors by using common.IsClientError(err), ensuring that invalid requests are not retried unnecessarily.


354-361: Approved: Preventing Retries for Write Methods

The addition properly prevents retries for write methods, which is important to maintain idempotency and avoid unintended side effects on state-changing operations.

common/json_rpc.go (3)

294-307: Consider Mutex Lock Ordering to Prevent Deadlocks

In MarshalZerologObject, multiple mutexes (resultMu, errMu) are locked separately. To prevent potential deadlocks, ensure consistent lock ordering across methods that use these mutexes.

Review the codebase to confirm that all methods acquiring these mutexes do so in the same order.


590-609: Consistent Use of Error Codes in TranslateToJsonRpcException

Ensure that all internal errors are translated to appropriate JSON-RPC error codes. Review the mapping of internal error codes to JSON-RPC error responses for completeness.

Verify that all possible internal error codes are correctly mapped, and consider adding unit tests to cover these cases.


477-484: ⚠️ Potential issue

Incorrect Method Receiver in MarshalZerologObject

The method MarshalZerologObject is defined with a receiver of *JsonRpcResponse but accesses fields (Method, Params, ID) that belong to JsonRpcRequest. This suggests that the receiver should be *JsonRpcRequest instead.

Apply this diff to correct the receiver type:

-func (r *JsonRpcResponse) MarshalZerologObject(e *zerolog.Event) {
+func (r *JsonRpcRequest) MarshalZerologObject(e *zerolog.Event) {
     if r == nil {
         return
     }

-    r.RLock()
-    defer r.RUnlock()
+    r.RLock()
+    defer r.RUnlock()

     e.Str("method", r.Method).
         Interface("params", r.Params).
         Interface("id", r.ID)
 }

Likely invalid or redundant comment.

erpc/http_server.go (2)

85-85: ⚠️ Potential issue

Ensure that disabling HTML escaping does not introduce XSS vulnerabilities

Disabling HTML escaping with encoder.SetEscapeHTML(false) can pose security risks if untrusted data is included in the response, potentially leading to XSS attacks. Please verify that all data written to the response is properly sanitized and does not include untrusted input.


483-485: ⚠️ Potential issue

Ensure error 'data' field does not expose sensitive information

Including jre.Details["data"] in the error response may unintentionally expose sensitive information to the client. Please verify that the data included is safe to share and does not contain confidential or internal details.

common/config.go (4)

380-383: Good addition: Prevent nil pointer dereferences in NetworkId().

Adding checks for c.Architecture and c.Evm in the NetworkId() method enhances robustness by ensuring that nil pointers are not dereferenced.


448-452: Verify the increased circuit breaker failure thresholds.

The FailureThresholdCount has been increased to 800 with a capacity of 1000. This change significantly alters when the circuit breaker will trip. Please ensure these new thresholds align with the desired failure tolerance and system resilience.

You can verify the impact of these thresholds by reviewing their usage and testing under simulated failure conditions.


480-495: Approved: Added NetworkDefaultFailsafeConfig for default failsafe settings.

Introducing NetworkDefaultFailsafeConfig centralizes the default failsafe configurations for networks, improving maintainability and consistency across the application.


497-516: Good practice: Added validation in NetworkConfig.UnmarshalYAML().

The validation ensures that Architecture is specified and that Evm configuration is present when Architecture is "evm". This prevents misconfigurations and potential runtime errors.

upstream/upstream.go (4)

146-146: Improved error message for clarity

The error message has been updated to "failed to unmarshal json-rpc request," which provides clearer communication and maintains consistent terminology.


290-294: Ensure sensitive data is not logged

Including resp in the debug log at trace level may expose sensitive information. Verify that logging the response does not compromise any sensitive data.


395-400: Improved error handling in EvmGetChainId

The changes enhance clarity by introducing a dedicated chainId variable and maintain consistent error handling after unmarshalling the result.


Line range hint 506-516: Efficient caching of method support results

The caching logic in shouldHandleMethod improves performance by storing method support results. This change ensures that method checks are efficient and thread-safe using proper synchronization.

erpc/http_server_test.go (2)

775-841: ⚠️ Potential issue

Remove duplicate definitions of createServerTestFixtures function

The createServerTestFixtures function is defined multiple times in the file. This will cause a compilation error and can lead to confusion. Please remove the duplicate definitions, keeping only one definition.

Apply this diff to fix the issue:

- // Duplicate definition of createServerTestFixtures function starting here
- func createServerTestFixtures(cfg *common.Config, t *testing.T) (
- 	func(body string, headers map[string]string, queryParams map[string]string) (int, string),
- 	string,
- ) {
- 	// Function body...
- }
- // Duplicate definition ends here

Likely invalid or redundant comment.


616-723: ⚠️ Potential issue

Ensure unique test names and avoid code duplication

The TestHttpServer_MultipleUpstreams function appears to be duplicated in the code. Duplicate test functions with the same name will cause compilation errors and can lead to confusion during test execution. Please remove the duplicate and ensure each test function has a unique name.

Apply this diff to fix the issue:

- // Remove duplicate TestHttpServer_MultipleUpstreams function
- func TestHttpServer_MultipleUpstreams(t *testing.T) {
-     // Function body...
- }

Likely invalid or redundant comment.

common/errors.go (6)

98-98: Ensure SonicCfg is properly initialized

The use of SonicCfg.Marshal instead of sonic.Marshal requires that SonicCfg is correctly configured before serialization. Verify that SonicCfg is properly initialized to prevent potential runtime errors during marshaling.


159-159: Consistent use of SonicCfg.Marshal for error serialization

The replacement of sonic.Marshal with SonicCfg.Marshal ensures consistent serialization using a custom configuration. This enhances control over the marshaling process.

Also applies to: 167-167, 175-175, 187-187


976-984: Addition of cause parameter enhances error context

The NewErrUpstreamHedgeCancelled function now includes a cause parameter, providing better context for the cancellation reason. This improves error tracing and debugging.


1349-1362: Definition of ErrEndpointTransportFailure is appropriate

The new ErrEndpointTransportFailure error type correctly represents failures in sending requests to remote endpoints, enhancing error categorization.


1452-1474: Introduction of ErrEndpointRequestTooLarge improves error specificity

Adding ErrEndpointRequestTooLarge and the TooLargeComplaint type provides more detailed feedback on large request errors, aiding in precise error handling.


1571-1571: Including Data field aligns with JSON-RPC error standards

Adding the Data field to ErrJsonRpcExceptionExternal allows for additional context in error responses, adhering to the JSON-RPC specification.

Comment on lines +9 to +11
func RandomID() int64 {
return int64(rand.Intn(math.MaxInt32)) // #nosec G404
}
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Issue Found: Missing Random Seed Initialization

No rand.Seed() calls found in the codebase. To ensure proper randomness, consider initializing the random number generator, for example, in an init() function or at the program start.

🔗 Analysis chain

LGTM: Implementation is correct, but consider random seed initialization.

The function correctly generates a random number within the 32-bit range as described. The use of math/rand is acknowledged with the #nosec G404 comment.

To ensure proper randomness, verify that the random number generator is seeded elsewhere in the codebase:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for rand.Seed() calls in the codebase

# Test: Search for rand.Seed() calls
rg 'rand\.Seed\('

# If no results, it might be worth adding a seed initialization
if [ $? -ne 0 ]; then
  echo "No rand.Seed() calls found. Consider adding one in an init() function or at program start."
fi

Length of output: 228

args: -exclude-dir=test -tests=false ./...
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Review the Codecov step modification

The Upload coverage reports to Codecov step has been modified to use args instead of token. This change appears to be incorrect and may prevent proper coverage reporting.

The current modification:

  1. Removes the necessary Codecov token.
  2. Applies arguments that are likely intended for the Gosec Security Scanner, not Codecov.

Please consider reverting this change and using the correct Codecov configuration:

      - name: Upload coverage reports to Codecov
        uses: codecov/[email protected]
        with:
          token: ${{ secrets.CODECOV_TOKEN }}

If you need to pass additional arguments to Codecov, please refer to the Codecov GitHub Action documentation for the correct syntax and available options.

@@ -10,7 +10,7 @@ import (
func RedactEndpoint(endpoint string) string {
// Calculate hash of the entire original endpoint
hasher := sha256.New()
hasher.Write([]byte(endpoint))
hasher.Write(Str2Mem(endpoint))
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Add tests for Str2Mem to ensure its safety and correctness

The Str2Mem function uses unsafe operations and currently lacks tests. To prevent potential memory safety issues and ensure it handles all input cases correctly, please:

  1. Implement comprehensive unit tests for Str2Mem, covering edge cases such as empty strings and Unicode characters.
  2. Review the use of unsafe.Pointer to ensure memory safety is not compromised.
🔗 Analysis chain

Verify the safety and correctness of Str2Mem

The change from []byte(endpoint) to Str2Mem(endpoint) likely aims to improve performance. However, please ensure that:

  1. Str2Mem correctly handles all possible input strings, including edge cases like empty strings and Unicode characters.
  2. The use of unsafe operations (if any) in Str2Mem doesn't introduce memory safety issues.

Consider adding a comment explaining why Str2Mem is used here instead of the standard conversion.

To verify the correctness of this change, please run the following script:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the implementation of Str2Mem and its usage

# Test 1: Find the implementation of Str2Mem
echo "Str2Mem implementation:"
rg -p "func Str2Mem" -A 10

# Test 2: Check for any unsafe operations in Str2Mem
echo "\nChecking for unsafe operations:"
rg "unsafe\." -A 5 -B 5

# Test 3: Look for existing tests of Str2Mem
echo "\nExisting tests for Str2Mem:"
rg "func Test.*Str2Mem" -A 10

# Test 4: Check for other usages of Str2Mem in the codebase
echo "\nOther usages of Str2Mem:"
rg "Str2Mem\(" -g '!*test*'

Length of output: 3254

Comment on lines +23 to +27
- name: Fetch multi-platform package version SHAs
id: multi-arch-digests
run: |
erpc=$(docker manifest inspect ghcr.io/erpc/erpc | jq -r '.manifests.[] | .digest' | paste -s -d ' ' -)
echo "multi-arch-digests=$erpc" >> $GITHUB_OUTPUT
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix potential word splitting in SHA fetching step

The current shell script may be prone to word splitting issues. Consider using double quotes to prevent this.

Apply this diff to fix the potential word splitting issue:

- erpc=$(docker manifest inspect ghcr.io/erpc/erpc | jq -r '.manifests.[] | .digest' | paste -s -d ' ' -)
- echo "multi-arch-digests=$erpc" >> $GITHUB_OUTPUT
+ erpc=$(docker manifest inspect ghcr.io/erpc/erpc | jq -r '.manifests.[] | .digest' | paste -s -d ' ' -)
+ echo "multi-arch-digests=\"$erpc\"" >> $GITHUB_OUTPUT
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Fetch multi-platform package version SHAs
id: multi-arch-digests
run: |
erpc=$(docker manifest inspect ghcr.io/erpc/erpc | jq -r '.manifests.[] | .digest' | paste -s -d ' ' -)
echo "multi-arch-digests=$erpc" >> $GITHUB_OUTPUT
- name: Fetch multi-platform package version SHAs
id: multi-arch-digests
run: |
erpc=$(docker manifest inspect ghcr.io/erpc/erpc | jq -r '.manifests.[] | .digest' | paste -s -d ' ' -)
echo "multi-arch-digests=\"$erpc\"" >> $GITHUB_OUTPUT
🧰 Tools
🪛 actionlint

25-25: shellcheck reported issue in this script: SC2086:info:2:36: Double quote to prevent globbing and word splitting

(shellcheck)

Comment on lines +132 to +137
cids, err := jrr.PeekStringByPath()
if err != nil {
return false, err
}

cidh, err := common.NormalizeHex(cids)
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

🛠️ Refactor suggestion

Potential Misuse of PeekStringByPath() Without Specifying a Path

The PeekStringByPath() method is called without any arguments in upstream/envio_http_json_rpc_client.go. This usage might not correctly extract the intended chain ID from the JSON-RPC response.

  • Recommendation: Specify the appropriate path when calling PeekStringByPath() to ensure accurate extraction. For example:

    cids, err := jrr.PeekStringByPath("result", "chainId")
    if err != nil {
        return false, fmt.Errorf("failed to extract chain ID: %w", err)
    }
🔗 Analysis chain

Verify the usage of PeekStringByPath() and consider improving error handling

The changes in extracting the chain ID from the JSON-RPC response raise a few concerns:

  1. The PeekStringByPath() method is called without any path argument. This might not be the intended usage, as typically you'd need to specify a path to extract a specific field from the JSON response.

  2. The error handling for PeekStringByPath() might hide underlying issues if it fails. Consider logging the error or passing it up the call stack for better debugging.

To ensure the correctness of this change, please run the following verification:

Consider refactoring the chain ID extraction as follows:

cids, err := jrr.PeekStringByPath("result")
if err != nil {
    return false, fmt.Errorf("failed to extract chain ID: %w", err)
}

This assumes that the chain ID is in the "result" field of the JSON-RPC response. Adjust the path as necessary based on the actual response structure.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of PeekStringByPath in the codebase

# Test: Search for other usages of PeekStringByPath to compare
rg -A 5 'PeekStringByPath'

# Test: Check the JsonRpcResponse type definition
rg -A 10 'type JsonRpcResponse'

Length of output: 8355

Comment on lines +939 to +941
func (e *ErrUpstreamMethodIgnored) ErrorStatusCode() int {
return http.StatusUnsupportedMediaType
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Evaluate the use of HTTP status code 415

The ErrorStatusCode() method returns http.StatusUnsupportedMediaType (415). Since ErrUpstreamMethodIgnored pertains to ignored methods, consider using http.StatusMethodNotAllowed (405) to more accurately reflect the nature of the error.

Comment on lines +1686 to +1690

func IsClientError(err error) bool {
return err != nil && (HasErrorCode(err, ErrCodeEndpointClientSideException) ||
HasErrorCode(err, ErrCodeJsonRpcRequestUnmarshal))
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Review error codes in IsClientError function

The IsClientError function checks for ErrCodeEndpointClientSideException and ErrCodeJsonRpcRequestUnmarshal. Consider including other client-side error codes, such as ErrCodeJsonRpcRequestUnresolvableMethod, to ensure comprehensive client error detection.

Comment on lines +1014 to +1029
if _, ok := cause.(*BaseError); ok {
return &ErrJsonRpcRequestUnmarshal{
BaseError{
Code: ErrCodeJsonRpcRequestUnmarshal,
Message: "failed to unmarshal json-rpc request",
Cause: cause,
},
}
} else if cause != nil {
return &ErrJsonRpcRequestUnmarshal{
BaseError{
Code: ErrCodeJsonRpcRequestUnmarshal,
Message: fmt.Sprintf("%s", cause),
},
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Ensure consistent error messages in NewErrJsonRpcRequestUnmarshal

When cause is not nil, the error message is set to the cause's string representation. This may lead to inconsistent messages. Consider setting a standard error message and assigning cause to the Cause field for consistency.

Apply this diff to standardize the error message:

} else if cause != nil {
	return &ErrJsonRpcRequestUnmarshal{
		BaseError{
			Code:    ErrCodeJsonRpcRequestUnmarshal,
-			Message: fmt.Sprintf("%s", cause),
+			Message: "failed to unmarshal json-rpc request",
+			Cause:   cause,
		},
	}
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if _, ok := cause.(*BaseError); ok {
return &ErrJsonRpcRequestUnmarshal{
BaseError{
Code: ErrCodeJsonRpcRequestUnmarshal,
Message: "failed to unmarshal json-rpc request",
Cause: cause,
},
}
} else if cause != nil {
return &ErrJsonRpcRequestUnmarshal{
BaseError{
Code: ErrCodeJsonRpcRequestUnmarshal,
Message: fmt.Sprintf("%s", cause),
},
}
}
if _, ok := cause.(*BaseError); ok {
return &ErrJsonRpcRequestUnmarshal{
BaseError{
Code: ErrCodeJsonRpcRequestUnmarshal,
Message: "failed to unmarshal json-rpc request",
Cause: cause,
},
}
} else if cause != nil {
return &ErrJsonRpcRequestUnmarshal{
BaseError{
Code: ErrCodeJsonRpcRequestUnmarshal,
Message: "failed to unmarshal json-rpc request",
Cause: cause,
},
}
}

@@ -218,13 +221,13 @@ func TestNetwork_Forward(t *testing.T) {
t.Run("ForwardUpstreamRetryIntermittentFailuresWithoutSuccessAndNoErrCode", func(t *testing.T) {
defer gock.Off()

var requestBytes = json.RawMessage(`{"jsonrpc":"2.0","id":1,"method":"eth_traceTransaction","params":["0x1273c18",false]}`)
var requestBytes = []byte(`{"jsonrpc":"2.0","id":1,"method":"eth_traceTransaction","params":["0x1273c18",false]}`)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor repeated requestBytes declarations into helper functions

The requestBytes variable is declared multiple times across different tests with similar or identical JSON payloads. To improve code maintainability and reduce duplication, consider refactoring these repeated declarations into helper functions or constants.

You can define a helper function or constant for the common request payloads, like so:

func newTraceTransactionRequestBytes() []byte {
	return []byte(`{"jsonrpc":"2.0","id":1,"method":"eth_traceTransaction","params":["0x1273c18",false]}`)
}

Then, in your tests, use:

var requestBytes = newTraceTransactionRequestBytes()

Also applies to: 328-328, 432-432, 576-576, 724-724, 911-911, 1286-1286, 1485-1485

Comment on lines +5674 to +5677
Delay(3 * time.Second).
BodyString(`{"jsonrpc":"2.0","id":4,"result":"0x1"}`)

totalRequests := 100
totalRequests := int64(100)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ensure mocked responses use dynamic IDs to match requests

In the JsonRpcIDConsistencyOnConcurrentRequests test, the mocked response currently returns a hardcoded ID of 4. Since each request has a unique ID, the mock should return the corresponding request ID to accurately test JSON-RPC ID consistency.

Consider modifying the mock to use ReplyFunc to dynamically set the response ID based on the incoming request's ID. This ensures that the response ID in the response matches the ID of each request, validating the consistency in your test.

@OBlackmon3 OBlackmon3 force-pushed the oblackmon3/rebase-polymer-develop-to-match-v0.0.25 branch from 572f721 to d5c66a0 Compare October 21, 2024 20:52
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: 4

🧹 Outside diff range and nitpick comments (17)
test/fake_server.go (1)

Line range hint 175-235: Enhanced request processing and error handling

The updates to processSingleRequest significantly improve the robustness of request processing. The method now correctly handles notifications (requests without an ID) as per the JSON-RPC 2.0 specification, and the simulation of different scenarios (rate limiting, failure) is more accurate.

Consider additional error handling for invalid params

While the method handles various scenarios well, it might be beneficial to add explicit handling for invalid params.

Consider adding a check for invalid params:

 if req.Jsonrpc != "2.0" || req.Method == "" {
     // ... existing error handling ...
 }
+if req.Params == nil {
+    return &JSONRPCResponse{
+        Jsonrpc: "2.0",
+        Error:   map[string]interface{}{"code": -32602, "message": "Invalid params"},
+        ID:      req.ID,
+    }
+}

This addition would provide more specific error feedback for requests with missing or invalid params.

erpc/networks.go (1)

25-26: Consider documenting the purpose of evmStatePollers

The new evmStatePollers field has been added to the Network struct. It would be helpful to add a comment explaining its purpose and how it's used within the network operations.

common/json_rpc.go (6)

60-81: Efficient NewJsonRpcResponseFromBytes function added

The new NewJsonRpcResponseFromBytes function is a valuable addition, allowing for efficient creation of JsonRpcResponse objects from raw byte data. This can potentially improve performance in scenarios where responses are received as byte streams.

Consider adding error handling for the case where both resultRaw and errBytes are empty, as this might indicate an invalid response.


83-121: Comprehensive ID parsing in parseID method

The parseID method effectively handles various ID types and edge cases, including numeric strings. However, the error handling for the final marshaling step could be improved.

Consider wrapping the error returned from SonicCfg.Marshal(r.id) with additional context:

- return err
+ return fmt.Errorf("failed to marshal parsed ID: %w", err)

This will provide more informative error messages if marshaling fails.


165-208: Memory-efficient ParseFromStream method with room for improvement

The ParseFromStream method efficiently parses a JSON-RPC response using ast.Searcher, which avoids loading the entire response into memory. This is a significant improvement for handling large responses.

However, the method doesn't handle the case where neither "result" nor "error" fields are present in the response. Consider adding an explicit error for this case:

 } else if err := r.ParseError(util.Mem2Str(data)); err != nil {
     return err
 }
+} else {
+    return fmt.Errorf("invalid JSON-RPC response: missing both result and error fields")
 }

This will ensure that invalid responses are properly handled and reported.


210-275: Robust error parsing with increased complexity

The ParseError method has been significantly improved to handle various error formats, including non-standard structures. This enhancement increases the robustness of error handling in the system.

However, the increased complexity might make future maintenance more challenging. Consider refactoring the special case handling into separate helper functions to improve readability and maintainability. For example:

func (r *JsonRpcResponse) ParseError(raw string) error {
    r.errMu.Lock()
    defer r.errMu.Unlock()

    r.errBytes = nil

    if err := r.parseStandardError(raw); err == nil {
        return nil
    }

    if err := r.parseSpecialCase1(raw); err == nil {
        return nil
    }

    if err := r.parseSpecialCase2(raw); err == nil {
        return nil
    }

    // Default case
    r.Error = NewErrJsonRpcExceptionExternal(
        int(JsonRpcErrorServerSideException),
        raw,
        "",
    )
    return nil
}

This structure would make the main method more readable and easier to extend with new special cases in the future.


342-397: Efficient GetReader method with room for improvement

The new GetReader method is an excellent addition, providing a custom implementation for marshalling JSON-RPC responses with minimal memory allocations. The use of io.MultiReader is a smart choice for performance optimization.

Consider the following improvements:

  1. Error handling: The error from SonicCfg.Marshal(r.Error) is properly handled, but you might want to add context to the error message.

  2. Resource management: Consider using a sync.Pool for the slice of readers to reduce allocations in high-frequency scenarios.

Example implementation for point 1:

- return nil, err
+ return nil, fmt.Errorf("failed to marshal error: %w", err)

428-475: Comprehensive UnmarshalJSON method with room for improvement

The new UnmarshalJSON method for JsonRpcRequest effectively handles various ID types and edge cases. However, the ID parsing logic is complex and contains some duplication. Consider refactoring this method to improve readability and maintainability:

  1. Extract the ID parsing logic into a separate method, similar to the parseID method in JsonRpcResponse.
  2. Use a switch statement instead of nested if-else blocks for cleaner code structure.

Here's a suggested refactoring:

func (r *JsonRpcRequest) parseID(rawID json.RawMessage) error {
    if rawID == nil {
        r.ID = util.RandomID()
        return nil
    }

    var id interface{}
    if err := SonicCfg.Unmarshal(rawID, &id); err != nil {
        return err
    }

    switch v := id.(type) {
    case float64:
        r.ID = int64(v)
    case string:
        if v == "" {
            r.ID = util.RandomID()
        } else {
            parsedID, err := strconv.ParseInt(v, 10, 64)
            if err != nil {
                return err
            }
            r.ID = parsedID
        }
    case nil:
        r.ID = util.RandomID()
    default:
        r.ID = util.RandomID()
    }

    if r.ID == 0 {
        r.ID = util.RandomID()
    }

    return nil
}

func (r *JsonRpcRequest) UnmarshalJSON(data []byte) error {
    type Alias JsonRpcRequest
    aux := &struct {
        *Alias
        ID json.RawMessage `json:"id,omitempty"`
    }{
        Alias: (*Alias)(r),
    }
    aux.JSONRPC = "2.0"

    if err := SonicCfg.Unmarshal(data, &aux); err != nil {
        return err
    }

    return r.parseID(aux.ID)
}

This refactoring separates concerns, reduces nesting, and makes the code more maintainable.

upstream/http_json_rpc_client.go (3)

172-182: LGTM! Enhanced logging for better observability.

The addition of detailed logging in the queueRequest method significantly improves the observability of batch processing. This will be valuable for debugging and monitoring.

Consider using structured logging (e.g., adding fields like batchSize instead of formatting them into the message) for easier parsing and analysis of logs.


Line range hint 204-274: LGTM! Improved batch processing with better logging and error handling.

The enhancements to the processBatch method, including additional logging and improved error handling, are excellent improvements. The use of common.SonicCfg.Marshal for JSON marshaling ensures consistency across the project.

Consider wrapping the error returned from http.NewRequestWithContext with additional context about the batch processing to make debugging easier.


Line range hint 579-821: LGTM! Greatly improved error handling and categorization.

The extensive additions to the extractJsonRpcError function significantly improve error handling and categorization. This will provide more meaningful and specific error responses, aiding in debugging and error management.

Consider refactoring some of the longer condition checks (e.g., lines 722-725, 748-751) into separate helper functions for improved readability and maintainability.

erpc/http_server_test.go (3)

725-773: Good start on integration tests, consider expanding

The addition of TestHttpServer_IntegrationTests is a valuable step towards ensuring the system works correctly as a whole. The test case for an unsupported method with DRPC is a good start.

Consider adding more integration test cases in the future to cover a wider range of scenarios and increase the overall test coverage.


Line range hint 843-909: Remove duplicate createServerTestFixtures function

There's an exact duplicate of the createServerTestFixtures function in the file. This duplication should be removed to avoid confusion and maintain code cleanliness.

Please remove this duplicate function implementation.


Line range hint 1-1007: Overall improvements to test coverage and reliability

The changes to this file significantly enhance the test suite for the HTTP server. New test functions for multiple upstreams and integration tests improve coverage, while adjustments to timeouts and configurations likely increase test reliability.

However, there are duplicate functions that need to be removed:

  1. A duplicate createServerTestFixtures function
  2. A duplicate TestHttpServer_MultipleUpstreams function

Once these duplications are addressed, the test file will be in excellent shape, providing comprehensive coverage of various scenarios and edge cases.

Please remove the identified duplicate functions to finalize these improvements.

erpc/networks_test.go (3)

Line range hint 37-40: Consider using a constant for the TRUE value.

The TRUE variable is defined as a global variable. It might be better to define it as a constant for clarity and to prevent accidental modification.

Consider changing the declaration to:

-var TRUE = true
+const TRUE = true

Line range hint 42-1275: TestNetwork_Forward function is comprehensive but could be split for better readability.

The TestNetwork_Forward function is quite long and contains multiple sub-tests. While it's good to have comprehensive tests, the function's length might make it difficult to maintain and understand.

Consider splitting this function into multiple smaller test functions, each focusing on a specific aspect of the Network's Forward functionality. This would improve readability and make it easier to maintain and extend the tests in the future.

For example, you could have separate test functions for:

  • Rate limiting scenarios
  • Error handling and retries
  • Caching behavior
  • Concurrent request handling

Each of these could be a separate function with its own sub-tests.


Line range hint 1891-1909: setupMocksForEvmStatePoller function could be more flexible.

While the setupMocksForEvmStatePoller function serves its purpose, it uses hardcoded values for the mock responses.

Consider parameterizing this function to allow for more flexible testing scenarios. For example:

func setupMocksForEvmStatePoller(blockNumber string) {
    // ... use blockNumber in the mock responses ...
}

This would allow tests to use different block numbers without modifying the function.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 572f721 and d5c66a0.

📒 Files selected for processing (10)
  • .github/workflows/test.yml (2 hunks)
  • common/errors.go (14 hunks)
  • common/json_rpc.go (4 hunks)
  • common/request.go (12 hunks)
  • common/response.go (6 hunks)
  • erpc/http_server_test.go (7 hunks)
  • erpc/networks.go (11 hunks)
  • erpc/networks_test.go (80 hunks)
  • test/fake_server.go (4 hunks)
  • upstream/http_json_rpc_client.go (22 hunks)
🧰 Additional context used
🪛 actionlint
.github/workflows/test.yml

6-6: label "large" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-14.0", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-13.0", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "macos-12.0", "macos-11", "macos-11.0", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)

🔇 Additional comments (47)
.github/workflows/test.yml (2)

28-28: ⚠️ Potential issue

Fix Codecov configuration

The Codecov step configuration has been incorrectly modified. The token input has been replaced with args, and the value is identical to the Gosec Security Scanner step. This will prevent Codecov from authenticating and uploading the coverage report.

Please revert this change and use the correct Codecov configuration:

      - name: Upload coverage reports to Codecov
        uses: codecov/[email protected]
        with:
          token: ${{ secrets.CODECOV_TOKEN }}

If you need to pass additional arguments to Codecov, please refer to the Codecov GitHub Action documentation for the correct syntax and available options.


6-6: Verify the runner label "large"

The runs-on value has been changed to large, which is not a standard GitHub-hosted runner label. This change might be intentional if you're using a custom self-hosted runner, but it could lead to workflow failures if not properly configured.

Please confirm one of the following:

  1. If "large" is a custom label for a self-hosted runner, ensure it's properly set up in your GitHub organization or repository settings.
  2. If you intended to use a GitHub-hosted runner with more resources, consider using one of the following labels instead:
    • ubuntu-latest-16-cores for a larger Ubuntu runner
    • windows-latest-8-cores for a larger Windows runner
    • macos-latest-xl or macos-latest-large for a larger macOS runner

To verify the available runners, you can run this script:

This will help ensure consistency across your workflows and prevent potential issues.

✅ Verification successful

Runner label "large" is consistently used across workflows

The "large" runner label appears in multiple workflow files, indicating it is likely a custom self-hosted runner. Ensure that the "large" runner is properly configured in your GitHub organization or repository settings to prevent workflow failures.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# List all workflow files and grep for 'runs-on' to see what runners are used across the repository
fd -e yml -e yaml . .github/workflows --exec grep -H 'runs-on:' {} \;

Length of output: 336

🧰 Tools
🪛 actionlint

6-6: label "large" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-14.0", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-13.0", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "macos-12.0", "macos-11", "macos-11.0", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)

test/fake_server.go (4)

136-156: Well-implemented batch request handling

The handleBatchRequest method is a solid implementation of batch request processing as per the JSON-RPC 2.0 specification. It correctly handles empty batch requests, processes each request individually, and efficiently collects and sends responses.


158-173: Efficient single request handling

The handleSingleRequest method is well-implemented. It correctly processes single JSON-RPC requests, sets appropriate headers, and efficiently determines the content length using a buffer before writing the response. The error handling is also appropriate.


237-249: Consistent error response handling

The sendErrorResponse method is a well-implemented utility for sending error responses. It correctly updates the server statistics and follows the JSON-RPC 2.0 specification for error response structure. This addition enhances the consistency of error handling across the server.


Line range hint 1-305: Overall improvements to FakeServer implementation

The changes to test/fake_server.go significantly enhance the functionality and robustness of the FakeServer. Key improvements include:

  1. Better handling of both batch and single JSON-RPC requests.
  2. More consistent and comprehensive error handling.
  3. Improved simulation of various scenarios (rate limiting, failures).
  4. Addition of large response generation for testing purposes.

These changes make the FakeServer more compliant with the JSON-RPC 2.0 specification and more useful for testing scenarios. The suggested improvements in the review comments will further enhance its reliability and effectiveness.

common/request.go (8)

5-5: LGTM: Import statements and constant declaration

The new import statements are appropriate for the changes made in the file. The constant declaration for RequestContextKey follows proper naming conventions.

Also applies to: 7-7, 10-10, 15-16


49-49: Improved thread-safety in NormalizedRequest struct

The changes to uid, lastValidResponse, and lastUpstream fields using atomic types enhance thread-safety by allowing concurrent access without explicit locking. This is a good improvement for concurrent operations.

Also applies to: 54-55


99-99: Thread-safe updates to SetLastValidResponse and LastValidResponse methods

The changes to use atomic.Pointer.Store() and atomic.Pointer.Load() provide thread-safe access to the lastValidResponse field. This is a good improvement for concurrent operations.

Also applies to: 106-106


190-193: Improved memory efficiency in ApplyDirectivesFromHttp

The consistent use of util.Mem2Str() instead of direct string conversions is a good change. This likely improves memory usage by avoiding unnecessary string allocations when working with fasthttp types.

Also applies to: 196-196, 200-200, 204-204, 208-208


299-299: Consistent use of memory-efficient operations and configured JSON marshaling

The changes in MarshalZerologObject and MarshalJSON methods are good:

  1. The use of util.Mem2Str() in MarshalZerologObject is consistent with other changes for memory efficiency.
  2. The use of SonicCfg.Marshal in MarshalJSON is consistent with the change in the JsonRpcRequest method, using the configured Sonic JSON parser.

These changes improve consistency and potentially performance across the codebase.

Also applies to: 340-342, 346-346


Line range hint 1-365: Summary of changes in common/request.go

The changes in this file significantly improve thread-safety and memory efficiency:

  1. Use of atomic types for concurrent access to shared fields.
  2. Consistent use of util.Mem2Str() for memory-efficient string operations.
  3. Use of a configured Sonic JSON parser for potentially improved JSON handling.

Most changes are improvements, but the Id method needs refactoring for consistency and simplicity. Overall, these changes enhance the robustness and performance of the NormalizedRequest struct and its methods.


253-253: Use of configured Sonic JSON parser

The change to use SonicCfg.Unmarshal instead of sonic.Unmarshal is good, as it likely uses a pre-configured instance of the Sonic JSON parser with specific settings.

To ensure the correct configuration is being used, please verify the SonicCfg setup:

Review the results to confirm that SonicCfg is properly configured for your use case.

✅ Verification successful

SonicCfg Configuration Properly Implemented

The SonicCfg is consistently used across the codebase, indicating proper configuration of the Sonic JSON parser.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for SonicCfg configuration
rg -n "SonicCfg" --type go

Length of output: 2635


Line range hint 116-170: Refactor Id method for consistency and simplicity

The Id method has undergone significant changes, but there are several issues to address:

  1. The change in return type from string to int64 may affect other parts of the codebase that expect a string ID.
  2. The parsing logic is complex and could be simplified.
  3. There's redundant locking and unlocking.
  4. The method doesn't handle all possible ID types consistently.

Consider refactoring the method as follows:

  1. Use a single atomic operation to get and set the ID.
  2. Simplify the parsing logic.
  3. Handle all ID types consistently.

Here's a suggested refactor:

func (r *NormalizedRequest) Id() int64 {
    if r == nil {
        return 0
    }

    if id := r.uid.Load(); id != nil {
        return id.(int64)
    }

    var newId int64
    if r.jsonRpcRequest != nil {
        newId = r.jsonRpcRequest.ID
    } else if len(r.body) > 0 {
        if idNode, err := sonic.Get(r.body, "id"); err == nil {
            switch v := idNode.Interface().(type) {
            case string:
                if parsed, err := strconv.ParseInt(v, 10, 64); err == nil {
                    newId = parsed
                }
            case float64:
                newId = int64(v)
            case int64:
                newId = v
            }
        }
    }

    r.uid.Store(newId)
    return newId
}

This refactored version:

  • Uses a single atomic operation to get and set the ID.
  • Simplifies the parsing logic.
  • Handles string, float64, and int64 ID types consistently.
  • Removes redundant locking.

To ensure this change doesn't break existing functionality, please run the following verification script:

Review the results to ensure that all callers of Id() can handle an int64 return type.

erpc/networks.go (8)

79-80: Reconsider logging pointer addresses

While logging the pointer address (fmt.Sprintf("%p", req)) can be useful for debugging, it might expose internal memory details. Consider if this level of detail is necessary for production logging, and if not, make it conditional based on a debug flag.


121-124: Consider re-throwing panics after logging

The panic recovery is a good practice, but simply logging the panic without re-throwing it might mask underlying issues. Consider re-throwing the panic after logging to ensure that the error is not silently ignored, as suggested in the existing comment.


221-224: LGTM: Improved context cancellation handling

The additional error checking for context cancellation enhances the robustness of the request handling process. This change ensures that the function promptly responds to cancellation signals, improving resource management.


246-250: LGTM: Enhanced response and hedged request handling

The additions improve error handling for response normalization and provide better insight into hedged request cancellations. These changes enhance the overall robustness and observability of the request processing pipeline.

Also applies to: 252-252, 255-257


367-370: LGTM: Improved null checks in EvmIsBlockFinalized

The addition of null checks for the network and evmStatePollers prevents potential nil pointer dereferences, enhancing the function's robustness and safety.


415-424: LGTM: Improved error handling in enrichStatePoller

The additional error checking for parsing block numbers and updating the state poller enhances the function's robustness. These changes align with the existing comment's suggestion to add nil checks before accessing upstream configurations.


435-435: LGTM: Improved error handling in normalizeResponse

The function now returns an error, and additional error handling has been added for setting the JSON-RPC response ID. These changes enhance the robustness of the response normalization process and align with the existing comment's suggestion to handle errors when obtaining JSON-RPC responses.

Also applies to: 441-448, 453-454


Line range hint 1-504: Overall improvements in error handling and robustness

The changes in this file significantly enhance error handling, null checks, and overall robustness of the network operations. The use of sync.Map for in-flight requests and the improvements in context and response handling are particularly noteworthy. While some potential issues were identified (such as logging pointer addresses and panic handling), the majority of the changes represent positive improvements to the codebase.

common/json_rpc.go (5)

22-45: Improved thread-safety and memory efficiency in JsonRpcResponse struct

The restructuring of the JsonRpcResponse struct with the addition of mutexes and byte slices for lazy loading is a significant improvement. This change enhances thread safety for concurrent access and potentially reduces memory usage, especially for large responses.


48-58: Improved type safety in NewJsonRpcResponse function

The change in the function signature to accept int64 for the ID improves type safety and aligns with the new JsonRpcResponse struct definition. This modification reduces the need for type assertions and potential runtime errors.


419-425: Improved type safety in JsonRpcRequest struct

The change of the ID field type from interface{} to int64 in the JsonRpcRequest struct is a positive improvement. This change enhances type safety, reduces the need for type assertions, and aligns with the modifications made to JsonRpcResponse. It should also lead to better performance and easier handling of request IDs throughout the codebase.


590-608: Enhanced error handling in TranslateToJsonRpcException

The additions to the TranslateToJsonRpcException function improve error handling by providing more specific JSON-RPC error codes for different types of errors. The new cases for ErrCodeUpstreamMethodIgnored and ErrCodeJsonRpcRequestUnmarshal allow for more precise error reporting, which should lead to easier debugging and better error handling for clients.

These changes align well with the JSON-RPC 2.0 specification and common practices for error handling in RPC systems.


Line range hint 1-624: Overall assessment: Significant improvements with minor suggestions for refinement

The changes made to common/json_rpc.go represent a substantial improvement to the codebase. Key enhancements include:

  1. Improved thread safety through the use of mutexes.
  2. Better memory efficiency with lazy loading and byte slice usage.
  3. Enhanced error handling with more specific error codes and robust parsing.
  4. New methods for efficient response creation and marshalling.

While the overall direction is very positive, there are a few areas where minor refinements could further improve the code:

  1. Some error handling could be more informative by adding context to returned errors.
  2. Complex methods like ParseError and UnmarshalJSON for JsonRpcRequest could benefit from refactoring for improved readability and maintainability.
  3. Consider adding more comprehensive input validation in some methods.

These suggestions aside, the changes significantly enhance the robustness and efficiency of the JSON-RPC handling in the system.

upstream/http_json_rpc_client.go (5)

Line range hint 14-18: LGTM! Improved JSON parsing and utility imports.

The switch to sonic/ast for JSON parsing and the addition of custom utility imports are good improvements. This change likely enhances the flexibility and performance of JSON handling in the client.


Line range hint 460-501: LGTM! Improved single request handling.

The changes to the sendSingleRequest method, including the use of common.SonicCfg.Marshal for JSON marshaling and the improved error handling, are good improvements. The chained method calls for creating the normalized response enhance readability.


838-853: LGTM! Improved handling of reverted transactions.

The addition of specific error handling for reverted transactions is a valuable improvement. This will help in identifying and properly handling these common scenarios in blockchain interactions.


Line range hint 1-857: Overall, excellent improvements to the HTTP JSON-RPC client.

The changes in this file significantly enhance the client's functionality, error handling, and observability. Key improvements include:

  1. Better batch processing and logging
  2. More comprehensive error handling and categorization
  3. Improved JSON parsing using AST
  4. Enhanced handling of reverted transactions

Please address the potential nil pointer dereference in the getJsonRpcResponseFromNode function and consider the suggested minor improvements for logging and code organization. These changes will further increase the robustness and maintainability of the client.


407-442: ⚠️ Potential issue

Good addition, but fix potential nil pointer dereference.

The new getJsonRpcResponseFromNode function is a good addition that leverages the AST-based parsing approach. However, there's a potential nil pointer dereference in the error handling case.

Fix the nil pointer dereference by initializing jrResp before using it:

 if rawResultErr != nil && rawErrorErr != nil {
-    var jrResp *common.JsonRpcResponse
+    jrResp := &common.JsonRpcResponse{}

     if rawID != "" {
         err := jrResp.SetIDBytes(util.Str2Mem(rawID))
         if err != nil {
             return nil, err
         }
     }

     cause := fmt.Sprintf("cannot parse json rpc response from upstream, for result: %s, for error: %s", rawResult, rawError)
-    jrResp = &common.JsonRpcResponse{
-        Result: util.Str2Mem(rawResult),
-        Error: common.NewErrJsonRpcExceptionExternal(
-            int(common.JsonRpcErrorParseException),
-            cause,
-            "",
-        ),
-    }
+    jrResp.Result = util.Str2Mem(rawResult)
+    jrResp.Error = common.NewErrJsonRpcExceptionExternal(
+        int(common.JsonRpcErrorParseException),
+        cause,
+        "",
+    )

     return jrResp, nil
 }

Likely invalid or redundant comment.

erpc/http_server_test.go (5)

38-38: Improved test reliability with adjusted timeouts

The changes to the MaxTimeout and mock response delays are likely to make the tests more stable and less prone to race conditions. This is a good improvement for test reliability.

Also applies to: 145-145, 154-154, 164-164, 176-176, 215-215


616-723: Excellent addition of multi-upstream test scenarios

The new TestHttpServer_MultipleUpstreams function significantly improves test coverage by including scenarios for multiple upstreams. It correctly tests upstream selection based on both headers and query parameters, which is crucial for the server's functionality.


775-841: Improved flexibility in test fixture creation

The updates to createServerTestFixtures enhance its flexibility and reusability. The new sendRequest function with support for headers and query parameters allows for more comprehensive testing of various request configurations.


Line range hint 911-1007: Remove duplicate TestHttpServer_MultipleUpstreams function

There's an exact duplicate of the TestHttpServer_MultipleUpstreams function at the end of the file. This duplication should be removed to avoid confusion and maintain code cleanliness.

This issue was previously identified in a past review comment. Please remove this duplicate function implementation.


291-293: ⚠️ Potential issue

Avoid in-place modification of shared configuration

Modifying the shared cfg variable in-place within the loop can cause unintended side effects between test cases, potentially leading to flaky tests. Consider creating a fresh copy of the cfg for each iteration to ensure test isolation.

Apply this diff to fix the issue:

 for _, applyCfgOverride := range cfgCases {
+    cfgCopy := *cfg // Create a shallow copy of cfg
+    applyCfgOverride(&cfgCopy)
+    sendRequest, baseURL := createServerTestFixtures(&cfgCopy, t)
-    applyCfgOverride(cfg)
-    sendRequest, baseURL := createServerTestFixtures(cfg, t)

Likely invalid or redundant comment.

erpc/networks_test.go (6)

Line range hint 1-35: Imports and package declaration look good.

The file starts with the appropriate package declaration and imports necessary packages for testing, including standard library packages and custom packages from the project. The import list is well-organized and doesn't contain any unused imports.


Line range hint 1277-1451: TestNetwork_InFlightRequests is well-structured with good coverage of concurrent scenarios.

This test function covers various scenarios for in-flight requests, including successful concurrent requests, failures, timeouts, and mixed success/failure cases. The use of goroutines and wait groups is appropriate for testing concurrent behavior.


Line range hint 1453-1720: Good coverage of edge cases in TestNetwork_InFlightRequests.

The additional test cases for JSON-RPC ID consistency, context cancellation, and long-running requests provide good coverage of important edge cases. The use of atomic operations and careful checking of in-flight request counts demonstrates attention to detail in concurrent scenarios.


Line range hint 1722-1889: setupTestNetwork helper function is well-designed.

The setupTestNetwork function provides a clean way to set up a test environment for the Network. It includes proper error checking and allows for customization of the upstream configuration.


Line range hint 1911-1920: Helper functions for gock management are useful.

The anyTestMocksLeft and resetGock functions provide useful utilities for managing the gock mocking library throughout the tests. This helps ensure clean test environments between runs.


Line range hint 1922-1930: safeReadBody function is a good utility for handling request bodies.

The safeReadBody function provides a safe way to read and reset the request body, which is useful for inspecting request contents in tests without interfering with subsequent operations.

common/response.go (1)

218-219: ⚠️ Potential issue

Remove unnecessary r.RUnlock() call in EvmBlockNumber()

In the EvmBlockNumber() method, there's a call to r.RUnlock() without a corresponding r.RLock(). This could lead to a runtime panic due to unlocking an unlocked mutex. Ensure that you acquire a read lock before unlocking, or remove the unnecessary r.RUnlock() call.

Apply this diff to fix the issue:

func (r *NormalizedResponse) EvmBlockNumber() (int64, error) {
	if r == nil {
		return 0, nil
	}

	if n := r.evmBlockNumber.Load(); n != 0 {
		return n, nil
	}
-	r.RUnlock()

	if r.request == nil {
		return 0, nil
	}
	// Rest of the code...
}

Likely invalid or redundant comment.

common/errors.go (3)

1349-1362: Introduction of 'ErrEndpointTransportFailure' improves error handling

The addition of the ErrEndpointTransportFailure error type enhances the granularity of error reporting for transport-related failures when communicating with remote endpoints.


1452-1474: Addition of 'ErrEndpointRequestTooLarge' with appropriate status code

The new ErrEndpointRequestTooLarge error type correctly handles scenarios where the remote endpoint indicates that the request is too large. Assigning the HTTP status code http.StatusRequestEntityTooLarge (413) in the ErrorStatusCode() method is appropriate for this error.


976-984: Ensure all calls to 'NewErrUpstreamHedgeCancelled' include the 'cause' parameter

The function NewErrUpstreamHedgeCancelled now accepts a cause parameter. Please verify that all invocations of this function are updated to pass the new argument to prevent any potential runtime errors.

Run the following script to identify any calls missing the cause parameter:

Comment on lines +107 to +134
// Read the request body
body, err := io.ReadAll(r.Body)
if err != nil {
fs.sendErrorResponse(w, nil, -32700, "Parse error")
return
}

// Try to unmarshal as a batch request
var batchReq []JSONRPCRequest
err = json.Unmarshal(body, &batchReq)
if err == nil {
// Handle batch request
fs.handleBatchRequest(w, batchReq)
return
}

// Try to unmarshal as a single request
var singleReq JSONRPCRequest
err = json.Unmarshal(body, &singleReq)
if err == nil {
// Handle single request
fs.handleSingleRequest(w, singleReq)
return
}

// Invalid JSON-RPC request
fs.sendErrorResponse(w, nil, -32600, "Invalid Request")
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improved request handling and error management

The changes to the handleRequest method significantly enhance the server's capability to process both batch and single JSON-RPC requests. The error handling is more robust and consistent with the use of sendErrorResponse.

Consider limiting the request body size

While the changes improve request handling, reading the entire request body without size limits could lead to potential Denial of Service (DoS) attacks.

Consider implementing a size limit for the request body. Here's a suggested implementation:

+const maxBodySize = 1 << 20 // 1MB

 // Read the request body
-body, err := io.ReadAll(r.Body)
+body, err := io.ReadAll(io.LimitReader(r.Body, maxBodySize))
 if err != nil {
     fs.sendErrorResponse(w, nil, -32700, "Parse error")
     return
 }
+if r.ContentLength > maxBodySize {
+    fs.sendErrorResponse(w, nil, -32600, "Request Entity Too Large")
+    return
+}

This change limits the body size to 1MB and returns an error for larger requests.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Read the request body
body, err := io.ReadAll(r.Body)
if err != nil {
fs.sendErrorResponse(w, nil, -32700, "Parse error")
return
}
// Try to unmarshal as a batch request
var batchReq []JSONRPCRequest
err = json.Unmarshal(body, &batchReq)
if err == nil {
// Handle batch request
fs.handleBatchRequest(w, batchReq)
return
}
// Try to unmarshal as a single request
var singleReq JSONRPCRequest
err = json.Unmarshal(body, &singleReq)
if err == nil {
// Handle single request
fs.handleSingleRequest(w, singleReq)
return
}
// Invalid JSON-RPC request
fs.sendErrorResponse(w, nil, -32600, "Invalid Request")
}
const maxBodySize = 1 << 20 // 1MB
// Read the request body
body, err := io.ReadAll(io.LimitReader(r.Body, maxBodySize))
if err != nil {
fs.sendErrorResponse(w, nil, -32700, "Parse error")
return
}
if r.ContentLength > maxBodySize {
fs.sendErrorResponse(w, nil, -32600, "Request Entity Too Large")
return
}
// Try to unmarshal as a batch request
var batchReq []JSONRPCRequest
err = json.Unmarshal(body, &batchReq)
if err == nil {
// Handle batch request
fs.handleBatchRequest(w, batchReq)
return
}
// Try to unmarshal as a single request
var singleReq JSONRPCRequest
err = json.Unmarshal(body, &singleReq)
if err == nil {
// Handle single request
fs.handleSingleRequest(w, singleReq)
return
}
// Invalid JSON-RPC request
fs.sendErrorResponse(w, nil, -32600, "Invalid Request")
}

Comment on lines +263 to +274
if txt, ok := sample.Response.Result.(string); ok {
if strings.HasPrefix(txt, "bigfake:") {
size, err := strconv.Atoi(txt[len("bigfake:"):])
fmt.Printf("Generating big response of size %d\n", size)
if err != nil {
return nil
}
// generate a random string with the size of the number
sample.Response.Result = make([]byte, size)
}
}

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improve large response generation

The addition of large response generation based on the "bigfake:" prefix is a useful feature for testing. However, there are a few areas that could be improved:

  1. Error handling: The error from strconv.Atoi is not being handled properly.
  2. Empty data: The generated byte slice is not filled with any data, which might not be realistic for testing.

Consider the following improvements:

 if txt, ok := sample.Response.Result.(string); ok {
     if strings.HasPrefix(txt, "bigfake:") {
         size, err := strconv.Atoi(txt[len("bigfake:"):])
-        fmt.Printf("Generating big response of size %d\n", size)
         if err != nil {
-            return nil
+            fmt.Printf("Invalid size in bigfake prefix: %v\n", err)
+            return &sample.Response
         }
+        fmt.Printf("Generating big response of size %d\n", size)
         // generate a random string with the size of the number
-        sample.Response.Result = make([]byte, size)
+        sample.Response.Result = make([]byte, size)
+        rand.Read(sample.Response.Result.([]byte))
     }
 }

These changes improve error handling and fill the generated byte slice with random data for more realistic testing.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if txt, ok := sample.Response.Result.(string); ok {
if strings.HasPrefix(txt, "bigfake:") {
size, err := strconv.Atoi(txt[len("bigfake:"):])
fmt.Printf("Generating big response of size %d\n", size)
if err != nil {
return nil
}
// generate a random string with the size of the number
sample.Response.Result = make([]byte, size)
}
}
if txt, ok := sample.Response.Result.(string); ok {
if strings.HasPrefix(txt, "bigfake:") {
size, err := strconv.Atoi(txt[len("bigfake:"):])
if err != nil {
fmt.Printf("Invalid size in bigfake prefix: %v\n", err)
return &sample.Response
}
fmt.Printf("Generating big response of size %d\n", size)
// generate a random string with the size of the number
sample.Response.Result = make([]byte, size)
rand.Read(sample.Response.Result.([]byte))
}
}

Comment on lines +76 to +77

r.lastUpstream.Store(upstream)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Thread-safe updates to SetLastUpstream and LastUpstream methods

The changes to use atomic.Value.Store() and atomic.Value.Load() provide thread-safe access to the lastUpstream field, which is a good improvement.

However, there's a redundant assignment in SetLastUpstream:

Remove the redundant assignment in SetLastUpstream:

 func (r *NormalizedRequest) SetLastUpstream(upstream Upstream) *NormalizedRequest {
     if r == nil {
         return r
     }
 
     r.lastUpstream.Store(upstream)
-    r.Lock()
-    defer r.Unlock()
-    r.lastUpstream = upstream
     return r
 }

Also applies to: 88-92

Comment on lines +768 to +769
reasons = append(reasons, fmt.Sprintf("%d user errors", client))
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Rename 'user errors' to 'client errors' in error summaries

In the SummarizeCauses method, the error summary uses "user errors" to represent client-side errors. For clarity and consistency, consider renaming it to "client errors" to accurately reflect the nature of these errors.

Apply this diff to make the change:

if client > 0 {
-    reasons = append(reasons, fmt.Sprintf("%d user errors", client))
+    reasons = append(reasons, fmt.Sprintf("%d client errors", client))
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
reasons = append(reasons, fmt.Sprintf("%d user errors", client))
}
reasons = append(reasons, fmt.Sprintf("%d client errors", client))
}

@OBlackmon3 OBlackmon3 closed this Oct 21, 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.

5 participants