Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Proposal logic for Slinky #1135

Merged
merged 2 commits into from
Mar 14, 2024

Conversation

Eric-Warehime
Copy link
Contributor

Changelist

This PR introduces interfaces and implementations of those interfaces in the Prepare and Process Proposal handlers.

We introduce Slinky-specific proposal handlers via price update generator and market price decoders. Existing behavior of the application is preserved in order to allow the changes to be introduced to the repo and turned on in a later PR which will include the end to end flow and feature flagging.

Test Plan

New changes include unit tests and are fully backwards compatible by using the default interfaces as existing impl.

Author/Reviewer Checklist

  • If this PR has changes that result in a different app state given the same prior state and transaction list, manually add the state-breaking label.
  • If the PR has breaking postgres changes to the indexer add the indexer-postgres-breaking label.
  • If this PR isn't state-breaking but has changes that modify behavior in PrepareProposal or ProcessProposal, manually add the label proposal-breaking.
  • If this PR is one of many that implement a specific feature, manually label them all feature:[feature-name].
  • If you wish to for mergify-bot to automatically create a PR to backport your change to a release branch, manually add the label backport/[branch-name].
  • Manually add any of the following labels: refactor, chore, bug.

Copy link
Contributor

coderabbitai bot commented Mar 4, 2024

Walkthrough

The overall change introduces a new architecture for handling market price updates within a blockchain protocol. It transitions from directly using a PricesKeeper for price updates to employing a more flexible and modular approach with PriceUpdateGenerator and MarketPriceDecoder interfaces. This rearchitecture facilitates the aggregation of votes for market prices and the validation of price updates, enhancing the protocol's ability to accurately and securely update market prices based on oracle votes or other mechanisms.

Changes

Files Change Summary
protocol/app/app.go Introduced priceUpdateGenerator and priceUpdateDecoder replacing direct access to PricesKeeper.
protocol/app/prepare/expected_keepers.go, protocol/app/prepare/prepare_proposal.go Removed PreparePricesKeeper interface and integrated priceUpdateGenerator with added functionality for encoding market price updates.
protocol/app/prepare/prices/... Added new files for handling price updates: DefaultPriceUpdateGenerator, InvalidPriceError, PriceUpdateGenerator, SlinkyPriceUpdateGenerator, and related errors.
protocol/app/process/... Introduced DefaultUpdateMarketPriceTxDecoder, SlinkyMarketPriceDecoder, and updates to error handling and proposal processing to incorporate UpdateMarketPriceTxDecoder for decoding and validating market price updates.
protocol/app/process/market_prices.go, protocol/app/process/market_prices_test.go Modified validation logic in UpdateMarketPricesTx and refactored decoding process in tests.
protocol/mocks/... Added mock generation for PriceUpdateGenerator and UpdateMarketPriceTxDecoder.
protocol/app/prepare/prices/slinky_price_update_generator_test.go, protocol/app/process/slinky_market_price_decoder_test.go Added test cases for SlinkyPriceUpdateGenerator and SlinkyMarketPriceDecoder, covering scenarios for vote extension aggregation and market price update validation.
protocol/app/constants/constants.go, protocol/Dockerfile Introduced constants related to Slinky and updated Dockerfile for building with Golang 1.22 and slinky oracle binary.

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

Share

Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit-tests 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 tests for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit tests.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

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 as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • 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/coderabbit-overrides.v2.json

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

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.

Review Status

Actionable comments generated: 11

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 7c6b3d9 and 7feaddb.
Files ignored due to path filters (2)
  • protocol/go.mod is excluded by: !**/*.mod
  • protocol/go.sum is excluded by: !**/*.sum
Files selected for processing (25)
  • protocol/app/app.go (5 hunks)
  • protocol/app/prepare/expected_keepers.go (2 hunks)
  • protocol/app/prepare/prepare_proposal.go (5 hunks)
  • protocol/app/prepare/prepare_proposal_test.go (17 hunks)
  • protocol/app/prepare/prices/default_price_update_generator.go (1 hunks)
  • protocol/app/prepare/prices/errors.go (1 hunks)
  • protocol/app/prepare/prices/price_update_generator.go (1 hunks)
  • protocol/app/prepare/prices/slinky_price_update_generator.go (1 hunks)
  • protocol/app/prepare/prices/slinky_price_update_generator_test.go (1 hunks)
  • protocol/app/process/default_market_price_decoder.go (1 hunks)
  • protocol/app/process/errors.go (1 hunks)
  • protocol/app/process/full_node_process_proposal.go (2 hunks)
  • protocol/app/process/full_node_process_proposal_test.go (1 hunks)
  • protocol/app/process/market_price_decoder.go (1 hunks)
  • protocol/app/process/market_prices_test.go (4 hunks)
  • protocol/app/process/process_proposal.go (2 hunks)
  • protocol/app/process/process_proposal_test.go (1 hunks)
  • protocol/app/process/slinky_market_price_decoder.go (1 hunks)
  • protocol/app/process/slinky_market_price_decoder_test.go (1 hunks)
  • protocol/app/process/transactions.go (4 hunks)
  • protocol/app/process/transactions_test.go (4 hunks)
  • protocol/mocks/Makefile (1 hunks)
  • protocol/mocks/PriceUpdateGenerator.go (1 hunks)
  • protocol/mocks/PricesKeeper.go (15 hunks)
  • protocol/mocks/UpdateMarketPriceTxDecoder.go (1 hunks)
Files skipped from review due to trivial changes (2)
  • protocol/mocks/PriceUpdateGenerator.go
  • protocol/mocks/UpdateMarketPriceTxDecoder.go
Additional comments: 42
protocol/app/prepare/prices/price_update_generator.go (1)
  • 8-12: The introduction of the PriceUpdateGenerator interface with the GetValidMarketPriceUpdates method is well-defined and aligns with the PR's objectives to enhance proposal handling mechanisms related to market price updates. The method signature is appropriate, and the use of sdk.Context is consistent with Cosmos SDK standards.
protocol/app/prepare/prices/errors.go (1)
  • 7-17: The InvalidPriceError struct and its associated Error method are well-implemented. The error message is clear and provides valuable information about the invalid price, including the market ID and the reason, which aligns with best practices for error handling.
protocol/app/prepare/expected_keepers.go (1)
  • 7-12: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1-18]

The removal of the PreparePricesKeeper interface and its method GetValidMarketPriceUpdates is consistent with the PR's objectives to refactor the proposal handling mechanism. The remaining keeper interfaces (PrepareClobKeeper, PreparePerpetualsKeeper, PrepareBridgeKeeper) are correctly defined and focus on different aspects of the PrepareProposal process.

protocol/app/process/market_price_decoder.go (1)
  • 8-28: The introduction of the UpdateMarketPriceTxDecoder interface with methods DecodeUpdateMarketPricesTx and GetTxOffset is well-defined, clearly outlining responsibilities for decoding market price transactions and managing transaction offsets. The NewUpdateMarketPricesTx function is correctly implemented, facilitating the creation of UpdateMarketPricesTx instances with the necessary parameters.
protocol/app/prepare/prices/default_price_update_generator.go (1)
  • 9-36: The PricesKeeper interface and the DefaultPriceUpdateGenerator struct, along with its GetValidMarketPriceUpdates method, are correctly implemented. The DefaultPriceUpdateGenerator adheres to the PriceUpdateGenerator interface's contract, and the error handling in GetValidMarketPriceUpdates ensures that a nil MsgUpdateMarketPrices is correctly managed, which is crucial for robustness.
protocol/app/process/errors.go (1)
  • 13-49: The new error types related to proposed price validation are correctly registered with the process_proposal module, and the functions for generating specific error instances are appropriately implemented. These changes enhance error reporting and provide detailed context for each error scenario, which is crucial for debugging and robustness.
protocol/app/process/default_market_price_decoder.go (1)
  • 7-42: The DefaultUpdateMarketPriceTxDecoder struct, implementing the UpdateMarketPriceTxDecoder interface, is correctly implemented. Its methods DecodeUpdateMarketPricesTx and GetTxOffset are clearly defined and align with the expected functionality. The constructor function is appropriately defined, ensuring that necessary dependencies are correctly passed.
protocol/app/process/full_node_process_proposal.go (1)
  • 15-21: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1-37]

The modification to the FullNodeProcessProposalHandler function, replacing the pricesKeeper parameter with pricesTxDecoder of type UpdateMarketPriceTxDecoder, aligns with the PR's objectives to enhance the proposal handling mechanism. The implementation of the proposal handling logic, including decoding transactions and measuring MEV metrics, is correctly done, ensuring robust and expected behavior.

protocol/app/process/full_node_process_proposal_test.go (1)
  • 88-94: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1-91]

The modifications to the TestFullNodeProcessProposalHandler function, specifically the use of process.NewDefaultUpdateMarketPriceTxDecoder with additional arguments, are correctly done. These changes ensure that the test aligns with the updated implementation of the FullNodeProcessProposalHandler function, providing the necessary dependencies for the decoder and reflecting the PR's objectives.

protocol/app/prepare/prices/slinky_price_update_generator.go (1)
  • 14-104: The SlinkyPriceUpdateGenerator struct, implementing the PriceUpdateGenerator interface, is correctly implemented. Its GetValidMarketPriceUpdates method is comprehensive, including checks for vote extensions, aggregation of votes, and mapping of currency pairs to market IDs. The constructor function is appropriately defined, ensuring that necessary dependencies are correctly passed. The error handling is clear, contributing to the robustness of the implementation.
protocol/app/process/process_proposal.go (1)
  • 40-40: The addition of the pricesTxDecoder parameter to the ProcessProposalHandler function signature is a significant change. It replaces the previous pricesKeeper parameter, indicating a shift towards a more decoupled and flexible approach for decoding market price transactions. This change aligns with the PR's objective to introduce new interfaces for handling proposals, specifically for market price updates. Ensure that all calls to ProcessProposalHandler throughout the codebase have been updated to pass the correct pricesTxDecoder implementation.
protocol/app/process/slinky_market_price_decoder.go (2)
  • 12-29: The SlinkyMarketPriceDecoder struct and its constructor NewSlinkyMarketPriceDecoder are well-defined, encapsulating the logic for decoding market price updates with consideration for vote-extensions. This design adheres to the principles of modularity and encapsulation, allowing for easy extension or modification in the future. It's important to ensure that the decoder and agg fields are properly initialized and used throughout the struct's methods to maintain consistency and reliability in the decoding process.
  • 80-88: The GetTxOffset method provides a straightforward way to determine the offset for injected transactions based on whether vote-extensions are enabled. This method enhances the flexibility of transaction processing by allowing dynamic adjustment of indices based on the application's configuration. It's a good practice to ensure that this method is used consistently wherever transaction offsets need to be calculated, to maintain coherence in handling injected transactions.
protocol/app/process/transactions.go (1)
  • 126-128: The adjustments to transaction index handling based on injected extensions, as seen in the handling of OtherTxs, demonstrate a thoughtful approach to accommodating dynamic transaction structures. This change ensures that the application can correctly process transactions even when additional data (e.g., vote-extensions) is injected. It's crucial to ensure that these adjustments are consistently applied across all relevant parts of the codebase to maintain the integrity of transaction processing.
protocol/mocks/Makefile (1)
  • 59-60: The addition of mock generation commands for PriceUpdateGenerator and UpdateMarketPriceTxDecoder in the Makefile is a necessary step to support unit testing of the new functionalities introduced in this PR. These commands facilitate the creation of mocks for the newly introduced interfaces, enabling comprehensive testing of their implementations and interactions. It's important to ensure that these mocks are utilized effectively in unit tests to validate the behavior of the interfaces under various conditions.
protocol/mocks/PricesKeeper.go (4)
  • 22-24: Adding panic checks for unspecified return values in the CreateMarket mock function improves the robustness of the test suite by ensuring that tests fail fast if the mock's return values are not properly set up. This is a good practice for mock functions as it helps identify issues in test setup early in the test execution process. Ensure that similar checks are consistently applied across all mock functions for consistency.
  • 50-52: The addition of panic checks for unspecified return values in the GetAllMarketParamPrices mock function follows best practices for mock setup and error handling. This ensures that tests using this mock will fail immediately if the return values are not correctly specified, aiding in quicker debugging and test reliability.
  • 80-82: Including panic checks for unspecified return values in the GetAllMarketParams mock function is a good practice. It ensures that any test relying on this mock function will encounter an immediate failure if the mock's return values are not properly configured, promoting test reliability and maintainability.
  • 100-102: The panic checks added for unspecified return values in the GetAllMarketPrices mock function enhance the test suite's robustness by ensuring immediate failure if the mock's return values are not set up correctly. This practice helps in early detection of issues in test setup, contributing to more reliable and maintainable tests.
protocol/app/process/process_proposal_test.go (1)
  • 288-288: The addition of process.NewDefaultUpdateMarketPriceTxDecoder(pricesKeeper, constants.TestEncodingCfg.TxConfig.TxDecoder()) as a new argument to the ProcessProposalHandler function call in the TestProcessProposalHandler_Error test is a significant change. This ensures that the test accurately reflects the updated function signature and its dependencies. It's important to verify that this change aligns with the intended design and that the DefaultUpdateMarketPriceTxDecoder is correctly utilized within the ProcessProposalHandler. This addition should also prompt a review of related tests to ensure they are updated accordingly to cover the new logic introduced by the DefaultUpdateMarketPriceTxDecoder.
protocol/app/prepare/prepare_proposal.go (3)
  • 13-16: The addition of new imports for handling price updates and market price decoders aligns with the PR's objectives to enhance proposal logic for Slinky. Ensure that these packages are used effectively within the file and that there are no unused imports to maintain code cleanliness.
  • 59-59: Replacing PreparePricesKeeper with priceUpdateGenerator in the PrepareProposalHandler function is a significant change. It's crucial to ensure that all references and usages of PreparePricesKeeper are updated to use priceUpdateGenerator correctly. This change should also be reflected in any related documentation or comments to avoid confusion.
Verification successful

The verification process confirms that PreparePricesKeeper is no longer actively used in the project's main codebase, with occurrences limited to mocks and tests. The priceUpdateGenerator is correctly integrated and used throughout the project. The review comment's concerns have been addressed, indicating a successful refactoring from PreparePricesKeeper to priceUpdateGenerator. The only minor issue noted is an outdated comment in default_price_update_generator.go, which does not impact the correctness of the implementation.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Verify that `PreparePricesKeeper` is no longer used in the project.
rg --type go "PreparePricesKeeper"
# Verify that `priceUpdateGenerator` is used correctly throughout the project.
rg --type go "priceUpdateGenerator"

Length of output: 1746

* 77-88: The logic for handling external commit bytes (`extCommitBzTx`) and generating valid market price updates seems correct. However, ensure that error handling is robust and that any potential issues with `priceUpdateGenerator.GetValidMarketPriceUpdates` are logged and handled appropriately. It's also important to verify that the `EmptyResponse` is the desired behavior in case of an error, as it might impact the proposal's preparation process.
protocol/app/process/slinky_market_price_decoder_test.go (6)
  • 16-38: The setup for the SlinkyMarketPriceDecoderSuite test suite is well-structured, with mock objects for the price update generator and the update market price tx decoder. This setup facilitates isolated testing of the SlinkyMarketPriceDecoder functionality. Ensure that all necessary teardown or cleanup steps are included if any stateful components are introduced in future tests.
  • 41-88: The tests for scenarios where vote extensions are not enabled (TestVoteExtensionsNotEnabled) are comprehensive, covering both the case where a non-empty proposed market-price update fails and the case where proposed prices must be empty. It's important to ensure that these tests accurately reflect the expected behavior of the system under these conditions. Additionally, consider adding more detailed comments or documentation to explain the rationale behind these expected behaviors for future maintainers.
  • 89-122: The tests under TestVoteExtensionsEnabled cover critical scenarios, including missing extended commit and failure of the price-update generator. These tests are crucial for ensuring the robustness of the vote extension logic. However, ensure that the error messages and failure conditions are clearly documented and that any mock expectations are verified at the end of each test to ensure test integrity.
  • 124-253: The tests for market price update validation (TestMarketPriceUpdateValidation_WithVoteExtensionsEnabled) are thorough, covering various failure scenarios such as decoding failures, conflicting updates, and validation failures. These tests are essential for ensuring the correctness of market price updates. Consider adding positive test cases as well, where the validation passes, to ensure comprehensive coverage of both success and failure paths.
  • 256-295: The happy path test (TestHappyPath_VoteExtensionsEnabled) effectively validates the successful decoding and validation of market price updates when vote extensions are enabled. This test is crucial for ensuring that the system behaves as expected under normal conditions. Ensure that this test is kept up-to-date as the implementation evolves to continue providing confidence in the system's correctness.
  • 297-320: The tests for GetTxOffset are well-designed, covering scenarios where vote extensions are either enabled or not. These tests ensure that the offset calculation behaves correctly under different conditions. It's important to maintain these tests and consider adding more scenarios if the logic for calculating the offset becomes more complex in the future.
protocol/app/process/transactions_test.go (4)
  • 119-119: The replacement of pricesKeeper with process.NewDefaultUpdateMarketPriceTxDecoder(pricesKeeper, constants.TestEncodingCfg.TxConfig.TxDecoder()) in the TestDecodeProcessProposalTxs_Error function correctly aligns with the PR objectives to enhance proposal handling with new decoding functionalities. This change is crucial for testing the new market price update mechanism and is implemented correctly.
  • 200-200: The use of process.NewDefaultUpdateMarketPriceTxDecoder(pricesKeeper, constants.TestEncodingCfg.TxConfig.TxDecoder()) in the TestDecodeProcessProposalTxs_Valid function is consistent with the PR objectives and correctly implements the new decoding functionality for market price updates. This ensures comprehensive testing of the new proposal handling mechanism across different scenarios.
  • 348-348: The replacement of pricesKeeper with process.NewDefaultUpdateMarketPriceTxDecoder(pricesKeeper, constants.TestEncodingCfg.TxConfig.TxDecoder()) in the TestProcessProposalTxs_Validate_Error and TestProcessProposalTxs_Validate_Valid functions is correctly implemented. This change ensures that the validation logic for process proposal transactions is tested using the updated decoding functionality, aligning with the PR objectives.
  • 455-455: The use of process.NewDefaultUpdateMarketPriceTxDecoder(pricesKeeper, constants.TestEncodingCfg.TxConfig.TxDecoder()) in the TestProcessProposalTxs_Validate_Valid function is consistent with the PR objectives and correctly implements the new decoding functionality for market price updates. This ensures comprehensive testing of the validation logic for process proposal transactions, aligning with the PR objectives.
protocol/app/prepare/prepare_proposal_test.go (9)
  • 37-49: The encoder functions (failingTxEncoder, emptyTxEncoder, passingTxEncoderOne, etc.) are well-defined for simulating different outcomes in the encoding process. This approach is effective for testing various scenarios, including failures and successes in transaction encoding.
  • 60-75: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [49-370]

The test function TestPrepareProposalHandler thoroughly tests various scenarios, including error cases and valid cases for handling price updates, funding, bridge acknowledgments, and operations. The use of mock objects and encoder functions to simulate different outcomes is effective for isolating the test cases from external dependencies. Ensure that the test cases accurately reflect the expected behavior of the PrepareProposalHandler, especially in light of any new logic introduced in the PR.

  • 446-453: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [370-450]

The test function TestPrepareProposalHandler_OtherTxs effectively tests the handling of "other" transactions by the PrepareProposalHandler, focusing on scenarios where other transactions contain disallowed messages. The test cases are well-designed to validate the filtering logic, ensuring that it is consistent with the application's requirements. Ensure comprehensive coverage of all relevant scenarios in the filtering logic.

  • 465-642: The test function TestSlinkyPrepareProposalHandler effectively tests the behavior of the SlinkyPrepareProposalHandler in scenarios where vote extensions (VEs) are enabled or not. The scenarios include testing the insertion of an empty UpdateMarketPrices transaction when VEs are not enabled and a valid UpdateMarketPricesTx when VEs are enabled. The use of mock objects and specific context configurations to simulate these scenarios is appropriate. Ensure that the test cases accurately reflect the expected behavior in the context of vote extensions.
  • 686-698: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [643-695]

The test function TestGetUpdateMarketPricesTx thoroughly tests the getMarketPriceUpdates function, covering scenarios such as nil messages, empty messages, encoding failures, and valid messages. The comprehensive range of test cases and the use of mock objects ensure that the function's behavior is accurately validated under various conditions. Ensure that the test cases reflect the expected behavior of the getMarketPriceUpdates function, particularly with any new logic introduced in the PR.

  • 704-723: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [716-762]

The test function TestGetAcknowledgeBridgesTx effectively validates the behavior of the GetAcknowledgeBridgesTx function under various scenarios, including empty lists of messages, encoding failures, and valid bridge events. The comprehensive test cases and the use of mock objects ensure accurate validation of the function's behavior under different conditions. Ensure that the test cases reflect the expected behavior of the GetAcknowledgeBridgesTx function.

  • 779-785: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [782-824]

The test function TestGetAddPremiumVotesTx thoroughly tests the GetAddPremiumVotesTx function, covering scenarios such as nil messages, empty messages, encoding failures, and valid messages with votes. The comprehensive range of test cases and the use of mock objects ensure that the function's behavior is accurately validated under various conditions. Ensure that the test cases reflect the expected behavior of the GetAddPremiumVotesTx function, particularly with any new logic introduced in the PR.

  • 841-847: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [844-889]

The test function TestGetProposedOperationsTx effectively validates the behavior of the GetProposedOperationsTx function under various scenarios, including nil messages, empty messages, encoding failures, and valid messages with operations. The comprehensive test cases and the use of mock objects ensure accurate validation of the function's behavior under different conditions. Ensure that the test cases reflect the expected behavior of the GetProposedOperationsTx function.

  • 904-910: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [907-929]

The test function TestEncodeMsgsIntoTxBytes thoroughly tests the EncodeMsgsIntoTxBytes utility function, covering scenarios such as setting messages failures, encoding failures, and valid encoding scenarios. The comprehensive range of test cases and the use of mock objects ensure that the function's behavior is accurately validated under various conditions. Ensure that the test cases reflect the expected behavior of the EncodeMsgsIntoTxBytes function.

Comment on lines 53 to 66
func (suite *SlinkyPriceUpdateGeneratorSuite) TestWithVoteExtensionsNotEnabled() {
// setup
ctx := testutils.UpdateContextWithVEHeight(testutils.CreateBaseSDKContext(suite.T()), 5)
// ctx.BlockHeight() < ctx.ConsensusParams.VoteExtensionsEnableHeight (ves are not enabled rn)
ctx = ctx.WithBlockHeight(4)

// expect
msg, err := suite.spug.GetValidMarketPriceUpdates(ctx, []byte{}) // 2nd argument shld be irrelevant

// assert
suite.NoError(err)
suite.NotNil(msg)
suite.Empty(msg.MarketPriceUpdates) // no updates
}
Copy link
Contributor

Choose a reason for hiding this comment

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

In the test TestWithVoteExtensionsNotEnabled, it's good practice to ensure that the test case is isolated and does not depend on external state or configurations that might change. This test assumes that vote extensions are not enabled based on the block height. It's recommended to explicitly document this assumption or, if possible, mock or control the enabling of vote extensions within the test setup to make the test more robust and understandable.

Comment on lines 69 to 111
func (suite *SlinkyPriceUpdateGeneratorSuite) TestVoteExtensionAggregationFails() {
// setup
ctx := testutils.UpdateContextWithVEHeight(testutils.CreateBaseSDKContext(suite.T()), 5)
ctx = ctx.WithBlockHeight(6) // ves enabled

// create vote-extensions
validator := []byte("validator")
// we j mock what the actual wire-transmitted bz are for this vote-extension
voteExtensionBz := []byte("vote-extension")
extCommitBz := []byte("ext-commit") // '' for ext-commit
extCommit := cmtabci.ExtendedCommitInfo{
Votes: []cmtabci.ExtendedVoteInfo{
{
Validator: cmtabci.Validator{
Address: validator,
},
VoteExtension: voteExtensionBz,
},
},
}

// mock codecs
suite.extCommitCodec.On("Decode", extCommitBz).Return(extCommit, nil)

ve := vetypes.OracleVoteExtension{
Prices: map[uint64][]byte{
1: []byte("price"),
},
}
suite.veCodec.On("Decode", voteExtensionBz).Return(ve, nil)

// expect an error from the vote-extension aggregator
suite.va.On("AggregateOracleVotes", ctx, []aggregator.Vote{
{
ConsAddress: sdk.ConsAddress(validator),
OracleVoteExtension: ve,
},
}).Return(nil, fmt.Errorf("error in aggregation"))

// execute
msg, err := suite.spug.GetValidMarketPriceUpdates(ctx, extCommitBz)
suite.Nil(msg)
suite.Error(err, "error in aggregation")
Copy link
Contributor

Choose a reason for hiding this comment

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

In the test TestVoteExtensionAggregationFails, the error handling for the aggregation of oracle votes is correctly tested. However, it's important to ensure that the error message being checked ("error in aggregation") matches exactly what is expected from the AggregateOracleVotes method. This is crucial for the test to accurately validate the error handling logic. Additionally, consider using constants for repeated string literals like error messages to reduce the chance of typos and make maintenance easier.

Comment on lines 114 to 163
// test that if price / ID conversion fails we fail
func (suite *SlinkyPriceUpdateGeneratorSuite) TestCurrencyPairConversionFails() {
// setup
ctx := testutils.UpdateContextWithVEHeight(testutils.CreateBaseSDKContext(suite.T()), 5)
ctx = ctx.WithBlockHeight(6) // ves enabled

// create vote-extensions
validator := []byte("validator")
// we j mock what the actual wire-transmitted bz are for this vote-extension
voteExtensionBz := []byte("vote-extension")
extCommitBz := []byte("ext-commit") // '' for ext-commit
extCommit := cmtabci.ExtendedCommitInfo{
Votes: []cmtabci.ExtendedVoteInfo{
{
Validator: cmtabci.Validator{
Address: validator,
},
VoteExtension: voteExtensionBz,
},
},
}

// mock codecs
suite.extCommitCodec.On("Decode", extCommitBz).Return(extCommit, nil)

ve := vetypes.OracleVoteExtension{
Prices: map[uint64][]byte{
1: []byte("price"),
},
}
suite.veCodec.On("Decode", voteExtensionBz).Return(ve, nil)

mogBtc := oracletypes.NewCurrencyPair("MOG", "BTC")
// expect an error from the vote-extension aggregator
suite.va.On("AggregateOracleVotes", ctx, []aggregator.Vote{
{
ConsAddress: sdk.ConsAddress(validator),
OracleVoteExtension: ve,
},
}).Return(map[oracletypes.CurrencyPair]*big.Int{
mogBtc: big.NewInt(1),
}, nil)

// expect an error from the currency-pair strategy
suite.cps.On("ID", ctx, mogBtc).Return(uint64(0), fmt.Errorf("error in currency-pair conversion"))

// execute
msg, err := suite.spug.GetValidMarketPriceUpdates(ctx, extCommitBz)
suite.Nil(msg)
suite.Error(err, "error in currency-pair conversion")
Copy link
Contributor

Choose a reason for hiding this comment

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

The test TestCurrencyPairConversionFails effectively checks the error handling when currency pair ID conversion fails. It's a good practice to ensure that the error message being asserted ("error in currency-pair conversion") is exactly what the system under test is expected to return. This ensures that the test is accurately validating the system's behavior. As with previous comments, using constants for error messages can improve maintainability.

Comment on lines 167 to 230
func (suite *SlinkyPriceUpdateGeneratorSuite) TestValidMarketPriceUpdate() {
// setup
ctx := testutils.UpdateContextWithVEHeight(testutils.CreateBaseSDKContext(suite.T()), 5)
ctx = ctx.WithBlockHeight(6) // ves enabled

// create vote-extensions
validator := []byte("validator")
// we j mock what the actual wire-transmitted bz are for this vote-extension
voteExtensionBz := []byte("vote-extension")
extCommitBz := []byte("ext-commit") // '' for ext-commit
extCommit := cmtabci.ExtendedCommitInfo{
Votes: []cmtabci.ExtendedVoteInfo{
{
Validator: cmtabci.Validator{
Address: validator,
},
VoteExtension: voteExtensionBz,
},
},
}

// mock codecs
suite.extCommitCodec.On("Decode", extCommitBz).Return(extCommit, nil)

ve := vetypes.OracleVoteExtension{
Prices: map[uint64][]byte{
1: []byte("price"),
},
}
suite.veCodec.On("Decode", voteExtensionBz).Return(ve, nil)

mogBtc := oracletypes.NewCurrencyPair("MOG", "BTC")
pepeEth := oracletypes.NewCurrencyPair("PEPE", "ETH")
// expect an error from the vote-extension aggregator
suite.va.On("AggregateOracleVotes", ctx, []aggregator.Vote{
{
ConsAddress: sdk.ConsAddress(validator),
OracleVoteExtension: ve,
},
}).Return(map[oracletypes.CurrencyPair]*big.Int{
mogBtc: big.NewInt(1),
pepeEth: big.NewInt(2),
}, nil)

// expect no error from currency-pair strategies
suite.cps.On("ID", ctx, mogBtc).Return(uint64(0), nil)
suite.cps.On("ID", ctx, pepeEth).Return(uint64(1), nil)

// execute
msg, err := suite.spug.GetValidMarketPriceUpdates(ctx, extCommitBz)
suite.NoError(err)

// check the message
suite.Len(msg.MarketPriceUpdates, 2)
expectedPrices := map[uint64]uint64{
0: 1,
1: 2,
}
for _, mpu := range msg.MarketPriceUpdates {
price, ok := expectedPrices[uint64(mpu.MarketId)]
suite.True(ok)

suite.Equal(price, mpu.Price)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The test TestValidMarketPriceUpdate successfully validates the correct generation of MsgUpdateMarketPricesTx when valid inputs are provided. This test covers the happy path scenario well. It's important to ensure that all edge cases and potential failure modes are also covered in separate tests to ensure comprehensive test coverage. Additionally, consider adding assertions for the entire structure of msg.MarketPriceUpdates to ensure that all fields are correctly populated, not just the MarketPriceUpdates length and prices.

@@ -72,7 +73,7 @@ func ProcessProposalHandler(
error_lib.LogErrorWithOptionalContext(ctx, "UpdateSmoothedPrices failed", err)
}

txs, err := DecodeProcessProposalTxs(ctx, txConfig.TxDecoder(), req, bridgeKeeper, pricesKeeper)
txs, err := DecodeProcessProposalTxs(ctx, txConfig.TxDecoder(), req, bridgeKeeper, pricesTxDecoder)
Copy link
Contributor

Choose a reason for hiding this comment

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

The usage of pricesTxDecoder within the ProcessProposalHandler function to decode market price transactions is a key part of the new proposal handling logic. This change ensures that the decoding process is abstracted away, allowing for different decoding strategies to be implemented and injected as needed. It's crucial to ensure that the pricesTxDecoder implementation correctly handles the decoding logic, including error handling and validation of market price updates. Comprehensive testing around this functionality is recommended to ensure its reliability and correctness.

Would you like assistance in creating additional unit tests for the pricesTxDecoder implementation?

Comment on lines 31 to 77
// DecodeUpdateMarketPricesTx returns a new `UpdateMarketPricesTx` after validating the following:
// - the underlying decoder decodes successfully
// - the UpdateMarketPricesTx follows correctly from the vote-extensions
// - vote-extensions are enabled: each price per market-id is derived from the injected extended commit
// - vote-extensions are disabled: no price updates are proposed
// - vote-extensions are inserted into the block if necessary
//
// If error occurs during any of the checks, returns error.
func (mpd *SlinkyMarketPriceDecoder) DecodeUpdateMarketPricesTx(
ctx sdk.Context, txs [][]byte) (*UpdateMarketPricesTx, error) {
expectedMsg := &pricestypes.MsgUpdateMarketPrices{}

// check if vote-extensions are enabled
if ve.VoteExtensionsEnabled(ctx) {
// if there isn't a vote-extension in the block when there should be, fail
if len(txs) < slinkyabci.NumInjectedTxs {
return nil, getDecodingError(
msgUpdateMarketPricesType,
fmt.Errorf("expected %v txs, got %v", slinkyabci.NumInjectedTxs, len(txs)))
}

// get the expected message from the injected vote-extensions
var err error
expectedMsg, err = mpd.agg.GetValidMarketPriceUpdates(ctx, txs[slinkyabci.OracleInfoIndex])
if err != nil {
return nil, getDecodingError(msgUpdateMarketPricesType, err)
}
}

// use the underlying decoder to get the UpdateMarketPricesTx
updateMarketPrices, err := mpd.decoder.DecodeUpdateMarketPricesTx(ctx, txs)
if err != nil {
return nil, err
}

updateMarketPricesMsg, ok := updateMarketPrices.GetMsg().(*pricestypes.MsgUpdateMarketPrices)
if !ok {
return nil, getDecodingError(
msgUpdateMarketPricesType, fmt.Errorf("expected %T, got %T", expectedMsg, updateMarketPricesMsg))
}

// check that the UpdateMarketPricesTx matches the expected message
if err := checkEqualityOfMarketPriceUpdate(expectedMsg, updateMarketPricesMsg); err != nil {
return nil, err
}

return updateMarketPrices, nil
Copy link
Contributor

Choose a reason for hiding this comment

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

The DecodeUpdateMarketPricesTx method in the SlinkyMarketPriceDecoder struct implements complex logic for decoding market price updates, taking into account whether vote-extensions are enabled. This method demonstrates a clear separation of concerns by first checking for vote-extensions, then using the underlying decoder for the actual decoding, and finally validating the decoded message against expected values. It's crucial to ensure comprehensive testing around this method, particularly to cover scenarios with and without vote-extensions, to validate its correctness and robustness.

Would you like assistance in creating additional unit tests for the DecodeUpdateMarketPricesTx method to cover various scenarios?

Comment on lines +77 to +100
pricesTxDecoder UpdateMarketPriceTxDecoder,
) (*ProcessProposalTxs, error) {
// Check len.
// Check len (accounting for offset from injected vote-extensions if applicable)
offset := pricesTxDecoder.GetTxOffset(ctx)
injectedTxCount := minTxsCount + offset
numTxs := len(req.Txs)
if numTxs < minTxsCount {
if numTxs < injectedTxCount {
return nil, errorsmod.Wrapf(
ErrUnexpectedNumMsgs,
"Expected the proposal to contain at least %d txs, but got %d",
minTxsCount,
injectedTxCount,
numTxs,
)
}

// Price updates.
updatePricesTx, err := pricesTxDecoder.DecodeUpdateMarketPricesTx(
ctx,
req.Txs,
)
if err != nil {
return nil, err
}

Copy link
Contributor

Choose a reason for hiding this comment

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

The addition of UpdateMarketPriceTxDecoder to the DecodeProcessProposalTxs function and its subsequent usage for decoding market price updates is a key enhancement. This change aligns with the PR's objective to introduce a more flexible and decoupled approach for handling market price updates. It's important to ensure that the pricesTxDecoder is correctly implemented and integrated, particularly in terms of error handling and validation of decoded transactions. Comprehensive testing around this functionality is recommended to ensure its reliability and correctness.

Would you like assistance in creating additional unit tests for the DecodeProcessProposalTxs function to cover various decoding scenarios?

Comment on lines +69 to +70
pricesTxDecoder := process.NewDefaultUpdateMarketPriceTxDecoder(k, encodingCfg.TxConfig.TxDecoder())
umpt, err := pricesTxDecoder.DecodeUpdateMarketPricesTx(ctx, [][]byte{tc.txBytes})
Copy link
Contributor

Choose a reason for hiding this comment

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

The introduction of the pricesTxDecoder object in the test functions for decoding market prices is a positive change, enhancing the clarity and structure of the test logic. This modification aligns with the changes made in the application code, ensuring that the tests accurately reflect the new decoding process. It's important to ensure that these tests cover a wide range of scenarios, including error cases and different configurations of the pricesTxDecoder, to thoroughly validate the decoding logic.

Would you like assistance in expanding the test coverage for the pricesTxDecoder usage in these test functions?

// Gather "FixedSize" group messages.
pricesTxResp, err := GetUpdateMarketPricesTx(ctx, txConfig, pricesKeeper)
pricesTxResp, err := EncodeMarketPriceUpdates(txConfig, msg)
Copy link
Contributor

Choose a reason for hiding this comment

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

Introducing the EncodeMarketPriceUpdates function to handle encoding market price updates is a good practice, as it encapsulates this specific logic into a separate, reusable component. Ensure that this function is thoroughly tested, especially for edge cases such as invalid inputs or encoding failures, to maintain the integrity of the proposal preparation process.

Would you like me to help with generating additional unit tests for EncodeMarketPriceUpdates to cover edge cases?

@@ -71,8 +74,21 @@ func PrepareProposalHandler(
return &EmptyResponse, nil
}

var extCommitBzTx []byte
if len(req.Txs) >= slinkyabci.NumInjectedTxs {
extCommitBzTx = req.Txs[slinkyabci.OracleInfoIndex]
Copy link
Contributor

Choose a reason for hiding this comment

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

is extended commit always at OracleInfoIndex?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, the VEs commit info is always injected as the first Tx in the block. See comment above.

}

// get the update market prices tx
msg, err := priceUpdateGenerator.GetValidMarketPriceUpdates(ctx, extCommitBzTx)
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe I'm missing something but this doesn't exclude the markets whose prices changed less than a threshold, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My understanding is that this is handled in the Prices Keeper.
https://github.com/dydxprotocol/v4-chain/pull/1139/files#diff-0da397be90196d47fd5225c12b6bfd6c7c4adc27b46e334f33776f510c0c1031R54

We only extend vote with "valid" market price updates. If a price update is not above the min_price threshold it would not be returned by that keeper method. Perhaps I'm mistaken though and this needs to be handled/validated outside the keeper?

Copy link
Contributor

Choose a reason for hiding this comment

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

makes sense!

"github.com/dydxprotocol/v4-chain/protocol/lib/metrics"
pricetypes "github.com/dydxprotocol/v4-chain/protocol/x/prices/types"
slinkyabci "github.com/skip-mev/slinky/abci/types"
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the best way to ensure that future changes to slinky packages do not result in a breaking change for dYdX chain?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same way that comet and the sdk are maintained. Breaking changes will only occur along with a major version bump. Dependency updates should be looked at and tested to make sure regression aren't introduced. Security and bugfixes will be backported to all supported versions.

protocol/app/prepare/prepare_proposal.go Outdated Show resolved Hide resolved
@@ -71,8 +74,21 @@ func PrepareProposalHandler(
return &EmptyResponse, nil
}

var extCommitBzTx []byte
if len(req.Txs) >= slinkyabci.NumInjectedTxs {
Copy link
Contributor

Choose a reason for hiding this comment

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

If I understand correctly, the first tx of the PrepareProposalRequest should be the VE of the previous block right? If len(req.Txs) == 0, does that mean that there were no VE in the previous block? Can you include in a comment?

Additionally similar to the OracleInfoIndex, can we have this constant stored in the dYdX code base?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah the prepare proposal handler will inject the VEs as the first tx in the block. If there are no txs, it means there were no VEs injected. This is basically only going to happen if the protocol hasn't enabled VEs yet.

Copy link
Contributor

Choose a reason for hiding this comment

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

can we include this in a comment?

Copy link
Contributor

Choose a reason for hiding this comment

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

Could we also change this constant name? NumInjectedTxs doesn't really mean anything. Ideally this would be a function named TxsContainsVEs or the constant would be something like MinTxRequiredForVEEnabled

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ended up at OracleVEInjectedTxs. Let me know if you'd prefer something else.

protocol/app/prepare/prepare_proposal_test.go Show resolved Hide resolved
pricestypes "github.com/dydxprotocol/v4-chain/protocol/x/prices/types"
)

// MarketPriceDecoder is an interface for decoding market price transactions, This interface is responsible
Copy link
Contributor

@Christopher-Li Christopher-Li Mar 6, 2024

Choose a reason for hiding this comment

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

Shouldnt this be UpdateMarketPriceTxDecoder since that's the name of the type? I'm confused where MarketPriceDecoder is defined

Copy link
Contributor

Choose a reason for hiding this comment

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

That is correct, the name of the type in the docs should be UpdateMarketPricesDecoder

// If error occurs during any of the checks, returns error.
func (mpd *DefaultUpdateMarketPriceTxDecoder) DecodeUpdateMarketPricesTx(
ctx sdk.Context, txs [][]byte) (*UpdateMarketPricesTx, error) {
return DecodeUpdateMarketPricesTx(ctx, mpd.pk, mpd.txDecoder, txs[len(txs)+updateMarketPricesTxLenOffset])
Copy link
Contributor

Choose a reason for hiding this comment

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

Where is this inner DecodeUpdateMarketPricesTx defined?

Copy link
Contributor

Choose a reason for hiding this comment

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

This is defined in app/process/market_prices.go this is used in the current dydx protocol to unmarshal price-update txs

}

// use the underlying decoder to get the UpdateMarketPricesTx
updateMarketPrices, err := mpd.decoder.DecodeUpdateMarketPricesTx(ctx, txs)
Copy link
Contributor

Choose a reason for hiding this comment

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

what is the purpose of this inner decoder? Is it so SlinkyMarketPriceDecoder can call DefaultMarketPriceDecoder?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@nivasan1 can probably comment more on this as he implemented it.

The idea is twofold:

  1. The existing behavior is preserved via just using DefaultMarketPricesDecoder so all of these changes are backwards compatible in the case where slinky is not yet enabled.
  2. The new implementation wraps the default encoder because we still want all the same behavior. But additionally we want to do checks on the equality of VE data with the changes being made in the UpdateMarketPrices tx.

So we first get the injected VE data, then get the UpdateMarketPricesTx via the default behavior, then verify that the two match.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's correct. The SlinkyUpdateMarketPriceDecoder's responsibility is to decode the price-update + determine whether or not the proposed prices followed exactly from the injected vote-extensions

Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need to define this whole decoder struct? Maybe I'm missing something but it doesn't seem to be doing much

Copy link
Contributor

Choose a reason for hiding this comment

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

The decoder struct is responsible for encapsulating the logical differences between dydx's ProcessProposal pre / post vote-extensions. Specifically

  • The DefaultMarketPriceDecoder decodes price-updates from proposals as they are done in the pre-vote extensions protoocl
  • The SlinkyMarketPriceDecoder decodes price-updates + verfies that they follow exactly from the injected vote-extensions

Copy link
Contributor

Choose a reason for hiding this comment

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

If we stop supporting our own Price Daemon and remove VEs, would you then delete this decoder struct and remove DefaultMarketPriceDecoder?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I understand correctly I think yes.

The interface is just in place to support having the existing implementation and the new one. If we clean up the old code we don't really need the interface/struct anymore and it can just be the function defined in slinky market price decoder.

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.

Review Status

Actionable comments generated: 1

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 7feaddb and 9cf8a67.
Files selected for processing (5)
  • protocol/app/prepare/prepare_proposal.go (5 hunks)
  • protocol/app/prepare/prices/slinky_price_update_generator.go (1 hunks)
  • protocol/app/prepare/prices/slinky_price_update_generator_test.go (1 hunks)
  • protocol/app/process/slinky_market_price_decoder_test.go (1 hunks)
  • protocol/app/process/transactions.go (4 hunks)
Files skipped from review as they are similar to previous changes (4)
  • protocol/app/prepare/prices/slinky_price_update_generator.go
  • protocol/app/prepare/prices/slinky_price_update_generator_test.go
  • protocol/app/process/slinky_market_price_decoder_test.go
  • protocol/app/process/transactions.go
Additional comments: 3
protocol/app/prepare/prepare_proposal.go (3)
  • 13-13: The addition of new imports for handling price updates and market price decoders aligns with the PR's objectives. Ensure that these packages are properly versioned to avoid potential breaking changes in the future.
  • 59-59: Replacing PreparePricesKeeper with priceUpdateGenerator in the PrepareProposalHandler function is a significant change. It's crucial to ensure that all instances where PreparePricesKeeper was used are now correctly utilizing priceUpdateGenerator. Additionally, verify that priceUpdateGenerator's methods are fully implemented and tested, especially in edge cases.
  • 74-96: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [77-216]

The changes from lines 77 to 216 introduce logic to handle market price updates in the PrepareProposalHandler function. This includes handling injected VEs from the previous block, generating and encoding market price updates, and integrating these updates into the proposal preparation process. Ensure that this logic is thoroughly tested, particularly the handling of edge cases such as empty transactions or errors during the encoding process. Additionally, consider the performance implications of these changes, especially in scenarios with a large number of market price updates.

Comment on lines 198 to 209
}
}

// GetUpdateMarketPricesTx returns a tx containing `MsgUpdateMarketPrices`.
func GetUpdateMarketPricesTx(
ctx sdk.Context,
// EncodeMarketPriceUpdates returns a tx containing `MsgUpdateMarketPrices`.
func EncodeMarketPriceUpdates(
txConfig client.TxConfig,
pricesKeeper PreparePricesKeeper,
msg *pricetypes.MsgUpdateMarketPrices,
) (PricesTxResponse, error) {
// Get prices to update.
msgUpdateMarketPrices := pricesKeeper.GetValidMarketPriceUpdates(ctx)
if msgUpdateMarketPrices == nil {
return PricesTxResponse{}, fmt.Errorf("MsgUpdateMarketPrices cannot be nil")
}

tx, err := EncodeMsgsIntoTxBytes(txConfig, msgUpdateMarketPrices)
tx, err := EncodeMsgsIntoTxBytes(txConfig, msg)
if err != nil {
return PricesTxResponse{}, err
}
Copy link
Contributor

Choose a reason for hiding this comment

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

📝 NOTE
This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [201-216]

Introducing the EncodeMarketPriceUpdates function to handle encoding market price updates is a good practice, as it encapsulates this specific logic into a separate, reusable component. However, the error message for an empty transaction could be more informative. Consider specifying the reason why the transaction is considered invalid, such as "transaction bytes are empty" instead of just showing the empty transaction in the error message.

- return PricesTxResponse{}, fmt.Errorf("Invalid tx: %v", tx)
+ return PricesTxResponse{}, fmt.Errorf("Invalid tx: transaction bytes are empty")

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.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 9cf8a67 and 0af5a49.
Files selected for processing (4)
  • protocol/app/constants/constants.go (1 hunks)
  • protocol/app/prepare/prepare_proposal.go (6 hunks)
  • protocol/app/process/slinky_market_price_decoder.go (1 hunks)
  • protocol/app/process/slinky_market_price_decoder_test.go (1 hunks)
Files skipped from review as they are similar to previous changes (3)
  • protocol/app/prepare/prepare_proposal.go
  • protocol/app/process/slinky_market_price_decoder.go
  • protocol/app/process/slinky_market_price_decoder_test.go
Additional comments: 1
protocol/app/constants/constants.go (1)
  • 11-16: The introduction of OracleInfoIndex and OracleVEInjectedTxs constants is clear and aligns well with the purpose described in the PR objectives. However, to enhance code readability and maintainability, consider adding more detailed comments explaining the rationale behind these specific values and how they are intended to be used within the Slinky integration context.

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.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 0af5a49 and 37720da.
Files selected for processing (1)
  • protocol/app/process/market_prices.go (1 hunks)
Additional comments: 1
protocol/app/process/market_prices.go (1)
  • 66-66: The change from true to false in the call to PerformStatefulPriceUpdateValidation alters the behavior of the price update validation process. It's crucial to understand the implications of this modification:
  • Ensure that this change aligns with the intended behavior and security requirements of the system.
  • Verify that this adjustment does not inadvertently weaken any validation checks that are critical for maintaining the integrity of price updates.
  • Consider adding comments in the code to explain the rationale behind using false instead of true, especially if this parameter controls significant validation logic.

Given the potential impact on the system's behavior, it's advisable to review the documentation or comments associated with the PerformStatefulPriceUpdateValidation method to understand the significance of this parameter change. Additionally, testing should be conducted to ensure that this modification does not introduce any unintended consequences.

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.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 37720da and 3bbf627.
Files selected for processing (2)
  • protocol/app/process/market_prices_test.go (5 hunks)
  • protocol/app/process/slinky_market_price_decoder.go (1 hunks)
Files skipped from review as they are similar to previous changes (2)
  • protocol/app/process/market_prices_test.go
  • protocol/app/process/slinky_market_price_decoder.go

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.

Review Status

Actionable comments generated: 2

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 3bbf627 and e806d67.
Files ignored due to path filters (3)
  • protocol/go.mod is excluded by: !**/*.mod
  • protocol/go.sum is excluded by: !**/*.sum
  • protocol/scripts/genesis/sample_pregenesis.json is excluded by: !**/*.json
Files selected for processing (3)
  • protocol/Dockerfile (3 hunks)
  • protocol/app/app.go (5 hunks)
  • protocol/mocks/Makefile (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • protocol/mocks/Makefile
Additional comments: 7
protocol/Dockerfile (3)
  • 3-3: The Dockerfile has been updated to use Golang version 1.22. This change is necessary for compatibility with the latest features or security patches. Ensure that all dependencies of the project are compatible with this Golang version to avoid any build or runtime issues.
  • 12-12: The base image for the builder stage has been updated to Golang 1.22. This is consistent with the earlier change to the Golang version. It's important to ensure that the entire build process is tested to confirm that there are no issues arising from this version change.
  • 59-61: The Dockerfile now copies the oracle binary and its configuration files (oracle.json and market.json) from the slinky build directory to the final image. This is a crucial step for integrating Slinky-specific functionality. Ensure that the configuration files (oracle.json and market.json) are properly reviewed and secure, as they could contain sensitive information or settings critical to the application's operation.
protocol/app/app.go (4)
  • 1340-1353: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1334-1344]

The introduction of priceUpdateGenerator in the PrepareProposal handler is a significant change that aligns with the PR's objectives to integrate Slinky-specific proposal handlers. Ensure that the implementation of NewDefaultPriceUpdateGenerator correctly generates price updates according to the Slinky protocol's requirements. It's also important to verify that this change does not disrupt existing operations and maintains backward compatibility as intended.

  • 1359-1365: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1350-1374]

Similarly, the use of priceUpdateDecoder in the ProcessProposal handler is crucial for decoding market price updates according to the Slinky protocol. Ensure that NewDefaultUpdateMarketPriceTxDecoder is implemented correctly and that it accurately decodes price updates. This change should enhance the application's functionality without affecting existing behavior, in line with the PR's objectives. It's essential to verify that these changes are thoroughly tested and validated to ensure robust error handling and validation.

  • 1340-1353: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1334-1374]

While reviewing the changes related to priceUpdateGenerator and priceUpdateDecoder, consider the performance implications of these implementations. Ensure that they are optimized for efficiency and do not introduce unnecessary computational overhead, especially in the context of handling large volumes of price updates. It may be beneficial to benchmark these changes to assess their impact on the application's overall performance.

  • 1340-1353: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1334-1374]

The modularization of price update generation and decoding through priceUpdateGenerator and priceUpdateDecoder is a positive step towards maintaining clean and maintainable code. Ensure that these components are well-documented and that their interfaces are clearly defined. Additionally, robust error handling and validation are crucial, especially given the critical nature of price updates in the application. Consider adding more comprehensive tests to cover edge cases and potential error conditions.

Comment on lines 46 to 48
RUN git clone https://github.com/skip-mev/slinky.git
WORKDIR /slinky
RUN make build
Copy link
Contributor

Choose a reason for hiding this comment

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

The Dockerfile now includes steps to clone the slinky repository and navigate to its directory. While this enables the building of the oracle binary, consider pinning the repository to a specific commit or tag to ensure reproducible builds. Cloning the latest version could introduce unexpected changes or incompatibilities.

- RUN git clone https://github.com/skip-mev/slinky.git
+ RUN git clone --branch <tag_name> --depth 1 https://github.com/skip-mev/slinky.git

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
RUN git clone https://github.com/skip-mev/slinky.git
WORKDIR /slinky
RUN make build
RUN git clone --branch <tag_name> --depth 1 https://github.com/skip-mev/slinky.git
WORKDIR /slinky
RUN make build

commit e806d67
Author: Eric <eric.warehime@gmail.com>
Date:   Mon Mar 11 12:21:02 2024 -0700

    Run update-sample-pregenesis

commit ea01d17
Merge: 97b29d4 340801a
Author: Eric <eric.warehime@gmail.com>
Date:   Mon Mar 11 11:53:03 2024 -0700

    Merge remote-tracking branch 'upstream' into eric/proposal-logic

commit 97b29d4
Author: Nikhil <nikhil@skip.money>
Date:   Fri Mar 8 14:17:49 2024 -0500

    update Dockerfile

commit 3bbf627
Author: Nikhil Vasan <nikhil@skip.money>
Date:   Fri Mar 8 11:02:19 2024 -0800

    lint

commit 37720da
Author: Nikhil Vasan <nikhil@skip.money>
Date:   Fri Mar 8 10:50:24 2024 -0800

    remove non-deterministic validation logic

commit 0af5a49
Author: Eric <eric.warehime@gmail.com>
Date:   Thu Mar 7 16:48:50 2024 -0800

    Update constants w/ slinky values

commit 9cf8a67
Author: Eric <eric.warehime@gmail.com>
Date:   Wed Mar 6 20:41:22 2024 -0800

    Update docs

commit 7feaddb
Author: Eric <eric.warehime@gmail.com>
Date:   Sun Mar 3 21:28:32 2024 -0800

    Fix import order

commit 382d45c
Author: Eric <eric.warehime@gmail.com>
Date:   Sun Mar 3 21:24:41 2024 -0800

    Prepare and Process logic for Slinky
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.

Review Status

Actionable comments generated: 1

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 525bb6f and 5ad38a3.
Files ignored due to path filters (3)
  • protocol/go.mod is excluded by: !**/*.mod
  • protocol/go.sum is excluded by: !**/*.sum
  • protocol/scripts/genesis/sample_pregenesis.json is excluded by: !**/*.json
Files selected for processing (28)
  • protocol/Dockerfile (3 hunks)
  • protocol/app/app.go (5 hunks)
  • protocol/app/constants/constants.go (1 hunks)
  • protocol/app/prepare/expected_keepers.go (2 hunks)
  • protocol/app/prepare/prepare_proposal.go (6 hunks)
  • protocol/app/prepare/prepare_proposal_test.go (17 hunks)
  • protocol/app/prepare/prices/default_price_update_generator.go (1 hunks)
  • protocol/app/prepare/prices/errors.go (1 hunks)
  • protocol/app/prepare/prices/price_update_generator.go (1 hunks)
  • protocol/app/prepare/prices/slinky_price_update_generator.go (1 hunks)
  • protocol/app/prepare/prices/slinky_price_update_generator_test.go (1 hunks)
  • protocol/app/process/default_market_price_decoder.go (1 hunks)
  • protocol/app/process/errors.go (1 hunks)
  • protocol/app/process/full_node_process_proposal.go (2 hunks)
  • protocol/app/process/full_node_process_proposal_test.go (1 hunks)
  • protocol/app/process/market_price_decoder.go (1 hunks)
  • protocol/app/process/market_prices.go (1 hunks)
  • protocol/app/process/market_prices_test.go (5 hunks)
  • protocol/app/process/process_proposal.go (2 hunks)
  • protocol/app/process/process_proposal_test.go (1 hunks)
  • protocol/app/process/slinky_market_price_decoder.go (1 hunks)
  • protocol/app/process/slinky_market_price_decoder_test.go (1 hunks)
  • protocol/app/process/transactions.go (4 hunks)
  • protocol/app/process/transactions_test.go (4 hunks)
  • protocol/mocks/Makefile (1 hunks)
  • protocol/mocks/PriceUpdateGenerator.go (1 hunks)
  • protocol/mocks/PricesKeeper.go (15 hunks)
  • protocol/mocks/UpdateMarketPriceTxDecoder.go (1 hunks)
Files skipped from review as they are similar to previous changes (26)
  • protocol/Dockerfile
  • protocol/app/constants/constants.go
  • protocol/app/prepare/expected_keepers.go
  • protocol/app/prepare/prepare_proposal.go
  • protocol/app/prepare/prices/default_price_update_generator.go
  • protocol/app/prepare/prices/errors.go
  • protocol/app/prepare/prices/price_update_generator.go
  • protocol/app/prepare/prices/slinky_price_update_generator.go
  • protocol/app/prepare/prices/slinky_price_update_generator_test.go
  • protocol/app/process/default_market_price_decoder.go
  • protocol/app/process/errors.go
  • protocol/app/process/full_node_process_proposal.go
  • protocol/app/process/full_node_process_proposal_test.go
  • protocol/app/process/market_price_decoder.go
  • protocol/app/process/market_prices.go
  • protocol/app/process/market_prices_test.go
  • protocol/app/process/process_proposal.go
  • protocol/app/process/process_proposal_test.go
  • protocol/app/process/slinky_market_price_decoder.go
  • protocol/app/process/slinky_market_price_decoder_test.go
  • protocol/app/process/transactions.go
  • protocol/app/process/transactions_test.go
  • protocol/mocks/Makefile
  • protocol/mocks/PriceUpdateGenerator.go
  • protocol/mocks/PricesKeeper.go
  • protocol/mocks/UpdateMarketPriceTxDecoder.go
Additional comments: 11
protocol/app/prepare/prepare_proposal_test.go (8)
  • 19-52: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [8-28]

The addition of new imports from github.com/skip-mev/slinky/abci/strategies/aggregator, github.com/skip-mev/slinky/abci/strategies/codec, and related packages indicates the integration of Slinky-specific logic into the proposal preparation tests. Ensure that these dependencies are properly versioned and maintained to avoid potential issues with breaking changes or security vulnerabilities.

  • 35-49: The introduction of various TxEncoder functions (failingTxEncoder, emptyTxEncoder, passingTxEncoderOne, etc.) is a good practice for testing different scenarios of transaction encoding. However, ensure that these encoders are thoroughly tested to simulate realistic encoding outcomes accurately.
  • 62-72: The test cases now include pricesEncoder, fundingEncoder, clobEncoder, and bridgeEncoder as part of their setup. This change allows for more granular control over the encoding process in different transaction types, which is crucial for testing the proposal preparation logic comprehensively. It's important to verify that these encoders are correctly implemented to reflect the actual behavior of the encoding process in production.
  • 366-373: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [339-370]

The creation of mockTxConfig with an array of sdk.TxEncoder and the subsequent setup of various mock keepers (mockPricesKeeper, mockPerpKeeper, mockBridgeKeeper, mockClobKeeper) are critical for setting up the test environment. This setup ensures that the tests can simulate the proposal preparation process accurately. It's essential to ensure that these mocks behave as expected and that the tests cover a wide range of scenarios to catch potential issues early.

  • 465-642: The tests for TestSlinkyPrepareProposalHandler focus on scenarios where vote extensions (VEs) are either enabled or disabled. These tests are crucial for ensuring that the proposal preparation logic correctly handles Slinky-specific logic under different conditions. Given the previous comment regarding the use of "ves" in the codebase, it's good to see clarity in the test descriptions regarding vote extensions. However, ensure that the tests cover all relevant scenarios, including edge cases that might arise from the interaction between vote extensions and other parts of the proposal preparation logic.
  • 686-698: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [643-716]

The function TestGetUpdateMarketPricesTx and its associated tests demonstrate thorough testing of the market price updates transaction generation process. It's important to ensure that these tests cover all possible outcomes of the getMarketPriceUpdates function, including error handling and successful transaction encoding. This will help ensure the robustness of the market price updates logic in the proposal preparation process.

  • 704-723: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [717-889]

Similar to the previous comment, the tests for TestGetAcknowledgeBridgesTx, TestGetAddPremiumVotesTx, and TestGetProposedOperationsTx are essential for verifying the correctness of transaction generation for different types of operations within the proposal preparation logic. Ensure that these tests are comprehensive and cover a wide range of scenarios, including error cases and successful transaction encoding, to maintain the integrity of the proposal preparation process.

  • 904-910: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [890-943]

The TestEncodeMsgsIntoTxBytes function and its tests are crucial for ensuring that messages can be correctly encoded into transaction bytes. This functionality is fundamental to the proposal preparation process, as it directly affects the ability to generate valid transactions. Ensure that the tests cover various scenarios, including errors during message setting and encoding failures, to guarantee the reliability of this functionality.

protocol/app/app.go (3)
  • 1340-1353: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1334-1344]

The introduction of priceUpdateGenerator in the PrepareProposal handler is a significant change. It's crucial to ensure that the PriceUpdateGenerator is properly implemented and tested, especially since it directly affects the proposal handling logic. Additionally, consider whether the priceUpdateGenerator needs to be configurable to support different strategies or protocols in the future.

  • 1359-1365: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1350-1374]

Similarly, the use of priceUpdateDecoder in the ProcessProposal handler is a critical addition. It's important to validate the correctness and efficiency of the UpdateMarketPriceTxDecoder implementation. Given that this decoder plays a key role in interpreting market price updates, thorough testing and validation are essential to prevent incorrect price data from affecting the system.

  • 1340-1353: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1-1374]

The New function is quite large and contains a significant amount of initialization logic. Consider refactoring some of this logic into separate, well-named functions or methods. This could improve readability and maintainability by making the main application setup more concise and easier to follow. For example, initialization of keepers, modules, and middleware could each be moved to their own functions.

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.

Review Status

Actionable comments generated: 1

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 5ad38a3 and 04c240d.
Files selected for processing (2)
  • protocol/app/app.go (5 hunks)
  • protocol/mocks/Makefile (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • protocol/mocks/Makefile
Additional comments: 1
protocol/app/app.go (1)
  • 1366-1379: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1360-1400]

The implementation of PrepareProposal and ProcessProposal handlers introduces new functionality related to price updates. It's crucial to ensure that these handlers are thoroughly tested, especially since they interact with critical components like the PricesKeeper, BridgeKeeper, ClobKeeper, and PerpetualsKeeper. Consider adding comprehensive unit tests covering various scenarios to ensure the correctness and robustness of these handlers.

Would you like assistance in generating unit tests for these handlers?

Comment on lines 100 to 106
"github.com/dydxprotocol/v4-chain/protocol/app/flags"
"github.com/dydxprotocol/v4-chain/protocol/app/middleware"
"github.com/dydxprotocol/v4-chain/protocol/app/prepare"
"github.com/dydxprotocol/v4-chain/protocol/app/prepare/prices"
"github.com/dydxprotocol/v4-chain/protocol/app/process"

"github.com/dydxprotocol/v4-chain/protocol/lib"
Copy link
Contributor

Choose a reason for hiding this comment

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

📝 NOTE
This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [726-726]

The gRPC server is initialized without specifying credentials, which could lead to insecure communication. It's recommended to secure the gRPC server by adding SSL/TLS credentials. This can be achieved by creating credentials using credentials.NewServerTLSFromFile("cert.pem", "cert.key") and passing them to the grpc.NewServer function using the grpc.Creds() option. This change will ensure that the communication between the client and server is encrypted and secure.

@Christopher-Li Christopher-Li merged commit dd41d0a into dydxprotocol:main Mar 14, 2024
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

4 participants