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

e2e test network #233

Merged
merged 27 commits into from
Nov 28, 2024
Merged

e2e test network #233

merged 27 commits into from
Nov 28, 2024

Conversation

leonz789
Copy link
Contributor

@leonz789 leonz789 commented Nov 1, 2024

Description

This PR supports testutil/network to work properly with exocorenetwork.
It starts a exocore network with n in process nodes with n validators. We can write UT to do e2e test by interact with this in-process network.
And this PR has a bug fix for NST balance change fail caused by Inappropriate assetID configure.

  • lcoanetwork test framework
  • gentx, queryclient, ed25519
  • add test cases
  • docs

Notable Changes

  • testutil/netowrk/: e2e frameworkd
  • tests/e2e/: e2e test cases
    • bank/
    • oracle/: LST price update, NST balance change, slashing
  • x/oracle/: oracle NST blanceupdate bug fix

Closes #XXX

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced new querying methods for various components of the Exocore network.
    • Added functionality for sending transactions to Ethereum precompile contracts.
    • Implemented end-to-end testing suites for the bank and oracle modules, validating core functionalities like coin transfers and price creation.
  • Improvements

    • Enhanced error handling and logging for balance updates and slashing processes.
    • Streamlined price data handling by transitioning from big.Int to string types, simplifying the codebase.
  • Bug Fixes

    • Improved clarity in error messages related to signature verification and public key validation during transaction simulations.
  • Chores

    • Updated dependencies in the go.mod file for improved compatibility and functionality.
    • Removed outdated GitHub Actions workflows related to E2E testing.

These updates enhance user experience, improve system reliability, and ensure robust testing of critical functionalities.

Copy link
Contributor

coderabbitai bot commented Nov 1, 2024

Walkthrough

This pull request introduces significant changes across multiple files in the Exocore network, primarily focusing on the genesis state configuration and network management. A new file, genesis_data.go, establishes default genesis state variables for various modules, while updates to network.go and util.go enhance configuration management and genesis state initialization. Additional files implement new methods for querying and sending transactions, alongside modifications to existing structures and error handling. The changes collectively improve the handling of staking assets, network operations, and transaction processing.

Changes

File Change Summary
testutil/network/genesis_data.go New file defining default genesis state variables for modules, including constants and initialization logic.
testutil/network/network.go Updates to Config struct; added DepositedTokens, removed BondedTokens, and modified initialization logic. New methods for state height queries added.
testutil/network/network_test.go Removed norace build tag; modified IntegrationTestSuite configuration and updated waiting methods.
testutil/network/util.go Removed collectGenFiles; updated initGenFiles to accept more parameters. New functions for genesis state generation added.
x/oracle/keeper/nonce.go Enhanced error message in CheckAndIncreaseNonce method for better clarity.
precompiles/assets/assets_test.go Removed unnecessary fmt import; updated tests for asset precompiles.
x/oracle/keeper/keeper.go Introduced memoryStore struct for better state management in Keeper.
x/oracle/keeper/keeper_suite_test.go Updated resetSingle function to accept a keeper.Keeper parameter.
x/oracle/keeper/msg_server_create_price.go Refactored method calls to use Keeper interface directly, improving encapsulation.
x/oracle/keeper/msg_server_create_price_test.go Updated expected block heights and cache retrieval methods in tests.
x/oracle/keeper/msg_server_update_params.go Refactored context retrieval and cache handling to use Keeper methods.
x/oracle/keeper/params.go Updated cache and aggregator context handling in RegisterNewTokenAndSetTokenFeeder.
x/oracle/keeper/prices.go Updated methods to use k.memStore.agc for better encapsulation of state.
x/oracle/keeper/single.go Transitioned functions to instance methods for better state management.
x/oracle/module.go Refactored BeginBlock and EndBlock methods to use am.keeper.
crypto/algo_ed25519.go Introduced Ed25519 cryptographic functionality with key management methods.
testutil/network/query.go New file defining methods for querying various Exocore network clients.
testutil/network/tx.go Added methods for sending transactions, including handling for Ed25519 signing.
go.mod Updated dependencies and replaced several with specific versions from Exocore forks.
tests/e2e/bank/bank_test.go Introduced a new E2E test suite for bank functionalities.
tests/e2e/bank/query.go New test function for querying native coin balances.
tests/e2e/bank/suite.go New package for E2E tests related to the bank module.
tests/e2e/bank/tx.go New test function for validating coin transfers between accounts.
tests/e2e/basesuite.go New base suite for E2E testing, managing network setup and teardown.
tests/e2e/oracle/oracle_test.go New test suite for E2E testing of the Oracle module.
tests/e2e/oracle/suite.go New E2E test suite for Oracle, including setup and teardown methods.
tests/e2e/util.go Introduced utility functions for querying balances and generating account addresses.
testutil/network/tx_internal.go New file for internal transaction handling within the network context.
app/ante/cosmos/sigverify.go Updated logic for public key validation and signature verification during transaction simulations.
tests/e2e/oracle/data.go New file introducing priceTime struct for price-related data management.
tests/e2e/oracle/create_price.go New E2E test suite for price creation and validation within the Oracle module.
x/oracle/keeper/aggregator/aggregator.go Modified price handling to use strings instead of *big.Int, affecting multiple methods.
x/oracle/keeper/aggregator/calculator.go Updated price fields to string types, adjusting related methods accordingly.
tests/e2e/oracle/helper_nstconvert.go New file for converting balance changes to byte arrays.
testutil/network/tx_precompile.go Implemented functionality for interacting with Ethereum precompile contracts.
.github/workflows/e2e-test-release.yml Removed E2E test release workflow.
.github/workflows/e2e-test.yml Removed E2E test workflow configuration.
x/delegation/keeper/update_native_restaking_balance.go Updated logic for handling negative amounts in staking rewards and slashing events.
x/oracle/keeper/aggregator/context.go Updated AggregatorContext methods for improved error handling and price validation.
x/oracle/keeper/aggregator/worker.go Changed return type of aggregate method to string, simplifying price handling.
x/oracle/keeper/native_token.go Renamed types and constants related to native staking assets for clarity.
x/oracle/types/types.go Streamlined OracleInfo struct by removing unused fields and adding a new constant.
x/oracle/keeper/aggregator/aggregator_test.go Updated price assertions in tests to use string representations.
x/oracle/keeper/aggregator/calculator_test.go Changed price assertions in tests to reflect new string handling.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Network
    participant Keeper
    participant Oracle

    User->>Network: Send transaction
    Network->>Keeper: Process transaction
    Keeper->>Oracle: Validate price
    Oracle-->>Keeper: Return price data
    Keeper-->>Network: Confirm transaction
    Network-->>User: Transaction complete
Loading

Possibly related PRs

Suggested reviewers

  • MaxMustermann2
  • mikebraver
  • TimmyExogenous
  • cloud8little

Poem

🐇 In the land of code where changes bloom,
New genesis states dispel the gloom.
With tokens and assets, we dance and play,
Enhancing our network in a vibrant way.
So hop along, let the tests run free,
For a brighter tomorrow, just wait and see! 🌼


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e8bc128 and d2b97ea.

📒 Files selected for processing (1)
  • x/oracle/keeper/native_token.go (9 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • x/oracle/keeper/native_token.go

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

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

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

CodeRabbit Commands (Invoked using PR comments)

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

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🧹 Outside diff range and nitpick comments (9)
testutil/network/genesis_data.go (1)

48-55: Remove commented code and add documentation.

The implementation is correct, but could benefit from cleanup and documentation.

  1. Remove the commented-out empty struct literals
  2. Add comments explaining why default genesis states are sufficient for testing purposes
-// DefaultGenStateOperator = operatortypes.GenesisState{}
+// DefaultGenStateOperator provides a basic operator genesis state for testing
 DefaultGenStateOperator = *operatortypes.DefaultGenesis()

-// DefaultGenStateDelegation = delegationtypes.GenesisState{}
+// DefaultGenStateDelegation provides a basic delegation genesis state for testing
 DefaultGenStateDelegation = *delegationtypes.DefaultGenesis()

+// DefaultGenStateDogfood provides a basic dogfood genesis state for testing
 DefaultGenStateDogfood = *dogfoodtypes.DefaultGenesis()
x/oracle/keeper/nonce.go (2)

131-131: Approve with minor formatting suggestion.

The enhanced error message is more descriptive and helpful for debugging. However, consider improving readability with proper spacing after the colon.

-	return 0, fmt.Errorf("validator for the consKey which signed the create-price tx is not included in active validator set, signer consAddr:%s", validator)
+	return 0, fmt.Errorf("validator for the consKey which signed the create-price tx is not included in active validator set, signer consAddr: %s", validator)

Line range hint 163-163: Consider tracking the performance TODO.

There's a TODO comment about improving performance by using a composite key (validator_feederID) for nonce storage. Consider creating an issue to track this performance optimization.

Would you like me to help create a GitHub issue to track this performance optimization task?

testutil/network/network.go (3)

119-121: Consider documenting the rationale for token value changes.

The token values have been significantly reduced from consensus power values. While this might be more manageable for testing, it would be helpful to document why these specific values were chosen.

Consider adding a comment explaining the reasoning:

 AccountTokens:     sdk.TokensFromConsensusPower(1000, evmostypes.PowerReduction), // Reduced from higher values for more manageable testing
 StakingTokens:     sdk.TokensFromConsensusPower(500, evmostypes.PowerReduction),  // Reduced to better represent realistic staking scenarios
 BondedTokens:      sdk.TokensFromConsensusPower(200, evmostypes.PowerReduction),  // Adjusted for testing different validator states

Line range hint 416-420: Consider enhancing the key seed file security.

While this is test code, it's storing sensitive information (private key seed words) in plain JSON.

Consider adding a warning comment and possibly encoding the data:

+// Warning: This is for testing only. Never store private keys in plain text in production.
 err = WriteFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, infoBz)

534-534: Remove commented-out code.

This line appears to be old configuration code that's no longer needed.

-// cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config)
testutil/network/util.go (3)

159-159: Remove Duplicate Word in Comment.

The comment at line 159 contains a duplicate word: "actually actually." This is a minor typographical error that should be corrected for clarity.

Apply this diff:

-// collectGenFiles doesn't actually actually collect gentx and fill into genesis since we use dogfood to replace staking module.
+// collectGenFiles doesn't actually collect gentx and fill into genesis since we use dogfood to replace the staking module.

341-347: Correct Typos and Improve Comment Clarity.

There are several typographical errors and unclear comments in this section:

  • Line 341: "evry" should be "every."
  • Line 343: Incomplete comment needing clarification.
  • Line 346: Spelling error in "lenght" (should be "length").

Revise the comments and error messages:

-// stakingAmount, each operator opt in evry AVS with stakingAmount of every assets
+// stakingAmount: each operator opts in every AVS with stakingAmount of every asset

-// intial price for every asset is 1 USD
+// Initial price for every asset is 1 USD

...

-	return DefaultGenStateOperator, fmt.Errorf("lenght of operatorAccAddresses %d should be equal to length of consPubKeys %d", len(operatorAccAddresses), len(consPubKeys))
+	return DefaultGenStateOperator, fmt.Errorf("length of operatorAccAddresses %d should be equal to length of consPubKeys %d", len(operatorAccAddresses), len(consPubKeys))

414-416: Remove or Address Commented-Out Code.

Lines 414-416 contain commented-out code that checks the lengths of consPubKeys and powers. If this code is no longer necessary, it should be removed to keep the codebase clean.

If the validation is needed, uncomment and ensure it's correctly implemented. Otherwise, remove it:

-	// if len(consPubKeys) != len(powers) {
-	// 	return DefaultGenStateDogfood, fmt.Errorf("length of consensusKey %d should be equal to length of powers %d", len(consPubKeys), len(powers))
-	// }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 328f75d and bfa4d7b.

📒 Files selected for processing (5)
  • testutil/network/genesis_data.go (1 hunks)
  • testutil/network/network.go (11 hunks)
  • testutil/network/network_test.go (0 hunks)
  • testutil/network/util.go (6 hunks)
  • x/oracle/keeper/nonce.go (2 hunks)
💤 Files with no reviewable changes (1)
  • testutil/network/network_test.go
🔇 Additional comments (9)
testutil/network/genesis_data.go (2)

1-9: LGTM! Package and imports are well-structured.

The imports are properly organized and all dependencies are correctly referenced.


1-55: Verify test coverage for genesis states.

Let's ensure these genesis states are properly utilized in tests.

✅ Verification successful

Let me gather more information about how these genesis states are actually used in tests.


Let me check one more thing to see how these genesis states are actually used in the network setup.


Let me check one final aspect to see how these genesis states are integrated into the test network setup.


Based on the comprehensive review of the codebase, I can now provide a final response about the genesis states usage.

Genesis states are properly integrated and utilized in the test framework

The genesis states defined in genesis_data.go are actively used in the network test setup:

  • They are properly initialized in NewGenStateAssets, NewGenStateOperator, NewGenStateDogfood, and NewGenStateDelegation functions
  • The states are integrated into the test network setup through initGenFiles function
  • The network package provides proper test utilities in network_test.go to verify the functionality
  • The genesis states are used as base configurations that can be customized for different test scenarios
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of these genesis states in test files
echo "Searching for test files using these genesis states..."
rg -t go "DefaultGenState(Assets|Operator|Delegation|Dogfood)" --type go

Length of output: 3473


Script:

#!/bin/bash
# Search for files that import and use these genesis states
echo "Searching for test files importing the network package..."
rg -l "\"github.com/ExocoreNetwork/exocore/testutil/network\"" --type go

echo -e "\nSearching for actual test usage..."
rg -t go "func.*Test.*\(.*testing\.T.*\)" -A 5 -C 10 testutil/network/

Length of output: 1966


Script:

#!/bin/bash
# Check how genesis states are used in network configuration
echo "Checking network configuration usage..."
rg -t go "DefaultGenState" -B 5 -A 10 testutil/network/network.go

# Also check if there are any other test files in the modules that use these states
echo -e "\nChecking module-specific tests..."
rg -t go "DefaultGenState" x/*/types/*_test.go

Length of output: 691


Script:

#!/bin/bash
# Check the network configuration and initialization
echo "Checking network configuration and initialization..."
cat testutil/network/network.go

# Also check the util.go file which showed usage in previous results
echo -e "\nChecking utility functions..."
cat testutil/network/util.go

Length of output: 38981

x/oracle/keeper/nonce.go (1)

5-5: LGTM: Import addition is appropriate.

The fmt import is correctly added and necessary for the enhanced error message formatting.

testutil/network/network.go (5)

83-85: LGTM! Documentation improvements for token fields.

The updated comments provide better clarity about the purpose of each token field in the Config struct.


374-385: LGTM! Improved node initialization with better error handling.

The code now properly initializes node validator files and handles P2P address parsing in a more structured way.


451-454: LGTM! Removed redundant P2P URL parsing code.

Good cleanup - this code was duplicated from the earlier P2P URL parsing at lines 380-383.


526-532: LGTM! Enhanced P2P configuration with sorted persistent peers.

The implementation properly:

  1. Sorts peer addresses for consistent configuration
  2. Sets unique persistent peers for each validator
  3. Excludes self from the peer list

342-343: Verify the impact of directory name changes.

The node directory paths have been updated to use 'exocored' and 'exocorecli'. Ensure this aligns with the expected binary names.

✅ Verification successful

The directory names 'exocored' and 'exocorecli' are correctly aligned with the binary names used throughout the codebase.

The verification shows that:

  • 'exocored' is consistently used as the main binary name across the codebase, including in:
    • App configuration (app/app.go)
    • Main command (cmd/exocored/main.go)
    • Build configurations (Dockerfile, Makefile)
    • Network scripts and configurations
  • While 'exocorecli' directory is created in the test network setup, it's appropriate as it represents the CLI configuration directory
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if these binary names are consistent across the codebase
rg -g '!*.{md,txt}' -i 'exocored|exocorecli'

Length of output: 8612

testutil/network/util.go (1)

389-395: Verify Correct Calculation of stakingValue and Power Reduction.

In the function NewGenStateOperator, at lines 389-395, the calculation of stakingValue uses sdktypes.TokensToConsensusPower, which may not produce the correct value if evmostypes.PowerReduction is not properly defined or if token values are not in the expected units.

Please ensure that stakingAmount and evmostypes.PowerReduction are correctly defined. Run the following script to verify the values:

✅ Verification successful

Let me gather more information about the PowerReduction value and its initialization.


Based on the gathered information, I can now provide the final response:

stakingValue Calculation is Correctly Implemented

The implementation is correct because:

  • PowerReduction is properly defined with BaseDenomUnit = 18, making it 10^18 (standard for Ethereum compatibility)
  • sdk.DefaultPowerReduction is correctly set to evmostypes.PowerReduction in app.go
  • The conversion between tokens and consensus power is consistently used across the codebase with the same PowerReduction value
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the calculation of stakingValue and ensure PowerReduction is correctly applied.

# Expected: PowerReduction should be a non-zero value.

# Check the definition of PowerReduction
rg 'PowerReduction' ./ -A 2

# Search for usages of TokensToConsensusPower
rg 'TokensToConsensusPower' ./ -A 3

Length of output: 6007


Script:

#!/bin/bash
# Check the BaseDenomUnit definition and PowerReduction initialization
rg 'BaseDenomUnit.*=' ./

# Check where PowerReduction is used in the context of staking value calculations
ast-grep --pattern 'TokensFromConsensusPower($amount, $reduction)'

Length of output: 252

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🧹 Outside diff range and nitpick comments (17)
x/oracle/keeper/keeper.go (2)

21-26: Add documentation for the memoryStore struct and its fields.

The new struct lacks documentation explaining:

  • The purpose of the memoryStore
  • The difference between agc and agcCheckTx
  • When and how updatedFeederIDs is used

Add documentation like this:

+// memoryStore holds the in-memory state for the oracle keeper
 type memoryStore struct {
+    // cs holds the cache for oracle data
     cs               *cache.Cache
+    // agc holds the aggregator context for delivery transactions
     agc              *aggregator.AggregatorContext
+    // agcCheckTx holds the aggregator context for check transactions
     agcCheckTx       *aggregator.AggregatorContext
+    // updatedFeederIDs tracks the IDs of feeders that have been updated
     updatedFeederIDs []string
 }

37-39: Fix inconsistent and unclear documentation.

The inline comment is inaccurate and contains typos:

  1. It mentions "four memory cache" but the struct shows different components (cache, two aggregator contexts, and feeder IDs)
  2. Contains a typo in "cpoies" (should be "copies")

Update the comment like this:

-    // wrap all four memory cache into one pointer to track them among cpoies of Keeper (msgServer, module)
+    // memStore holds the in-memory state that needs to be shared across keeper copies (msgServer, module)
     memStore *memoryStore
testutil/network/genesis_data.go (2)

29-51: Standardize test token configurations.

Both tokens use the same staking amount (5000) without explanation. Consider:

  1. Using constants for common values
  2. Adding documentation for why these specific amounts were chosen
  3. Making amounts different to catch potential bugs in amount handling
+const (
+    // TestETHStakingAmount represents a realistic staking amount for ETH in tests
+    TestETHStakingAmount = 5000
+    // TestNSTETHStakingAmount is intentionally different from ETH to catch bugs
+    TestNSTETHStakingAmount = 3000
+)

 Tokens: []assetstypes.StakingAssetInfo{
     {
         // ...
-        StakingTotalAmount: sdkmath.NewInt(5000),
+        StakingTotalAmount: sdkmath.NewInt(TestETHStakingAmount),
     },
     {
         // ...
-        StakingTotalAmount: sdkmath.NewInt(5000),
+        StakingTotalAmount: sdkmath.NewInt(TestNSTETHStakingAmount),
     },
 },

53-62: Clean up commented code and document initialization choices.

The file contains commented-out alternatives for genesis state initialization. Either:

  1. Remove the comments if they're no longer needed
  2. Document why empty states are preferred over default genesis
x/oracle/keeper/params.go (1)

Line range hint 33-114: Consider refactoring for better maintainability

The RegisterNewTokenAndSetTokenFeeder function is handling multiple responsibilities and could benefit from the following improvements:

  1. Split the function into smaller, focused functions
  2. Add input validation for oInfo
  3. Document the function's behavior and parameters
  4. Move magic numbers to named constants

Consider breaking down the function like this:

// validateOracleInfo validates the input parameters
func (k Keeper) validateOracleInfo(oInfo *types.OracleInfo) error

// findOrCreateChain returns the chain ID, creating a new chain if necessary
func (k Keeper) findOrCreateChain(p types.Params, chainInfo *types.Chain) (uint64, error)

// bindAssetToExistingToken attempts to bind an assetID to an existing token
func (k Keeper) bindAssetToExistingToken(ctx sdk.Context, p types.Params, oInfo *types.OracleInfo, chainID uint64) error

// createNewTokenAndFeeder creates a new token and its associated feeder
func (k Keeper) createNewTokenAndFeeder(ctx sdk.Context, p types.Params, oInfo *types.OracleInfo, chainID uint64) error

Would you like me to provide the complete implementation for these functions?

x/oracle/keeper/keeper_suite_test.go (3)

76-79: Consider extracting duplicated parameter initialization

This parameter initialization logic is duplicated in the SetupTest method (lines 110-113). Consider extracting it into a helper method to maintain DRY principles.

+func (suite *KeeperSuite) initializeTestParams() {
+    p4Test := types.DefaultParams()
+    p4Test.TokenFeeders[1].StartBaseBlock = 1
+    suite.k.SetParams(suite.ctx, p4Test)
+    suite.ctx = suite.ctx.WithBlockHeight(12)
+}

77-77: Document the significance of StartBaseBlock modification

The modification of StartBaseBlock for the second token feeder lacks documentation explaining its purpose and significance in the test context.


116-118: Consider a more descriptive function name

While the function implementation is correct, the name resetSingle could be more descriptive. Consider renaming it to better reflect its purpose, such as resetKeeperState or resetOracleKeeper.

-func resetSingle(k keeper.Keeper) {
+func resetKeeperState(k keeper.Keeper) {
     k.ResetAggregatorContext()
     k.ResetCache()
 }
x/oracle/keeper/msg_server_create_price_test.go (1)

67-68: Remove commented code and document the architectural change.

The cache retrieval has been moved from the local keeper to the app's oracle keeper. While this change makes sense architecturally, please:

  1. Remove the commented code if it's no longer needed
  2. Consider adding a comment explaining why the app's oracle keeper is preferred over the local keeper instance
-			c = ks.App.OracleKeeper.GetCaches()
-			// c = ks.ms.Keeper.GetCaches()
+			// Using app's oracle keeper to ensure consistent cache state across the application
+			c = ks.App.OracleKeeper.GetCaches()
x/oracle/keeper/msg_server_create_price.go (1)

Line range hint 19-81: Consider breaking down the CreatePrice function for better maintainability

The function handles multiple responsibilities including:

  • Gas metering
  • Timestamp validation
  • Price creation
  • Cache management
  • Event emission
  • Nonce management

Consider extracting some of these into helper methods to improve readability and maintainability.

Example refactoring:

func (ms msgServer) CreatePrice(goCtx context.Context, msg *types.MsgCreatePrice) (*types.MsgCreatePriceResponse, error) {
    ctx := sdk.UnwrapSDKContext(goCtx)
    
+   if err := ms.setupGasMeter(ctx); err != nil {
+       return nil, err
+   }
+   
+   if err := ms.validatePriceProposal(ctx, msg); err != nil {
+       return nil, err
+   }
+   
+   newItem, caches, err := ms.processPriceCreation(ctx, msg)
+   if err != nil {
+       return nil, err
+   }
+   
+   if err := ms.handleCacheAndEvents(ctx, newItem, caches, msg); err != nil {
+       return nil, err
+   }
    
    return &types.MsgCreatePriceResponse{}, nil
}
x/oracle/keeper/msg_server_update_params_test.go (1)

169-169: LGTM! Consider adding a comment explaining the block height choice.

Setting the block height is important for this test as it establishes a specific blockchain state for validating TokenFeeder updates. However, it would be helpful to document why block height 2 was specifically chosen.

Consider adding a comment like:

+  // Set block height to 2 to test TokenFeeder updates after genesis
   ks.ctx = ks.ctx.WithBlockHeight(2)
x/oracle/module.go (1)

213-220: Improve event emission robustness

The current implementation could be enhanced for better reliability and maintainability.

Consider these improvements:

-    if feederIDs := am.keeper.GetUpdatedFeederIDs(); len(feederIDs) > 0 {
+    feederIDs := am.keeper.GetUpdatedFeederIDs()
+    // Reset early to ensure it happens even if event emission fails
+    am.keeper.ResetUpdatedFeederIDs()
+    
+    if len(feederIDs) > 0 {
+        // Validate feederIDs before joining
+        validFeederIDs := make([]string, 0, len(feederIDs))
+        for _, id := range feederIDs {
+            if id != "" {
+                validFeederIDs = append(validFeederIDs, id)
+            }
+        }
+        
+        if len(validFeederIDs) > 0 {
+            feederIDsStr := strings.Join(validFeederIDs, "_")
             ctx.EventManager().EmitEvent(sdk.NewEvent(
                 types.EventTypeCreatePrice,
                 sdk.NewAttribute(types.AttributeKeyPriceUpdated, types.AttributeValuePriceUpdatedSuccess),
                 sdk.NewAttribute(types.AttributeKeyFeederIDs, feederIDsStr),
             ))
         }
-        am.keeper.ResetUpdatedFeederIDs()
     }
x/oracle/keeper/prices.go (1)

204-204: Consider consolidating cache accesses.

The method accesses k.memStore.agc multiple times for different parameter retrievals. Consider consolidating these accesses by retrieving all needed parameters at once at the start of the method.

Here's a suggested refactoring:

func (k Keeper) AppendPriceTR(ctx sdk.Context, tokenID uint64, priceTR types.PriceTimeRound) bool {
    nextRoundID := k.GetNextRoundID(ctx, tokenID)
    // This should not happen
    if nextRoundID != priceTR.RoundID {
        return false
    }
+   var p types.Params
+   if k.memStore.agc != nil {
+       p = k.memStore.agc.GetParams()
+   } else {
+       p = k.GetParams(ctx)
+   }

    store := k.getPriceTRStore(ctx, tokenID)
    b := k.cdc.MustMarshal(&priceTR)
    store.Set(types.PricesRoundKey(nextRoundID), b)
-   if expiredRoundID := nextRoundID - k.memStore.agc.GetParamsMaxSizePrices(); expiredRoundID > 0 {
+   if expiredRoundID := nextRoundID - p.MaxSizePrices; expiredRoundID > 0 {
        store.Delete(types.PricesRoundKey(expiredRoundID))
    }
    roundID := k.IncreaseNextRoundID(ctx, tokenID)

    // update for native tokens
    // TODO: set hooks as a genral approach
-   var p types.Params
-   // get params from cache if exists
-   if k.memStore.agc != nil {
-       p = k.memStore.agc.GetParams()
-   } else {
-       p = k.GetParams(ctx)
-   }
    assetIDs := p.GetAssetIDsFromTokenID(tokenID)
    // ... rest of the method

Also applies to: 213-214

testutil/network/util.go (4)

203-233: Improve error handling consistency.

The error handling pattern is inconsistent. Some errors are returned directly while others might be silently propagated through MustMarshalJSON.

Consider wrapping the MustMarshalJSON calls in a try-catch block or use regular MarshalJSON with proper error handling:

-cfg.GenesisState[assetstypes.ModuleName] = cfg.Codec.MustMarshalJSON(&assetsGenState)
+marshaledState, err := cfg.Codec.MarshalJSON(&assetsGenState)
+if err != nil {
+    return fmt.Errorf("failed to marshal assets genesis state: %w", err)
+}
+cfg.GenesisState[assetstypes.ModuleName] = marshaledState

380-380: Replace magic number with a named constant.

The value 18446744073709551615 (max uint64) is hardcoded. This should be defined as a constant for better maintainability.

+const MaxOptOutHeight = uint64(18446744073709551615)

-OptedOutHeight: 18446744073709551615,
+OptedOutHeight: MaxOptOutHeight,

415-417: Consider making epoch parameters configurable.

The epoch parameters are hardcoded which might not be suitable for all test scenarios.

Consider making these parameters configurable through the function arguments:

-func NewGenStateDogfood(consPubKeys []string, stakingAmount sdkmath.Int, genStateAssets assetstypes.GenesisState) (dogfoodtypes.GenesisState, error) {
+func NewGenStateDogfood(consPubKeys []string, stakingAmount sdkmath.Int, genStateAssets assetstypes.GenesisState, epochConfig *DogfoodEpochConfig) (dogfoodtypes.GenesisState, error) {
     // ...
-    DefaultGenStateDogfood.Params.EpochIdentifier = "minute"
-    DefaultGenStateDogfood.Params.EpochsUntilUnbonded = 5
-    DefaultGenStateDogfood.Params.MinSelfDelegation = sdkmath.NewInt(100)
+    if epochConfig == nil {
+        epochConfig = DefaultDogfoodEpochConfig
+    }
+    DefaultGenStateDogfood.Params.EpochIdentifier = epochConfig.Identifier
+    DefaultGenStateDogfood.Params.EpochsUntilUnbonded = epochConfig.UntilUnbonded
+    DefaultGenStateDogfood.Params.MinSelfDelegation = epochConfig.MinSelfDelegation

293-293: Consider using common.BytesToAddress for Ethereum address conversion.

Using hexutil.Encode directly on the address bytes might not handle all edge cases correctly.

-stakerAddrStr := hexutil.Encode(operatorAccAddress)
+stakerAddrStr := common.BytesToAddress(operatorAccAddress).Hex()
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between bfa4d7b and f0b82eb.

📒 Files selected for processing (15)
  • precompiles/assets/assets_test.go (0 hunks)
  • testutil/network/genesis_data.go (1 hunks)
  • testutil/network/network.go (10 hunks)
  • testutil/network/network_test.go (1 hunks)
  • testutil/network/util.go (5 hunks)
  • x/oracle/keeper/keeper.go (3 hunks)
  • x/oracle/keeper/keeper_suite_test.go (2 hunks)
  • x/oracle/keeper/msg_server_create_price.go (2 hunks)
  • x/oracle/keeper/msg_server_create_price_test.go (5 hunks)
  • x/oracle/keeper/msg_server_update_params.go (1 hunks)
  • x/oracle/keeper/msg_server_update_params_test.go (1 hunks)
  • x/oracle/keeper/params.go (2 hunks)
  • x/oracle/keeper/prices.go (4 hunks)
  • x/oracle/keeper/single.go (4 hunks)
  • x/oracle/module.go (3 hunks)
💤 Files with no reviewable changes (1)
  • precompiles/assets/assets_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • testutil/network/network_test.go
🧰 Additional context used
🪛 GitHub Check: Run golangci-lint
testutil/network/network.go

[failure] 19-19:
ST1019: package "cosmossdk.io/math" is being imported more than once (stylecheck)


[failure] 20-20:
ST1019(related information): other import of "cosmossdk.io/math" (stylecheck)

testutil/network/util.go

[failure] 17-17:
ST1019: package "github.com/cosmos/cosmos-sdk/types" is being imported more than once (stylecheck)


[failure] 18-18:
ST1019(related information): other import of "github.com/cosmos/cosmos-sdk/types" (stylecheck)

🪛 GitHub Check: CodeQL
x/oracle/module.go

[warning] 160-160: Panic in BeginBock or EndBlock consensus methods
path flow from Begin/EndBlock to a panic call


[warning] 169-169: Panic in BeginBock or EndBlock consensus methods
path flow from Begin/EndBlock to a panic call

🔇 Additional comments (37)
x/oracle/keeper/msg_server_update_params.go (2)

Line range hint 1-71: LGTM for the rest of the implementation.

The overall structure, error handling, and parameter update logic are well-implemented with proper validation and logging.


69-69: ⚠️ Potential issue

Avoid discarding the aggregator context result.

The result from GetAggregatorContext is being discarded with _. If this method returns important state or error information, it should be properly handled.

Let's check the implementation of GetAggregatorContext:

Consider handling the return value or document why it's safe to ignore.

x/oracle/keeper/keeper.go (2)

14-15: LGTM: Import statements are correctly organized.

The new imports for aggregator and cache packages are necessary for the memoryStore implementation.


Line range hint 21-73: Verify memory state management across transactions.

The introduction of in-memory state requires careful handling:

  1. When and how is the memory state reset between blocks?
  2. Is there a risk of state leakage between transactions?
  3. How is the memory state handled during chain halts or panics?

Let's check for memory state cleanup methods:

✅ Verification successful

Let me gather more context about where these reset methods are called.


Let me check one more aspect - the message handling and transaction boundaries.


Based on the gathered evidence, I can now provide a final response about the memory state management.

Memory state is properly managed with clear boundaries

The codebase implements proper memory state management through:

  • Explicit reset methods for each memory component (ResetAggregatorContext, ResetCache, ResetAggregatorContextCheckTx, ResetUpdatedFeederIDs)
  • Separate contexts for CheckTx and DeliverTx with proper isolation (copy4CheckTx methods)
  • Cache commitment and reset mechanisms via CommitCache
  • Clear memory cleanup by setting components to nil

The implementation follows best practices for state isolation between transactions and blocks, with proper cleanup mechanisms to prevent state leakage.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for methods that might handle memory state cleanup
rg -A 5 "func.*[Rr]eset|func.*[Cc]lean|func.*[Cc]lear" x/oracle/keeper/

Length of output: 2373


Script:

#!/bin/bash
# Search for where reset methods are called
rg -A 3 "ResetAggregatorContext|ResetCache|ResetAggregatorContextCheckTx|ResetUpdatedFeederIDs" x/oracle/keeper/

# Search for BeginBlock/EndBlock handlers
ast-grep --pattern 'func ($k Keeper) BeginBlock$_($ctx $_) {
  $$$
}'

ast-grep --pattern 'func ($k Keeper) EndBlock$_($ctx $_) {
  $$$
}'

Length of output: 2214


Script:

#!/bin/bash
# Search for transaction boundary handling in msg_server
rg -A 5 "func.*DeliverTx|func.*CheckTx|func.*Commit" x/oracle/keeper/

# Look for message handlers that might use the memory store
ast-grep --pattern 'func ($s msgServer) $_($ctx $_) {
  $$$
}'

Length of output: 3604

testutil/network/genesis_data.go (1)

1-10: LGTM! Clean and well-organized imports.

x/oracle/keeper/params.go (1)

111-112: Same error handling issue as above

This code segment has the same issue with discarding potential errors from GetAggregatorContext.

Apply the same error handling pattern as suggested above.

x/oracle/keeper/keeper_suite_test.go (3)

70-70: LGTM: Correctly updated resetSingle call

The update properly passes the OracleKeeper instance to match the new function signature.


104-113: LGTM: Proper initialization sequence

The initialization sequence is correct, with keeper reset followed by proper setup of the keeper, message server, and parameters.


116-118: Verify test coverage for reset functionality

Let's ensure there are tests verifying that the keeper's state is properly reset.

✅ Verification successful

Reset functionality is properly used in test setup

The reset functionality is well integrated into the test infrastructure:

  • resetSingle is called in key test setup points:
    • During test suite initialization
    • In the Reset() method of KeeperSuite
    • Before keeper initialization in test setup
  • The reset functions (ResetAggregatorContext and ResetCache) are properly implemented in x/oracle/keeper/single.go to clear memory store state
  • The reset pattern is consistently used across the test suite to ensure a clean state between tests
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for test cases that verify the reset functionality
rg -l "TestReset|Test.*Reset.*State" --type go

# Search for actual usage of ResetAggregatorContext and ResetCache
ast-grep --pattern 'func ($STRUCT *$TYPE) ResetAggregatorContext()' 
ast-grep --pattern 'func ($STRUCT *$TYPE) ResetCache()'

Length of output: 479


Script:

#!/bin/bash
# Let's search for test cases that might be using these reset functions
rg -B 5 -A 5 "ResetAggregatorContext|ResetCache" --type go

# Also search for any test setup functions that might be using resetSingle
rg -B 5 -A 5 "resetSingle" --type go

Length of output: 6903

x/oracle/keeper/msg_server_create_price_test.go (3)

63-63: Verify all BasedBlock values are consistently updated.

The BasedBlock value has been changed from 1 to 11 in multiple test messages. While the changes appear consistent in this file, please verify that all related test files have been updated accordingly.

#!/bin/bash
# Search for other BasedBlock occurrences in test files
rg -A 2 "BasedBlock:" "**/*_test.go"

Also applies to: 85-85, 97-97


47-47: Verify block height change rationale.

The block height expectation has been increased from 2 to 12. This change appears to correlate with the BasedBlock changes from 1 to 11 in the test messages. Please confirm if this significant increase in block height is intentional and necessary for the test scenarios.

✅ Verification successful

Let me search for more context about block height usage in the tests and related files to better understand the change.


Based on the search results, I can now provide a conclusive response about the block height change:

Block height change is consistent with test setup

The block height change from 2 to 12 is intentional and consistent with the test environment setup. This is evidenced by:

  • The test suite initialization in keeper_suite_test.go explicitly sets suite.ctx = suite.ctx.WithBlockHeight(12)
  • This block height is used as the standard test context across the oracle keeper tests
  • The change aligns with the codebase's block height usage patterns, particularly in cache management and round sealing logic
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other block height dependencies
rg -A 3 "BlockHeight\(\)" x/oracle/

Length of output: 49


Script:

#!/bin/bash
# Search for block height related tests and assertions
rg -A 3 "BlockHeight\(\)" --type go x/oracle/keeper/

# Search for block height setup in test files
rg -A 3 "WithBlockHeight" --type go x/oracle/keeper/

# Look for block-related constants or variables
rg -A 3 "(blockHeight|BlockHeight)" --type go x/oracle/types/

Length of output: 7038


106-118: Verify price list structure changes and round ID sequence.

The price list structure has been significantly modified:

  1. NextRoundID increased to 3
  2. Added a new price entry with RoundID: 1
  3. Changed existing entry's RoundID to 2

These changes suggest a modification in how rounds are tracked. Please verify:

  1. The round ID sequence is correct
  2. The empty timestamp in the new entry is intentional
✅ Verification successful

Based on the shell script results, I can now provide a final response about the price list structure changes:

Price list structure and round ID sequence are correctly implemented

The changes in the test file align with the implementation in keeper/prices.go:

  • Round ID 0 is reserved as per implementation: // 0 roundId is reserved, expect the roundid corresponds to the slice index
  • NextRoundID increment from 2 to 3 is consistent with adding a new price entry
  • The empty timestamp in the new entry with RoundID: 1 is valid as timestamps are optional in the PriceTimeRound struct
  • Round IDs are sequential (1, 2) which matches the implementation's requirement for continuous round IDs
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for related round ID handling in the implementation
ast-grep --pattern 'NextRoundID = $_' x/oracle/

Length of output: 49


Script:

#!/bin/bash
# Search for NextRoundID usage in the codebase with context
rg -A 5 "NextRoundID" x/oracle/

# Search for round ID related test cases
rg -A 5 "RoundID" x/oracle/keeper/*test.go

# Search for price list related code
ast-grep --pattern 'type PriceTimeRound struct {
  $$$
}'

Length of output: 23376

x/oracle/keeper/msg_server_create_price.go (2)

Line range hint 33-38: LGTM: Clean encapsulation of aggregator context access

The refactoring to access the aggregator context through ms.Keeper improves encapsulation and follows Cosmos SDK best practices.


73-77: Verify thread safety of cache operations

While the encapsulation through ms.Keeper.GetCaches() is good, ensure that the cache operations are thread-safe if multiple validators or goroutines might access them concurrently.

x/oracle/module.go (1)

166-169: ⚠️ Potential issue

Add error handling for keeper operations in EndBlock

The current implementation lacks proper error handling for critical keeper operations that could potentially panic during consensus.

Consider adding proper error handling:

func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
+    logger := am.keeper.Logger(ctx)
+    
+    cs, err := am.keeper.GetCaches()
+    if err != nil {
+        logger.Error("failed to get caches", "error", err, "height", ctx.BlockHeight())
+        return []abci.ValidatorUpdate{}
+    }
+    if cs == nil {
+        logger.Error("nil caches returned", "height", ctx.BlockHeight())
+        return []abci.ValidatorUpdate{}
+    }
+
     validatorUpdates := am.keeper.GetValidatorUpdates(ctx)
     forceSeal := false
-    agc := am.keeper.GetAggregatorContext(ctx)
+    
+    agc, err := am.keeper.GetAggregatorContext(ctx)
+    if err != nil {
+        logger.Error("failed to get aggregator context", "error", err, "height", ctx.BlockHeight())
+        return []abci.ValidatorUpdate{}
+    }
+    if agc == nil {
+        logger.Error("nil aggregator context returned", "height", ctx.BlockHeight())
+        return []abci.ValidatorUpdate{}
+    }

Let's verify the error handling in the keeper methods:

🧰 Tools
🪛 GitHub Check: CodeQL

[warning] 169-169: Panic in BeginBock or EndBlock consensus methods
path flow from Begin/EndBlock to a panic call

x/oracle/keeper/prices.go (2)

60-61: LGTM! Efficient parameter caching implementation.

The cache-first approach for parameter access is well-implemented and follows Cosmos SDK best practices for performance optimization.


94-95: LGTM! Consistent caching pattern.

The implementation maintains consistency with the caching pattern used throughout the keeper.

testutil/network/util.go (1)

17-18: ⚠️ Potential issue

Consolidate duplicate SDK type imports.

The package github.com/cosmos/cosmos-sdk/types is imported twice with different aliases (sdk and sdktypes). This can lead to confusion and inconsistency.

 sdk "github.com/cosmos/cosmos-sdk/types"
-sdktypes "github.com/cosmos/cosmos-sdk/types"

Update all references of sdktypes to sdk throughout the code.

Likely invalid or redundant comment.

🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 17-17:
ST1019: package "github.com/cosmos/cosmos-sdk/types" is being imported more than once (stylecheck)


[failure] 18-18:
ST1019(related information): other import of "github.com/cosmos/cosmos-sdk/types" (stylecheck)

x/oracle/keeper/single.go (7)

14-19: LGTM!

The GetCaches method has been updated to use the memStore field of the Keeper struct, ensuring that the cache is tied to the specific instance of Keeper. This change enhances the encapsulation of state management within the Keeper instance.


23-56: LGTM!

The GetAggregatorContext method has been refactored to access the aggregator context from the memStore field of the Keeper struct, replacing the previous global variables. The logic for initializing and resetting the aggregator context has also been modified to utilize the instance's memStore. These changes improve the encapsulation of the Keeper's state and promote a more object-oriented design.


Line range hint 59-157: LGTM!

The recacheAggregatorContext function has been converted to an instance method of the Keeper struct, allowing it to operate on the instance's state. It now uses instance methods like GetAllExocoreValidators and GetParams to manage validator powers and parameters, enhancing the encapsulation of the Keeper's state. The changes align with the overall goal of improving the object-oriented design and maintainability of the codebase.


Line range hint 160-182: LGTM!

The initAggregatorContext function has been updated to take a pointer to the Keeper struct as a parameter, allowing it to access the instance's methods directly. This change is consistent with the overall refactoring effort to enhance the encapsulation and object-oriented design of the Keeper.


184-193: LGTM!

The ResetAggregatorContext, ResetCache, and ResetAggregatorContextCheckTx methods have been modified to clear the respective fields in the memStore of the Keeper instance, rather than relying on global variables. This change ensures that the state is managed within the instance, promoting better encapsulation and maintainability.


204-215: LGTM!

The ResetUpdatedFeederIDs, GetUpdatedFeederIDs, and AppendUpdatedFeederIDs methods have been updated to operate on the updatedFeederIDs field of the memStore in the Keeper instance. This change ensures that the updated feeder IDs are managed within the instance, enhancing the encapsulation and consistency of state management.


Line range hint 1-216: Verify the impact of the changes on the codebase.

The refactoring of the Keeper struct to encapsulate state management is a significant change that affects multiple parts of the codebase. It's crucial to ensure that all the code that interacts with the Keeper has been updated accordingly.

Run the following script to identify potential areas that may require updates:

Analyze the output to identify any inconsistencies or areas that may require further updates to align with the refactored Keeper struct.

✅ Verification successful

Based on the search results, I can now generate the final response since I have comprehensive information about how the Keeper's methods and fields are used across the codebase.

The refactoring of the Keeper struct appears to be consistent across the codebase

The search results show that all interactions with the Keeper's memory store fields (memStore.cs, memStore.agc, memStore.agcCheckTx, memStore.updatedFeederIDs) are properly encapsulated through the corresponding getter and setter methods. The usage patterns found in the codebase are consistent:

  • Memory store fields are only accessed directly within the Keeper's own methods in single.go
  • External code only interacts with the memory store through public methods
  • All reset operations are properly handled through dedicated methods
  • The state management logic in GetAggregatorContext correctly handles both CheckTx and non-CheckTx modes
  • Cache operations are properly synchronized with the aggregator context lifecycle
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash

# Description: 
# Verify that the code interacting with the Keeper struct has been updated
# to use the new instance methods and fields.

# Test 1: Search for usage of the updated methods
methods=(
  "GetCaches"
  "GetAggregatorContext"
  "recacheAggregatorContext"
  "ResetAggregatorContext"
  "ResetCache"
  "ResetAggregatorContextCheckTx"
  "ResetUpdatedFeederIDs"
  "GetUpdatedFeederIDs"
  "AppendUpdatedFeederIDs"
)

for method in "${methods[@]}"; do
  echo "Checking usage of $method:"
  rg -A 5 "\.$method"
done

# Test 2: Search for usage of the memStore fields
fields=(
  "memStore.cs"
  "memStore.agc"
  "memStore.agcCheckTx"
  "memStore.updatedFeederIDs"
)

for field in "${fields[@]}"; do
  echo "Checking usage of $field:"
  rg -A 5 "\.$field"
done

Length of output: 19372

testutil/network/network.go (12)

13-13: ****

The sort package import is necessary for sorting the addressesIPs slice later in the code.


82-95: LGTM!

The changes to the Config struct look good:

  • The AccountTokens field comment is updated to clarify the token denomination.
  • A new DepositedTokens field is added.
  • The StakingTokens field comment is updated to indicate the amount for every supported asset.

The other fields and their comments remain unchanged.


240-240: LGTM!

Initializing the addressesIPs slice with the correct size (cfg.NumValidators) is the appropriate approach. This avoids unnecessary allocations and resizing of the slice later.


340-341: LGTM!

The changes to construct the nodeDir and clientDir paths using filepath.Join with the network.BaseDir and nodeDirName are correct. This ensures that the directories are created within the network's base directory and have the appropriate naming convention.


377-382: LGTM!

Parsing the p2pAddr to extract the hostname and port, and constructing the addressesIPs entries by combining the nodeID, hostname, and port is the correct approach. This ensures that the addressesIPs slice contains the complete addresses for each validator.


413-417: LGTM!

Writing the private key seed words to a file named key_seed.json in the clientDir is a good practice for secure storage of the mnemonic. The file name and location are appropriate.


421-421: LGTM!

Adding the new sdk.NewCoin with the cfg.DepositedTokens amount to the balances is correct. This ensures that the deposited tokens are included in the genesis balances for each validator.


Line range hint 431-439: LGTM!

The changes to set the custom app template, write the app configuration file, and read the configuration using ctx.Viper are all valid and follow the expected pattern. This ensures that the application configuration is properly set up for each validator.


469-478: LGTM!

The changes to sort the addressesIPs slice and set the persistentPeers field in the config.toml file for each validator are correct. This ensures that each validator has the correct persistent peers configuration based on the sorted addressesIPs.

Sorting the addressesIPs slice provides a deterministic order, and excluding the validator's own address from its persistentPeers list prevents self-connection attempts.

Writing the updated configuration to the config.toml file using tmcfg.WriteConfigFile is the appropriate way to persist the changes.


480-481: Verify the impact of the commission rate change.

The commissionRate is now set to 0.5 using sdkmath.LegacyNewDecFromStr. This value is passed to the initGenFiles function.

Verify that the commission rate change does not have any unintended consequences on the network's functionality and incentive structure. Ensure that the chosen commission rate aligns with the desired economic model of the network.

#!/bin/bash
# Description: Verify the impact of the commission rate change.

# Test 1: Check if the validators are created with the correct commission rate.
rg -A 10 -B 10 'stakingTypes\.Commission' | rg 'Rate: "0.5"'

# Test 2: Check if the network incentives and rewards are functioning as expected with the new commission rate.
rg -A 10 -B 10 'k\.hooks\.AfterValidatorCreated' | rg 'commission rate'

371-376: Verify the initialization of node key and consensus key.

The genutil.InitializeNodeValidatorFiles function is used to initialize the node key and consensus private key files under the nodeDir. This is an important step in setting up the validator files.

Verify that the InitializeNodeValidatorFiles function is working as expected and the generated files are correctly placed in the config directory.

#!/bin/bash
# Description: Verify the initialization of node key and consensus key files.

# Test: Check if the node key and consensus key files are generated for each validator.
for i in $(seq 0 $((cfg.NumValidators-1))); do
  nodeDir="$network.BaseDir/node$i/exocored"
  ls "$nodeDir/config/node_key.json" "$nodeDir/config/priv_validator_key.json"
done

117-120: Verify the impact of reducing the token amounts.

The DefaultConfig function is updated to initialize AccountTokens, DepositedTokens, and StakingTokens with smaller values using sdk.TokensFromConsensusPower. This change reduces the token amounts compared to the previous large values.

Ensure that reducing these token amounts does not adversely affect the functionality or testing of the network. Verify that the network can still operate correctly with these reduced values.

✅ Verification successful

Based on the gathered information, I can now provide a final response:

The reduced token amounts are safe and sufficient for testing purposes

The reduced token amounts (1000, 500, and 200 tokens) are still significantly higher than the minimum requirements found in the codebase:

  • The MinSelfDelegation parameter is set to 100 tokens
  • The network tests successfully initialize and run with these values
  • No test assertions or validations fail due to insufficient token amounts

The changes maintain a proper ratio between account, deposit, and staking tokens while reducing the overall magnitude, which is a good practice for test environments.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the network operates correctly with reduced token amounts.

# Test 1: Check if the network can be started and validators created with the reduced token amounts.
rg -A 10 -B 10 'func New\(.*\*Network' | rg 'return network, nil'

# Test 2: Check if transactions can be successfully executed with the reduced token amounts.
rg -A 10 -B 10 'tx, err := val\.ClientCtx\.TxConfig\.TxEncoder\(\)\.Encode\(builder\.GetTx\(\)\)' | rg 'err == nil'

Length of output: 230


Script:

#!/bin/bash
# Let's verify the token amounts usage in tests and network setup

# Check where these token amounts are used in test scenarios
rg -A 5 -B 5 "TokensFromConsensusPower" testutil/

# Check for any test failures or assertions related to token amounts
rg -A 5 "require\.NoError|assert\.NoError" testutil/ | grep -i "token"

# Look for network initialization and validator setup
rg -A 10 "func New" testutil/network/

Length of output: 7963


Script:

#!/bin/bash
# Let's check test files to verify if these reduced amounts are sufficient

# Check test files that use this network setup
rg -A 10 "network.New\(" testutil/

# Check if there are any minimum token requirements or validations
rg -A 5 "MinSelfDelegation|MinDeposit" testutil/

# Look for any token-related test assertions or validations
rg -A 5 "require\.True|assert\.True" testutil/ | grep -i "token\|amount"

Length of output: 2252

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🧹 Outside diff range and nitpick comments (8)
testutil/network/query.go (3)

12-35: Add method documentation and improve error handling.

While the implementation is functional, consider these improvements:

  1. Add godoc comments for each method describing their purpose
  2. Add validation for n.Validators to prevent panic if empty

Example implementation:

+// QueryOracle returns a query client for the oracle module using the first validator's context
 func (n *Network) QueryOracle() oracletypes.QueryClient {
+    if len(n.Validators) == 0 {
+        panic("no validators in network")
+    }
     return oracletypes.NewQueryClient(n.Validators[0].ClientCtx)
 }
🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 18-18:
File is not gofumpt-ed (gofumpt)


16-19: Fix formatting in QueryBank method.

Remove the extra newline between the return statement and the closing brace.

 func (n *Network) QueryBank() banktypes.QueryClient {
     return banktypes.NewQueryClient(n.Validators[0].ClientCtx)
-
 }
🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 18-18:
File is not gofumpt-ed (gofumpt)


12-35: Consider supporting multiple validator queries.

Currently, all query methods are hardcoded to use the first validator's context. Consider:

  1. Adding a parameter to specify which validator's context to use
  2. Or providing additional methods to query specific validators

Example enhancement:

// QueryOracleFromValidator returns a query client for the oracle module using the specified validator's context
func (n *Network) QueryOracleFromValidator(validatorIndex int) oracletypes.QueryClient {
    if validatorIndex >= len(n.Validators) {
        panic(fmt.Sprintf("validator index %d out of range", validatorIndex))
    }
    return oracletypes.NewQueryClient(n.Validators[validatorIndex].ClientCtx)
}
🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 18-18:
File is not gofumpt-ed (gofumpt)

crypto/algo_ed25519.go (2)

4-4: Clean up commented imports

There are commented-out imports that should either be removed or uncommented if they'll be needed in the future. This helps maintain clean and clear code.

-	// "github.com/cometbft/cometbft/crypto/ed25519"
-	// "github.com/evmos/evmos/v16/crypto/ethsecp256k1"

Also applies to: 12-12


50-55: Enforce test-only usage

Since this option is intended for testing only, consider adding runtime checks to prevent accidental usage in production.

 func Ed25519Option() keyring.Option {
+	if !isTestEnvironment() {
+		panic("Ed25519Option is only for testing purposes")
+	}
 	return func(options *keyring.Options) {
 		options.SupportedAlgos = SupportedAlgorithms
 	}
testutil/network/util.go (1)

Line range hint 158-234: Consider modularizing genesis state initialization.

The function handles initialization of multiple modules in a sequential manner. While functional, it could benefit from modularization for better maintainability.

Consider breaking down the initialization into module-specific helper functions:

+func initBasicModulesGenState(cfg Config) error {
+    // Initialize auth, bank, gov, crisis, evm modules
+}
+
+func initValidatorModulesGenState(cfg Config, validators []*Validator, commissionRate sdkmath.LegacyDec) error {
+    // Initialize assets, operator, dogfood modules
+}

 func initGenFiles(...) error {
-    // Current implementation
+    if err := initBasicModulesGenState(cfg); err != nil {
+        return err
+    }
+    return initValidatorModulesGenState(cfg, validators, commissionRate)
 }
testutil/network/network.go (1)

485-486: Consider parameterizing commission rate

The commission rate is hardcoded to 0.5. Consider making it configurable through the Config struct to allow for different test scenarios.

 type Config struct {
     // ... existing fields ...
+    CommissionRate string // the validator commission rate
 }

 func DefaultConfig() Config {
     // ... existing code ...
+    commissionRate: "0.5",
 }

-commissionRate, _ := sdkmath.LegacyNewDecFromStr("0.5")
+commissionRate, _ := sdkmath.LegacyNewDecFromStr(cfg.CommissionRate)
testutil/network/tx.go (1)

14-14: Improve the function comment for clarity

The comment has grammatical errors and can be enhanced for better readability.

Suggested change:

-// GenSignedTx construct a tx with input messages and sign it privatekey stored in keyring
+// GenSignedTx constructs a transaction with input messages and signs it with the private key stored in the keyring.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between f0b82eb and 36e54dd.

📒 Files selected for processing (6)
  • crypto/algo_ed25519.go (1 hunks)
  • testutil/network/network.go (11 hunks)
  • testutil/network/network_test.go (4 hunks)
  • testutil/network/query.go (1 hunks)
  • testutil/network/tx.go (1 hunks)
  • testutil/network/util.go (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • testutil/network/network_test.go
🧰 Additional context used
🪛 GitHub Check: Run golangci-lint
crypto/algo_ed25519.go

[warning] 32-32:
unused-parameter: parameter 'path' seems to be unused, consider removing or renaming it as _ (revive)


[failure] 44-44:
SA1019: ed25519.PrivKey is deprecated: PrivKey defines a ed25519 private key. NOTE: ed25519 keys must not be used in SDK apps except in a tendermint validator context. (staticcheck)

testutil/network/network.go

[failure] 19-19:
ST1019: package "cosmossdk.io/math" is being imported more than once (stylecheck)


[failure] 20-20:
ST1019(related information): other import of "cosmossdk.io/math" (stylecheck)

testutil/network/query.go

[failure] 18-18:
File is not gofumpt-ed (gofumpt)

testutil/network/tx.go

[failure] 29-29:
Error return value of txBuilder.SetMsgs is not checked (errcheck)

testutil/network/util.go

[failure] 17-17:
ST1019: package "github.com/cosmos/cosmos-sdk/types" is being imported more than once (stylecheck)


[failure] 18-18:
ST1019(related information): other import of "github.com/cosmos/cosmos-sdk/types" (stylecheck)

🔇 Additional comments (7)
testutil/network/query.go (1)

1-10: LGTM! Well-structured package and imports.

The package structure and imports are well-organized, with clear aliases for type packages.

crypto/algo_ed25519.go (1)

18-21: Verify supported algorithms configuration

The Ed25519 type is defined but not included in SupportedAlgorithms. If Ed25519 should be supported, consider adding it to the list.

testutil/network/util.go (1)

17-18: ⚠️ Potential issue

Consolidate duplicate SDK type imports.

The same package github.com/cosmos/cosmos-sdk/types is imported twice with different aliases (sdk and sdktypes). This can lead to confusion and inconsistency in the codebase.

Apply this diff to consolidate the imports:

 sdk "github.com/cosmos/cosmos-sdk/types"
-sdktypes "github.com/cosmos/cosmos-sdk/types"

Update all references of sdktypes to sdk throughout the code.

Likely invalid or redundant comment.

🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 17-17:
ST1019: package "github.com/cosmos/cosmos-sdk/types" is being imported more than once (stylecheck)


[failure] 18-18:
ST1019(related information): other import of "github.com/cosmos/cosmos-sdk/types" (stylecheck)

testutil/network/network.go (4)

474-482: Well-structured peer configuration

Good improvement! Sorting the addressesIPs ensures deterministic peer connections across test runs, enhancing test stability and reproducibility.


114-114: Consider impact of reduced timeout

The TimeoutCommit has been reduced from 3s to 2s, and MinGasPrices increased to "10hua". While this might speed up tests, please verify that:

  1. 2s is sufficient for consensus in test scenarios
  2. The increased gas price doesn't impact existing tests
#!/bin/bash
# Search for timeout-related test failures
rg -A 5 "timeout.*exceeded" 
# Search for gas price assertions in tests
rg -A 5 "MinGasPrices.*assert"

Also applies to: 119-120


19-20: ⚠️ Potential issue

Remove duplicate import of "cosmossdk.io/math"

Keep only the aliased import sdkmath "cosmossdk.io/math" and remove the unaliased one.

-	"cosmossdk.io/math"
 	sdkmath "cosmossdk.io/math"

Likely invalid or redundant comment.

🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 19-19:
ST1019: package "cosmossdk.io/math" is being imported more than once (stylecheck)


[failure] 20-20:
ST1019(related information): other import of "cosmossdk.io/math" (stylecheck)


82-84: Verify staking tokens comment accuracy

The comment for StakingTokens states it's "for every supported asset", but it's not clear how this is enforced or where the supported assets are defined. Please verify if this is accurate and consider adding more context.

@leonz789 leonz789 changed the title [WIP] e2e test network e2e test network Nov 8, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 14

🧹 Outside diff range and nitpick comments (30)
tests/e2e/oracle/oracle_test.go (2)

10-16: Add documentation for the test suite function.

Consider adding a descriptive comment explaining the purpose and setup of this e2e test suite.

+// TestE2ESuite initializes and runs end-to-end tests for the oracle package
+// using a single validator network configuration.
 func TestE2ESuite(t *testing.T) {

11-14: Consider extracting configuration values to constants.

The network configuration values are hardcoded. Consider extracting these to named constants with explanatory comments, especially if these values will be reused across other test files.

+const (
+    // DefaultValidatorCount defines the number of validators for e2e tests
+    DefaultValidatorCount = 1
+)
+
 func TestE2ESuite(t *testing.T) {
     cfg := network.DefaultConfig()
-    cfg.NumValidators = 1
+    cfg.NumValidators = DefaultValidatorCount
     cfg.CleanupDir = true
     cfg.EnableTMLogging = true
tests/e2e/bank/bank_test.go (2)

10-16: Add documentation and consider test coverage improvements.

While the test setup is functional, consider the following improvements:

  1. Add documentation explaining the purpose of this E2E test suite and its configuration choices
  2. Consider if single validator setup is sufficient for all E2E scenarios
  3. Document the expected behavior of NewE2ETestSuite

Add documentation like this:

+// TestE2ETestSuite initializes and runs the bank module's E2E test suite.
+// It sets up a single validator network configuration with cleanup enabled
+// and Tendermint logging disabled to focus on test outputs.
 func TestE2ETestSuite(t *testing.T) {

10-16: Expand test coverage for bank module operations.

Since this PR is WIP and test cases are pending, consider adding the following test scenarios:

  1. Bank module query operations (balances, total supply)
  2. Transaction operations (send, multi-send)
  3. Error cases (insufficient funds, invalid addresses)
  4. IBC token transfers (if applicable)

Would you like me to help create a GitHub issue tracking these test scenarios or provide example test implementations?

tests/e2e/basesuite.go (2)

8-13: Add documentation for BaseSuite struct and its fields.

Consider adding documentation to improve code maintainability:

+// BaseSuite provides a base test suite for E2E testing with network configuration and setup.
 type BaseSuite struct {
 	suite.Suite
 
+	// Cfg holds the network configuration for the test suite
 	Cfg     network.Config
+	// Network represents the running test network instance
 	Network *network.Network
 }

15-17: Add documentation and parameter validation to constructor.

Consider these improvements for better maintainability and robustness:

+// NewBaseSuite creates a new BaseSuite instance with the provided network configuration.
+// It initializes the Cfg field but leaves Network nil, which will be initialized in SetupSuite.
 func NewBaseSuite(cfg network.Config) *BaseSuite {
+	if cfg.NumValidators == 0 {
+		cfg.NumValidators = 1 // Set a default if not specified
+	}
 	return &BaseSuite{Cfg: cfg}
 }
tests/e2e/bank/suite.go (2)

8-13: Add documentation for the test suite struct and its fields.

Consider adding GoDoc comments to improve code documentation:

+// E2ETestSuite defines a test suite for bank module E2E tests
 type E2ETestSuite struct {
 	suite.Suite
 
+	// cfg holds the network configuration
 	cfg     network.Config
+	// network is the testing network instance
 	network *network.Network
 }

15-17: Enhance constructor with documentation and validation.

Consider adding documentation and basic validation:

+// NewE2ETestSuite creates a new E2E test suite with the given network configuration
 func NewE2ETestSuite(cfg network.Config) *E2ETestSuite {
+	if cfg.NumValidators == 0 {
+		cfg.NumValidators = 1 // Set default if not specified
+	}
 	return &E2ETestSuite{cfg: cfg}
 }
tests/e2e/oracle/suite.go (3)

8-13: Add documentation for the test suite struct.

Consider adding a documentation comment for the E2ETestSuite struct to describe its purpose and usage. This helps other developers understand how to use and extend the test suite.

+// E2ETestSuite defines a test suite for Oracle end-to-end testing.
+// It provides network configuration and setup for testing Oracle functionality
+// in a simulated network environment.
 type E2ETestSuite struct {
     suite.Suite
 
     cfg     network.Config
     network *network.Network
 }

15-17: Add documentation for the constructor.

The constructor should have a documentation comment explaining its purpose and parameters.

+// NewE2ETestSuite creates a new E2E test suite with the given network configuration.
+// It returns an initialized but not yet set up test suite instance.
 func NewE2ETestSuite(cfg network.Config) *E2ETestSuite {
     return &E2ETestSuite{cfg: cfg}
 }

19-26: Improve SetupSuite implementation.

Consider the following improvements to make the setup more robust and maintainable:

  1. Add cleanup in case of initialization failure
  2. Make the target block height configurable
  3. Add more descriptive error context
+// SetupSuite initializes the test network and ensures it reaches a minimum block height
+// before proceeding with tests.
 func (s *E2ETestSuite) SetupSuite() {
     s.T().Log("setting up e2e test suite")
     var err error
     s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
-    s.Require().NoError(err)
+    if err != nil {
+        s.T().Fatalf("failed to initialize test network: %v", err)
+    }
+
+    // Ensure cleanup on initialization failure
+    defer func() {
+        if err != nil && s.network != nil {
+            s.network.Cleanup()
+        }
+    }()
+
+    // Wait for network to produce blocks to ensure it's ready for testing
+    const minBlockHeight = 2 // Minimum height required for network stability
     _, err = s.network.WaitForHeight(2)
-    s.Require().NoError(err)
+    if err != nil {
+        s.T().Fatalf("failed waiting for network height: %v", err)
+    }
 }
tests/e2e/oracle/tx.go (2)

10-10: Consider using standard time layout constants.

Instead of defining a custom layout, consider using time.RFC3339 or other standard layouts from the time package for better consistency and maintainability.

-const layout = "2006-01-02 15:04:05"
+// Use time.RFC3339 or other standard layouts as needed

33-39: Document or implement empty test functions.

The empty test functions should either be implemented or documented with TODO comments explaining their intended purpose and test scenarios.

 func (s *E2ETestSuite) TestCreatePriceNST() {
-
+    // TODO: Implement test for NST price creation
+    // Test scenarios:
+    // 1. Create NST price with valid parameters
+    // 2. Verify price creation
 }

 func (s *E2ETestSuite) TestSlashing() {
-
+    // TODO: Implement slashing test
+    // Test scenarios:
+    // 1. Trigger slashing conditions
+    // 2. Verify slashing penalties
 }
🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 34-34:
File is not gofumpt-ed (gofumpt)


[failure] 38-38:
File is not gofumpt-ed (gofumpt)

testutil/network/tx.go (2)

11-12: Improve function documentation.

The current documentation is minimal. Consider adding details about:

  • Parameter requirements
  • Error conditions
  • Why synchronous broadcast is used
  • Example usage
-// SendTx construct and sign that tx with input msgs
+// SendTx constructs and broadcasts a transaction with the given messages.
+// It uses the first validator's client context and broadcasts synchronously.
+// Parameters:
+//   - msgs: List of messages to include in the transaction (must not be empty)
+//   - keyName: Name of the key in the keyring to sign with
+//   - keyring: Keyring containing the signing key
+// Returns an error if key lookup, address retrieval, or broadcast fails

25-34: Consider making gas adjustment configurable.

The gas adjustment factor of 1.5 is hardcoded. Consider making this configurable through the network configuration.

+// In network/config.go:
+type Config struct {
+    // ... existing fields ...
+    GasAdjustment float64
+}

+// In this file:
 txf := tx.Factory{}.
     WithChainID(ctx.ChainID).
     WithKeybase(keyring).
     WithTxConfig(ctx.TxConfig).
     WithSignMode(signing.SignMode_SIGN_MODE_DIRECT).
-    WithGasAdjustment(1.5).
+    WithGasAdjustment(n.Config.GasAdjustment).
     WithAccountRetriever(ctx.AccountRetriever).
     WithGasPrices(n.Config.MinGasPrices).
     WithSimulateAndExecute(true)
tests/e2e/util.go (1)

14-21: LGTM with a minor suggestion about context handling.

The function correctly implements the balance query using the bank module. Consider accepting a context parameter instead of creating a background context internally, to allow better control over timeouts and cancellation from the caller's side.

-func QueryNativeCoinBalance(address sdk.AccAddress, n *network.Network) (*banktypes.QueryBalanceResponse, error) {
-	return n.QueryBank().Balance(context.Background(), &banktypes.QueryBalanceRequest{
+func QueryNativeCoinBalance(ctx context.Context, address sdk.AccAddress, n *network.Network) (*banktypes.QueryBalanceResponse, error) {
+	return n.QueryBank().Balance(ctx, &banktypes.QueryBalanceRequest{
tests/e2e/bank/tx.go (5)

10-10: Add a descriptive comment for the test function.

Consider adding a comment that describes the test scenario and its objectives for better documentation.

+// TestSendCoin validates the following scenarios:
+// 1. A validator can send native coins to a new account
+// 2. The new account can send coins to another new account
 func (s *E2ETestSuite) TestSendCoin() {

12-12: Fix typo in comment.

The word "recieve" is misspelled and should be "receive".

-	// generate a new account with ethsecp256k1 to recieve/send native coins (hua)
+	// generate a new account with ethsecp256k1 to receive/send native coins (hua)
🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 12-12:
recieve is a misspelling of receive (misspell)


17-17: Consider extracting magic numbers into named constants.

The amount 2000000 should be defined as a constant at the package level for better maintainability and clarity.

+const (
+	// InitialTransferAmount represents the amount of coins to transfer in the first transaction
+	InitialTransferAmount = 2000000
+)

-	msg := banktypes.NewMsgSend(fromAddr, toAddr, sdk.NewCoins(sdk.NewCoin(s.network.Config.NativeDenom, sdkmath.NewInt(2000000))))
+	msg := banktypes.NewMsgSend(fromAddr, toAddr, sdk.NewCoins(sdk.NewCoin(s.network.Config.NativeDenom, sdkmath.NewInt(InitialTransferAmount))))

34-37: Remove redundant comment and extract magic number.

The comment on line 35 is redundant with the code. Also, consider extracting the transfer amount into a named constant.

+const (
+	SecondaryTransferAmount = 100
+)

 	msg = banktypes.NewMsgSend(toAddr, toAddr2, sdk.NewCoins(sdk.NewCoin(s.network.Config.NativeDenom, sdkmath.NewInt(100))))
-	// send sendCoinMsg
 	err = s.network.SendTx([]sdk.Msg{msg}, "user1", kr)

10-47: Consider enhancing test coverage and organization.

The test function could be improved in the following ways:

  1. Break down the test into subtests using t.Run() for better organization and clarity
  2. Add negative test cases to verify proper error handling, such as:
    • Insufficient balance
    • Invalid addresses
    • Zero amount transfers

This would provide more comprehensive test coverage of the bank module's functionality.

Would you like me to provide an example of how to restructure the test with these improvements?

🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 12-12:
recieve is a misspelling of receive (misspell)

crypto/algo_ed25519.go (3)

4-4: Clean up commented imports.

Remove the commented imports if they are no longer needed. If they will be used later, add a TODO comment explaining the intention.

-	// "github.com/cometbft/cometbft/crypto/ed25519"
+	// TODO: Switch to CometBFT's ed25519 implementation when X is implemented

Also applies to: 12-12


50-55: Enhance test safety measures.

The function modifies global state through SupportedAlgorithms which could affect other tests. Consider:

  1. Adding runtime checks to ensure this is only called in test environments
  2. Implementing a way to restore the previous algorithm list after tests
  3. Using a test-specific keyring configuration instead of modifying global state

Example implementation:

func Ed25519Option() keyring.Option {
    return func(options *keyring.Options) {
        if !isTestEnvironment() {
            panic("Ed25519Option is only for testing purposes")
        }
        // Store previous algorithms
        prevAlgos := options.SupportedAlgos
        options.SupportedAlgos = SupportedAlgorithms
        
        // Optional: Register cleanup in test context
        if t, ok := testing.T.(*testing.T); ok {
            t.Cleanup(func() {
                options.SupportedAlgos = prevAlgos
            })
        }
    }
}

1-55: Isolate test-only code to prevent production usage.

This file contains several non-standard implementations and security bypasses that are marked as "mainly for testing". To prevent accidental usage in production:

  1. Move the file to a testutil or similar test-specific directory
  2. Rename the package to cryptotest to make its purpose clear
  3. Add build tags to prevent compilation in production builds:
//go:build testing
// +build testing

Would you like assistance in restructuring this code to better isolate test utilities?

🧰 Tools
🪛 GitHub Check: Run golangci-lint

[warning] 32-32:
unused-parameter: parameter 'path' seems to be unused, consider removing or renaming it as _ (revive)


[failure] 44-44:
SA1019: ed25519.PrivKey is deprecated: PrivKey defines a ed25519 private key. NOTE: ed25519 keys must not be used in SDK apps except in a tendermint validator context. (staticcheck)

go.mod (1)

266-266: Remove TODO comment and provide clear documentation.

The TODO comment in the replacement directive for evmos fork should be removed and replaced with a clear explanation of why this fork is necessary.

-	// use exocore fork of evmos TODO
+	// use exocore fork of evmos for network testing compatibility
testutil/network/tx_internal.go (4)

24-24: Correct the function comment for clarity and grammar.

The function comment on line 24 contains grammatical errors that might reduce clarity. Please revise it for better readability.

Apply this diff to correct the function comment:

-// GenSignedTx construct a tx with input messages and sign it privatekey stored in keyring
+// genSignedTxInternal constructs a transaction with input messages and signs it using the private key stored in the keyring.

29-29: Remove commented-out code to improve code cleanliness.

The commented line // record, err := ctx.Keyring.Key(keyName) seems unnecessary and could be removed to keep the code clean.

Apply this diff:

-    // record, err := ctx.Keyring.Key(keyName)

54-63: Use proper parsing for MinGasPrices instead of substring manipulation.

Subtracting the length of n.Config.NativeDenom from len(n.Config.MinGasPrices) to extract minGasPriceStr is error-prone and may not work correctly if the format changes or if multiple denominations are specified. Consider using sdk.ParseDecCoins to parse MinGasPrices and extract the minimum gas price for the desired denomination.

Here's how you might refactor the code:

-    l := len(n.Config.MinGasPrices) - len(n.Config.NativeDenom)
-    fee := sdkmath.ZeroInt()
-    if l > 0 {
-        minGasPriceStr := n.Config.MinGasPrices[:l]
-        minGasPrice, err := sdkmath.NewIntFromString(minGasPriceStr)
-        if err != nil {
-            return nil, err
-        }
-        fee = gasLimitInt.Mul(minGasPrice)
-    }
+    fee := sdkmath.ZeroInt()
+    minGasPrices, err := sdk.ParseDecCoins(n.Config.MinGasPrices)
+    if err != nil {
+        return nil, err
+    }
+    minGasPrice := minGasPrices.AmountOf(n.Config.NativeDenom)
+    feeDec := minGasPrice.MulInt64(int64(gasLimit))
+    fee = feeDec.Ceil().TruncateInt()

73-73: Remove commented-out code to maintain code cleanliness.

The commented line // WithKeybase(ctx.Keyring) is unnecessary and can be removed to keep the code clean and maintainable.

Apply this diff:

-        // WithKeybase(ctx.Keyring).
testutil/network/util.go (1)

244-244: Correct typo in comment

There's a typo in the comment. "statse" should be "state".

Apply this diff to fix the typo:

-	// set oracle genesis statse
+	// set oracle genesis state
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 36e54dd and 1fd83d4.

📒 Files selected for processing (15)
  • crypto/algo_ed25519.go (1 hunks)
  • go.mod (1 hunks)
  • tests/e2e/bank/bank_test.go (1 hunks)
  • tests/e2e/bank/query.go (1 hunks)
  • tests/e2e/bank/suite.go (1 hunks)
  • tests/e2e/bank/tx.go (1 hunks)
  • tests/e2e/basesuite.go (1 hunks)
  • tests/e2e/oracle/oracle_test.go (1 hunks)
  • tests/e2e/oracle/suite.go (1 hunks)
  • tests/e2e/oracle/tx.go (1 hunks)
  • tests/e2e/util.go (1 hunks)
  • testutil/network/network.go (12 hunks)
  • testutil/network/tx.go (1 hunks)
  • testutil/network/tx_internal.go (1 hunks)
  • testutil/network/util.go (5 hunks)
🧰 Additional context used
🪛 GitHub Check: Run golangci-lint
crypto/algo_ed25519.go

[warning] 32-32:
unused-parameter: parameter 'path' seems to be unused, consider removing or renaming it as _ (revive)


[failure] 44-44:
SA1019: ed25519.PrivKey is deprecated: PrivKey defines a ed25519 private key. NOTE: ed25519 keys must not be used in SDK apps except in a tendermint validator context. (staticcheck)

tests/e2e/bank/tx.go

[failure] 12-12:
recieve is a misspelling of receive (misspell)

tests/e2e/oracle/tx.go

[failure] 14-14:
Error return value of s.network.WaitForHeight is not checked (errcheck)


[failure] 28-28:
Error return value of s.network.SendTx is not checked (errcheck)


[failure] 30-30:
Error return value of s.network.WaitForHeight is not checked (errcheck)


[failure] 34-34:
File is not gofumpt-ed (gofumpt)


[failure] 38-38:
File is not gofumpt-ed (gofumpt)

testutil/network/network.go

[failure] 19-19:
ST1019: package "cosmossdk.io/math" is being imported more than once (stylecheck)

🔇 Additional comments (26)
tests/e2e/oracle/oracle_test.go (3)

1-8: LGTM: Package and imports are well-structured.

The package name and imports are appropriate for an end-to-end test file.


15-15: 🛠️ Refactor suggestion

Add error handling for suite initialization.

The suite.Run() call assumes NewE2ETestSuite will always succeed. Consider adding error handling or validation for the suite initialization.

#!/bin/bash
# Check if NewE2ETestSuite has any error handling
rg -A 5 "NewE2ETestSuite.*error"

10-16: Verify NewE2ETestSuite implementation.

The code calls NewE2ETestSuite() but this function is not defined in the current file.

✅ Verification successful

NewE2ETestSuite implementation is properly defined

The NewE2ETestSuite function is correctly implemented in tests/e2e/oracle/suite.go. It initializes and returns an E2ETestSuite struct with the provided network configuration. The implementation includes:

  • A properly defined E2ETestSuite struct with required fields
  • A constructor function NewE2ETestSuite that takes a network.Config parameter
  • Associated setup methods for the test suite
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for NewE2ETestSuite implementation
echo "Searching for NewE2ETestSuite implementation..."
rg -A 5 "func NewE2ETestSuite"

# Search for E2ETestSuite struct definition
echo "Searching for E2ETestSuite struct definition..."
ast-grep --pattern "type E2ETestSuite struct {
  $$$
}"

Length of output: 512


Script:

#!/bin/bash
# Let's try a different approach to search for NewE2ETestSuite and E2ETestSuite
# Search in the same directory first
echo "Searching in oracle directory..."
rg -l "NewE2ETestSuite|E2ETestSuite" tests/e2e/oracle/

# Then search in the entire codebase
echo "Searching in entire codebase..."
rg -l "NewE2ETestSuite|E2ETestSuite"

# Get the content of files that contain these terms
echo "Content of relevant files:"
rg "type E2ETestSuite|func NewE2ETestSuite" -A 10

Length of output: 2396

tests/e2e/bank/bank_test.go (2)

1-8: LGTM! Package and imports are well-structured.

The package name matches the directory structure, and imports are appropriately organized.


10-16: Verify test coverage with multiple validators.

The current setup uses a single validator which might not catch issues that only appear in a multi-validator setup.

Let's check if there are other E2E tests that might require multiple validators:

tests/e2e/bank/query.go (2)

1-6: LGTM!

The package declaration and imports are appropriate and follow Go conventions.


9-9: Verify helper function implementation

The test relies on e2e.QueryNativeCoinBalance helper function. Let's ensure it properly handles edge cases and error conditions.

✅ Verification successful

Let me gather more information about the error handling in the bank query implementation.


Let me check the actual implementation of the bank query client to understand the error handling at the network level.


Based on the gathered information, I can now provide the final response:

Helper function implementation is adequately handling errors

The QueryNativeCoinBalance implementation in tests/e2e/util.go properly:

  • Uses the network's bank query client which handles RPC communication
  • Passes both address and denom validation through the standard SDK types
  • Returns errors through the standard error interface

The function is simple and delegates the actual work to the well-tested SDK bank module, making additional error checks unnecessary in this helper.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the implementation of QueryNativeCoinBalance helper function
# Expected: Find the implementation and verify error handling

# Search for the QueryNativeCoinBalance function implementation
echo "Searching for QueryNativeCoinBalance implementation..."
ast-grep --pattern 'func QueryNativeCoinBalance($_, $_) $$ {
  $$$
}'

# Look for error handling patterns in the implementation
echo "Checking error handling..."
rg -A 5 "QueryNativeCoinBalance.*\{" 

Length of output: 707


Script:

#!/bin/bash
# Check the QueryBalance implementation in the bank module
echo "Checking bank.Balance implementation..."
rg -A 10 "Balance.*\{.*QueryBalanceRequest" 

# Check if there are any test cases for error scenarios
echo "Checking test cases..."
rg -A 5 "TestQueryNativeCoinBalance|TestBalance.*func"

# Look for any related error handling patterns
echo "Checking error handling patterns..."
rg "ErrInvalidAddress|ErrInvalidDenom" 

Length of output: 1229


Script:

#!/bin/bash
# Check the network bank query client implementation
echo "Checking network bank query implementation..."
rg -A 10 "type BankQuery.*struct|func.*BankQuery" tests/

# Check for any error handling in the e2e test setup
echo "Checking e2e test setup error handling..."
rg -A 5 "network.*Error|ValidateBasic" tests/e2e/

Length of output: 304

tests/e2e/basesuite.go (2)

1-7: LGTM!

The package name and imports are appropriate for the e2e testing framework.


19-26: 🛠️ Refactor suggestion

Enhance SetupSuite with better documentation and error handling.

While the basic setup is good, consider these improvements for better robustness:

+// SetupSuite implements suite.SetupAllSuite interface.
+// It initializes the test network and ensures it reaches a stable state before tests begin.
 func (s *BaseSuite) SetupSuite() {
 	s.T().Log("setting up e2e test suite")
 	var err error
+	
+	// Initialize network with provided configuration
 	s.Network, err = network.New(s.T(), s.T().TempDir(), s.Cfg)
 	s.Require().NoError(err)
+	
+	// Ensure network is stable and producing blocks
+	s.T().Log("waiting for network to produce blocks")
 	_, err = s.Network.WaitForHeight(2)
 	s.Require().NoError(err)
+	
+	s.T().Log("network setup completed successfully")
 }

Also consider adding:

  1. A configurable minimum height parameter
  2. A TearDownSuite method for proper cleanup
  3. Context with timeout for network initialization
tests/e2e/bank/suite.go (2)

1-7: LGTM! Package and imports are well-structured.

The package name and imports are appropriate for an E2E test suite.


1-26: Verify integration with other test components.

Since this is part of a larger test framework implementation:

  1. Ensure this test suite integrates with other components (gentx, queryclient, ed25519)
  2. Consider adding test coverage requirements
✅ Verification successful

Test suite integration is properly implemented

The verification shows that:

  • Both bank and oracle test suites follow consistent patterns using the shared network configuration
  • Common utility functions in util.go are available across test suites
  • Test suites properly inherit from BaseSuite and implement consistent SetupSuite patterns
  • Test coverage is managed through standard Go testing framework

No additional integration requirements or coverage configurations are needed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for other test components and potential integration points
echo "Checking for related test components..."
rg -l "E2ETestSuite" tests/e2e/

echo "Checking for test coverage configuration..."
fd -g "*test*.go" tests/e2e/ --exec grep -l "coverage"

Length of output: 468


Script:

#!/bin/bash
# Check integration patterns between test components
echo "Checking integration patterns in bank suite..."
rg -A 5 "func.*Test" tests/e2e/bank/bank_test.go

echo "Checking oracle suite integration..."
rg -A 5 "func.*Test" tests/e2e/oracle/oracle_test.go

echo "Checking utility functions used across suites..."
cat tests/e2e/util.go

echo "Checking common setup patterns..."
rg "SetupSuite|TearDownSuite" tests/e2e/

Length of output: 2430

tests/e2e/oracle/suite.go (1)

3-7: LGTM: Clean and appropriate imports.

The imports are minimal and correctly include the necessary packages for E2E testing.

tests/e2e/oracle/tx.go (1)

1-8: LGTM: Package and imports are well-structured.

testutil/network/tx.go (2)

1-9: LGTM! Clean and well-organized imports.

The package declaration and imports are appropriate for the functionality being implemented.


12-37: Verify the impact on existing test cases.

This new SendTx method might be used by existing test cases. We should verify that the synchronous broadcast mode is appropriate for all use cases.

✅ Verification successful

Let's examine the usage of SendTx in these files to understand the context better.


Based on the search results, I can now generate the final response as the usage pattern is clear.

The synchronous broadcast mode is appropriate for the existing test cases

The current implementation using BroadcastSync mode is correct because:

  • All test cases using SendTx follow it with either WaitForNextBlock() or WaitForHeight() calls
  • This pattern ensures proper transaction inclusion verification in the test scenarios
  • Examples found in:
    • tests/e2e/bank/tx.go: Uses WaitForNextBlock()
    • tests/e2e/oracle/tx.go: Uses WaitForHeight()
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for existing test cases that might be affected by this new method
rg -l "SendTx.*\(" --type go

Length of output: 129


Script:

#!/bin/bash
# Check the usage of SendTx in test files
rg "SendTx.*\(" -A 5 --type go

Length of output: 1749

tests/e2e/util.go (1)

23-27: LGTM!

The function correctly implements coin creation using the native denomination from network configuration.

go.mod (2)

Line range hint 267-272: Security improvements in dependency replacements.

The replacement directives include important security fixes:

  1. Gin-gonic update addressing security advisory GHSA-h395-qcrw-5vmq
  2. Goleveldb fix for broken version
  3. Cosmos-SDK fork enabling Ledger functionality

These changes enhance the security posture of the codebase.


Line range hint 1-272: Verify dependency version compatibility for e2e testing.

The dependencies appear to be correctly configured for the e2e test network implementation. However, please verify the compatibility between the following critical dependencies:

  1. github.com/evmos/cosmos-sdk v0.47.5-evmos.2
  2. github.com/ExocoreNetwork/evmos/v16 v16.0.3-0.20240828081344-d5cfcd34a812
  3. github.com/evmos/go-ethereum v1.10.26-evmos-rc2

These versions should be tested together to ensure they work correctly with the e2e test network components (gentx, queryclient, ed25519).

✅ Verification successful

Based on the search results, I can now generate a final response since I have enough information to verify the dependency compatibility:

Dependencies are correctly configured and compatible for e2e testing

The verification shows that:

  • The Cosmos SDK fork (github.com/evmos/cosmos-sdk v0.47.5-evmos.2) is consistently used across the codebase
  • The Evmos fork (github.com/ExocoreNetwork/evmos/v16) and go-ethereum fork (github.com/evmos/go-ethereum) are properly integrated in key components:
    • EVM module and keeper
    • Precompiles
    • App initialization
    • Transaction handling
    • Network testing utilities

The dependencies work together to support e2e testing functionality, particularly for:

  • Transaction signing and verification
  • State transitions
  • Network setup
  • Contract interactions
  • Keeper operations
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify dependency compatibility by checking import usage
# Test: Search for imports of these packages to ensure correct usage
echo "Checking cosmos-sdk imports..."
rg -l "github.com/cosmos/cosmos-sdk" --type go

echo "Checking evmos imports..."
rg -l "github.com/evmos/evmos/v16" --type go

echo "Checking go-ethereum imports..."
rg -l "github.com/ethereum/go-ethereum" --type go

Length of output: 22366

testutil/network/network.go (5)

19-20: Remove duplicate import.

This issue was previously identified in an earlier review. The package "cosmossdk.io/math" is imported twice.

🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 19-19:
ST1019: package "cosmossdk.io/math" is being imported more than once (stylecheck)


489-497: LGTM! Improved deterministic network setup.

Good improvements:

  1. Sorting addressesIPs ensures consistent peer configuration
  2. Clear persistent peers setup for each validator

437-439: Simplification of validator token setup needs verification.

The token setup has been simplified to only use NativeDenom. Please verify:

  1. This doesn't break staking functionality
  2. Validators have sufficient tokens for operation
  3. Test scenarios aren't affected by removed token types
#!/bin/bash
# Check for dependencies on multiple token types
rg "sdk.NewCoin.*token"

85-91: Verify the impact of reduced timeout and token amounts.

Several significant changes have been made:

  1. TimeoutCommit reduced from 3s to 2s
  2. Token amounts significantly reduced
  3. BondDenom replaced with NativeDenom

Please ensure these changes don't affect:

  • Network stability with reduced timeout
  • Test scenarios that depend on specific token amounts

Also applies to: 117-117, 124-126

✅ Verification successful

Let me check the actual usage of these configurations to better understand the impact.


Let me check one more thing to understand if there are any test failures or issues reported due to these changes.


Based on the gathered information, I can now provide the final response:

Changes to timeout and denominations are safe to proceed

The modifications are well-contained and aligned with the codebase:

  • TimeoutCommit reduction to 2s is only used in test networks and doesn't affect production
  • BondDenom to NativeDenom change is a rename that maintains consistency, as the value "hua" remains unchanged
  • Token amount reductions are test-specific and don't impact production environments

The changes are properly reflected in:

  • Test configurations in testutil/network/network.go
  • Test setup files that reference these values
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any test files that might be affected by these changes
rg -l "TimeoutCommit.*3.*Second" 
rg -l "BondDenom"

Length of output: 302


Script:

#!/bin/bash
# Check the context of BondDenom usage and TimeoutCommit in the affected files
rg "BondDenom" -A 3 -B 3 testutil/network/network.go app/ante/utils/setup_test.go app/ante/cosmos/setup_test.go app/ante/evm/setup_test.go
rg "TimeoutCommit" -A 3 -B 3 testutil/network/network.go

Length of output: 4112


Script:

#!/bin/bash
# Check for any test files that might be using these configurations
rg "cfg\.TimeoutCommit" -A 3 -B 3
rg "DefaultConfig\(\)" -A 10 -B 3 testutil/network/network.go

Length of output: 1623


384-389: Verify the switch to Ed25519 signing algorithm.

The change from EthSecp256k1 to Ed25519 for key generation is significant. Please ensure:

  1. This aligns with the network's consensus requirements
  2. All dependent components support Ed25519
  3. No compatibility issues with existing keys
✅ Verification successful

Let me gather more information about the cryptographic setup to verify the changes.


Based on the extensive search results, I can now provide a final response regarding the switch to Ed25519.

The switch to Ed25519 signing algorithm is valid and properly supported.

The codebase shows:

  1. Ed25519 is explicitly supported as part of the supported algorithms (crypto/algo_ed25519.go)
  2. The consensus system is designed to work with Ed25519 keys (types/keys/consensus.go)
  3. The operator module has proper handling for Ed25519 consensus keys (x/operator/types/tx.pb.go)
  4. There's no tight coupling to EthSecp256k1 for consensus operations

The change aligns with the network's consensus requirements and maintains compatibility with the existing infrastructure.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any dependencies on EthSecp256k1
rg "EthSecp256k1"
# Check for Ed25519 support in related files
rg "Ed25519"

Length of output: 1916


Script:

#!/bin/bash
# Check for supported algorithms configuration
ast-grep --pattern 'SupportedAlgorithms = $_'

# Check for any key generation or validation logic
ast-grep --pattern 'func NewMnemonic($$$) {
  $$$
}'

# Check for any consensus key related configurations
rg -A 3 "consensus.*key" --type go

Length of output: 32896

testutil/network/util.go (3)

17-18: Consolidate duplicate imports of github.com/cosmos/cosmos-sdk/types

The imports at lines 17 and 18 both reference github.com/cosmos/cosmos-sdk/types but use different aliases (sdk and sdktypes). This can lead to confusion and inconsistencies in the codebase.


293-349: Avoid mutating global variables in NewGenStateAssets

The function NewGenStateAssets modifies the global variable DefaultGenStateAssets. Mutating global state can lead to unintended side effects and makes the code harder to test and maintain.


358-358: Add overflow protection for stakingAmount calculations

The multiplication of stakingAmount with the number of tokens could potentially overflow for large values.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

🧹 Outside diff range and nitpick comments (13)
tests/e2e/oracle/data.go (1)

9-13: Consider using time.Time for timestamp field.

While the current implementation works, using time.Time instead of string for the Timestamp field would provide better type safety and built-in parsing/formatting capabilities.

 type priceTime struct {
 	Price     string
 	Decimal   int32
-	Timestamp string
+	Timestamp time.Time
 }
tests/e2e/oracle/create-price.go (3)

14-47: Add documentation for test scenarios

The test involves complex interactions between validators and blockchain height progression. Consider adding documentation to explain the test flow and expected behavior.

Add comments explaining:

  • The purpose of moving to specific heights
  • Why two validators are needed
  • The expected state after each operation
🧰 Tools
🪛 GitHub Check: CodeQL

[warning] 40-40: Useless assignment to local variable
This definition of err is never used.


49-55: Implement or document empty test functions

The test functions TestCreatePriceNST and TestSlashing are empty. These should either be implemented or documented with TODO comments explaining their intended purpose.

Would you like me to help create test cases for these functions or create GitHub issues to track their implementation?


57-67: Add documentation for utility functions

The utility functions moveToAndCheck and moveNAndCheck would benefit from documentation explaining their purpose and usage.

Add godoc comments:

+ // moveToAndCheck advances the blockchain to a specific height and verifies the operation
 func (s *E2ETestSuite) moveToAndCheck(height int64) {

+ // moveNAndCheck advances the blockchain by n blocks and verifies each advancement
 func (s *E2ETestSuite) moveNAndCheck(n int64) {
testutil/network/tx.go (3)

25-27: Fix typos in function name and comments

Several typos need to be corrected:

  • Function name: "Createprice" should be "CreatePrice"
  • Comments: "consturct" → "construct", "senario" → "scenario", "unexists" → "non-existent"

Apply this diff to fix the typos:

-// SendTxOracleCreatePrice consturct and sign that tx with input msgs, it's different from SendTx, since when we use ed25519 for oracle senario, we allowed that signer is an unexists account, this implementation skip the 'accoutn exists' related checks
+// SendTxOracleCreatePrice constructs and signs a tx with input msgs. It's different from SendTx since when we use ed25519 for oracle scenario,
+// we allow the signer to be a non-existent account. This implementation skips the 'account exists' related checks.
 // Also, if you want to sign some normal message (not oracle-create-price) with ed25519, just use SendTx is fine, we support ed25519 signing in keyring
-func (n *Network) SendTxOracleCreateprice(msgs []sdk.Msg, keyName string, keyring keyring.Keyring) error {
+func (n *Network) SendTxOracleCreatePrice(msgs []sdk.Msg, keyName string, keyring keyring.Keyring) error {

57-62: Improve error handling and documentation

The function returns the result of PrintProto without documenting the expected output format or handling potential formatting errors.

Consider returning the broadcast result directly and let the caller handle the formatting:

-    return ctx.PrintProto(res)
+    return nil

Or improve the documentation to explain the output format:

+// SendTxOracleCreatePrice constructs, signs and broadcasts a transaction. It returns an error if any operation fails.
+// On success, it prints the transaction response in Protocol Buffer JSON format to the configured output writer.
 func (n *Network) SendTxOracleCreatePrice(msgs []sdk.Msg, keyName string, keyring keyring.Keyring) error {

64-89: Improve configuration flexibility and validation

The function has several areas for improvement:

  1. Broadcast mode is hardcoded to sync
  2. No validation for minGasPrice format
  3. No validation for gas adjustment value
  4. Factory pattern could be more fluent

Consider these improvements:

-func generateTxf(ctx client.Context, keyName string, kr keyring.Keyring, adjustment float64, minGasPrice string) (tx.Factory, client.Context, error) {
+func generateTxf(ctx client.Context, keyName string, kr keyring.Keyring, opts TxFactoryOptions) (tx.Factory, client.Context, error) {
+    if opts.GasAdjustment <= 0 {
+        return txf, ctx, fmt.Errorf("gas adjustment must be positive")
+    }
+    if opts.MinGasPrice == "" {
+        return txf, ctx, fmt.Errorf("min gas price cannot be empty")
+    }
     // ... existing code ...
-    txf = tx.Factory{}.
-        WithChainID(ctx.ChainID).
+    txf = tx.NewFactory(ctx.ChainID).
         WithKeybase(kr).
         WithTxConfig(ctx.TxConfig).
         WithSignMode(signing.SignMode_SIGN_MODE_DIRECT).
-        WithGasAdjustment(adjustment).
+        WithGasAdjustment(opts.GasAdjustment).
         WithAccountRetriever(ctx.AccountRetriever).
-        WithGasPrices(minGasPrice).
+        WithGasPrices(opts.MinGasPrice).
-        WithSimulateAndExecute(true)
+        WithSimulateAndExecute(opts.SimulateAndExecute)

-    ctx.BroadcastMode = flags.BroadcastSync
+    ctx.BroadcastMode = opts.BroadcastMode
     return txf, ctx, nil
 }

+// TxFactoryOptions contains configurable options for transaction factory
+type TxFactoryOptions struct {
+    GasAdjustment     float64
+    MinGasPrice       string
+    BroadcastMode     flags.BroadcastMode
+    SimulateAndExecute bool
+}
go.mod (1)

269-270: Version pinning recommendation for evmos fork.

The evmos fork is pinned to a specific version tag. Consider adding a comment explaining why this specific version is required.

Add a comment explaining the version requirement:

  // use Evmos geth fork
+ // Pin to rc2 for compatibility with evmos v16.0.0
  github.com/ethereum/go-ethereum => github.com/evmos/go-ethereum v1.10.26-evmos-rc2
app/ante/cosmos/sigverify.go (3)

73-75: Enhance error message for better debugging

While the signature verification logic is correct, the error message could be more descriptive to aid in debugging.

-				return ctx, sdkerrors.ErrInvalidPubKey.Wrapf("pubKey does not match signer address %s with signer index: %d", signers[i], i)
+				return ctx, sdkerrors.ErrInvalidPubKey.Wrapf("public key verification failed: expected signer %s but got %s at index %d", signers[i], pk.Address(), i)

Line range hint 1-577: Review architectural approach for oracle transaction validation

The current implementation creates a separate validation path for oracle transactions by bypassing standard Cosmos SDK transaction validation mechanisms. This architectural decision has several implications:

  1. It breaks the uniform transaction processing model of Cosmos SDK.
  2. It makes security auditing more complex due to special cases.
  3. It might make future upgrades and maintenance more difficult.

Consider implementing oracle transaction validation using Cosmos SDK's standard validation pipeline with custom validation decorators instead of bypassing the existing ones.


Line range hint 1-577: Standardize error handling across decorators

The error handling patterns vary across different decorators. Consider standardizing the approach:

  1. Use consistent error wrapping patterns.
  2. Provide detailed context in error messages.
  3. Consider adding error codes for different validation failures.

Example improvement:

- return ctx, sdkerrors.ErrTxDecode.Wrap("invalid transaction type")
+ return ctx, sdkerrors.ErrTxDecode.Wrapf(
+   "invalid transaction type: expected SigVerifiableTx, got %T",
+   tx,
+ )
testutil/network/network.go (2)

488-496: Well-structured peer configuration implementation

The new code segment efficiently handles peer configuration:

  1. Sorts address IPs for consistent peer ordering
  2. Sets persistent peers for each validator
  3. Properly writes configuration to files

However, consider adding error handling for the config file write operation.

Consider adding error handling:

-tmcfg.WriteConfigFile(filepath.Join(cfgTmp.RootDir, "config", "config.toml"), cfgTmp)
+err := tmcfg.WriteConfigFile(filepath.Join(cfgTmp.RootDir, "config", "config.toml"), cfgTmp)
+if err != nil {
+    return nil, fmt.Errorf("failed to write validator %d config file: %w", i, err)
+}

499-500: Consider making commission rate configurable

The commission rate is hardcoded to "0.5". Consider making this a configurable parameter in the Config struct for better flexibility in testing different scenarios.

Add a new field to Config struct:

type Config struct {
    // ... existing fields ...
+   CommissionRate string // default: "0.5"
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1fd83d4 and fe0a6a4.

📒 Files selected for processing (8)
  • app/ante/cosmos/sigverify.go (1 hunks)
  • crypto/algo_ed25519.go (1 hunks)
  • go.mod (1 hunks)
  • tests/e2e/oracle/create-price.go (1 hunks)
  • tests/e2e/oracle/data.go (1 hunks)
  • tests/e2e/oracle/oracle_test.go (1 hunks)
  • testutil/network/network.go (12 hunks)
  • testutil/network/tx.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/e2e/oracle/oracle_test.go
🧰 Additional context used
📓 Learnings (1)
testutil/network/network.go (1)
Learnt from: bwhour
PR: ExocoreNetwork/exocore#222
File: precompiles/avs/avs_test.go:8-11
Timestamp: 2024-11-10T20:28:27.115Z
Learning: `math/big` and `cosmossdk.io/math` are different libraries and should not be considered duplicate imports.
🪛 GitHub Check: CodeQL
tests/e2e/oracle/create-price.go

[warning] 40-40: Useless assignment to local variable
This definition of err is never used.

tests/e2e/oracle/data.go

[warning] 33-33: Calling the system time
Calling the system time may be a possible source of non-determinism


[warning] 42-42: Calling the system time
Calling the system time may be a possible source of non-determinism

🔇 Additional comments (13)
tests/e2e/oracle/data.go (2)

1-7: LGTM! Clean package structure and imports.

The package is well-organized with appropriate imports.


15-30: LGTM! Well-structured conversion methods.

The methods provide clean conversion between internal and external types.

crypto/algo_ed25519.go (2)

19-23: LGTM!

The struct definition and Name method implementation are correct and straightforward.


36-43: Duplicate of previous review comment

The security concerns about validation and deprecated type usage have been previously raised.

tests/e2e/oracle/create-price.go (2)

1-10: LGTM: Package structure and imports are well organized.


1-67: Verify test suite initialization

The test file uses E2ETestSuite, but the suite setup is not visible in this file.

Let's verify the test suite setup:

✅ Verification successful

Let me gather more information about the test suite setup and initialization:


Test suite is properly initialized

The E2ETestSuite is well-structured with proper initialization:

  • Defined in tests/e2e/oracle/suite.go with required fields (network config and network instance)
  • Implements SetupSuite() that initializes the network and waits for initial blocks
  • The test methods in the reviewed file use the initialized network instance for testing
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for E2ETestSuite setup in related files
echo "Searching for test suite setup..."
rg -A 10 "type E2ETestSuite struct" tests/e2e/

Length of output: 1050


Script:

#!/bin/bash
# Search for SetupSuite or similar setup methods in the oracle test suite
echo "Searching for test suite setup methods..."
rg -A 10 "func \(.*E2ETestSuite\) Setup" tests/e2e/oracle/

Length of output: 606

🧰 Tools
🪛 GitHub Check: CodeQL

[warning] 40-40: Useless assignment to local variable
This definition of err is never used.

go.mod (3)

Line range hint 271-272: Verify security fix for gin-gonic/gin.

The replacement addresses security advisory GHSA-h395-qcrw-5vmq. Let's verify if v1.9.1 is still the latest secure version.

#!/bin/bash
# Description: Check for newer versions of gin-gonic/gin and any new security advisories

# Check latest version
gh api repos/gin-gonic/gin/releases/latest --jq .tag_name

# Check for security advisories
gh api graphql -f query='
{
  securityVulnerabilities(first: 5, ecosystem: GO, package: "github.com/gin-gonic/gin") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

268-269: Verify gogoproto version compatibility.

The replace directive for gogoproto is marked with "fix cosmos-sdk error". Let's verify if this version is still required.

#!/bin/bash
# Description: Check gogoproto version compatibility with cosmos-sdk

# Search for gogoproto version requirements in cosmos-sdk
cd /Users/linqing/workplace/github.com/leonz/evmos-cosmossdk/cosmos-sdk
rg -A 5 "github.com/cosmos/gogoproto" go.mod

# Check for any version-related issues
gh issue list -R cosmos/cosmos-sdk -l "dependencies,gogoproto" --json number,title,state | jq -r '.[] | "\(.number): \(.title) [\(.state)]"'

265-267: Verify the commented-out replace directive.

The commented-out replace directive suggests a transition from evmos/cosmos-sdk to a local fork. Please verify if this change is intentional and if the local fork contains necessary changes.

app/ante/cosmos/sigverify.go (1)

Line range hint 273-290: Review oracle transaction signature verification

The current implementation has several security considerations:

  1. The TODO comment about multi-sig support needs to be addressed.
  2. The signature verification for oracle transactions skips some standard checks.
  3. There's no explicit error handling if VerifySignature fails.

Let's verify the oracle transaction handling across the codebase:

testutil/network/network.go (3)

19-20: Skip review of duplicate imports

A past review comment already addresses the duplicate import of "cosmossdk.io/math". The comment is still valid and applicable.


85-101: Config struct changes improve clarity and functionality

The changes to the Config struct are well-structured:

  • Removed BondDenom in favor of NativeDenom for better semantic clarity
  • Added DepositedTokens for managing staked assets
  • Updated comments to better describe field purposes

379-406: Improved key generation and node initialization process

The changes enhance the node setup process:

  • Uses Ed25519 for validator consensus keys
  • Properly initializes node validator files from mnemonic
  • Generates and stores node IDs and addresses systematically

Comment on lines 17 to 18
priceTest1 := price1.updateTimestamp()
priceTimeDetID := priceTest1.getPriceTimeDetID("9")
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix undefined variable reference

The variable price1 is undefined. This will cause compilation errors.

Please define the price1 variable or use the correct reference. Consider adding a helper function to create test price data:

func createTestPrice() *oracletypes.Price {
    return &oracletypes.Price{
        // Add necessary fields
    }
}

if err != nil {
return err
}
gasAdjusted := uint64(txf.GasAdjustment() * float64(simRes.GasInfo.GasUsed))

Check notice

Code scanning / CodeQL

Floating point arithmetic Note test

Floating point arithmetic operations are not associative and a possible source of non-determinism
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (15)
x/oracle/keeper/aggregator/util.go (1)

5-10: Add documentation for the copyBigInt function

The implementation is correct and safely handles nil cases. However, consider adding a documentation comment to explain its purpose and behavior, especially since it's used across multiple places in the aggregator package.

+// copyBigInt creates a deep copy of a big.Int pointer.
+// Returns nil if the input is nil, otherwise returns a new independent copy.
 func copyBigInt(i *big.Int) *big.Int {
tests/e2e/oracle/oracle_test.go (2)

10-16: Add documentation for the test suite setup

The test function would benefit from documentation explaining the purpose of the e2e test suite and why specific configuration values were chosen (e.g., why 4 validators).

Consider adding a doc comment like:

+// TestE2ESuite initializes and runs the end-to-end test suite for the oracle package.
+// It configures a network with 4 validators to ensure proper consensus and price
+// feed validation across multiple nodes.
 func TestE2ESuite(t *testing.T) {

11-14: Consider extracting configuration values as constants

The network configuration values (4 validators, cleanup settings) could be extracted as named constants to improve maintainability and make the configuration more explicit.

Consider refactoring like this:

+const (
+    // DefaultValidatorCount defines the number of validators required for oracle consensus
+    DefaultValidatorCount = 4
+)
+
 func TestE2ESuite(t *testing.T) {
     cfg := network.DefaultConfig()
-    cfg.NumValidators = 4
+    cfg.NumValidators = DefaultValidatorCount
     cfg.CleanupDir = true
     cfg.EnableTMLogging = true
tests/e2e/oracle/data.go (2)

9-13: Consider improving type safety and adding documentation.

The struct could benefit from:

  1. Using a more appropriate type for Price (e.g., decimal.Decimal)
  2. Adding field validation
  3. Including documentation for the struct and its fields
+// priceTime represents a price entry with its metadata for testing purposes
 type priceTime struct {
+    // Price represents the asset price as a string (consider using decimal.Decimal)
     Price     string
+    // Decimal indicates the number of decimal places in the price
     Decimal   int32
+    // Timestamp represents the UTC time when the price was recorded
     Timestamp string
 }

49-60: Document test data significance.

The test price values (199999 and 299999) seem arbitrary. Consider adding comments explaining what these values represent and why they were chosen for testing.

 var (
+    // price1 represents a test price of 1.99999 with 18 decimal places
     price1 = priceTime{
         Price:     "199999",
         Decimal:   18,
         Timestamp: time.Now().UTC().Format(layout),
     }
+    // price2 represents a test price of 2.99999 with 18 decimal places
     price2 = priceTime{
         Price:     "299999",
         Decimal:   18,
         Timestamp: time.Now().UTC().Format(layout),
     }
 )
x/oracle/keeper/aggregator/calculator.go (1)

Line range hint 1-190: Consider architectural improvements for scalability.

The current implementation maintains multiple price lists and creates deep copies, which could impact performance at scale. Consider the following improvements:

  1. Cache confirmed prices to avoid redundant calculations
  2. Implement pruning for old rounds to manage memory usage
  3. Consider using a more efficient data structure for price lookups

Would you like me to provide a detailed proposal for implementing these improvements?

x/oracle/keeper/aggregator/aggregator.go (1)

Line range hint 1-200: Address architectural concerns before production use.

Several critical issues need attention:

  1. Round ID Comparison: Using string comparison (id < priceSourceRound.detID) for round IDs is unsafe and could lead to incorrect ordering. Consider using numeric types.

  2. Error Handling: Price parsing with SetString ignores errors:

pTR.price, _ = (&big.Int{}).SetString(pSource.Prices[0].Price, 10)
  1. Incomplete Features: Multiple TODOs indicate unfinished functionality:

    • Different consensus modes
    • Rule implementations
    • Proper error handling
  2. Mock Implementation: The consensus mechanism is marked as "mock way to suite V1" which needs proper implementation.

Consider these fixes:

- if id := agg.dsPrices[priceSourceRound.sourceID]; len(id) == 0 || (len(id) > 0 && id < priceSourceRound.detID) {
+ roundID, err := strconv.ParseUint(priceSourceRound.detID, 10, 64)
+ if err != nil {
+     return fmt.Errorf("invalid round ID: %v", err)
+ }
+ currentRound, err := strconv.ParseUint(id, 10, 64)
+ if err != nil && len(id) > 0 {
+     return fmt.Errorf("invalid current round: %v", err)
+ }
+ if len(id) == 0 || currentRound < roundID {
- pTR.price, _ = (&big.Int{}).SetString(pSource.Prices[0].Price, 10)
+ var ok bool
+ pTR.price, ok = (&big.Int{}).SetString(pSource.Prices[0].Price, 10)
+ if !ok {
+     return fmt.Errorf("invalid price format: %s", pSource.Prices[0].Price)
+ }

Before deploying to production:

  1. Implement proper consensus mechanisms
  2. Add comprehensive error handling
  3. Complete the TODO items
  4. Add thorough testing for edge cases

Would you like me to help create GitHub issues to track these architectural improvements?

tests/e2e/oracle/create_price.go (5)

15-24: Enhance test case documentation readability

Consider improving the documentation:

  1. Complete the empty "nonce" section or remove it if not needed
  2. Format test cases using a more structured approach, e.g.:
/*
Test Cases (requiring >2/3 validator power):

Case 1: Initial Price Submission
- Block 1.1: V1 submits price P1 → No round 1 price (insufficient power)
- Block 1.2: V2 & V3 submit price P1 → Round 1 price P1 confirmed (sufficient power)

Case 2: Failed Price Update
...
*/

36-37: Remove commented-out code

Remove the commented-out code for validator 3 if it's not needed. If it will be used in future tests, add a TODO comment explaining the intention.


49-49: Define block height constants

Consider defining constants for block heights instead of using magic numbers (10, 11, 20, 30, 40). This would make the test more maintainable and the progression of blocks more clear.

+ const (
+   case1StartBlock = 10
+   case2StartBlock = 20
+   case3StartBlock = 30
+   case4StartBlock = 40
+ )

Also applies to: 60-60, 90-90, 118-118, 147-147


26-164: Refactor repeated test patterns

Consider creating helper functions for common operations to reduce code duplication:

  1. Price message creation
  2. Validator transaction submission
  3. Price verification

Example helper function:

func (s *E2ETestSuite) submitValidatorPrice(
    creator sdk.AccAddress,
    kr keyring.Keyring,
    valKey string,
    priceSource *oracletypes.PriceSource,
    height int64,
) error {
    msg := oracletypes.NewMsgCreatePrice(creator.String(), 1, []*oracletypes.PriceSource{priceSource}, height, 1)
    return s.network.SendTxOracleCreateprice([]sdk.Msg{msg}, valKey, kr)
}
🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 163-163:
File is not gofumpt-ed (gofumpt)


166-172: Document empty test functions

Add TODO comments to empty test functions explaining their intended purpose and implementation timeline.

 func (s *E2ETestSuite) TestCreatePriceNST() {
+    // TODO: Implement negative scenario tests for price creation
+    // - Invalid price submissions
+    // - Incorrect validator signatures
+    // - Out of order submissions
 }

 func (s *E2ETestSuite) TestSlashing() {
+    // TODO: Implement slashing tests for malicious behavior
+    // - Double signing
+    // - Invalid price submissions
+    // - Timeout violations
 }
🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 167-167:
File is not gofumpt-ed (gofumpt)

go.mod (1)

266-266: Remove TODO comment or provide context

The TODO comment in the replace directive for evmos fork needs to be addressed or removed. If there are pending tasks related to this fork, they should be documented properly.

Apply this change:

- // use exocore fork of evmos TODO
+ // use exocore fork of evmos for custom modifications
testutil/network/network.go (2)

85-92: Review the Config struct field changes.

The changes look good, but please add documentation for the new DepositedTokens field to clarify its purpose and relationship with other token fields.

 	AccountTokens     math.Int            // the amount of system tokens(e.g. 1000hua)
-	DepositedTokens   math.Int
+	DepositedTokens   math.Int            // the amount of tokens deposited for staking/validation
 	StakingTokens     math.Int // the amount of tokens each validator stakes for every supporte asset

436-438: Update token denomination handling.

The commented-out code suggests a transition in token denomination handling. Please clean up the old commented code since it's no longer needed.

 		balances := sdk.NewCoins(
-			//	sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), cfg.AccountTokens),
-			// sdk.NewCoin(cfg.BondDenom, cfg.DepositedTokens),
 			sdk.NewCoin(cfg.NativeDenom, cfg.AccountTokens),
 		)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between fe0a6a4 and 0967104.

📒 Files selected for processing (8)
  • go.mod (1 hunks)
  • tests/e2e/oracle/create_price.go (1 hunks)
  • tests/e2e/oracle/data.go (1 hunks)
  • tests/e2e/oracle/oracle_test.go (1 hunks)
  • testutil/network/network.go (12 hunks)
  • x/oracle/keeper/aggregator/aggregator.go (2 hunks)
  • x/oracle/keeper/aggregator/calculator.go (1 hunks)
  • x/oracle/keeper/aggregator/util.go (1 hunks)
🧰 Additional context used
📓 Learnings (1)
testutil/network/network.go (1)
Learnt from: bwhour
PR: ExocoreNetwork/exocore#222
File: precompiles/avs/avs_test.go:8-11
Timestamp: 2024-11-12T10:03:10.791Z
Learning: `math/big` and `cosmossdk.io/math` are different libraries and should not be considered duplicate imports.
🪛 GitHub Check: Run golangci-lint
tests/e2e/oracle/create_price.go

[failure] 163-163:
File is not gofumpt-ed (gofumpt)


[failure] 167-167:
File is not gofumpt-ed (gofumpt)


[failure] 179-179:
func (*E2ETestSuite).moveNAndCheck is unused (unused)

tests/e2e/oracle/data.go

[warning] 38-38:
unused-parameter: parameter 'sourceID' seems to be unused, consider removing or renaming it as _ (revive)

testutil/network/network.go

[failure] 19-19:
ST1019: package "cosmossdk.io/math" is being imported more than once (stylecheck)


[failure] 20-20:
ST1019(related information): other import of "cosmossdk.io/math" (stylecheck)

🔇 Additional comments (12)
x/oracle/keeper/aggregator/util.go (1)

5-10: Add unit tests for copyBigInt

As mentioned in the PR objectives about adding test cases, please ensure this utility function is covered by unit tests. The tests should verify:

  1. Copying non-nil big.Int values
  2. Handling nil input
  3. Verifying the returned copy is independent (modifications don't affect the original)

Would you like me to help generate comprehensive unit tests for this function?

tests/e2e/oracle/oracle_test.go (1)

1-9: LGTM: Package and imports are well-structured

The package name and imports are appropriate for an end-to-end test file, providing the necessary testing utilities and suite functionality.

x/oracle/keeper/aggregator/calculator.go (1)

78-86: LGTM! Good improvement in big.Int handling.

The use of copyBigInt instead of direct assignments improves safety by preventing unintended mutations through shared references. This is particularly important for consensus-critical values like price and power.

Let's verify the copyBigInt implementation is available and properly used:

Consider adding the following safety measures:

  1. Add debug logging when copies are made to help trace any potential issues
  2. Consider implementing value range validation for price and power values
✅ Verification successful

Verified: copyBigInt is correctly implemented and appropriately used across the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify copyBigInt implementation and usage
# Expected: Find copyBigInt definition and all its usages

# Find copyBigInt definition
echo "=== copyBigInt definition ==="
ast-grep --pattern 'func copyBigInt($_) *big.Int { $$$}'

# Find all copyBigInt usages
echo -e "\n=== copyBigInt usages ==="
rg 'copyBigInt\(' -A 2

Length of output: 2047

x/oracle/keeper/aggregator/aggregator.go (1)

53-55: Verify the implementation of copyBigInt and add documentation.

The changes consistently use copyBigInt for deep copying big.Int values, which is good for preventing shared references. However:

  1. Let's verify the implementation of copyBigInt
  2. The deep copy requirement should be documented

Add documentation to explain why deep copying is necessary:

 func (agg *aggregator) copy4CheckTx() *aggregator {
+    // Creates a deep copy of the aggregator for CheckTx validation
+    // Deep copying is required to prevent shared state between CheckTx and DeliverTx
     ret := &aggregator{

Also applies to: 65-66, 71-71

✅ Verification successful

copyBigInt implementation is correct. Add documentation for clarity.

  • Document the purpose and necessity of deep copying using copyBigInt in x/oracle/keeper/aggregator/util.go.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation of copyBigInt function
# Expected: Should find the implementation in util.go or similar files

# Search for copyBigInt implementation
rg -p "func copyBigInt" x/oracle/keeper/

# Search for imports of the file containing copyBigInt
rg -p "\"math/big\"" x/oracle/keeper/

Length of output: 898


Script:

# Retrieve the implementation of copyBigInt function in x/oracle/keeper/aggregator/util.go
ast-grep --pattern 'func copyBigInt($_)' x/oracle/keeper/aggregator/util.go

Length of output: 401

tests/e2e/oracle/create_price.go (1)

73-75: Add price value validation

The test verifies the presence of prices but doesn't validate the actual price values. Consider adding assertions to verify the correctness of the price values themselves.

Also applies to: 99-102, 132-135, 159-162

go.mod (3)

Line range hint 270-271: Security fix properly implemented

The replacement of gin-gonic/gin to address security advisory GHSA-h395-qcrw-5vmq is correctly implemented. The comment properly documents the security consideration.


267-267: Verify cosmos-sdk compatibility

The gogoproto version fix for cosmos-sdk error needs verification to ensure compatibility across the cosmos ecosystem packages.

Run the following script to verify version compatibility:

✅ Verification successful

Cosmos-SDK Compatibility Verified

The cosmos-sdk version v0.47.5-evmos.2 and gogoproto version v1.4.10 are compatible across the cosmos ecosystem packages. No version conflicts were found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check version compatibility between cosmos-related packages

# Check cosmos-sdk version in replace directive
echo "Checking cosmos-sdk version..."
rg "github.com/cosmos/cosmos-sdk =>" -A 1

# Check gogoproto version in replace directive
echo "Checking gogoproto version..."
rg "github.com/cosmos/gogoproto =>" -A 1

# Check for potential version conflicts in cosmos packages
echo "Checking for version conflicts..."
rg "cosmossdk.io/" --type go

Length of output: 17112


Line range hint 4-4: Verify Go version compatibility

The Go version 1.21.12 is quite specific. Ensure this version requirement aligns with all dependencies, especially the cosmos ecosystem packages.

Run the following script to check Go version compatibility:

✅ Verification successful

Go version compatibility verified successfully

All dependencies align with Go version 1.21.12, and no conflicting build constraints were found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check Go version compatibility with dependencies

# Check for any go.mod files in dependencies that might specify different Go versions
echo "Checking Go versions in dependencies..."
fd -t f "go.mod$" -x rg "^go \d+\.\d+(\.\d+)?"

# Check for any build constraints in .go files
echo "Checking Go build constraints..."
rg "^//\s*\+build\s+go\d+\.\d+(\.\d+)?"

Length of output: 265


Script:

#!/bin/bash
# Description: Comprehensive check for Go version compatibility across all dependencies

echo "Listing all go.mod files and their Go versions..."
fd -t f "go.mod$" | xargs -I {} rg "^go \d+\.\d+(\.\d+)?" {} --files-with-matches --no-filename --only-matching

echo "Searching for Go build constraints in .go files..."
rg "^//\s*go:\s*build\s+go\d+\.\d+(\.\d+)?" --type go

Length of output: 400

testutil/network/network.go (4)

488-496: LGTM: Improved peer configuration.

Good improvement in peer configuration:

  1. Sorting addressesIPs ensures consistent peer configuration
  2. Each validator gets all other validators as persistent peers
  3. Configuration is properly persisted to config.toml

19-20: ⚠️ Potential issue

Remove duplicate import of cosmossdk.io/math.

The package is imported twice, once as a direct import and once with an alias. Keep only the aliased import.

-	"cosmossdk.io/math"
 	sdkmath "cosmossdk.io/math"

Likely invalid or redundant comment.

🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 19-19:
ST1019: package "cosmossdk.io/math" is being imported more than once (stylecheck)


[failure] 20-20:
ST1019(related information): other import of "cosmossdk.io/math" (stylecheck)


379-389: Review the switch from eth-secp256k1 to ed25519.

The change from eth-secp256k1 to ed25519 for key generation is a significant architectural change. Please ensure:

  1. All dependent systems support ed25519 keys
  2. This change is documented in the changelog
  3. Migration path is provided for existing test keys

124-126: Verify token amounts are sufficient for test scenarios.

The token amounts have been significantly reduced:

  • AccountTokens: 1000 power
  • DepositedTokens: 500 power
  • StakingTokens: 200 power

Please ensure these amounts are sufficient for your test scenarios, especially with 4 validators.

@leonz789 leonz789 mentioned this pull request Nov 15, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Outside diff range and nitpick comments (16)
crypto/algo_ed25519.go (2)

28-29: Improve documentation for non-standard key derivation

The comments mention compatibility with genutil package but lack crucial details:

  1. What specific compatibility issues are being addressed?
  2. Why is standard SLIP-0010 derivation not suitable?
  3. What are the security implications of this approach?

Please enhance the documentation to explain these aspects for better maintainability.

Also applies to: 32-32


50-50: Clarify usage restrictions in documentation

The comment "mainly used for test" is ambiguous. If this is strictly for testing purposes, the documentation should explicitly state:

  1. This should never be used in production
  2. What specific test scenarios this is intended for
  3. What alternatives should be used in production

Consider updating the comment to be more explicit about these restrictions.

testutil/network/genesis_data.go (2)

42-51: Remove or document commented code alternatives

There are commented alternatives for initializing DefaultGenStateOperator and DefaultGenStateDelegation. Either:

  1. Remove the commented code if it's no longer needed
  2. Document why we're using empty states instead of DefaultGenesis()
  3. Use the DefaultGenesis() approach consistently across all states

60-70: Add function documentation

Add a documentation comment for the NewTestToken function explaining its purpose and parameters:

+// NewTestToken creates a new StakingAssetInfo for testing purposes.
+// Parameters:
+//   name: The token name
+//   metaInfo: Additional information about the token
+//   address: The token's contract address
+//   chainID: The LayerZero chain ID
+//   amount: The total staking amount
 func NewTestToken(name, metaInfo, address string, chainID uint64, amount int64) assetstypes.StakingAssetInfo {
testutil/network/network.go (5)

84-91: Review field naming and documentation.

The Config struct changes look good, but consider:

  • The comment for AccountTokens could be more specific about its purpose
  • The StakingTokens comment mentions "supporte" which has a typo
-	AccountTokens     sdkmath.Int         // the amount of system tokens(e.g. 1000hua)
+	AccountTokens     sdkmath.Int         // the amount of tokens initially allocated to each account (e.g. 1000hua)
-	StakingTokens     sdkmath.Int // the amount of tokens each validator stakes for every supporte asset
+	StakingTokens     sdkmath.Int // the amount of tokens each validator stakes for every supported asset

383-388: Consider error handling improvement.

The error handling for keyring algorithms could be more robust. Consider combining the error checks.

-	keyringAlgos, _ := kb.SupportedAlgorithms()
-	algo, err := keyring.NewSigningAlgoFromString(string(cosmoshd.Ed25519Type), keyringAlgos)
-	if err != nil {
-		return nil, err
-	}
+	keyringAlgos, err := kb.SupportedAlgorithms()
+	if err != nil {
+		return nil, fmt.Errorf("failed to get supported algorithms: %w", err)
+	}
+	algo, err := keyring.NewSigningAlgoFromString(string(cosmoshd.Ed25519Type), keyringAlgos)
+	if err != nil {
+		return nil, fmt.Errorf("failed to create signing algorithm: %w", err)
+	}

487-495: Improve peer configuration logic.

The peer configuration logic could be more efficient:

  • Consider pre-allocating the IPs slice
  • The string join operation could be moved outside the loop
sort.Strings(addressesIPs)
for i := 0; i < cfg.NumValidators; i++ {
	cfgTmp := network.Validators[i].Ctx.Config
-	IPs := make([]string, 0, cfg.NumValidators-1)
+	IPs := make([]string, 0, len(addressesIPs)-1)
	IPs = append(IPs, addressesIPs[0:i]...)
	IPs = append(IPs, addressesIPs[i+1:]...)
	cfgTmp.P2P.PersistentPeers = strings.Join(IPs, ",")
	tmcfg.WriteConfigFile(filepath.Join(cfgTmp.RootDir, "config", "config.toml"), cfgTmp)
}

498-499: Consider making commission rate configurable.

The commission rate is hardcoded to "0.5". Consider making this a configurable parameter in the Config struct.

+	// Add to Config struct
+	CommissionRate string // the validator commission rate (default: "0.5")

-	commissionRate, _ := sdkmath.LegacyNewDecFromStr("0.5")
+	commissionRate, err := sdkmath.LegacyNewDecFromStr(cfg.CommissionRate)
+	if err != nil {
+		return nil, fmt.Errorf("invalid commission rate: %w", err)
+	}

435-437: Clean up commented code.

Remove commented out code that's no longer needed.

-			//	sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), cfg.AccountTokens),
-			// sdk.NewCoin(cfg.BondDenom, cfg.DepositedTokens),
			sdk.NewCoin(cfg.NativeDenom, cfg.AccountTokens),
tests/e2e/oracle/create_price.go (3)

155-157: Implement TestCreatePriceNST or add a TODO comment

The function TestCreatePriceNST is currently empty. Please provide an implementation or add a TODO comment to indicate future work.

Would you like assistance in writing the test cases for this function?

🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 156-156:
File is not gofumpt-ed (gofumpt)


159-161: Implement TestSlashing or add a TODO comment

The function TestSlashing is currently empty. Please provide an implementation or add a TODO comment to indicate future work.

Would you like assistance in writing the test cases for this function?

🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 160-160:
File is not gofumpt-ed (gofumpt)


156-156: Format the code using gofumpt

Lines 156 and 160 are not formatted according to gofumpt standards. Please run gofumpt to format the code.

Also applies to: 160-160

🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 156-156:
File is not gofumpt-ed (gofumpt)

testutil/network/util.go (4)

44-44: Use math.MaxUint64 instead of hardcoded value

The constant MaxOptedOutHeight is defined as 18446744073709551615. To improve readability and align with standard library constants, consider using math.MaxUint64 for clarity.

Apply this change:

-const MaxOptedOutHeight uint64 = 18446744073709551615
+const MaxOptedOutHeight uint64 = math.MaxUint64

Don't forget to import the math package:

+import (
+    "math"
+    // other imports...
+)

428-428: Consider integer overflow checks in power calculation

At line 428, the calculation:

power := sdk.TokensToConsensusPower(stakingAmount.Mul(sdkmath.NewInt(int64(len(genStateAssets.Tokens)))), evmostypes.PowerReduction)

might risk integer overflow when stakingAmount and the number of tokens are large.

Consider adding overflow checks or using sdkmath.Int's Overflow() method to ensure safe calculations.


173-183: Set BaseFee directly from cfg.MinGasPrices if possible

The current logic slices cfg.MinGasPrices and attempts to parse it into an sdkmath.Int. This approach assumes a specific format of cfg.MinGasPrices.

If cfg.MinGasPrices is guaranteed to be in the correct format, consider simplifying the code:

-var feemarketGenState feemarkettypes.GenesisState
-cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[feemarkettypes.ModuleName], &feemarketGenState)
-l := len(cfg.MinGasPrices) - len(cfg.NativeDenom)
-minGasPrice := sdkmath.ZeroInt()
-if l > 0 {
-    minGasPriceStr := cfg.MinGasPrices[:l]
-    minGasPrice, _ = sdkmath.NewIntFromString(minGasPriceStr)
-}
-feemarketGenState.Params.BaseFee = minGasPrice
+feemarketGenState := feemarkettypes.DefaultGenesisState()
+feemarketGenState.Params.BaseFee = sdkmath.NewIntFromUint64(1)

Ensure that this change aligns with your application's requirements.


289-347: Avoid modifying global variables in genesis state functions

Functions like NewGenStateAssets modify DefaultGenStateAssets, which is a global variable. This practice can lead to unintended side effects and make the code harder to test and maintain.

Refactor the function to create and return a new GenesisState without altering the global state:

func NewGenStateAssets(operatorAccAddresses []sdk.AccAddress, depositAmount, stakingAmount sdkmath.Int) (assetstypes.GenesisState, error) {
    genStateAssets := assetstypes.GenesisState{
        // initialize with default values or copy from DefaultGenStateAssets
    }
    // Modify genStateAssets instead of DefaultGenStateAssets
    // ...
    return genStateAssets, nil
}

This approach enhances modularity and testability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0967104 and 09b748e.

📒 Files selected for processing (9)
  • crypto/algo_ed25519.go (1 hunks)
  • tests/e2e/bank/query.go (1 hunks)
  • tests/e2e/oracle/create_price.go (1 hunks)
  • tests/e2e/oracle/data.go (1 hunks)
  • testutil/network/genesis_data.go (1 hunks)
  • testutil/network/network.go (12 hunks)
  • testutil/network/tx_internal.go (1 hunks)
  • testutil/network/util.go (5 hunks)
  • x/oracle/keeper/msg_server_update_params_test.go (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • tests/e2e/bank/query.go
  • tests/e2e/oracle/data.go
  • testutil/network/tx_internal.go
  • x/oracle/keeper/msg_server_update_params_test.go
🧰 Additional context used
📓 Learnings (2)
testutil/network/genesis_data.go (1)
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: testutil/network/util.go:292-349
Timestamp: 2024-11-15T07:01:04.078Z
Learning: In the Go code for Exocore, specifically in the `testutil/network/util.go` file, functions like `NewGenStateAssets` are expected to modify the global variable `DefaultGenStateAssets`. Modifying global variables in these functions is acceptable and expected behavior in this context.
testutil/network/util.go (3)
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: testutil/network/util.go:358-358
Timestamp: 2024-11-16T04:47:03.403Z
Learning: In test code, during initialization in `testutil/network/util.go`, unprotected integer multiplications like `stakingAmount` calculations are acceptable as the risk of integer overflow is minimal.
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: testutil/network/util.go:309-309
Timestamp: 2024-11-16T04:41:59.771Z
Learning: In the `NewGenStateAssets` function in `testutil/network/util.go`, when generating `stakerAddrStr`, it is expected to use `hexutil.Encode(operatorAccAddress)` instead of `operatorAccAddress.String()`.
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: testutil/network/util.go:40-40
Timestamp: 2024-11-15T06:58:30.450Z
Learning: In the Go file `testutil/network/util.go`, the import `evmostypes` (`github.com/evmos/evmos/v16/types`) is used for `evmostypes.PowerReduction` in the functions `NewGenStateOperator` and `NewGenStateDogfood`.
🪛 GitHub Check: Run golangci-lint
crypto/algo_ed25519.go

[failure] 44-44:
SA1019: ed25519.PrivKey is deprecated: PrivKey defines a ed25519 private key. NOTE: ed25519 keys must not be used in SDK apps except in a tendermint validator context. (staticcheck)

tests/e2e/oracle/create_price.go

[failure] 156-156:
File is not gofumpt-ed (gofumpt)


[failure] 160-160:
File is not gofumpt-ed (gofumpt)


[failure] 168-168:
func (*E2ETestSuite).moveNAndCheck is unused (unused)

🔇 Additional comments (5)
testutil/network/genesis_data.go (2)

1-10: LGTM: Clean and well-organized imports

The imports are properly organized and all necessary for the genesis state definitions.


53-58: ⚠️ Potential issue

Add bounds checking for array access

The init function assumes the arrays in DefaultGenStateOracle.Params have the expected elements. Add bounds checking to prevent panic:

 func init() {
+    if len(DefaultGenStateOracle.Params.Tokens) < 2 {
+        panic("Oracle genesis state requires at least 2 tokens")
+    }
+    if len(DefaultGenStateOracle.Params.TokenFeeders) < 2 {
+        panic("Oracle genesis state requires at least 2 token feeders")
+    }
     DefaultGenStateOracle.Params.Tokens[1].AssetID = "0xdac17f958d2ee523a2206206994597c13d831ec7_0x65,0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee_0x65"
     DefaultGenStateOracle.Params.TokenFeeders[1].StartBaseBlock = 10
 }

Likely invalid or redundant comment.

testutil/network/network.go (1)

116-131: Verify configuration values.

The default configuration values have been significantly modified:

  • TimeoutCommit reduced from 3s to 2s
  • MinGasPrices changed to "10hua"
  • New token amounts introduced
testutil/network/util.go (2)

417-417: Ensure correct calculation in TokensToConsensusPower

The function sdk.TokensToConsensusPower is used with totalStakingAmount at line 417. Ensure that the calculation aligns with the expected consensus power, especially considering token denominations and potential overflows.

Run the following script to verify the calculation:

Replace ... with the expected value based on your test parameters.

✅ Verification successful

Let me gather more information about the TokensToConsensusPower function and PowerReduction to verify the calculation.


Let me check the BaseDenomUnit value and look for any tests that verify the TokensToConsensusPower calculation.


Based on the gathered information, I can now provide the final response:

TokensToConsensusPower calculation is correctly implemented

The calculation is correct and safe because:

  • PowerReduction is properly defined with BaseDenomUnit of 18 (10^18)
  • The code includes a comment explicitly stating "the price unit of assets is 1 not decimal 18"
  • The conversion is consistently used across the codebase with the same PowerReduction parameter
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Confirm that TokensToConsensusPower yields the expected value.

# Expected total staking amount
EXPECTED_TOTAL_STAKING_AMOUNT=...

# Check the consensus power calculation
grep -A 5 'TokensToConsensusPower' testutil/network/util.go

Length of output: 1126


Script:

#!/bin/bash
# Search for TokensToConsensusPower implementation and PowerReduction definition
rg "func TokensToConsensusPower" -A 5

# Search for PowerReduction constant in evmostypes
rg "PowerReduction" types/ -A 2

Length of output: 415


Script:

#!/bin/bash
# Search for BaseDenomUnit definition
rg "BaseDenomUnit.*=" -A 2

# Search for test cases involving TokensToConsensusPower
rg "TestTokensToConsensusPower|test.*TokensToConsensusPower" -A 5

# Look for any test files that use this calculation
rg "TokensToConsensusPower.*PowerReduction" testutil/ -B 2 -A 2

Length of output: 1982


379-388: Check for duplicate operator records

When appending to DefaultGenStateOperator.OperatorRecords, ensure that duplicate entries are not introduced, especially if initGenFiles can be called multiple times.

Run the following script to check for duplicates:

✅ Verification successful

No risk of duplicate operator records

The code is safe from duplicate operator records because:

  1. DefaultGenStateOperator is initialized as an empty state in genesis_data.go
  2. The initGenFiles function is called only once during test network setup
  3. Each operator record is added in a controlled loop over validators, where each validator has a unique address and consensus key
  4. The operator records are built from scratch each time, not appending to existing records
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that OperatorRecords have unique entries.

grep -A 5 'DefaultGenStateOperator.OperatorRecords = append' testutil/network/util.go

# Check for duplicates in the generated data
# This assumes you have a way to access the generated OperatorRecords
# For example, if you have output in JSON format:
jq '.OperatorRecords[] | .OperatorAddress' generated_genesis.json | sort | uniq -d

Length of output: 574


Script:

#!/bin/bash
# Let's analyze the code to understand the context and potential for duplicates

# First, let's see where DefaultGenStateOperator is defined and initialized
rg -A 5 "var DefaultGenStateOperator" testutil/network

# Then check the full implementation of the function where this append happens
ast-grep --pattern 'func $_ ($$$) {
  $$$
  DefaultGenStateOperator.OperatorRecords = append($$$)
  $$$
}'

# Also check if there are any checks or cleanups before appending
rg -B 5 "DefaultGenStateOperator.OperatorRecords = append" testutil/network

Length of output: 570


Script:

#!/bin/bash
# Let's check the broader context of the file and initialization

# Check the full file content to understand the initialization and usage
cat testutil/network/util.go

# Also check if DefaultGenStateOperator is reset anywhere
rg "DefaultGenStateOperator.*=" testutil/network

Length of output: 19585

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (4)
x/oracle/module.go (1)

196-196: Consider batching state updates and events

The code performs multiple state updates (reset context, update feeder IDs) with separate event emissions. Consider:

  1. Batching related state updates
  2. Emitting a single consolidated event

Example refactor:

- am.keeper.ResetAggregatorContextCheckTx()
  if feederIDs := am.keeper.GetUpdatedFeederIDs(); len(feederIDs) > 0 {
    feederIDsStr := strings.Join(feederIDs, "_")
    ctx.EventManager().EmitEvent(sdk.NewEvent(
      types.EventTypeCreatePrice,
      sdk.NewAttribute(types.AttributeKeyPriceUpdated, types.AttributeValuePriceUpdatedSuccess),
      sdk.NewAttribute(types.AttributeKeyFeederIDs, feederIDsStr),
    ))
-   am.keeper.ResetUpdatedFeederIDs()
  }
+ // Batch state updates
+ am.keeper.BatchReset(ctx)
+ // Emit consolidated event
+ if feederIDs := am.keeper.GetUpdatedFeederIDs(); len(feederIDs) > 0 {
+   ctx.EventManager().EmitEvent(createPriceUpdateEvent(feederIDs))
+ }

Also applies to: 209-216

tests/e2e/oracle/create_price.go (3)

46-74: Refactor duplicated code in test cases

The test cases case_1 to case_4 contain repetitive code patterns for setting up prices, creating messages, sending transactions, and querying results. Refactoring these sections can improve maintainability and reduce code duplication.

Consider creating helper functions to handle repetitive tasks. For example:

func (s *E2ETestSuite) preparePrice(price *PriceStruct, tokenID string, round uint64) (oracletypes.PriceSource, error) {
	priceTest := price.updateTimestamp()
	priceTimeDetID := priceTest.getPriceTimeDetID(tokenID)
	priceSource := oracletypes.PriceSource{
		SourceID: 1,
		Prices: []*oracletypes.PriceTimeDetID{
			&priceTimeDetID,
		},
	}
	return priceSource, nil
}

func (s *E2ETestSuite) sendPriceFromValidators(creators []sdk.AccAddress, msgs []*oracletypes.MsgCreatePrice, keys []string, kr []Keyring) error {
	for i, msg := range msgs {
		err := s.network.SendTxOracleCreateprice([]sdk.Msg{msg}, keys[i], kr[i])
		if err != nil {
			return err
		}
	}
	return nil
}

Then, you can use these helpers in your test cases to reduce repetition.

Also applies to: 75-101, 102-134, 135-153


155-155: Add implementation or TODO comment for TestCreatePriceNST

The test function TestCreatePriceNST is currently empty. If this test is intended to be implemented later, consider adding a TODO comment to indicate future work.

Would you like assistance in implementing this test or adding a TODO comment?


157-157: Add implementation or TODO comment for TestSlashing

The test function TestSlashing is empty. To maintain code clarity, consider adding a TODO comment or implementing the test if it's ready.

Would you like help in implementing this test or adding a TODO comment?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 09b748e and bf34582.

📒 Files selected for processing (4)
  • tests/e2e/bank/tx.go (1 hunks)
  • tests/e2e/oracle/create_price.go (1 hunks)
  • testutil/network/query.go (1 hunks)
  • x/oracle/module.go (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/e2e/bank/tx.go
  • testutil/network/query.go
🧰 Additional context used
🪛 GitHub Check: Run golangci-lint
tests/e2e/oracle/create_price.go

[failure] 164-164:
func (*E2ETestSuite).moveNAndCheck is unused (unused)

🔇 Additional comments (3)
x/oracle/module.go (3)

29-30: LGTM!

The module interface implementations are correctly declared.


162-165: Verify state consistency between caches and context

The retrieval of caches and aggregator context should be atomic to ensure consistency. Consider adding validation to ensure both are successfully retrieved before proceeding.

Let's check for similar patterns in the codebase:

#!/bin/bash
# Search for cache and context retrieval patterns
rg -A 10 "GetCaches.*GetAggregatorContext" --glob "x/oracle/**/*.go"

156-157: Consider improving initialization strategy

While the current implementation works for the test framework, there are two concerns:

  1. Error values from GetCaches() and GetAggregatorContext() are discarded
  2. As noted in the TODO, initialization in BeginBlock may not be ideal

Consider:

  1. Moving initialization to InitGenesis or module constructor
  2. Adding error handling for production use

Let's verify the initialization pattern in other Cosmos SDK modules:

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
tests/e2e/oracle/create_price.go (3)

24-153: Consider refactoring TestCreatePriceLST for better readability

The TestCreatePriceLST function is quite lengthy and encompasses multiple test cases within a single function. Splitting it into smaller, focused test functions or utilizing sub-tests with s.Run() can enhance readability and maintainability.

Apply this refactoring to introduce sub-tests:

 func (s *E2ETestSuite) TestCreatePriceLST() {
+    s.Run("Case 1: Achieving supermajority with initial price submissions", func() {
+        // Original code for case 1
+    })
+
+    s.Run("Case 2: Failing to reach supermajority", func() {
+        // Original code for case 2
+    })
+
+    s.Run("Case 3: Reaching supermajority after additional submissions", func() {
+        // Original code for case 3
+    })
+
+    s.Run("Case 4: Successful price update with all validators", func() {
+        // Original code for case 4
+    })
 }

37-84: Simplify repetitive price source initialization

The initialization of priceSource objects is repetitive across different test cases. Consider creating a helper function to streamline this process and reduce code duplication.

Introduce a helper function:

+func createPriceSource(priceTest PriceTest, detID string, sourceID uint64) oracletypes.PriceSource {
+    priceTimeDetID := priceTest.getPriceTimeDetID(detID)
+    return oracletypes.PriceSource{
+        SourceID: sourceID,
+        Prices: []*oracletypes.PriceTimeDetID{
+            &priceTimeDetID,
+        },
+    }
+}

 // Usage in case 1
-priceTest1R1 := price1.updateTimestamp()
-priceTimeDetID1R1 := priceTest1R1.getPriceTimeDetID("9")
-priceSource1R1 := oracletypes.PriceSource{
-    SourceID: 1,
-    Prices: []*oracletypes.PriceTimeDetID{
-        &priceTimeDetID1R1,
-    },
-}
+priceTest1R1 := price1.updateTimestamp()
+priceSource1R1 := createPriceSource(priceTest1R1, "9", 1)

 // Similar changes for other cases

Also applies to: 104-111, 138-141


155-157: Implement or remove empty test functions

The functions TestCreatePriceNST and TestSlashing are empty. To maintain code clarity, either implement these test cases or remove them if they are not needed.

Add TODO comments if these tests are planned for future implementation:

 func (s *E2ETestSuite) TestCreatePriceNST() {
+    // TODO: Implement test cases for non-supermajority thresholds
 }

 func (s *E2ETestSuite) TestSlashing() {
+    // TODO: Implement slashing mechanism tests
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between bf34582 and ce6ddc2.

📒 Files selected for processing (3)
  • crypto/algo_ed25519.go (1 hunks)
  • tests/e2e/oracle/create_price.go (1 hunks)
  • tests/e2e/oracle/data.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • crypto/algo_ed25519.go
  • tests/e2e/oracle/data.go
🧰 Additional context used
📓 Learnings (1)
tests/e2e/oracle/create_price.go (1)
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: tests/e2e/oracle/create_price.go:37-39
Timestamp: 2024-11-16T11:07:01.278Z
Learning: In `tests/e2e/oracle/create_price.go`, variables like `price1` and `price2` may be defined in other files such as `tests/e2e/oracle/data.go` within the same PR. Ensure to check for variable definitions across all related files in the PR before flagging them as undefined.

Comment on lines 52 to 56
for precompileName, precompilePath := range precompilePaths {
p := filepath.Join(basePath, precompilePath)
abis[precompileName], err = parseABI(p)
if err != nil {
fmt.Printf("Failed to parse abi from path:%s\r\n", p)
return
}
}

Check warning

Code scanning / CodeQL

Iteration over map Warning test

Iteration over map may be a possible source of non-determinism
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (16)
testutil/network/network.go (2)

84-90: Improve comment consistency for configuration fields.

The comments for configuration fields should follow a consistent style. Some fields have comments while others don't.

Apply this diff to maintain consistency:

-  AccountTokens     sdkmath.Int         // the amount of system tokens(e.g. 1000hua)
-  DepositedTokens   sdkmath.Int
-  StakingTokens     sdkmath.Int // the amount of tokens each validator stakes for every supporte asset
+  AccountTokens     sdkmath.Int         // The amount of system tokens (e.g. 1000hua)
+  DepositedTokens   sdkmath.Int         // The amount of tokens deposited into the system
+  StakingTokens     sdkmath.Int         // The amount of tokens each validator stakes for every supported asset

393-404: Enhance error handling in node initialization.

The node initialization code could benefit from more descriptive error messages to aid in debugging test failures.

Consider wrapping errors with context:

-nodeID, pubKey, err := genutil.InitializeNodeValidatorFilesFromMnemonic(tmCfg, mnemonic)
+nodeID, pubKey, err := genutil.InitializeNodeValidatorFilesFromMnemonic(tmCfg, mnemonic)
 if err != nil {
-    return nil, err
+    return nil, fmt.Errorf("failed to initialize node %d validator files: %w", i, err)
 }
tests/e2e/oracle/helper_nstconvert.go (6)

12-12: Typo in comment: 'alls takers' should be 'all stakers'.

There's a minor typo in the comment at line 12. It should read "all stakers" instead of "alls takers".


16-17: Use more descriptive variable names for clarity.

Variables like str and index could be renamed to more descriptive names to enhance readability. For example:

  • Rename str to stakerBitmask or bitString to reflect that it represents a bitmask of staker indices.
  • Rename index to currentStakerIndex to indicate its purpose in tracking the staker positions.

34-56: Simplify the bit length calculation and byte shifting logic.

The logic for calculating bits and manipulating changeBytes is complex. Consider the following improvements:

  • Use bits = bits.Len(uint(change)) from the math/bits package to simplify bit length calculation.
  • Refactor the byte shifting operations to make the code more concise and less error-prone.

This can enhance performance and maintainability.


59-68: Clarify the bit manipulation operations on bitsLengthBytes.

The bitwise operations modifying bitsLengthBytes[0] involve shifting and masking that may not be immediately clear. Adding comments to explain each operation will improve code readability and help future maintainers understand the intent.


88-123: Refactor the loop combining changeBytesList into changeResult for better readability.

The loop from lines 91 to 123 is complex and handles intricate bit manipulations. Consider breaking this logic into smaller helper functions with descriptive names, or adding detailed comments to explain:

  • The purpose of variables like delta, left, and how they affect the concatenation of byte slices.
  • The conditions under which bytes are shifted or combined.

This will make the code easier to understand and maintain.


10-129: Add unit tests for convertBalanceChangeToBytes to ensure correctness.

Given the complexity of this function and its crucial role in data encoding, it's important to have comprehensive unit tests covering various scenarios, including edge cases and error conditions.

Would you like assistance in creating unit tests for this function?

🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 10-10:
func convertBalanceChangeToBytes is unused (unused)

testutil/network/tx_precompile.go (4)

135-135: Fix Typo in Function Name PaddnigAddressTo32

There's a typo in the function name PaddnigAddressTo32; it should be PaddingAddressTo32.

Apply this diff to correct the function name and comment:

-// PaddnigAddressTo32 pads the 20-length address to 32 bytes with 0s
-func PaddnigAddressTo32(address common.Address) []byte {
+// PaddingAddressTo32 pads the 20-length address to 32 bytes with zeros
+func PaddingAddressTo32(address common.Address) []byte {

Also, ensure all calls to this function are updated accordingly.


47-48: Use Proper Error Handling Instead of fmt.Println

Using fmt.Println for error messages is not ideal. Consider returning the error or using a logging mechanism for better control over error handling.

Apply this diff to return an error:

-	fmt.Println("Failed to get current file path")
-	return
+	return fmt.Errorf("failed to get current file path")

And update the init function to handle the error:

-func init() {
+func init() {
+	err := initializePrecompiles()
+	if err != nil {
+		log.Fatalf("Initialization error: %v", err)
+	}
+}

-func initializePrecompiles() {
+func initializePrecompiles() error {

106-106: Avoid Using fmt.Println for Logging Transaction ID

Directly printing to stdout is not recommended. Use a logging framework or return the transaction ID to the caller.

Apply this diff to use proper logging:

-	fmt.Println("the txID is:", signTx.Hash().String())
+	log.Println("Transaction ID:", signTx.Hash().String())

Ensure the log package is imported:

import (
	// other imports
	"log"
)

Alternatively, consider returning the transaction ID to the caller for better handling.


64-64: Use Pointer Receiver for Network Method

The method SendPrecompileTx has a value receiver func (n Network). If Network contains fields that are expensive to copy or if you plan to modify its state, consider using a pointer receiver to improve performance.

Apply this diff to change the receiver to a pointer:

-func (n Network) SendPrecompileTx(preCompileName precompile, methodName string, args ...interface{}) error {
+func (n *Network) SendPrecompileTx(preCompileName precompile, methodName string, args ...interface{}) error {
tests/e2e/oracle/create_price.go (4)

188-188: Typo in comment: 'automaticlly' should be 'automatically'

There's a minor typographical error in the comment. Please correct 'automaticlly' to 'automatically'.


60-63: Refactor repeated code into helper functions to reduce duplication

The code for creating messages and sending transactions is repeated multiple times across the test cases. Consider refactoring this code into helper functions to enhance maintainability and readability.

For example, you could create a helper function:

func (s *E2ETestSuite) sendCreatePrice(creator sdk.AccAddress, priceSource *oracletypes.PriceSource, height int64, valConsKey string, kr keyring.Keyring) error {
	msg := oracletypes.NewMsgCreatePrice(creator.String(), 1, []*oracletypes.PriceSource{priceSource}, height, 1)
	err := s.network.SendTxOracleCreateprice([]sdk.Msg{msg}, valConsKey, kr)
	return err
}

Then use this helper function in your test cases:

err := s.sendCreatePrice(creator0, &priceSource1R1, 10, "valconskey0", kr0)
s.Require().NoError(err)

Also applies to: 71-74, 76-79, 105-107, 129-131, 133-135, 137-139, 154-159


167-167: Add TODO comment to unimplemented test function

The function testCreatePriceNST is currently empty. Adding a TODO comment can indicate its intended future implementation.

Suggested change:

 func (s *E2ETestSuite) testCreatePriceNST() {
+    // TODO: Implement test cases for creating NST prices
 }

170-170: Add TODO comment to unimplemented test function

The function testSlashing is currently empty. Adding a TODO comment can indicate its intended future implementation.

Suggested change:

 func (s *E2ETestSuite) testSlashing() {
+    // TODO: Implement slashing test scenarios
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ce6ddc2 and 129d588.

📒 Files selected for processing (4)
  • tests/e2e/oracle/create_price.go (1 hunks)
  • tests/e2e/oracle/helper_nstconvert.go (1 hunks)
  • testutil/network/network.go (12 hunks)
  • testutil/network/tx_precompile.go (1 hunks)
🧰 Additional context used
📓 Learnings (1)
tests/e2e/oracle/create_price.go (1)
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: tests/e2e/oracle/create_price.go:37-39
Timestamp: 2024-11-16T11:07:01.278Z
Learning: In `tests/e2e/oracle/create_price.go`, variables like `price1` and `price2` may be defined in other files such as `tests/e2e/oracle/data.go` within the same PR. Ensure to check for variable definitions across all related files in the PR before flagging them as undefined.
🪛 GitHub Check: Run golangci-lint
tests/e2e/oracle/helper_nstconvert.go

[failure] 10-10:
func convertBalanceChangeToBytes is unused (unused)

🪛 Gitleaks
testutil/network/tx_precompile.go

21-21: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (3)
testutil/network/network.go (1)

487-495: Verify peer configuration impact.

The changes to peer configuration look correct, but we should verify that all validators can connect to each other properly.

✅ Verification successful

Let me gather more information about the peer configuration setup to ensure there are no conflicts or issues.


Based on the analysis of the shell script outputs, I can now provide a final response:

P2P configuration is correctly implemented

The peer configuration implementation is sound and follows best practices:

  • The code correctly sets unique persistent peers for each validator by excluding self-connections
  • P2P configurations are properly isolated per validator with no conflicting settings
  • The implementation handles address management and peer connections appropriately through:
    • P2P.ListenAddress for binding
    • P2P.AddrBookStrict = false and P2P.AllowDuplicateIP = true to allow test network flexibility
    • Proper persistent peer string formatting with strings.Join(IPs, ",")
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any potential issues with peer configuration
# Test: Search for P2P configuration patterns that might conflict with the new setup

# Check for any other P2P configuration that might interfere
rg -A 5 "P2P\.PersistentPeers.*=.*"

# Check for any hardcoded peer addresses that might conflict
rg "tcp://.*@.*:.*"

Length of output: 873


Script:

#!/bin/bash
# Check the network configuration setup in both files
cat testutil/network/network.go cmd/exocored/testnet.go | grep -A 10 -B 10 "P2P.PersistentPeers"

# Check for any other P2P related configurations
rg "P2P\." -A 3

# Look for any address or port configurations that might be related
rg "Address.*=.*:" -A 2

Length of output: 28818

tests/e2e/oracle/helper_nstconvert.go (2)

10-10: Function convertBalanceChangeToBytes is currently unused in the codebase.

According to static analysis, the function convertBalanceChangeToBytes is not used elsewhere. If this function is intended for future use or by reflection, please ensure it's correctly integrated. Otherwise, consider removing it to prevent dead code accumulation.

🧰 Tools
🪛 GitHub Check: Run golangci-lint

[failure] 10-10:
func convertBalanceChangeToBytes is unused (unused)


28-32: ⚠️ Potential issue

Potential off-by-one error when handling negative change amounts.

After converting negative change values to positive (line 30), the code decrements change by 1 (line 32). If change is -1, it becomes 1 after change *= -1, and then change-- makes it 0. This may lead to unintended behavior or incorrect encoding for small negative values. Please verify if decrementing change after making it positive is necessary and correct.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (1)
testutil/network/tx_precompile.go (1)

28-28: Consider making gas limit configurable

The hardcoded gas limit of 500000 might not be suitable for all precompile operations. Consider making it configurable based on the operation type or accepting it as a parameter.

-const gasLimit = uint64(500000)
+var DefaultGasLimit = uint64(500000)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 129d588 and eae3a00.

📒 Files selected for processing (2)
  • tests/e2e/oracle/helper_nstconvert.go (1 hunks)
  • testutil/network/tx_precompile.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/e2e/oracle/helper_nstconvert.go
🧰 Additional context used
🪛 Gitleaks
testutil/network/tx_precompile.go

23-23: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (3)
testutil/network/tx_precompile.go (1)

43-59: Improve error handling in init function

The error messages could be more descriptive to aid in debugging:

 func init() {
 	_, currentFile, _, ok := runtime.Caller(0)
 	if !ok {
-		fmt.Println("Failed to get current file path")
-		panic("Failed to get current file path")
+		panic("Failed to get current file path using runtime.Caller")
 	}
 	basePath := filepath.Dir(currentFile)
 	var err error
 	for precompileName, precompilePath := range precompilePaths {
 		p := filepath.Join(basePath, precompilePath)
 		abis[precompileName], err = parseABI(p)
 		if err != nil {
-			panic(fmt.Sprintf("Failed to parse abi from path:%s\r\n", p))
+			panic(fmt.Sprintf("Failed to parse ABI for precompile %s from path %s: %v", precompileName, p, err))
 		}
 	}
 }
🧰 Tools
🪛 GitHub Check: CodeQL

[warning] 52-58: Iteration over map
Iteration over map may be a possible source of non-determinism

testutil/network/network.go (2)

52-58: Consider organizing imports for better maintainability.

The commented out import ekeyring on line 57 should be removed if it's no longer needed.

-// ekeyring "github.com/evmos/evmos/v16/crypto/keyring"

425-428: Consider improving key seed file security.

The key seed file is being written with default permissions. Consider adding more restrictive file permissions for better security.

-err = WriteFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, infoBz)
+err = WriteFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, infoBz, 0600)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between eae3a00 and 905eb74.

📒 Files selected for processing (5)
  • .github/workflows/e2e-test-release.yml (0 hunks)
  • .github/workflows/e2e-test.yml (0 hunks)
  • tests/e2e/bank/tx.go (1 hunks)
  • testutil/network/network.go (12 hunks)
  • testutil/network/tx_precompile.go (1 hunks)
💤 Files with no reviewable changes (2)
  • .github/workflows/e2e-test-release.yml
  • .github/workflows/e2e-test.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/e2e/bank/tx.go
🧰 Additional context used
🪛 GitHub Check: CodeQL
testutil/network/tx_precompile.go

[notice] 9-9: Sensitive package import
Certain system packages contain functions which may be a possible source of non-determinism


[warning] 52-58: Iteration over map
Iteration over map may be a possible source of non-determinism

🔇 Additional comments (5)
testutil/network/tx_precompile.go (1)

124-139: LGTM! Helper functions are well-implemented

Both parseABI and PaddingAddressTo32 functions are correctly implemented with proper error handling and resource cleanup.

testutil/network/network.go (4)

484-492: Good improvement in peer address handling.

The sorting of addressesIPs and systematic assignment of persistent peers improves network stability and determinism.


84-91: Verify token denomination changes across the codebase.

The removal of BondDenom and addition of NativeDenom represents a significant change in token handling. This change needs careful verification across the codebase to ensure consistency.

#!/bin/bash
# Search for any remaining references to BondDenom
rg "BondDenom" 

# Search for NativeDenom usage to ensure consistent implementation
rg "NativeDenom"

# Search for token denomination strings to verify consistency
rg -g '!*.md' '"hua"'

499-505: 🛠️ Refactor suggestion

Avoid hardcoding gateway address.

The gateway address should be configurable rather than hardcoded. This allows for different test environments and improves maintainability.

Consider moving this to the Config struct:

+type Config struct {
+    // ... existing fields ...
+    GatewayAddress string
}

+func DefaultConfig() Config {
+    return Config{
+        // ... existing initialization ...
+        GatewayAddress: "exo18cggcpvwspnd5c6ny8wrqxpffj5zmhklprtnph",
+    }
}

-gateWayAddressStr := "exo18cggcpvwspnd5c6ny8wrqxpffj5zmhklprtnph"
+gateWayAddressStr := cfg.GatewayAddress

Likely invalid or redundant comment.


116-123: Review token power reduction values.

The token amounts have been significantly reduced:

  • AccountTokens: 1000 power
  • DepositedTokens: 500 power
  • StakingTokens: 200 power

These values seem quite low for a test network. Consider if these reductions might impact test scenarios.

Comment on lines 61 to 120
// SendPrecompileTx wraps the function to send a transaction to precompile contract with gateway address
// which defined in the test genesis state
func (n Network) SendPrecompileTx(preCompileName precompile, methodName string, args ...interface{}) error {
ctx := context.Background()

ethC := n.Validators[0].JSONRPCClient

chainID, err := ethC.ChainID(ctx)
if err != nil {
return fmt.Errorf("failed to get chainID, error:%w", err)
}

precompileAddr := precompileAddresses[preCompileName]
precompileABI := abis[preCompileName]

data, err := precompileABI.Pack(methodName, args...)
if err != nil {
return fmt.Errorf("failed to pack message for %s, error:%w", methodName, err)
}

nonce, err := ethC.NonceAt(ctx, callAddr, nil)
if err != nil {
return err
}

gasPrice, err := ethC.SuggestGasPrice(ctx)
if err != nil {
return err
}

retTx := types.NewTx(&types.LegacyTx{
Nonce: nonce,
To: &precompileAddr,
Value: big.NewInt(0),
Gas: gasLimit,
GasPrice: gasPrice,
Data: data,
})
signer := types.LatestSignerForChainID(chainID)
signTx, err := types.SignTx(retTx, signer, sk)
if err != nil {
return err
}

fmt.Println("the txID is:", signTx.Hash().String())
msg := ethereum.CallMsg{
From: callAddr,
To: retTx.To(),
Data: retTx.Data(),
}
_, err = ethC.CallContract(context.Background(), msg, nil)
if err != nil {
return fmt.Errorf("failed to call contract:%s, error:%w", preCompileName, err)
}

err = ethC.SendTransaction(ctx, signTx)
if err != nil {
return fmt.Errorf("failed to send transaction, error:%w", err)
}

return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance transaction handling and error recovery

Several improvements can make this function more robust:

  1. Add transaction receipt handling to confirm success
  2. Use context with timeout
  3. Estimate gas instead of using fixed limit
  4. Improve error handling with more context
-func (n Network) SendPrecompileTx(preCompileName precompile, methodName string, args ...interface{}) error {
+func (n Network) SendPrecompileTx(ctx context.Context, preCompileName precompile, methodName string, args ...interface{}) (*types.Receipt, error) {
-	ctx := context.Background()
+	if ctx == nil {
+		var cancel context.CancelFunc
+		ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second)
+		defer cancel()
+	}

 	ethC := n.Validators[0].JSONRPCClient
 	chainID, err := ethC.ChainID(ctx)
 	if err != nil {
-		return fmt.Errorf("failed to get chainID, error:%w", err)
+		return nil, fmt.Errorf("failed to get chainID: %w", err)
 	}

 	precompileAddr := precompileAddresses[preCompileName]
 	precompileABI := abis[preCompileName]

+	// Estimate gas instead of using fixed limit
+	msg := ethereum.CallMsg{
+		From: callAddr,
+		To:   &precompileAddr,
+		Data: data,
+	}
+	gasLimit, err := ethC.EstimateGas(ctx, msg)
+	if err != nil {
+		return nil, fmt.Errorf("failed to estimate gas: %w", err)
+	}
+	// Add 20% buffer to gas estimate
+	gasLimit = gasLimit * 120 / 100

 	// ... rest of the function ...

 	err = ethC.SendTransaction(ctx, signTx)
 	if err != nil {
-		return fmt.Errorf("failed to send transaction, error:%w", err)
+		return nil, fmt.Errorf("failed to send transaction to %s.%s: %w", preCompileName, methodName, err)
 	}

+	receipt, err := ethC.TransactionReceipt(ctx, signTx.Hash())
+	if err != nil {
+		return nil, fmt.Errorf("failed to get receipt for tx %s: %w", signTx.Hash().String(), err)
+	}
+
+	if receipt.Status == 0 {
+		return receipt, fmt.Errorf("transaction failed: %s", signTx.Hash().String())
+	}
+
-	return nil
+	return receipt, nil
 }

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (1)
testutil/network/tx_precompile.go (1)

103-103: Replace fmt.Println with proper logging

Direct console output using fmt.Println is not ideal for a test utility. Consider using a proper logging framework that can be configured based on the test environment.

Example implementation:

-fmt.Println("the txID is:", signTx.Hash().String())
+log.Printf("Transaction sent with hash: %s", signTx.Hash().String())
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 905eb74 and d70cfb9.

📒 Files selected for processing (1)
  • testutil/network/tx_precompile.go (1 hunks)
🧰 Additional context used
🪛 GitHub Check: CodeQL
testutil/network/tx_precompile.go

[notice] 9-9: Sensitive package import
Certain system packages contain functions which may be a possible source of non-determinism


[warning] 50-56: Iteration over map
Iteration over map may be a possible source of non-determinism

🔇 Additional comments (1)
testutil/network/tx_precompile.go (1)

122-137: LGTM! Helper functions are well-implemented

Both parseABI and PaddingAddressTo32 functions are correctly implemented with proper error handling and memory management.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🧹 Outside diff range and nitpick comments (22)
testutil/network/tx.go (5)

18-18: Consider making gas adjustment configurable

The gas adjustment value of 1.5 is hardcoded. Consider making this configurable through network configuration to allow for different test scenarios and network conditions.

-    txf, ctx, err := generateTxf(n.Validators[0].ClientCtx, keyName, keyring, 1.5, n.Config.MinGasPrices)
+    txf, ctx, err := generateTxf(n.Validators[0].ClientCtx, keyName, keyring, n.Config.GasAdjustment, n.Config.MinGasPrices)

27-27: Fix function name to follow Go naming conventions

The function name has inconsistent capitalization. Rename from SendTxOracleCreateprice to SendTxOracleCreatePrice to follow Go naming conventions.


64-64: Add function documentation

Add a detailed godoc comment explaining the purpose, parameters, and return values of this helper function.

+// generateTxf creates and configures a transaction factory with the given parameters.
+// It also updates the client context with the sender's address and name.
+// Parameters:
+//   - ctx: The client context to be updated
+//   - keyName: The name of the key to be used for signing
+//   - kr: The keyring containing the keys
+//   - adjustment: Gas adjustment factor
+//   - minGasPrice: Minimum gas price to be used
+// Returns the configured transaction factory, updated context, and any error encountered.
 func generateTxf(ctx client.Context, keyName string, kr keyring.Keyring, adjustment float64, minGasPrice string) (tx.Factory, client.Context, error) {

87-87: Consider making broadcast mode configurable

The broadcast mode is hardcoded to BroadcastSync. Consider making this configurable through the network configuration to support different test scenarios.

-    ctx.BroadcastMode = flags.BroadcastSync
+    ctx.BroadcastMode = n.Config.BroadcastMode

25-26: Fix typos in comments

There are several typos in the comments:

  • "consturct" should be "construct"
  • "senario" should be "scenario"
  • "unexists" should be "non-existent"
x/oracle/keeper/keeper_suite_test.go (2)

76-80: Consider extracting duplicated parameter initialization

This parameter initialization code is duplicated in the SetupTest method. Consider extracting it into a helper method to improve maintainability.

+func (suite *KeeperSuite) initializeTestParams() {
+    p4Test := types.DefaultParams()
+    p4Test.TokenFeeders[1].StartBaseBlock = 1
+    suite.k.SetParams(suite.ctx, p4Test)
+    suite.ctx = suite.ctx.WithBlockHeight(12)
+}

 func (suite *KeeperSuite) Reset() {
-    p4Test := types.DefaultParams()
-    p4Test.TokenFeeders[1].StartBaseBlock = 1
-    suite.k.SetParams(suite.ctx, p4Test)
-    suite.ctx = suite.ctx.WithBlockHeight(12)
+    suite.initializeTestParams()
     suite.ctrl = gomock.NewController(suite.t)
     resetSingle(suite.App.OracleKeeper)
 }

116-118: Consider a more descriptive function name

The function name resetSingle could be more descriptive of its purpose. Consider renaming it to something like resetKeeperState or resetOracleState to better reflect its functionality of resetting both the aggregator context and cache.

-func resetSingle(k keeper.Keeper) {
+func resetKeeperState(k keeper.Keeper) {
     k.ResetAggregatorContext()
     k.ResetCache()
 }
x/oracle/keeper/msg_server_create_price_test.go (2)

85-87: Consider adding negative test cases

The test covers the happy path with three validators creating prices successfully. Consider adding test cases for:

  • Invalid BasedBlock values
  • Out of order messages
  • Duplicate messages from the same validator

Also applies to: 97-99


Line range hint 28-46: Address TODO: Remove monkey patching

The current test uses monkey patching with gomonkey which can be fragile and maintenance-heavy. Consider:

  1. Using proper mocking with the existing mockgen setup
  2. Creating a proper test double for the dogfood keeper

Would you like help creating a proper mock implementation to replace the monkey patches?

testutil/network/tx_precompile.go (1)

44-47: Remove redundant error logging before panic

The code logs the error using fmt.Println and then immediately panics with the same message. This is redundant as the panic message will be logged anyway.

Apply this diff to remove the redundant logging:

 	if !ok {
-		fmt.Println("Failed to get current file path")
 		panic("Failed to get current file path")
 	}
x/oracle/keeper/single.go (4)

23-56: Consider refactoring to reduce code duplication.

The method contains similar initialization logic in both CheckTx and non-CheckTx paths. This could be refactored into a shared helper method to improve maintainability.

Consider refactoring like this:

func (k *Keeper) GetAggregatorContext(ctx sdk.Context) *aggregator.AggregatorContext {
+    func initNewContext() *aggregator.AggregatorContext {
+        c := k.GetCaches()
+        c.ResetCaches()
+        agc := aggregator.NewAggregatorContext()
+        if ok := k.recacheAggregatorContext(ctx, agc, c); !ok {
+            initAggregatorContext(ctx, agc, k, c)
+        }
+        return agc
+    }

    if ctx.IsCheckTx() {
        if k.memStore.agcCheckTx != nil {
            return k.memStore.agcCheckTx
        }
        if k.memStore.agc == nil {
-            c := k.GetCaches()
-            c.ResetCaches()
-            k.memStore.agcCheckTx = aggregator.NewAggregatorContext()
-            if ok := k.recacheAggregatorContext(ctx, k.memStore.agcCheckTx, c); !ok {
-                initAggregatorContext(ctx, k.memStore.agcCheckTx, k, c)
-            }
+            k.memStore.agcCheckTx = initNewContext()
            return k.memStore.agcCheckTx
        }
        k.memStore.agcCheckTx = k.memStore.agc.Copy4CheckTx()
        return k.memStore.agcCheckTx
    }

    if k.memStore.agc != nil {
        return k.memStore.agc
    }

-    c := k.GetCaches()
-    c.ResetCaches()
-    k.memStore.agc = aggregator.NewAggregatorContext()
-    if ok := k.recacheAggregatorContext(ctx, k.memStore.agc, c); !ok {
-        initAggregatorContext(ctx, k.memStore.agc, k, c)
-    }
+    k.memStore.agc = initNewContext()
    return k.memStore.agc
}

Line range hint 59-157: Address TODO comment and consider breaking down the method.

  1. The TODO comment about hot fix needs attention:
// TODO: these 4 lines are mainly used for hot fix

This suggests technical debt that should be addressed.

  1. The method is handling multiple responsibilities (validator powers, parameter updates, message processing). Consider breaking it down into smaller, focused methods for better maintainability.

Would you like help creating a GitHub issue to track the TODO and/or assistance in breaking down this method into smaller, more focused methods?


Line range hint 160-182: Convert to Keeper method for consistency.

This function should be a method on the Keeper struct to maintain consistency with other methods and improve encapsulation. Also consider adding comments explaining the power calculations.

-func initAggregatorContext(ctx sdk.Context, agc *aggregator.AggregatorContext, k *Keeper, c *cache.Cache) {
+func (k *Keeper) initAggregatorContext(ctx sdk.Context, agc *aggregator.AggregatorContext, c *cache.Cache) {
    // ... rest of the function ...
}

207-209: Simplify ResetUpdatedFeederIDs method.

The condition check is unnecessary since setting nil is safe regardless of the current value.

func (k *Keeper) ResetUpdatedFeederIDs() {
-    if k.memStore.updatedFeederIDs != nil {
-        k.memStore.updatedFeederIDs = nil
-    }
+    k.memStore.updatedFeederIDs = nil
}
testutil/network/util.go (2)

261-269: Optimize genesis document initialization.

The InitialHeight and GenesisTime are set inside the validator loop, but these values are the same for all validators.

Move these initializations outside the loop:

 gTime := cmttime.Now()
+if genDoc.InitialHeight == 0 {
+    genDoc.InitialHeight = 1
+}
+genDoc.GenesisTime = gTime
+
 for i := 0; i < cfg.NumValidators; i++ {
-    if genDoc.InitialHeight == 0 {
-        genDoc.InitialHeight = 1
-    }
-    genDoc.GenesisTime = gTime
     if err := genDoc.ValidateAndComplete(); err != nil {
         return err
     }

427-451: Add validation for power calculation.

The power calculation could potentially result in a zero or negative value if stakingAmount is too small.

 power := sdk.TokensToConsensusPower(stakingAmount.Mul(sdkmath.NewInt(int64(len(genStateAssets.Tokens)))), evmostypes.PowerReduction)
+if power <= 0 {
+    return DefaultGenStateDogfood, fmt.Errorf("calculated power must be positive, got: %d", power)
+}
testutil/network/network.go (1)

84-91: Config struct field changes need documentation updates

The changes to the Config struct fields need better documentation:

  • AccountTokens comment should clarify these are native tokens
  • DepositedTokens is missing a comment explaining its purpose
  • StakingTokens comment needs clarity on "supported asset"

Add or update the comments as follows:

-  AccountTokens     sdkmath.Int         // the amount of system tokens(e.g. 1000hua)
+  AccountTokens     sdkmath.Int         // the amount of native tokens each account receives initially (e.g. 1000hua)
+  DepositedTokens   sdkmath.Int         // the amount of tokens deposited into the network's liquidity pools
   StakingTokens     sdkmath.Int         // the amount of tokens each validator stakes for every supporte asset
+  StakingTokens     sdkmath.Int         // the amount of tokens each validator stakes for each supported asset type
testutil/network/tx_internal.go (2)

70-75: Initialize tx.Factory with proper settings

The transaction factory is being initialized but lacks some configurations:

  • Gas Adjustment: It's recommended to set the gas adjustment factor.
  • Gas Prices: Set the gas prices to match network configurations.
  • Sign Mode: Ensure the appropriate sign mode is set.

Consider updating the factory initialization:

     txf := tx.Factory{}.
         WithChainID(ctx.ChainID).
         WithKeybase(kr).
         WithTxConfig(txConfig).
         WithAccountNumber(num).
         WithSequence(seq)
+        WithGasAdjustment(1.5).
+        WithGasPrices(n.Config.MinGasPrices).
+        WithSignMode(txConfig.SignModeHandler().DefaultMode())

77-79: Ensure single signature in transaction signing

When signing the transaction, the overwrite parameter is set to true. This will overwrite any existing signatures. If multiple signers are needed in the future, this could cause issues.

Consider setting overwrite to false if you plan to support multisig transactions.

-    if err := tx.Sign(txf, keyName, txBuilder, true); err != nil {
+    if err := tx.Sign(txf, keyName, txBuilder, false); err != nil {
app/ante/cosmos/sigverify.go (3)

Line range hint 117-122: Potential Security Risk: Skipping Signature Gas Consumption

In the SigGasConsumeDecorator, the gas consumption for signatures is skipped for oracle create-price transactions. This could lead to inaccurate gas accounting and potential exploitation, such as denial-of-service attacks through the submission of numerous transactions without incurring the appropriate gas costs.

Ensure that gas consumption is properly accounted for all transaction types to prevent abuse and maintain network stability.


Line range hint 165-182: Potential Security Risk: Skipping Signature Verification

The SigVerificationDecorator bypasses signature verification for oracle create-price transactions. This allows transactions to be processed without authenticating the sender's identity, posing a significant security risk by potentially accepting unauthorized or malicious transactions.

All transactions should undergo signature verification to authenticate the sender and prevent unauthorized actions. Consider removing the bypass for oracle create-price transactions or implementing secure alternative validation mechanisms.


Line range hint 336-344: Inconsistent Sequence Handling in IncrementSequenceDecorator

The IncrementSequenceDecorator skips incrementing the account sequence for oracle create-price transactions and instead relies on nonce handling via CheckAndIncreaseNonce. This deviation from standard sequence management may lead to inconsistencies in transaction ordering and compromise replay protection mechanisms.

Maintain consistent sequence management across all transaction types or ensure that the nonce mechanism provides equivalent security guarantees. If using nonces, thoroughly document and validate their implementation to prevent potential vulnerabilities.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d70cfb9 and c96883e.

📒 Files selected for processing (39)
  • .github/workflows/e2e-test-release.yml (0 hunks)
  • .github/workflows/e2e-test.yml (0 hunks)
  • app/ante/cosmos/sigverify.go (1 hunks)
  • crypto/algo_ed25519.go (1 hunks)
  • go.mod (1 hunks)
  • precompiles/assets/assets_test.go (0 hunks)
  • tests/e2e/bank/bank_test.go (1 hunks)
  • tests/e2e/bank/query.go (1 hunks)
  • tests/e2e/bank/suite.go (1 hunks)
  • tests/e2e/bank/tx.go (1 hunks)
  • tests/e2e/basesuite.go (1 hunks)
  • tests/e2e/oracle/create_price.go (1 hunks)
  • tests/e2e/oracle/data.go (1 hunks)
  • tests/e2e/oracle/helper_nstconvert.go (1 hunks)
  • tests/e2e/oracle/oracle_test.go (1 hunks)
  • tests/e2e/oracle/suite.go (1 hunks)
  • tests/e2e/util.go (1 hunks)
  • testutil/network/genesis_data.go (1 hunks)
  • testutil/network/network.go (12 hunks)
  • testutil/network/network_test.go (4 hunks)
  • testutil/network/query.go (1 hunks)
  • testutil/network/tx.go (1 hunks)
  • testutil/network/tx_internal.go (1 hunks)
  • testutil/network/tx_precompile.go (1 hunks)
  • testutil/network/util.go (5 hunks)
  • x/oracle/keeper/aggregator/aggregator.go (2 hunks)
  • x/oracle/keeper/aggregator/calculator.go (1 hunks)
  • x/oracle/keeper/aggregator/util.go (1 hunks)
  • x/oracle/keeper/keeper.go (3 hunks)
  • x/oracle/keeper/keeper_suite_test.go (2 hunks)
  • x/oracle/keeper/msg_server_create_price.go (2 hunks)
  • x/oracle/keeper/msg_server_create_price_test.go (5 hunks)
  • x/oracle/keeper/msg_server_update_params.go (1 hunks)
  • x/oracle/keeper/msg_server_update_params_test.go (7 hunks)
  • x/oracle/keeper/nonce.go (2 hunks)
  • x/oracle/keeper/params.go (2 hunks)
  • x/oracle/keeper/prices.go (4 hunks)
  • x/oracle/keeper/single.go (4 hunks)
  • x/oracle/module.go (4 hunks)
💤 Files with no reviewable changes (3)
  • .github/workflows/e2e-test-release.yml
  • .github/workflows/e2e-test.yml
  • precompiles/assets/assets_test.go
🚧 Files skipped from review as they are similar to previous changes (27)
  • crypto/algo_ed25519.go
  • go.mod
  • tests/e2e/bank/bank_test.go
  • tests/e2e/bank/query.go
  • tests/e2e/bank/suite.go
  • tests/e2e/bank/tx.go
  • tests/e2e/basesuite.go
  • tests/e2e/oracle/create_price.go
  • tests/e2e/oracle/data.go
  • tests/e2e/oracle/helper_nstconvert.go
  • tests/e2e/oracle/oracle_test.go
  • tests/e2e/oracle/suite.go
  • tests/e2e/util.go
  • testutil/network/genesis_data.go
  • testutil/network/network_test.go
  • testutil/network/query.go
  • x/oracle/keeper/aggregator/aggregator.go
  • x/oracle/keeper/aggregator/calculator.go
  • x/oracle/keeper/aggregator/util.go
  • x/oracle/keeper/keeper.go
  • x/oracle/keeper/msg_server_create_price.go
  • x/oracle/keeper/msg_server_update_params.go
  • x/oracle/keeper/msg_server_update_params_test.go
  • x/oracle/keeper/nonce.go
  • x/oracle/keeper/params.go
  • x/oracle/keeper/prices.go
  • x/oracle/module.go
🧰 Additional context used
📓 Learnings (2)
testutil/network/tx_internal.go (1)
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: testutil/network/tx_internal.go:21-21
Timestamp: 2024-11-16T08:56:12.141Z
Learning: In `testutil/network/tx_internal.go`, the `Validators` slice in the `Network` struct is guaranteed to have at least one validator, so it's unnecessary to check if `n.Validators` is non-empty before accessing `n.Validators[0]`.
testutil/network/util.go (3)
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: testutil/network/util.go:358-358
Timestamp: 2024-11-16T04:47:03.403Z
Learning: In test code, during initialization in `testutil/network/util.go`, unprotected integer multiplications like `stakingAmount` calculations are acceptable as the risk of integer overflow is minimal.
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: testutil/network/util.go:309-309
Timestamp: 2024-11-16T04:41:59.771Z
Learning: In the `NewGenStateAssets` function in `testutil/network/util.go`, when generating `stakerAddrStr`, it is expected to use `hexutil.Encode(operatorAccAddress)` instead of `operatorAccAddress.String()`.
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: testutil/network/util.go:40-40
Timestamp: 2024-11-15T06:58:30.450Z
Learning: In the Go file `testutil/network/util.go`, the import `evmostypes` (`github.com/evmos/evmos/v16/types`) is used for `evmostypes.PowerReduction` in the functions `NewGenStateOperator` and `NewGenStateDogfood`.
🔇 Additional comments (24)
x/oracle/keeper/keeper_suite_test.go (3)

70-70: LGTM: Correctly updated resetSingle call

The update properly passes the OracleKeeper instance to match the new function signature.


82-82: LGTM: Correctly updated resetSingle call

The update properly passes the OracleKeeper instance to match the new function signature.


104-109: LGTM: Proper initialization sequence

The initialization sequence is correct:

  1. Resetting the keeper state
  2. Setting up the keeper and message server references
  3. Setting up the context
x/oracle/keeper/msg_server_create_price_test.go (1)

47-47: Verify block height and BasedBlock relationship

The test setup shows coordinated changes:

  • Block height increased to 12
  • BasedBlock increased to 11
  • Cache access pattern updated to use App.OracleKeeper

Please verify if there's a specific requirement for the block height to be exactly one more than the BasedBlock. If this is a critical relationship, consider adding a comment explaining it.

Also applies to: 63-63, 67-68

✅ Verification successful

Let me analyze the results and generate additional verification scripts to understand the relationship better.


Based on the search results, I can now generate the final response since I have enough context to verify the relationship between block height and BasedBlock.

Block height and BasedBlock relationship is correct

The relationship between block height (12) and BasedBlock (11) is intentional and follows a consistent pattern in the oracle module where:

  • BasedBlock represents the block on which price data is based
  • Block height is always one block ahead of BasedBlock to allow for price data to be collected and processed

This is evidenced by:

  1. The pattern appears in multiple test files (msg_server_create_price_test.go, context_test.go)
  2. The oracle module's aggregator context explicitly uses this relationship for round preparation (x/oracle/keeper/aggregator/context_test.go)
  3. The relationship is used consistently across price creation messages
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other test files that might establish this pattern
rg -A 2 "BasedBlock.*11" --type go
rg -A 2 "BlockHeight.*12" --type go

Length of output: 1638


Script:

#!/bin/bash
# Search for the test setup and context initialization
ast-grep --pattern 'func $_ {
  $$$
  ctx = ctx.WithBlockHeight($height)
  $$$
}'

# Look for any comments or documentation about block height and based block relationship
rg -B2 -A2 "BasedBlock|BlockHeight" --type go --type md

Length of output: 66215

testutil/network/tx_precompile.go (2)

1-17: LGTM! Package structure and imports are well organized.


122-137: LGTM! Helper functions are well implemented.

Both parseABI and PaddingAddressTo32 functions are concise, correct, and handle their responsibilities appropriately.

x/oracle/keeper/single.go (2)

14-19: LGTM! Clean implementation of lazy initialization pattern.

The conversion to use memStore for caching is well implemented, following the lazy initialization pattern which helps with memory efficiency.


213-219: LGTM! Clean and straightforward implementation.

The getter and append methods for feederIDs are well implemented with appropriate type conversion.

testutil/network/util.go (6)

9-44: LGTM! Well-organized imports and constant definition.

The new imports are properly organized and necessary for the genesis state management functionality. The MaxOptedOutHeight constant is appropriately defined to replace magic numbers in the code.


208-248: LGTM! Well-structured genesis state initialization.

The initialization of validator-related modules is well-organized and follows a clear sequence:

  1. Collect validator addresses and public keys
  2. Initialize assets genesis state
  3. Initialize operator genesis state
  4. Initialize dogfood genesis state
  5. Initialize delegation genesis state
  6. Initialize oracle genesis state

Each step properly handles errors and maintains the chain of dependencies.


292-347: LGTM! Well-implemented assets genesis state generation.

The function properly validates inputs and handles the initialization of deposits and operator assets. The use of DefaultGenStateAssets is acceptable in test code as per the learnings.


453-481: LGTM! Well-structured delegation genesis state generation.

The function properly handles the initialization of delegation states and associations. The use of maps to track linked staker IDs is an efficient approach.


483-485: LGTM! Simple oracle genesis state initialization.

The function provides a clean interface to initialize oracle genesis state using the default values.


354-422: 🛠️ Refactor suggestion

Replace magic number with MaxOptedOutHeight constant.

The function uses a magic number 18446744073709551615 for OptedOutHeight instead of the defined constant.

-                    OptedOutHeight: 18446744073709551615,
+                    OptedOutHeight: MaxOptedOutHeight,

Likely invalid or redundant comment.

testutil/network/network.go (4)

484-492: Good addition of sorted persistent peers

The addition of sorted persistent peers is a good improvement that ensures consistent network topology across test runs.


499-505: 🛠️ Refactor suggestion

Avoid hardcoding gateway address

The gateway address should not be hardcoded as it reduces flexibility and makes testing different scenarios difficult.

Move this to the Config struct:

type Config struct {
    // ... existing fields ...
+   GatewayAddress string // The address of the gateway account
}

func DefaultConfig() Config {
    // ... existing initialization ...
+   GatewayAddress: "exo18cggcpvwspnd5c6ny8wrqxpffj5zmhklprtnph",
}

-gateWayAddressStr := "exo18cggcpvwspnd5c6ny8wrqxpffj5zmhklprtnph"
+gateWayAddressStr := cfg.GatewayAddress

Likely invalid or redundant comment.


380-394: 🛠️ Refactor suggestion

Enhance key generation security

The key generation process could be improved:

  1. Using a fixed English language for mnemonics reduces entropy
  2. No entropy source is specified for mnemonic generation

Consider enhancing the key generation:

- _, mnemonic, err := kb.NewMnemonic(fmt.Sprintf("valconskey%d", i), keyring.English, sdk.GetConfig().GetBech32AccountPubPrefix(), keyring.DefaultBIP39Passphrase, algo)
+ entropy, err := bip39.NewEntropy(256)
+ if err != nil {
+     return nil, err
+ }
+ _, mnemonic, err := kb.NewMnemonic(
+     fmt.Sprintf("valconskey%d", i),
+     keyring.English,
+     sdk.GetConfig().GetBech32AccountPubPrefix(),
+     keyring.DefaultBIP39Passphrase,
+     algo,
+     entropy,
+ )

Likely invalid or redundant comment.


116-123: Review default token allocations

The token allocation values seem quite low for a test network:

  • AccountTokens: 1000 power
  • DepositedTokens: 500 power
  • StakingTokens: 200 power

These values might not be sufficient for comprehensive testing scenarios, especially for operations requiring significant liquidity.

Let's verify if these values align with other test configurations:

✅ Verification successful

Let me search for more context about token allocations in test configurations.


Let me search for any test failures or issues related to token amounts to verify if the current values are causing any problems.


Based on the gathered evidence, I can now provide a final response:

Token allocations are appropriate for test scenarios

The current token allocations (1000, 500, and 200 power) appear to be sufficient for testing purposes as:

  • These values are consistently used across test configurations
  • No test failures related to insufficient balances were found
  • The e2e tests successfully validate balances with these amounts
  • The values maintain appropriate proportions between account, deposit, and staking operations
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other token allocation patterns in test files
rg -A 2 "TokensFromConsensusPower.*evmostypes.PowerReduction" testutil/

Length of output: 742


Script:

#!/bin/bash
# Search for other test configurations and token allocations
rg -B 2 -A 2 "AccountTokens|StakingTokens|DepositedTokens" tests/ testutil/

Length of output: 4287


Script:

#!/bin/bash
# Search for test failures or issues related to token amounts
rg -B 2 -A 2 "insufficient.*balance|not enough|token.*fail" tests/

Length of output: 68

testutil/network/tx_internal.go (6)

25-25: Check for empty Validators slice before accessing index 0

Similar to the previous comment, ensure that n.Validators[0] is safely accessed.

Since this concern was previously raised, and the user indicated that there's always at least one validator, we can proceed with caution. However, for future-proofing, consider adding a check.


42-45: Handle error returned by TxEncoder when encoding the transaction

The error from txConfig.TxEncoder()(txBuilder.GetTx()) is being correctly handled here. Good job on ensuring that potential errors are not ignored.


46-52: Properly handle errors from simulation

The simulation step correctly checks and handles errors returned by txClient.Simulate. This ensures that any issues during gas estimation are caught early.


81-84: Handle error when encoding the signed transaction

Good job handling the error returned when encoding the signed transaction. This ensures any issues during encoding are caught.


86-86: Return the signed transaction bytes

The function correctly returns the signed transaction bytes.


14-21: Ensure the existence of validators before accessing index 0

Accessing n.Validators[0] without checking if n.Validators is non-empty can lead to a runtime panic if the slice is empty. Even though previous learning indicates that Validators is guaranteed to have at least one validator, it's safer to include a check to prevent potential issues if future changes alter this assumption.

Run the following script to confirm that Validators is always populated:

resSigningInfo, err := s.network.QuerySlashing().SigningInfo(context.Background(), &slashingtypes.QuerySigningInfoRequest{ConsAddress: sdk.ConsAddress(s.network.Validators[3].PubKey.Address()).String()})
s.Require().NoError(err)
// validator3 is jailed
s.Require().True(resSigningInfo.ValSigningInfo.JailedUntil.After(time.Now()))

Check warning

Code scanning / CodeQL

Calling the system time Warning test

Calling the system time may be a possible source of non-determinism
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 20

🧹 Outside diff range and nitpick comments (27)
tests/e2e/oracle/suite.go (3)

10-15: Consider improving field encapsulation.

The network field could be made private (renamed to network) since it's an implementation detail. If external access is needed, consider adding getter methods.

 type E2ETestSuite struct {
 	suite.Suite
 
 	cfg     network.Config
-	network *network.Network
+	network *network.Network // private field for better encapsulation
 }

21-28: Consider making timeout and target height configurable.

The hardcoded values for timeout (20 seconds) and target height (2) could be made configurable through constants or suite fields. This would allow for different test environments that might need longer timeouts or higher block heights.

+const (
+	defaultSetupTimeout  = 20 * time.Second
+	defaultTargetHeight  = 2
+)
+
 func (s *E2ETestSuite) SetupSuite() {
 	s.T().Log("setting up e2e test suite")
 	var err error
 	s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
 	s.Require().NoError(err)
-	_, err = s.network.WaitForHeightWithTimeout(2, 20*time.Second)
+	_, err = s.network.WaitForHeightWithTimeout(defaultTargetHeight, defaultSetupTimeout)
 	s.Require().NoError(err)
 }

30-32: Enhance teardown with logging and error handling.

Consider adding logging and error handling to ensure proper cleanup and help with debugging test failures.

 func (s *E2ETestSuite) TearDownSuite() {
+	s.T().Log("tearing down e2e test suite")
 	s.network.Cleanup()
+	s.T().Log("cleanup completed")
 }
x/oracle/types/types.go (2)

Line range hint 19-23: Clean up commented-out code

The struct definitions contain commented-out fields that should be completely removed rather than left as comments. This improves code readability and maintenance.

Apply this diff to clean up the commented-out code:

 	Token struct {
 		Name string `json:"name"`
 		Desc string
-		// Chain struct {
-		// 	Name string `json:"name"`
-		// 	Desc string `json:"desc"`
-		// } `json:"chain"`
 		Decimal  string `json:"decimal"`
 		Contract string `json:"contract"`
 		AssetID  string `json:"asset_id"`
 	} `json:"token"`
 	Feeder struct {
-		// Start    string `json:"start"`
-		// End      string `json:"end"`
 		Interval string `json:"interval"`
-		// RuleID   string `json:"rule_id"`
 	} `json:"feeder"`

Also applies to: 26-28


49-50: Document the purpose of NSTIDPrefix constant

The new constant NSTIDPrefix lacks documentation explaining its purpose and usage. Since it's used for Non-Standard Token identification, this should be clearly documented.

Add documentation comment:

+// NSTIDPrefix defines the prefix used for Non-Standard Token identifiers
 const (
 	DefaultPriceValue   = 1
 	DefaultPriceDecimal = 0
 	NSTIDPrefix = "NST"
 )
testutil/network/query.go (1)

13-39: Consider refactoring to reduce code duplication.

All query methods follow the same pattern, differing only in the type-specific NewQueryClient function. Consider introducing a generic helper to reduce duplication.

Here's a suggested approach using generics:

// Generic helper function
func (n *Network) queryClient[T any](newClient func(client.Context) T) T {
    if len(n.Validators) == 0 {
        panic("network has no validators")
    }
    return newClient(n.Validators[0].ClientCtx)
}

// Example usage for one method
func (n *Network) QueryOracle() oracletypes.QueryClient {
    return n.queryClient(oracletypes.NewQueryClient)
}
tests/e2e/oracle/data.go (2)

9-9: Consider using RFC3339 time format.

The custom time format could lead to parsing issues. Consider using the standard RFC3339 format for better interoperability.

-const layout = "2006-01-02 15:04:05"
+const layout = time.RFC3339

41-41: Specify reasons for linting suppressions.

The //nolint:all directive suppresses all linting checks without specifying why. Consider using specific linting suppressions with explanatory comments.

-//nolint:all
+// nolint:unused // sourceID is required for interface compatibility
testutil/network/genesis_data.go (2)

15-24: Improve constant naming and documentation.

While the constants are documented, consider these improvements:

  1. Use a more descriptive prefix for test-specific constants (e.g., TEST_EVM_CHAIN_ID).
  2. Add documentation for NativeAssetAddress, ETHAssetAddress, NativeAssetID, and ETHAssetID.
  3. Consider grouping related constants together (chain-related, address-related, ID-related).
 const (
-	// TestEVMChainID represents the LayerZero chain ID for the test EVM chain
-	TestEVMChainID = 101
-	// EVMAddressLength is the standard length of EVM addresses in bytes
-	EVMAddressLength   = 20
-	NativeAssetAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
-	ETHAssetAddress    = "0xdac17f958d2ee523a2206206994597c13d831ec7"
-	NativeAssetID      = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee_0x65"
-	ETHAssetID         = "0xdac17f958d2ee523a2206206994597c13d831ec7_0x65"
+	// Chain-related constants
+	TEST_EVM_CHAIN_ID = 101 // LayerZero chain ID for the test EVM chain
+
+	// Address-related constants
+	EVM_ADDRESS_LENGTH = 20 // Standard length of EVM addresses in bytes
+	// Test addresses for assets (DO NOT USE IN PRODUCTION)
+	TEST_NATIVE_ASSET_ADDRESS = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
+	TEST_ETH_ASSET_ADDRESS    = "0xdac17f958d2ee523a2206206994597c13d831ec7"
+
+	// Asset ID constants for testing
+	TEST_NATIVE_ASSET_ID = TEST_NATIVE_ASSET_ADDRESS + "_0x65"
+	TEST_ETH_ASSET_ID    = TEST_ETH_ASSET_ADDRESS + "_0x65"
 )

49-54: Remove commented-out code.

The commented-out code for DefaultGenStateOperator and DefaultGenStateDelegation should either be used or removed to maintain code clarity.

x/oracle/keeper/aggregator/calculator.go (4)

19-20: Consider type consistency between price and power

The struct now mixes string (price) and *big.Int (power) types. This could lead to confusion in operations and comparisons. Consider:

  1. Documenting the expected string format for price
  2. Adding helper methods for price comparisons

27-29: Remove or document the commented field

The commented confirmed field should either be removed if no longer needed or documented if planned for future use.


Line range hint 179-184: Address TODO comments and document version constraints

The code contains multiple TODO comments indicating temporary solutions and future improvements:

  1. "just in v1 with mode==1"
  2. "this may delay to current block finish"

These should be tracked and addressed in future updates.

Would you like me to create GitHub issues to track these TODO items?


Line range hint 1-197: Consider architectural implications of string-based price representation

The transition from *big.Int to string for price representation has several architectural implications:

  1. Performance: String operations vs numerical operations
  2. Precision: Potential loss of precision in string representation
  3. Validation: Need for consistent string format validation
  4. Interoperability: Impact on external systems and APIs

Consider documenting these design decisions and their rationale.

x/oracle/keeper/aggregator/aggregator.go (3)

27-41: Consider logging non-standard price formats.

The early return for non-standard prices (NST) is a reasonable approach, but consider adding logging to track such occurrences. This would help monitor the frequency of non-standard price submissions.

 if !ok {
+    // TODO: Add logging for non-standard price formats
     return p.price
 }

59-61: Consider using a string pool for frequently used price strings.

While string copying is simpler than big.Int copying, consider using a string pool for frequently occurring price values to reduce memory allocations, especially in high-throughput scenarios.

Also applies to: 71-72, 77-77


Line range hint 171-195: Document consensus implications for non-standard prices.

The early return for non-standard prices when power exceeds threshold could affect consensus mechanism. Consider:

  1. Documenting this behavior in comments
  2. Adding metrics to track frequency of non-standard price consensus
  3. Implementing a more robust consensus mechanism for mixed price formats
x/oracle/module.go (1)

Line range hint 357-377: Consider optimizing cache operations

The cache operations and event emissions could be optimized and made more maintainable.

Consider extracting the cache and event handling logic into separate methods:

+func (am AppModule) handleCacheUpdates(ctx sdk.Context, cs cache.Caches, agc types.AggregatorContext) error {
+    if _, _, paramsUpdated := cs.CommitCache(ctx, false, am.keeper); paramsUpdated {
+        var p cache.ItemP
+        if err := cs.GetCache(&p); err != nil {
+            return err
+        }
+        params := types.Params(p)
+        agc.SetParams(&params)
+        ctx.EventManager().EmitEvent(sdk.NewEvent(
+            types.EventTypeCreatePrice,
+            sdk.NewAttribute(types.AttributeKeyParamsUpdated, types.AttributeValueParamsUpdatedSuccess),
+        ))
+    }
+    return nil
+}
x/oracle/keeper/native_token.go (2)

26-33: Consider extracting hardcoded values to configuration

The constants contain hardcoded Ethereum addresses and chain IDs. This could make it difficult to update values or add support for new networks.

Consider:

  1. Moving these values to a configuration file or genesis parameters
  2. Creating a more flexible structure to support different asset types beyond NSTETH
-const (
-	NSTETHAssetAddr = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
-	NSTETHAssetIDMainnet  NSTAssetID = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee_0x7595"
-	NSTETHAssetIDLocalnet NSTAssetID = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee_0x65"
-	NSTETHAssetIDHolesky  NSTAssetID = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee_0x9d19"
-	NSTETHAssetIDSepolia  NSTAssetID = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee_0x9ce1"
-)
+var (
+	networkConfig = types.NetworkConfig{
+		NSTETHAssetAddr: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
+		Networks: map[string]types.NetworkInfo{
+			"mainnet":  {ChainID: "0x7595", Address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"},
+			"localnet": {ChainID: "0x65", Address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"},
+			"holesky":  {ChainID: "0x9d19", Address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"},
+			"sepolia":  {ChainID: "0x9ce1", Address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"},
+		},
+	}
+)

28-29: Address TODO comments about NSTETH limitations

The TODO comments indicate limitations in the current implementation:

  1. Only NSTETH is supported with capped effective balance
  2. The endpoint versioning approach is noted as "bad practice"

Would you like me to help create GitHub issues to track:

  1. Support for additional asset types beyond NSTETH
  2. Improved endpoint versioning strategy
testutil/network/network.go (2)

484-492: Add error handling for peer setup

The peer setup logic is good but could be more robust:

  1. Consider handling edge cases (e.g., when no peers are available)
  2. Add validation for the peer addresses format
 sort.Strings(addressesIPs)
+if len(addressesIPs) == 0 {
+    return nil, errors.New("no peer addresses available")
+}
 for i := 0; i < cfg.NumValidators; i++ {
     cfgTmp := network.Validators[i].Ctx.Config
     IPs := make([]string, 0, cfg.NumValidators-1)
     IPs = append(IPs, addressesIPs[0:i]...)
     IPs = append(IPs, addressesIPs[i+1:]...)
+    for _, ip := range IPs {
+        if !strings.Contains(ip, "@") {
+            return nil, fmt.Errorf("invalid peer address format: %s", ip)
+        }
+    }
     cfgTmp.P2P.PersistentPeers = strings.Join(IPs, ",")

582-633: Improve documentation and reduce duplication

The state height methods are well-implemented but need improvements:

  1. Add detailed documentation explaining the difference between block height and state height
  2. Consider reducing code duplication with block height methods
+// LatestStateHeight returns the latest state height from ABCI info.
+// Unlike LatestHeight which returns the latest block height,
+// this method returns the height at which all state transitions are completed.
 func (n *Network) LatestStateHeight() (int64, error) {

Consider extracting common waiting logic:

+func (n *Network) waitForHeightWithTimeoutAndQuery(h int64, t time.Duration, queryFn func() (int64, error)) (int64, error) {
+    ticker := time.NewTicker(time.Second)
+    timeout := time.After(t)
+
+    if len(n.Validators) == 0 {
+        return 0, errors.New("no validators available")
+    }
+
+    var latestHeight int64
+    for {
+        select {
+        case <-timeout:
+            ticker.Stop()
+            return latestHeight, errors.New("timeout exceeded waiting for block")
+        case <-ticker.C:
+            height, err := queryFn()
+            if err == nil {
+                latestHeight = height
+                if latestHeight >= h {
+                    return latestHeight, nil
+                }
+            }
+        }
+    }
+}
x/delegation/keeper/update_native_restaking_balance.go (2)

Line range hint 65-65: Fix typo in comment: 'ture' should be 'true'

There's a minor typo in the comment that should be corrected for clarity.

Apply the following diff:

-    // return ture to break the iteration if there isn't remaining amount to be slashed
+    // return true to break the iteration if there isn't remaining amount to be slashed

Line range hint 76-80: Avoid variable shadowing of err in closure functions

In the opFunc functions, the variable err is redeclared using :=, which shadows the outer err variable. This can lead to confusion and potential bugs. It's recommended to use = when assigning to err if it has already been declared.

Apply the following diff to fix the variable shadowing:

-        opAccAddr, err := sdk.AccAddressFromBech32(keys.OperatorAddr)
+        opAccAddr, err = sdk.AccAddressFromBech32(keys.OperatorAddr)

Alternatively, declare a new variable name:

-        opAccAddr, err := sdk.AccAddressFromBech32(keys.OperatorAddr)
+        opAccAddr, addrErr := sdk.AccAddressFromBech32(keys.OperatorAddr)
+        if addrErr != nil {
+            return true, addrErr
+        }
tests/e2e/oracle/create_price.go (3)

106-106: Reminder: Address the TODO regarding block height variance

The TODO comment suggests that the block height may exceed 13 and recommends using a larger price window (nonce > 3) to increase confidence. Addressing this will enhance test reliability.

Would you like assistance in adjusting the test parameters or updating the price window to accommodate this scenario?


334-334: Remove debug print statements from committed code

The statement fmt.Println("debug----->jailed:", resOperator.Jailed) appears to be for debugging purposes. It's best practice to remove such statements or replace them with proper logging before committing code.


290-297: Refactor repeated code for creating and sending price messages

The code for creating and sending price messages for multiple validators is duplicated. Consider refactoring this into a helper function to improve maintainability and reduce redundancy.

You could create a function like sendPriceMessages(validators, priceSource, height, nonce) to encapsulate this logic.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between c96883e and 9a8474c.

📒 Files selected for processing (17)
  • tests/e2e/oracle/create_price.go (1 hunks)
  • tests/e2e/oracle/data.go (1 hunks)
  • tests/e2e/oracle/helper_nstconvert.go (1 hunks)
  • tests/e2e/oracle/suite.go (1 hunks)
  • testutil/network/genesis_data.go (1 hunks)
  • testutil/network/network.go (15 hunks)
  • testutil/network/query.go (1 hunks)
  • x/delegation/keeper/update_native_restaking_balance.go (1 hunks)
  • x/oracle/keeper/aggregator/aggregator.go (9 hunks)
  • x/oracle/keeper/aggregator/calculator.go (5 hunks)
  • x/oracle/keeper/aggregator/context.go (4 hunks)
  • x/oracle/keeper/aggregator/worker.go (2 hunks)
  • x/oracle/keeper/native_token.go (3 hunks)
  • x/oracle/keeper/prices.go (5 hunks)
  • x/oracle/module.go (5 hunks)
  • x/oracle/types/params.go (2 hunks)
  • x/oracle/types/types.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/e2e/oracle/helper_nstconvert.go
  • x/oracle/keeper/prices.go
🧰 Additional context used
📓 Learnings (3)
tests/e2e/oracle/create_price.go (1)
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: tests/e2e/oracle/create_price.go:37-39
Timestamp: 2024-11-16T11:07:01.278Z
Learning: In `tests/e2e/oracle/create_price.go`, variables like `price1` and `price2` may be defined in other files such as `tests/e2e/oracle/data.go` within the same PR. Ensure to check for variable definitions across all related files in the PR before flagging them as undefined.
tests/e2e/oracle/data.go (1)
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: tests/e2e/oracle/create_price.go:37-39
Timestamp: 2024-11-16T11:07:01.278Z
Learning: In `tests/e2e/oracle/create_price.go`, variables like `price1` and `price2` may be defined in other files such as `tests/e2e/oracle/data.go` within the same PR. Ensure to check for variable definitions across all related files in the PR before flagging them as undefined.
testutil/network/genesis_data.go (1)
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: testutil/network/util.go:292-349
Timestamp: 2024-11-15T07:01:04.078Z
Learning: In the Go code for Exocore, specifically in the `testutil/network/util.go` file, functions like `NewGenStateAssets` are expected to modify the global variable `DefaultGenStateAssets`. Modifying global variables in these functions is acceptable and expected behavior in this context.
🪛 GitHub Check: CodeQL
tests/e2e/oracle/create_price.go

[warning] 319-319: Calling the system time
Calling the system time may be a possible source of non-determinism

tests/e2e/oracle/data.go

[warning] 36-36: Calling the system time
Calling the system time may be a possible source of non-determinism


[warning] 57-57: Calling the system time
Calling the system time may be a possible source of non-determinism


[warning] 71-71: Calling the system time
Calling the system time may be a possible source of non-determinism

x/oracle/module.go

[warning] 160-160: Panic in BeginBock or EndBlock consensus methods
path flow from Begin/EndBlock to a panic call


[warning] 163-165: Iteration over map
Iteration over map may be a possible source of non-determinism

🔇 Additional comments (22)
tests/e2e/oracle/suite.go (1)

1-32: Verify consistency with other e2e test suites.

Let's ensure this suite structure follows the same patterns as other e2e test suites in the project.

✅ Verification successful

Based on the extensive output from examining the test suites in the codebase, I can now provide a definitive response about the consistency of the e2e test suite structure.

E2E test suite structure is consistent with project patterns

The oracle e2e test suite follows the same patterns used in other e2e test suites in the project, specifically:

  1. It properly embeds suite.Suite
  2. It contains the standard network configuration and setup fields:
    • cfg network.Config
    • network *network.Network
  3. It implements the required suite lifecycle methods:
    • SetupSuite() for initialization
    • TearDownSuite() for cleanup
  4. It follows the same network setup pattern seen in other e2e suites like bank/suite.go
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistency with other e2e test suites
# Look for similar suite structures in other e2e tests

# Search for other e2e test suites
ast-grep --pattern 'type $_TestSuite struct {
    suite.Suite
    $$$
}'

# Search for other SetupSuite implementations
ast-grep --pattern 'func ($_ *$_TestSuite) SetupSuite() {
    $$$
}'

Length of output: 145


Script:

#!/bin/bash
# Let's try a different approach using ripgrep to find test suites

# Search for test suite struct definitions
rg -l "type.*TestSuite.*struct" --type go

# Then let's examine the content of these files
for file in $(rg -l "type.*TestSuite.*struct" --type go); do
  echo "=== $file ==="
  cat "$file"
  echo -e "\n\n"
done

Length of output: 104111

x/oracle/types/types.go (1)

50-50: Verify the integration of NSTIDPrefix

Let's ensure this new prefix is properly integrated and doesn't conflict with existing token identifiers.

✅ Verification successful

Let me gather more information about the usage of this prefix and related functionality.


Based on the search results, I can now provide a final response about the NSTIDPrefix integration:

NSTIDPrefix is properly integrated and used consistently

The prefix "NST" is well-integrated into the codebase and is used consistently for native staking token functionality:

  • Used in price updates via UpdateNSTByBalanceChange
  • Properly validated through IsNST checks
  • Integrated with token systems through DepositNST and WithdrawNST operations
  • No conflicts found with other ID prefixes (only other prefix found is ChainIDPrefix which serves a different purpose)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of NSTIDPrefix and similar prefix constants
echo "Searching for NSTIDPrefix usage and other ID prefixes..."
rg --type go "IDPrefix.*=.*\".*\"" 

# Search for potential prefix-related functions
echo "Searching for prefix-related functions..."
ast-grep --pattern 'func $$$($$$) {
  $$$
  NST$$$
  $$$
}'

Length of output: 421


Script:

#!/bin/bash
# Search for any NST related code or strings
echo "Searching for NST related code..."
rg --type go "NST"

# Search for functions that might be generating or validating IDs
echo "Searching for ID generation/validation functions..."
rg --type go "func.*(Generate|Valid|New).*ID"

# Search for test files that might be using this prefix
echo "Searching in test files..."
rg --type go -t test "NST"

Length of output: 18316

testutil/network/query.go (1)

1-11: LGTM! Clean import organization.

The imports are well-organized and properly grouped between Exocore-specific and Cosmos SDK types.

tests/e2e/oracle/data.go (1)

11-15: LGTM! Well-structured data type.

The struct is well-defined with appropriate field types. Using string for Price allows handling arbitrary precision values.

x/oracle/keeper/aggregator/worker.go (2)

98-100: Verify the impact of return type change from *big.Int to string

The change in return type is a breaking change that could affect consumers of this API. Let's verify all usages to ensure they've been updated accordingly.

✅ Verification successful

Let me gather more information about the usage context.


Let me check one more thing to understand how the worker interacts with the aggregator.


Based on the comprehensive analysis of the code, I can now provide the final response:

The return type change from *big.Int to string is properly handled throughout the codebase

The change is part of a consistent design where:

  1. The worker's aggregate() method simply delegates to the underlying aggregator
  2. The aggregator handles all price values as strings internally
  3. The conversion between *big.Int and string happens only when needed for mathematical operations (median calculation)
  4. All price-related structures (priceWithTimeAndRound, reportPrice, aggregator) are already using string representation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for direct calls to worker.aggregate() to verify all consumers are updated
ast-grep --pattern 'worker.aggregate()' 

# Search for any remaining *big.Int price handling that might need updating
rg -l 'big\.Int.*price' 

Length of output: 108


Script:

#!/bin/bash
# Check the content of aggregator.go to understand the usage
cat x/oracle/keeper/aggregator/aggregator.go

# Search for any references to worker type or its methods
ast-grep --pattern 'type worker struct'
ast-grep --pattern 'func (w *worker)'

# Look for any price-related string handling that might be related
rg -l 'string.*price|price.*string'

Length of output: 8576


Script:

#!/bin/bash
# Check the worker implementation to understand the complete context
cat x/oracle/keeper/aggregator/worker.go

# Also check for any tests that might show the expected behavior
cat x/oracle/keeper/aggregator/helper_test.go

Length of output: 4514


108-108: Verify precision handling in string price representation

With the switch from *big.Int to string representation, we need to ensure that:

  1. The decimal precision is maintained as per the worker's decimal field
  2. No precision loss occurs during price aggregation
✅ Verification successful

Let me gather more information about the aggregation implementation to verify the precision handling.


Let me gather more information about the aggregation implementation to verify how the decimal precision is handled.


Let me try one more search to find the aggregator implementation and price decimal handling.


Based on the code analysis, I can now provide a final response about the precision handling in the price representation.

Decimal precision is properly maintained in price aggregation

The verification shows that decimal precision is handled correctly:

  1. The decimal precision is preserved through the aggregation process:

    • Decimal value is obtained from token info configuration: decimal: agc.params.GetTokenInfo(feederID).Decimal
    • Decimal validation is enforced through CheckDecimal function that ensures reported prices match the configured decimal precision
    • The aggregator preserves the decimal value in the final price structure: PriceTimeRound{ Price: finalPrice, Decimal: agc.params.GetTokenInfo(msg.FeederID).Decimal }
  2. No precision loss occurs during aggregation:

    • Price values are handled as strings and converted to big.Int for calculations
    • The aggregator maintains the full precision during calculations by using big.Int arithmetic
    • The final aggregated price is converted back to string representation preserving the full precision
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Look for price string format handling in the aggregator
ast-grep --pattern $'func \(.*aggregator\) aggregate\(\) string {
  $$$
}'

# Search for decimal precision handling
rg -A 5 'decimal.*price' 

Length of output: 9085


Script:

#!/bin/bash
# Look for the aggregator implementation
ast-grep --pattern $'func \(a \*aggregator\) aggregate\(\) string {
  $$$
}'

# Search for price-related type definitions and conversions
rg -A 5 'type.*Price'

# Look for any string to decimal/number conversions in the oracle module
rg -A 5 'strconv\.' x/oracle/

Length of output: 96685


Script:

#!/bin/bash
# Look for the aggregator implementation
ast-grep --pattern 'func \(a \*aggregator\) aggregate\(\) string {
  $$$
}'

# Look for decimal validation in the oracle module
rg -A 5 'decimal.*valid' x/oracle/

# Look for decimal conversion or handling in the oracle module
rg -A 5 'NewDecFromStr|NewDecFromInt' x/oracle/

Length of output: 1030


Script:

#!/bin/bash
# Search for aggregator implementation in worker.go
rg -A 10 'aggregate\(\) string' x/oracle/

# Look for decimal checks in the aggregator context
rg -A 5 'decimal' x/oracle/keeper/aggregator/

# Look for price validation in the aggregator
rg -A 5 'validate.*price|check.*price' x/oracle/keeper/aggregator/

Length of output: 7932

x/oracle/keeper/aggregator/calculator.go (2)

77-86: Verify copyBigInt implementation

The method uses copyBigInt for deep copying *big.Int values. Let's ensure this helper function is properly implemented.

✅ Verification successful

Implementation of copyBigInt is correct and safe

The copyBigInt implementation in x/oracle/keeper/aggregator/util.go is properly handling deep copying of *big.Int values by:

  • Correctly handling nil input by returning nil
  • Using big.NewInt(0).Set(i) which creates a new big.Int and copies the value from the input, ensuring a true deep copy
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for copyBigInt implementation
ast-grep --pattern 'func copyBigInt($_) *big.Int {
  $$$
}'

Length of output: 385


13-13: Verify string format validation for price field

The change from *big.Int to string for price representation requires careful validation to ensure correct numerical format and precision.

✅ Verification successful

Based on the search results from both shell script executions, I can now generate the final response:

String price field requires validation before use

The change from *big.Int to string for price representation is validated through multiple layers:

  • Price strings are validated for numerical format when converted using sdkmath.NewIntFromString in aggregator logic
  • Sanity checks ensure non-empty price values through sanityCheck function
  • Price proposals go through validation rules defined in params
  • Invalid price formats result in errors like ErrPriceProposalIgnored and ErrInvalidMsg
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for price string validation logic
rg -A 5 'func.*[Vv]alidate.*[Pp]rice|func.*[Pp]arse.*[Pp]rice' 

Length of output: 64


Script:

#!/bin/bash
# Let's search for any string-to-number conversion or validation logic for prices
rg -A 5 'price.*string|string.*price' -i

# Also search for any functions that might handle price validation
ast-grep --pattern 'func $_($$$) {
  $$$
  price
  $$$
}'

Length of output: 53354


Script:

#!/bin/bash
# Let's search for validation or conversion logic specifically in the aggregator package
rg -A 5 'NewIntFromString.*[Pp]rice|[Vv]alidate.*[Pp]rice|[Cc]onvert.*[Pp]rice' x/oracle/keeper/aggregator/

# Also search for any price-related error handling
rg -A 3 'err.*[Pp]rice|[Pp]rice.*err' x/oracle/keeper/aggregator/

Length of output: 2903

x/oracle/keeper/aggregator/aggregator.go (3)

45-45: LGTM: Consistent type change for price representation.

The change to string for finalPrice while maintaining *big.Int for power calculations is appropriate.


224-224: LGTM: Consistent price field handling.

The price field assignment maintains consistency with the new string-based price representation while preserving the existing ordering and filtering logic.


12-12: Verify string-to-bigint conversion handling throughout the codebase.

The change from *big.Int to string for price fields allows for more flexible price representations (including non-standard formats) but requires careful handling of string-to-bigint conversions. Ensure all conversion points properly handle potential parsing errors.

Also applies to: 21-21

✅ Verification successful

Let me check the conversion handling in the aggregator implementation to ensure proper error handling.


String-to-bigint conversion handling is properly implemented

The code already implements proper error handling for string-to-bigint conversions:

  • In both conversion points, the code checks the ok flag returned by SetString
  • When conversion fails (!ok), it gracefully handles non-standard price formats by returning the original string price
  • This implementation allows for both numerical prices and non-standard price formats (NST) to coexist safely
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for potential string-to-bigint conversion points that might need error handling
rg "SetString|new\(big\.Int\).*String" --type go

Length of output: 542


Script:

#!/bin/bash
# Get the context around string-to-bigint conversions in the aggregator
rg "SetString|new\(big\.Int\).*String" x/oracle/keeper/aggregator/aggregator.go -B 3 -A 3

Length of output: 716

x/oracle/module.go (1)

161-163: ⚠️ Potential issue

Ensure deterministic map iteration

The iteration over validatorPowers map could lead to non-deterministic behavior across nodes.

Consider sorting the validators before iteration:

+    // Get sorted validators for deterministic iteration
+    validators := make([]string, 0, len(validatorPowers))
+    for validator := range validatorPowers {
+        validators = append(validators, validator)
+    }
+    sort.Strings(validators)
-    for validator := range validatorPowers {
+    for _, validator := range validators {
         am.keeper.InitValidatorReportInfo(ctx, validator, ctx.BlockHeight())
     }
⛔ Skipped due to learnings
Learnt from: leonz789
PR: ExocoreNetwork/exocore#224
File: x/oracle/module.go:0-0
Timestamp: 2024-11-12T10:03:15.304Z
Learning: In `x/oracle/module.go`, iterating over `validatorPowers` without sorting is acceptable because the order does not affect consensus in this context.
x/oracle/keeper/aggregator/context.go (2)

207-208: LGTM: Good improvements to error handling

The changes properly propagate the context and use structured error wrapping, which improves error handling and debugging capabilities.


Line range hint 124-146: Consider revising the error handling strategy in check mode

The current implementation suppresses errors during transaction simulation (isCheckMode), which could lead to inconsistent behavior between simulation and actual execution. This might cause transactions to pass simulation but fail during actual execution.

Consider one of these alternatives:

  1. Return a specific simulation-only error type that can be handled differently by the caller
  2. Add logging in check mode to help diagnose potential issues

Let's verify the impact of this change on transaction simulation:

x/oracle/keeper/native_token.go (1)

423-428: LGTM: Type conversion is safe

The helper functions have been correctly updated to use the new NSTAssetID type. The type conversion is safe as it's just a string type alias, and all network values are properly initialized in the maps.

x/oracle/types/params.go (3)

Line range hint 1-500: LGTM with validations

The extensive validation logic in the Params.Validate() method provides good safeguards for the new configurations. The method includes comprehensive checks for:

  • Token parameters
  • TokenFeeder parameters
  • Cross-validation between different components

Line range hint 67-115: Verify RuleID configuration consistency

Both ETH and NSTETH tokens use RuleID: 1, which implies they share the same price source rules. Verify this is intentional and the rules are appropriate for both tokens.

✅ Verification successful

Based on the search results, I can now provide a final response as we have sufficient information about the RuleSource configuration:

RuleID 1 configuration is appropriate for both ETH and NSTETH tokens

The RuleSource with ID 1 is configured with SourceIDs: []uint64{0}, where according to the code comments, setting the first source ID to 0 means "all valid sources" will be used. This is an intentional and appropriate configuration for both tokens as:

  • It ensures maximum price accuracy by considering all valid price sources
  • It provides consistency in price sourcing for related assets (ETH and its staked variant NSTETH)
  • The configuration aligns with the protocol's design for price feed validation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for RuleSource configurations
ast-grep --pattern 'type RuleSource struct {
  $$$
}'

# Search for documentation about rule configurations
rg "RuleSource" -A 5 -B 5

Length of output: 18115


109-115: Verify StartBaseBlock configuration

The StartBaseBlock (10) is significantly lower than the ETH token's configuration (1000000). This large difference might indicate:

  1. A potential configuration error
  2. Different requirements for NSTETH price updates
✅ Verification successful

Based on the search results, I can now provide a final response as there's sufficient context about the StartBaseBlock configurations and their purpose:

Different StartBaseBlock values are intentional and correct

The different StartBaseBlock values between ETH (1000000) and NSTETH (10) tokens are intentional:

  1. The code shows consistent patterns of different StartBaseBlock values being used for different tokens:
    • In genesis data: ETH token uses 10, NSTETH uses 7
    • In test cases: Various values (1, 10, 1000000) are used
  2. The StartBaseBlock parameter represents when price updates begin for a token, and the documentation states: "include, first block which start_round_id can be settled is at least start_base_block+1"
  3. The validation logic ensures StartBaseBlock values are properly validated against overlaps and continuity between token feeders
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other TokenFeeder configurations to verify StartBaseBlock patterns
ast-grep --pattern 'TokenID: $_,
  RuleID: $_,
  StartRoundID: $_,
  StartBaseBlock: $_,
  Interval: $_'

# Search for documentation or comments about StartBaseBlock configuration
rg "StartBaseBlock" -A 3 -B 3

Length of output: 26447

testutil/network/network.go (3)

84-91: LGTM: Config struct changes are well-documented

The new fields are properly documented and follow consistent naming conventions.


495-505: 🛠️ Refactor suggestion

Move hardcoded values to configuration

The gateway setup has two issues:

  1. Hardcoded gateway address reduces flexibility
  2. Fixed commission rate should be configurable

Consider moving these to the Config struct for better maintainability and testing.

+type Config struct {
+    // ... existing fields ...
+    GatewayAddress string
+    CommissionRate string
+}

+func DefaultConfig() Config {
+    return Config{
+        // ... existing initialization ...
+        GatewayAddress: "exo18cggcpvwspnd5c6ny8wrqxpffj5zmhklprtnph",
+        CommissionRate: "0.5",
+    }
}

-commissionRate, _ := sdkmath.LegacyNewDecFromStr("0.5")
-gateWayAddressStr := "exo18cggcpvwspnd5c6ny8wrqxpffj5zmhklprtnph"
+commissionRate, err := sdkmath.LegacyNewDecFromStr(cfg.CommissionRate)
+if err != nil {
+    return nil, fmt.Errorf("invalid commission rate: %v", err)
+}
+gateWayAddr, err := sdk.AccAddressFromBech32(cfg.GatewayAddress)

Likely invalid or redundant comment.


380-394: 🛠️ Refactor suggestion

Enhance key generation security

While switching to Ed25519 is good, consider these security improvements:

  1. Add entropy parameter to mnemonic generation
  2. Verify the key derivation path is appropriate for Ed25519
-_, mnemonic, err := kb.NewMnemonic(fmt.Sprintf("valconskey%d", i), keyring.English, sdk.GetConfig().GetBech32AccountPubPrefix(), keyring.DefaultBIP39Passphrase, algo)
+entropy, err := bip39.NewEntropy(256)
+if err != nil {
+    return nil, err
+}
+_, mnemonic, err := kb.NewMnemonic(
+    fmt.Sprintf("valconskey%d", i),
+    keyring.English,
+    sdk.GetConfig().GetBech32AccountPubPrefix(),
+    keyring.DefaultBIP39Passphrase,
+    algo,
+    entropy,
+)

Likely invalid or redundant comment.

x/delegation/keeper/update_native_restaking_balance.go (1)

48-49: Approved: Logic adjustment for pendingSlashAmount

The adjustment to set pendingSlashAmount to zero when it is not positive ensures correct handling of slashing amounts and prevents potential negative values.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (4)
x/oracle/keeper/aggregator/calculator_test.go (1)

57-60: LGTM! Consider enhancing test readability

The string representation changes are correct and maintain the test's ability to handle different source orderings.

Consider extracting the expected values into named constants to improve test maintainability:

+ const (
+   expectedPrice1 = "12"
+   expectedPrice2 = "15"
+ )
  So(confirmed[i].detID, ShouldEqual, "2")
- So(confirmed[i].price, ShouldResemble, "12")
+ So(confirmed[i].price, ShouldResemble, expectedPrice1)
  So(confirmed[1-i].detID, ShouldEqual, "3")
- So(confirmed[1-i].price, ShouldResemble, "15")
+ So(confirmed[1-i].price, ShouldResemble, expectedPrice2)
x/oracle/keeper/aggregator/aggregator_test.go (3)

18-18: LGTM! Consider enhancing test readability.

The initial price validation checks are correct, using string representation as expected.

Consider adding comments to clarify the expected empty state:

-So(report.prices[1].price, ShouldEqual, "")
+// Verify price is initially empty before confirmation
+So(report.prices[1].price, ShouldEqual, "")

Also applies to: 22-22, 26-27


33-33: Consider adding boundary test cases.

While the current test cases validate the basic functionality, consider adding tests for:

  • Edge cases (very large numbers, zero)
  • Invalid price formats
  • Negative prices (if applicable)

Example addition:

{
    sourceID:  1,
    detID:     "10",
    price:     "999999999999999999", // Test large numbers
    timestamp: "-",
},

Also applies to: 39-39, 45-45, 48-48, 51-51


58-61: Document the price aggregation formula.

While the test validates the final prices correctly, it would be beneficial to document how "15" is derived from the input prices.

Add a comment block explaining the calculation:

+// Price aggregation formula:
+// v1: average of source1 (10) and source2 (20) = 15
+// v2: only source1 (10) = 10
+// v3: only source2 (20) = 20
+// finalPrice: median of validator prices (10, 15, 20) = 15
So(a.getReport("v1").price, ShouldEqual, "15")
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 9a8474c and 87760a9.

📒 Files selected for processing (3)
  • testutil/network/genesis_data.go (1 hunks)
  • x/oracle/keeper/aggregator/aggregator_test.go (1 hunks)
  • x/oracle/keeper/aggregator/calculator_test.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • testutil/network/genesis_data.go
🔇 Additional comments (4)
x/oracle/keeper/aggregator/calculator_test.go (3)

39-39: LGTM! String representation matches test scenario

The assertion correctly validates the expected price value of "10" for detid=1 consensus case.


66-66: LGTM! Consistent with single source consensus test

The string representation correctly validates the expected price for the single source consensus scenario.


34-34: LGTM! Verify string conversion handling

The change from big.Int to string representation is consistent with the codebase-wide updates.

✅ Verification successful

Based on the search results, I can see that there's been a consistent transition from big.Int to string representation for prices across the codebase. The test assertions are correctly using string comparisons, and the underlying types (PriceTimeDetID, PriceTimeRound, etc.) all use string representation for prices. This change is part of a broader, intentional modification to handle prices as strings throughout the system.

String price representation is the correct approach

The change from big.Int to string for price assertions is consistent with the codebase's design where prices are stored and handled as strings. This is evidenced by:

  • The PriceTimeDetID and PriceTimeRound structs use string for price fields
  • All price-related test assertions across the codebase use string comparisons
  • The aggregator and calculator components work with string prices
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify consistent price type usage across the codebase
ast-grep --pattern 'price.*big.Int'

Length of output: 37


Script:

#!/bin/bash
# Search for price-related assertions in test files
rg -A 2 'price.*ShouldResemble' --type go

# Search for price type declarations and usages
rg -A 2 'type.*Price' --type go
rg -A 2 'price.*string' --type go

Length of output: 63317

x/oracle/keeper/aggregator/aggregator_test.go (1)

Line range hint 1-67: Verify consistent string representation across related files.

The transition to string representation for prices is well implemented in this test file.

Let's verify consistency across related files:

✅ Verification successful

Let me gather more information to verify the consistency of string representation across the codebase.


Based on the comprehensive search results, I can now generate the final response:

String representation for prices is consistently implemented across the codebase

The verification shows:

  • All price-related structs and fields use string type for price values
  • Price comparisons and validations consistently handle string representations
  • The only big.Int usage is for internal calculations in calculator.go and aggregator.go, where prices are properly converted to/from strings
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any remaining big.Int price fields or numerical price comparisons
rg -t go "price.*big\.Int|price.*ShouldEqual.*[0-9]+" x/oracle/

# Check for consistent string price handling
ast-grep --pattern 'price.*ShouldEqual.*"[0-9]+"' x/oracle/

Length of output: 1107


Script:

#!/bin/bash
# Check for any price-related type definitions and struct fields
rg -t go "type.*[Pp]rice|price.*string|price.*[Ii]nt" x/oracle/

# Check for price-related function signatures and return types
ast-grep --pattern 'func $_($$$) $_Price' x/oracle/

# Look for price comparison or validation logic
rg -t go "compare.*[Pp]rice|validate.*[Pp]rice" x/oracle/

Length of output: 24122

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (4)
testutil/network/genesis_data.go (1)

49-54: Document empty genesis states.

The empty genesis states for Operator and Delegation modules need explanation. The commented-out default genesis initialization suggests incomplete implementation.

Add comments explaining why these genesis states are empty and when they should be populated.

testutil/network/tx_precompile.go (3)

21-22: Consider making gas limit configurable

The hardcoded gas limit of 500000 might not be suitable for all precompile transactions. Consider making it configurable or using gas estimation.

-const (
-	privateKey = "D196DCA836F8AC2FFF45B3C9F0113825CCBB33FA1B39737B948503B263ED75AE" // gitleaks:allow
-	gasLimit   = uint64(500000)
+var (
+	privateKey = os.Getenv("EXOCORE_TEST_PRIVATE_KEY") // Default to a test key if not set
+	gasLimit   = uint64(500000) // Default gas limit
)

+// SetGasLimit allows configuring the gas limit for precompile transactions
+func SetGasLimit(limit uint64) {
+	gasLimit = limit
+}

36-39: Document precompile addresses

The precompile addresses are hardcoded without documentation explaining their significance or how they were derived. Consider adding documentation about these addresses and their purpose.

 var (
+	// precompileAddresses maps precompile names to their designated addresses in the Exocore network
+	// 0x804: Assets precompile for managing network assets
+	// 0x805: Delegation precompile for managing validator delegations
 	precompileAddresses = map[precompile]common.Address{
 		ASSETS:     common.HexToAddress("0x0000000000000000000000000000000000000804"),
 		DELEGATION: common.HexToAddress("0x0000000000000000000000000000000000000805"),
 	}

124-131: Enhance parseABI error handling

The parseABI function could provide more context in error messages to help diagnose ABI parsing issues.

 func parseABI(abiPath string) (abi.ABI, error) {
 	f, err := os.Open(abiPath)
 	if err != nil {
-		return abi.ABI{}, err
+		return abi.ABI{}, fmt.Errorf("failed to open ABI file %s: %w", abiPath, err)
 	}
 	defer f.Close()
-	return abi.JSON(f)
+	abi, err := abi.JSON(f)
+	if err != nil {
+		return abi, fmt.Errorf("failed to parse ABI JSON from %s: %w", abiPath, err)
+	}
+	return abi, nil
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 87760a9 and cb2d760.

📒 Files selected for processing (4)
  • tests/e2e/bank/tx.go (1 hunks)
  • testutil/network/genesis_data.go (1 hunks)
  • testutil/network/tx_precompile.go (1 hunks)
  • x/oracle/keeper/native_token.go (8 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/e2e/bank/tx.go
  • x/oracle/keeper/native_token.go
🧰 Additional context used
📓 Learnings (1)
testutil/network/genesis_data.go (2)
Learnt from: MaxMustermann2
PR: ExocoreNetwork/exocore#192
File: x/assets/keeper/client_chain_asset.go:69-79
Timestamp: 2024-11-12T10:03:15.304Z
Learning: When suggesting input validation, be aware that there may be duplicated code around validations that can be refactored. Consider proposing the creation of `ClientChainInfo.Validate` and `StakingAssetInfo.Validate` functions, and suggest calling them in the relevant functions as well as in `genesis.Validate`.
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: testutil/network/util.go:292-349
Timestamp: 2024-11-15T07:01:04.078Z
Learning: In the Go code for Exocore, specifically in the `testutil/network/util.go` file, functions like `NewGenStateAssets` are expected to modify the global variable `DefaultGenStateAssets`. Modifying global variables in these functions is acceptable and expected behavior in this context.
🔇 Additional comments (4)
testutil/network/genesis_data.go (2)

15-24: ⚠️ Potential issue

Consider using dedicated test addresses instead of production ones.

While the constants are well-documented, using production addresses (USDT, ETH) in tests could lead to confusion and potential security risks if test configurations accidentally make it to production.

Consider using clearly marked test addresses:

-	NativeAssetAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
-	ETHAssetAddress    = "0xdac17f958d2ee523a2206206994597c13d831ec7"
+	NativeAssetAddress = "0xTEST000000000000000000000000000000000001"
+	ETHAssetAddress    = "0xTEST000000000000000000000000000000000002"

60-85: ⚠️ Potential issue

Document magic numbers and add bounds checking.

The init function uses magic numbers and assumes array indices exist without validation.

Consider these improvements:

  1. Document the significance of magic numbers:
+const (
+    // ETHTokenFeederStartBlock is the initial block for ETH price feeds
+    ETHTokenFeederStartBlock = 10
+    // NSTTokenFeederStartBlock is the initial block for NST price feeds
+    NSTTokenFeederStartBlock = 7
+)
  1. Add bounds checking:
 func init() {
+    if len(DefaultGenStateOracle.Params.Tokens) < 2 {
+        panic("insufficient tokens in oracle genesis state")
+    }
+    if len(DefaultGenStateOracle.Params.TokenFeeders) < 2 {
+        panic("insufficient token feeders in oracle genesis state")
+    }

Likely invalid or redundant comment.

testutil/network/tx_precompile.go (2)

43-58: 🛠️ Refactor suggestion

Improve initialization error handling

The init function uses panic for error handling, which is not ideal for a test utility. Consider making the initialization explicit and returning errors.

-func init() {
+// InitializePrecompiles initializes the precompile ABIs
+func InitializePrecompiles() error {
 	_, currentFile, _, ok := runtime.Caller(0)
 	if !ok {
-		fmt.Println("Failed to get current file path")
-		panic("Failed to get current file path")
+		return fmt.Errorf("failed to get current file path")
 	}
 	basePath := filepath.Dir(currentFile)
 	var err error
 	for precompileName, precompilePath := range precompilePaths {
 		p := filepath.Join(basePath, precompilePath)
 		abis[precompileName], err = parseABI(p)
 		if err != nil {
-			panic(fmt.Sprintf("Failed to parse abi from path:%s\r\n", p))
+			return fmt.Errorf("failed to parse ABI from path %s: %w", p, err)
 		}
 	}
+	return nil
 }

Likely invalid or redundant comment.


62-64: 🛠️ Refactor suggestion

Add context timeout and improve context handling

Using context.Background() without a timeout could lead to hanging transactions. Consider adding a timeout and accepting a context parameter.

-func (n Network) SendPrecompileTx(preCompileName precompile, methodName string, args ...interface{}) error {
-	ctx := context.Background()
+func (n Network) SendPrecompileTx(ctx context.Context, preCompileName precompile, methodName string, args ...interface{}) error {
+	if ctx == nil {
+		var cancel context.CancelFunc
+		ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second)
+		defer cancel()
+	}

Likely invalid or redundant comment.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (2)
x/oracle/keeper/aggregator/aggregator.go (2)

27-41: Consider adding error logging for failed price conversions.

The price aggregation logic correctly handles both numeric and non-numeric prices. However, it would be helpful to log when price conversion fails to aid in debugging.

 priceInt, ok := new(big.Int).SetString(p.price, 10)
 // price is not a number (NST), we will just return instead of calculation
 if !ok {
+    // Log conversion failure for debugging
+    log.Printf("Failed to convert price %s to big.Int for aggregation", p.price)
     return p.price
 }

186-192: Consider enhancing error context for non-numeric prices.

While the handling of non-numeric prices is correct, adding more context about which validator's price caused the conversion failure would be helpful for debugging.

 priceInt, ok := new(big.Int).SetString(validatorReport.aggregate(), 10)
 if !ok {
+    // Log which validator's price caused the conversion failure
+    log.Printf("Non-numeric price from validator %s: %s", validatorReport.validator, validatorReport.aggregate())
     // price is not number, we just return the price when power exceeds threshold
     agg.finalPrice = validatorReport.aggregate()
     return agg.finalPrice
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between cb2d760 and 64033dc.

📒 Files selected for processing (4)
  • x/oracle/keeper/aggregator/aggregator.go (7 hunks)
  • x/oracle/keeper/aggregator/calculator.go (4 hunks)
  • x/oracle/keeper/aggregator/util.go (1 hunks)
  • x/oracle/keeper/native_token.go (8 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • x/oracle/keeper/aggregator/calculator.go
  • x/oracle/keeper/aggregator/util.go
  • x/oracle/keeper/native_token.go
🧰 Additional context used
📓 Learnings (1)
x/oracle/keeper/aggregator/aggregator.go (2)
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: x/oracle/keeper/aggregator/aggregator.go:107-113
Timestamp: 2024-11-27T06:16:50.976Z
Learning: For non-deterministic sources (NS), string values for prices are acceptable without additional validation before storage.
Learnt from: leonz789
PR: ExocoreNetwork/exocore#233
File: x/oracle/keeper/aggregator/context.go:187-191
Timestamp: 2024-11-27T06:19:17.106Z
Learning: In the `x/oracle/keeper/aggregator/context.go` file, we accept 'nan' strings for NST scenarios and do not need to add price validation in this context.
🔇 Additional comments (5)
x/oracle/keeper/aggregator/aggregator.go (5)

12-12: LGTM! Type changes align with the new string-based price representation.

The conversion from *big.Int to string for price fields is consistent across the structs.

Also applies to: 21-21


45-45: LGTM! Consistent type change for finalPrice.

The change to string type for finalPrice maintains consistency with the new price representation model.


107-113: LGTM! Non-deterministic source price handling is correct.

The direct string assignment for NS prices aligns with the established requirements, as confirmed by previous learnings.

Also applies to: 124-125


148-148: LGTM! Price validation check is appropriate.

The length check for string prices is the correct approach for validating completed IVA prices.


224-224: LGTM! Return type is consistent.

The price field type in the return structure correctly uses the string type.

@leonz789 leonz789 merged commit 1d03aa3 into imua-xyz:develop Nov 28, 2024
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants