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(accounts): implement account abstraction execution #18499

Merged
merged 22 commits into from
Dec 4, 2023

Conversation

testinginprod
Copy link
Contributor

@testinginprod testinginprod commented Nov 17, 2023

Description

BaseApp.MsgRouter changes

We add a new method in the router to extract the response type given the request name, this is needed since the Handler API follows gRPC semantics, in which both request and response are well-known types as can be seen by the following function signature: https://github.com/cosmos/cosmos-sdk/blob/main/baseapp/internal/protocompat/protocompat.go#L24 (response is passed in and not returned, whihc assumes we know the response).

Problem is that we cannot assume to always know how request and responses map together. So this method simply allows a consumer to know which is the response type expected from a handler.

Introduction of account abstraction execution logic in x/accounts

This PR also introduces the execution logic of a user operation, the execution logic can either be executed in a single step, so with the execution of ExecuteUserOperation, or each method can be executed in separate steps.

Specifically:

Authenticate

Takes care of running authentication in an x/account which implements the AA interface.

Execute Messages

Runs the Execution step of TX messages, in case it's not implemented by an x/account, then it defaults to simply sending the messages to the router after verifying that no impersonation has happened.

Pay Bundler

Behaves the same as Execute Messages.

x/accounts refactor

This PR also adds a small cleanup on x/accounts in:

  • the usage of dependencies.
  • the way it sends messages to modules on behalf of other accounts.

Author Checklist

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

I have...

  • included the correct type prefix in the PR title
  • added ! to the type prefix if API or client breaking change
  • targeted the correct branch (see PR Targeting)
  • provided a link to the relevant issue or specification
  • followed the guidelines for building modules
  • included the necessary unit and integration tests
  • added a changelog entry to CHANGELOG.md
  • included comments for documenting Go code
  • updated the relevant documentation or specification
  • reviewed "Files changed" and left comments if necessary
  • run make lint and make test
  • confirmed all CI checks have passed

Reviewers Checklist

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

I have...

  • confirmed the correct type prefix in the PR title
  • confirmed ! in the type prefix if API or client breaking change
  • confirmed all author checklist items have been addressed
  • reviewed state machine logic
  • reviewed API design and naming
  • reviewed documentation is accurate
  • reviewed tests and test coverage
  • manually tested (if applicable)

Summary by CodeRabbit

  • New Features

    • Introduced a new mapping system for request and response types in message routing.
    • Added fields to protocol buffer definitions to support account abstraction features.
    • Implemented new test suites for account abstraction and enhanced existing tests.
    • Expanded functionality for working with protobuf Any messages and module execution.
  • Improvements

    • Updated the MsgServiceRouter with additional methods for response type retrieval.
    • Enhanced the Keeper structure with new methods for message and query handling.
    • Improved error handling with the introduction of new error variables.
  • Refactor

    • Refactored import statements across various files for better organization.
    • Updated function signatures and test setups to align with new features and improvements.
  • Bug Fixes

    • Corrected the generation of unimplemented status errors in the ExecuteBundle function.
  • Documentation

    • Updated CHANGELOG.md to summarize the inclusion of MsgRouter response type enhancements.

Copy link
Contributor

coderabbitai bot commented Nov 17, 2023

Walkthrough

Walkthrough

The changes involve enhancements to the Cosmos SDK, focusing on message routing, account abstraction, and protobuf compatibility. A new MsgRouter response type function has been added, and the MsgServiceRouter has been updated to map request to response types. The account abstraction feature has been expanded with new fields in proto messages, error handling, and testing for abstracted account operations. Protobuf-related utilities have been improved for better message handling, and the Keeper structure has been extended with new functionalities and error definitions.

Changes

File Path Change Summary
CHANGELOG.md Added entry for new MsgRouter response type function.
baseapp/.../protocompat.go Added ResponseFullNameFromMethodDesc function; modified RequestFullNameFromMethodDesc.
baseapp/msg_service_router.go Added responseByRequest map and ResponseByRequestName method; updated registerHybridHandler.
proto/cosmos/accounts/.../interface.proto Added bundler field to messages; updated field numbers.
proto/cosmos/accounts/.../account_abstraction.proto Removed sequence field; reassigned field numbers; added error field.
simapp/app.go Added imports and accounts for account_abstraction.
tests/e2e/accounts/... New tests for account abstraction; added setupApp function.
testutil/testdata/testpb/... Reordered imports; removed unused imports.
x/accounts/accountstd/exports.go Added functions for protobuf Any messages; added accountsModuleAddress variable.
x/accounts/genesis_test.go Replaced import; updated k.queryRouter assignment.
x/accounts/internal/implementation/... Added IsRoutingError function; significant changes to MakeAccountContext and related functions.
x/accounts/keeper.go Added imports, global variables, and methods; updated NewKeeper and Keeper struct.
x/accounts/keeper_account_abstraction.go New package for abstracted account operations; added functions and error variables.
x/accounts/... Various updates to tests and test utilities; added new interfaces and functions.
x/accounts/module.go Added import; initialized "ModuleAccountAddress".
x/accounts/msg_server.go Updated ExecuteBundle function to use status.Error.
x/accounts/msg_server_test.go, x/accounts/query_server_test.go Updated test setups and function assignments.
x/accounts/testing/account_abstraction/... New structs and methods for account abstraction testing; updated dependencies and handlers.

Tips

Chat with CodeRabbit Bot (@coderabbitai)

  • If you reply to a review comment from CodeRabbit, the bot will automatically respond.
  • To engage with CodeRabbit bot directly around the specific lines of code in the PR, mention @coderabbitai in your review comment
  • Note: Review comments are made on code diffs or files, not on the PR overview.
  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

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.

Note: For conversation with the bot, please use the review comments on code diffs or files.

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

@testinginprod testinginprod marked this pull request as ready for review November 20, 2023 18:21
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: 54

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 8644e6b and 31cd9e3.
Files ignored due to filter (7)
  • testutil/testdata/query.pb.go
  • testutil/testdata/testdata.pb.go
  • testutil/testdata/testpb/query_grpc.pb.go
  • testutil/testdata/testpb/tx_grpc.pb.go
  • testutil/testdata/tx.pb.go
  • testutil/testdata/unknonwnproto.pb.go
  • x/accounts/v1/account_abstraction.pb.go
Files selected for processing (30)
  • CHANGELOG.md (1 hunks)
  • api/cosmos/accounts/interfaces/account_abstraction/v1/interface.pulsar.go (43 hunks)
  • api/cosmos/accounts/v1/account_abstraction.pulsar.go (40 hunks)
  • baseapp/internal/protocompat/protocompat.go (1 hunks)
  • baseapp/msg_service_router.go (3 hunks)
  • proto/cosmos/accounts/interfaces/account_abstraction/v1/interface.proto (3 hunks)
  • proto/cosmos/accounts/v1/account_abstraction.proto (3 hunks)
  • simapp/app.go (2 hunks)
  • tests/e2e/accounts/account_abstraction_test.go (1 hunks)
  • tests/e2e/accounts/setup_test.go (1 hunks)
  • testutil/testdata/testpb/query.pulsar.go (1 hunks)
  • testutil/testdata/testpb/testdata.pulsar.go (1 hunks)
  • testutil/testdata/testpb/tx.pulsar.go (1 hunks)
  • testutil/testdata/testpb/unknonwnproto.pulsar.go (1 hunks)
  • x/accounts/accountstd/exports.go (2 hunks)
  • x/accounts/genesis_test.go (2 hunks)
  • x/accounts/internal/implementation/api_builder.go (1 hunks)
  • x/accounts/internal/implementation/context.go (2 hunks)
  • x/accounts/internal/implementation/context_test.go (2 hunks)
  • x/accounts/internal/implementation/proto_util.go (1 hunks)
  • x/accounts/keeper.go (12 hunks)
  • x/accounts/keeper_account_abstraction.go (1 hunks)
  • x/accounts/keeper_test.go (6 hunks)
  • x/accounts/module.go (2 hunks)
  • x/accounts/msg_server.go (1 hunks)
  • x/accounts/msg_server_test.go (2 hunks)
  • x/accounts/query_server_test.go (2 hunks)
  • x/accounts/testing/account_abstraction/full.go (1 hunks)
  • x/accounts/testing/account_abstraction/minimal.go (1 hunks)
  • x/accounts/utils_test.go (1 hunks)
Files not summarized due to errors (2)
  • api/cosmos/accounts/interfaces/account_abstraction/v1/interface.pulsar.go: Error: Message exceeds token limit
  • api/cosmos/accounts/v1/account_abstraction.pulsar.go: Error: Message exceeds token limit
Files skipped from review due to trivial changes (5)
  • testutil/testdata/testpb/query.pulsar.go
  • testutil/testdata/testpb/testdata.pulsar.go
  • testutil/testdata/testpb/tx.pulsar.go
  • testutil/testdata/testpb/unknonwnproto.pulsar.go
  • x/accounts/msg_server_test.go
Additional comments: 47
tests/e2e/accounts/setup_test.go (1)
  • 9-13: The setupApp function correctly sets up a simapp.SimApp instance for testing purposes. It's good practice to call t.Helper() to mark the function as a test helper function. However, ensure that the simapp.Setup function does not require any additional parameters or configuration changes to support the new account abstraction features mentioned in the pull request summary.
x/accounts/module.go (1)
  • 14-20: The addition of the new import statement for "github.com/cosmos/cosmos-sdk/types/address" is appropriate given the use of the address package on line 28. This change is necessary for the new functionality being introduced.
baseapp/internal/protocompat/protocompat.go (1)
  • 225-235: The new function ResponseFullNameFromMethodDesc is a good addition for symmetry with RequestFullNameFromMethodDesc and will be useful for retrieving the response type associated with a gRPC method. However, ensure that there are corresponding tests for this new function to verify its behavior and handle edge cases.
x/accounts/query_server_test.go (2)
  • 6-11: The removal of the import "google.golang.org/protobuf/runtime/protoiface" is appropriate given the change in the function signature from protoiface.MessageV1 to proto.Message. This change aligns with the updated usage within the test function.

  • 17-21: The change from k.queryModuleFunc to k.queryRouter and the corresponding function signature update from protoiface.MessageV1 to proto.Message is consistent with the broader updates to the Cosmos SDK's account abstraction feature. This change simplifies the interface and aligns with the updated protobuf definitions. Ensure that all references to the old function and its signature are updated across the codebase to prevent any breakage.

proto/cosmos/accounts/interfaces/account_abstraction/v1/interface.proto (3)
  • 8-18: The addition of the bundler field to MsgAuthenticate is consistent with the change summary. However, ensure that all services that construct or handle MsgAuthenticate messages are updated to include and process this new field. Also, verify that the documentation and comments are updated to reflect this change.

  • 27-37: Similar to the MsgAuthenticate, the bundler field has been added to MsgPayBundler. Ensure that the corresponding handling logic and documentation are updated accordingly. Additionally, verify that the security implications of allowing the account to modify the bundler_payment_messages are thoroughly reviewed and documented.

  • 48-58: The bundler field has been added to MsgExecute as well. Ensure that the handling logic for this message type is updated to accommodate the new field. It's also important to ensure that the execution_messages can be safely modified by the account, as this could have security implications.

simapp/app.go (2)
  • 22-28: The import statement for "cosmossdk.io/x/accounts/testing/account_abstraction" has been added to include the account abstraction testing accounts. This is part of the feature update to implement account abstraction execution in the Cosmos SDK. Ensure that this new dependency is properly managed and that the package is used elsewhere in the code as expected.

  • 285-296: The accountsKeeper is being initialized with new account types "counter", "aa_minimal", and "aa_full". This is part of the setup for account abstraction testing. Ensure that the corresponding functions counter.NewAccount, account_abstraction.NewMinimalAbstractedAccount, and account_abstraction.NewFullAbstractedAccount are correctly implemented and that they adhere to the expected interface for account types. Additionally, verify that error handling is correctly implemented for the case where accounts.NewKeeper returns an error, as the application will panic in such a scenario.

x/accounts/genesis_test.go (2)
  • 5-11: The import of "google.golang.org/protobuf/runtime/protoiface" has been correctly replaced with "google.golang.org/protobuf/proto". This change aligns with the usage of proto.Message in the test file. Ensure that there are no remaining references to protoiface that would require this import.

  • 17-18: The assignment of k.queryRouter has been updated to use a mockQuery function. This is a good practice for unit testing as it allows for the isolation of the test environment from external dependencies. However, ensure that the mockQuery function is defined somewhere in the test file or test helpers, as it is not shown in the provided code.

x/accounts/internal/implementation/context_test.go (2)
  • 6-11: The import google.golang.org/protobuf/runtime/protoiface has been removed, which is good if it's no longer used. However, ensure that no other parts of the codebase are affected by this removal. If this import was used elsewhere, those parts of the code will need to be updated accordingly.

  • 43-74: The refactoring of MakeAccountContext to accept different function signatures for module execution and querying is a good approach to enhance flexibility and maintainability. It allows for more granular control over the behavior of the account context in different scenarios. The tests are well-structured and ensure that the context is correctly set up and that the execution and querying of modules work as expected. The use of generics with ExecModule and ExecModuleUntyped is a modern feature of Go that improves type safety and reduces the need for type assertions.

x/accounts/accountstd/exports.go (3)
  • 2-21: The introduction of a new global variable accountsModuleAddress is a significant change. Ensure that this variable is used consistently across the codebase and that its introduction does not introduce any security or logical issues, such as unauthorized access to the accounts module address or conflicts with other modules.

  • 72-78: The function SenderIsAccountsModule is a security-sensitive check. It is crucial to ensure that the comparison between the sender's address and the accountsModuleAddress is done securely and correctly. Using bytes.Equal is appropriate for this purpose, but ensure that the Sender function is reliable and cannot be spoofed or manipulated.

  • 80-126: The ExecModuleAnys function is performing multiple operations that could fail, such as unpacking messages, executing them, and packing responses. It is important to ensure that the error handling is robust and that any errors are logged or handled appropriately. Additionally, consider the implications of a partial failure where some messages are executed successfully while others fail. The current implementation will return on the first error, which may or may not be the desired behavior depending on the use case.

proto/cosmos/accounts/v1/account_abstraction.proto (3)
  • 18-26: The reassignment of field numbers in the UserOperation message is a breaking change. Ensure that all serialized data and client code that interacts with these messages are updated to reflect the new field numbers. This is critical for maintaining compatibility and preventing potential data corruption or misinterpretation of message fields.

  • 30-44: The addition of bundler_payment_messages and execution_messages as repeated google.protobuf.Any fields allows for flexibility in the types of messages that can be included. However, it's important to ensure that the code handling these messages is equipped to safely unpack the Any type and handle the dynamic message types appropriately. This is crucial for preventing runtime errors and ensuring the robustness of the message handling logic.

  • 58-66: The addition of the error field to the UserOperationResponse message is a good practice for error handling. It allows clients to understand the nature of the failure without having to infer it from other fields. However, ensure that the error messages are clear, actionable, and properly documented so that clients can handle them effectively.

x/accounts/internal/implementation/context.go (5)
  • 13-13: The AccountStatePrefix is being created with a fixed value of 255. This could potentially lead to conflicts if other parts of the system use the same prefix value. It's important to ensure that this prefix is unique across the system to avoid key collisions in the store.

  • 23-30: The contextValue struct has been updated to include moduleExecUntyped. This change should be reflected in all parts of the code where contextValue is used to ensure that the new functionality is properly integrated and that there are no missing or misaligned usages of the struct.

  • 42-57: The MakeAccountContext function has been updated to include a new parameter moduleExecUntyped. Ensure that all invocations of this function are updated to pass the new argument. Additionally, consider if the function signature change could break any existing code that relies on the previous signature.

  • 60-71: The new ExecModuleUntyped function has been added to execute a module message when the response type is unknown. This is a significant addition and should be thoroughly tested to ensure that it handles all possible error conditions and edge cases correctly. It's also important to ensure that the function is thread-safe if it's going to be used in a concurrent environment.

  • 73-83: The ExecModule function has been updated to include the new moduleExecUntyped parameter. This change should be carefully reviewed to ensure that it doesn't introduce any regressions or bugs, especially since it affects the execution of module messages. Additionally, the type assertion on line 76 should be accompanied by a check to handle the case where the assertion fails, to prevent potential panics at runtime.

x/accounts/utils_test.go (1)
  • 1-80: The test utilities introduced in this hunk seem to be well-structured and follow the interface definitions required for the Cosmos SDK's account abstraction feature. The addressCodec, eventService, mockQuery, mockSigner, and mockExec are all mock implementations of their respective interfaces, which is a common pattern for unit testing. The newKeeper function is a helper that sets up a new Keeper instance for testing, and the use of t.Helper() is appropriate for indicating that this is a test helper function.

However, there are a few points to consider:

  • The addressCodec implementation is very simplistic and may not reflect the actual complexity of address encoding and decoding in a real-world scenario. Ensure that this simplicity is sufficient for the tests being written.
  • The eventService and its methods do not perform any actions. If event emission is a critical part of the functionality being tested, you may need to implement a more sophisticated mock that can track emitted events.
  • The mockQuery, mockSigner, and mockExec types are defined as function types, which is a flexible way to create mocks that can have different behaviors for different tests. Just ensure that the tests using these mocks are providing the necessary function implementations to simulate the desired behavior.
  • The newKeeper function does not allow for customization of the eventService, addressCodec, or other dependencies beyond the AccountCreatorFunc. If tests require more control over these dependencies, consider adding parameters to newKeeper to allow for this customization.

Overall, the test utilities appear to be correctly implemented for the purpose of unit testing within the Cosmos SDK's account abstraction feature. Just ensure that the simplicity of the mocks aligns with the requirements of the tests they are intended to support.

x/accounts/testing/account_abstraction/full.go (2)
  • 3-9: The import statements are clear and well-organized. However, ensure that the new dependency account_abstractionv1 is properly managed in the project's dependency management files (e.g., go.mod) and that the correct version is being used.

  • 65-77: The RegisterInitHandler, RegisterExecuteHandlers, and RegisterQueryHandlers methods delegate to the embedded MinimalAbstractedAccount. This is a good use of composition to avoid code duplication. However, ensure that the delegation to MinimalAbstractedAccount is intentional and that there are no additional handlers that FullAbstractedAccount should be registering.

x/accounts/testing/account_abstraction/minimal.go (3)
  • 3-14: The import section looks clean and well-organized. However, ensure that all imported packages are used within the file to avoid unnecessary dependencies.

  • 23-28: The NewMinimalAbstractedAccount function correctly initializes a new MinimalAbstractedAccount with a public key and sequence. Ensure that error handling is implemented if any of the initialization steps can fail.

  • 59-70: The registration of handlers for initialization, execution, and querying is done correctly. However, ensure that the handlers being registered (e.g., RotatePubKey, Authenticate, QueryAuthenticateMethods) are fully implemented and tested, as some are currently returning "not implemented" errors.

baseapp/msg_service_router.go (6)
  • 31-36: The addition of the responseByRequest map to the MsgServiceRouter struct is a significant change. It's important to ensure that all parts of the code that interact with MsgServiceRouter are aware of this new map and handle it appropriately. This change could potentially break existing functionality if not integrated correctly. Make sure to update any relevant documentation and consider the impact on serialization if MsgServiceRouter is ever persisted or sent over the network.

  • 40-47: The constructor NewMsgServiceRouter has been updated to initialize the new responseByRequest map. This is a good practice as it ensures that the map is never nil, preventing potential nil pointer dereferences when the map is used later on.

  • 93-95: The new method ResponseByRequestName provides a way to retrieve the response type based on the request name. It's important to ensure that this method is used consistently across the codebase wherever such a mapping is required. Additionally, consider adding error handling for cases where the request name is not found in the map to prevent unexpected behavior.

  • 97-115: The registerHybridHandler method has been modified to include the mapping of request types to their corresponding response types. This is a critical change that enhances the message routing capabilities of the MsgServiceRouter. However, it's important to ensure that the inputName and outputName are always valid and that the mapping does not introduce any conflicts or overwrite existing entries without proper checks. Also, consider what should happen if a mapping already exists for a given inputName. Should it be overwritten, ignored, or should an error be raised? This needs to be clearly defined to avoid unexpected behavior.

  • 112-112: The mapping of inputName to outputName is done by casting them to string. Ensure that the protocompat.RequestFullNameFromMethodDesc and protocompat.ResponseFullNameFromMethodDesc methods guarantee that the returned names are unique and valid for casting to string. If there's any possibility of non-unique names, this could lead to incorrect behavior in message routing.

  • 114-115: The check for msr.circuitBreaker == nil is used to decide whether to decorate the handler with a circuit breaker. It's important to ensure that the circuit breaker is correctly initialized before this method is called. If the circuit breaker is intended to be optional, then this logic is correct. However, if a circuit breaker is expected to be present, then the absence of it should be handled as an error condition.

x/accounts/keeper_account_abstraction.go (1)
  • 3-12: The import section is well-organized and follows the convention of grouping standard library imports separately from third-party libraries. However, it's important to ensure that all imported packages are used within the file to avoid unnecessary dependencies. If any of the imported packages are not used, they should be removed to keep the code clean and maintainable.
x/accounts/keeper.go (4)
  • 3-22: The new imports introduced here should be reviewed to ensure they are all necessary for the functionality being added. Unused imports should be removed to keep the code clean and maintainable.

  • 28-32: The error errAccountTypeNotFound is defined but not used in the provided code. If it is not used elsewhere in the codebase, it should be removed to avoid dead code.

  • 74-91: > Note: This review was outside of the patch, so it was mapped to the patch with the greatest overlap. Original lines [65-89]

The NewKeeper function has been updated to take an additional BranchExecutor parameter and new fields have been added to the Keeper struct. Ensure that all instances where NewKeeper is called have been updated to pass the new parameter. Additionally, verify that the new fields are properly initialized and used throughout the codebase.

  • 140-153: The Init method now takes an additional ctx parameter. Ensure that all calls to this method have been updated accordingly. Also, verify that the context is being used correctly within the method.
x/accounts/keeper_test.go (5)
  • 6-26: The test TestKeeper_Init has been updated to use a mockQuery function for the queryRouter. This mock function is specific to a QueryBalanceRequest and QueryBalanceResponse from the bankv1beta1 package. Ensure that this mock is sufficient for all tests within TestKeeper_Init and that it does not need to handle other request types. If other request types are needed, the mock function should be adjusted accordingly.

  • 53-58: The TestKeeper_Execute function setup includes creating a new account. It's important to ensure that the account creation process is successful before proceeding with the rest of the tests. The test should include assertions to verify that the account was created correctly and that the initial state is as expected.

  • 73-86: The TestKeeper_Execute function includes a subtest "exec module" that uses a mockExec function for the msgRouter and a mockSigner for the signerProvider. This test is specifically checking the execution of a MsgSend from the bankv1beta1 package. Ensure that the mockExec and mockSigner functions are correctly simulating the expected behavior of the msgRouter and signerProvider in the context of the Execute method. If there are other message types that need to be tested, consider adding additional cases or a more generic mock function.

  • 94-98: In the TestKeeper_Query function, a generic mockQuery function is set up for the queryRouter that does not perform any specific checks or actions. This might be intentional for certain tests, but if specific behavior is expected from the queryRouter during the tests, the mock function should be updated to reflect that behavior.

  • 116-122: > Note: This review was outside of the patch, so it was mapped to the patch with the greatest overlap. Original lines [116-130]

The subtest "query module" within TestKeeper_Query is using a mockQuery function that is specific to a QueryBalanceRequest and sets a fixed response. This is a good practice for unit testing as it isolates the test scenario. However, ensure that the test is comprehensive and covers all necessary aspects of the Query method's behavior, including error handling and edge cases.

x/accounts/msg_server.go Show resolved Hide resolved
x/accounts/module.go Show resolved Hide resolved
x/accounts/internal/implementation/api_builder.go Outdated Show resolved Hide resolved
Comment on lines +1 to +349
BundlerPaymentMessages: intoAny(t, &bankv1beta1.MsgSend{
FromAddress: aaFullAddrStr,
ToAddress: bundlerAddrStr,
Amount: coins(t, "1stake"), // we expect this to fail since the account is implement in such a way not to allow bank sends.
}),
BundlerPaymentGasLimit: 50000,
ExecutionMessages: intoAny(t, &bankv1beta1.MsgSend{
FromAddress: aaFullAddrStr,
ToAddress: aliceAddrStr,
Amount: coins(t, "2000stake"),
}),
ExecutionGasLimit: 36000,
})
// in order to assert the call we expect an error to be returned.
require.Contains(t, resp.Error, accounts.ErrBundlerPayment.Error()) // error is bundler payment
require.Contains(t, resp.Error, "this account does not allow bank send messages") // error is bundler payment
})

t.Run("implements execution - fail", func(t *testing.T) {
resp := ak.ExecuteUserOperation(ctx, bundlerAddrStr, &accountsv1.UserOperation{
Sender: aaFullAddrStr,
AuthenticationMethod: "secp256k1",
AuthenticationData: []byte("signature"),
AuthenticationGasLimit: 10000,
BundlerPaymentMessages: nil,
BundlerPaymentGasLimit: 50000,
ExecutionMessages: intoAny(t, &stakingv1beta1.MsgDelegate{
DelegatorAddress: aaFullAddrStr,
ValidatorAddress: "some-validator",
Amount: coins(t, "2000stake")[0],
}),
ExecutionGasLimit: 36000,
})
// in order to assert the call we expect an error to be returned.
require.Contains(t, resp.Error, accounts.ErrExecution.Error()) // error is in execution
require.Contains(t, resp.Error, "this account does not allow delegation messages")
})

t.Run("implements bundler payment and execution - success", func(t *testing.T) {
// we simulate the abstracted account pays the bundler using an NFT.
require.NoError(t, app.NFTKeeper.SaveClass(ctx, nft.Class{
Id: "omega-rare",
}))
require.NoError(t, app.NFTKeeper.Mint(ctx, nft.NFT{
ClassId: "omega-rare",
Id: "the-most-rare",
}, aaFullAddr))

resp := ak.ExecuteUserOperation(ctx, bundlerAddrStr, &accountsv1.UserOperation{
Sender: aaFullAddrStr,
AuthenticationMethod: "secp256k1",
AuthenticationData: []byte("signature"),
AuthenticationGasLimit: 10000,
BundlerPaymentMessages: intoAny(t, &nftv1beta1.MsgSend{
ClassId: "omega-rare",
Id: "the-most-rare",
Sender: aaFullAddrStr,
Receiver: bundlerAddrStr,
}),
BundlerPaymentGasLimit: 50000,
ExecutionMessages: intoAny(t, &bankv1beta1.MsgSend{
FromAddress: aaFullAddrStr,
ToAddress: aliceAddrStr,
Amount: coins(t, "2000stake"),
}),
ExecutionGasLimit: 36000,
})
require.Empty(t, resp.Error) // no error
})
}

func intoAny(t *testing.T, msgs ...proto.Message) (anys []*anypb.Any) {
t.Helper()
for _, msg := range msgs {
any, err := anyutil.New(msg)
require.NoError(t, err)
anys = append(anys, any)
}
return
}

func coins(t *testing.T, s string) []*v1beta1.Coin {
t.Helper()
coins, err := sdk.ParseCoinsNormalized(s)
require.NoError(t, err)
coinsv2 := make([]*v1beta1.Coin, len(coins))
for i, coin := range coins {
coinsv2[i] = &v1beta1.Coin{
Denom: coin.Denom,
Amount: coin.Amount.String(),
}
}
return coinsv2
}

func balanceIs(t *testing.T, ctx context.Context, app *simapp.SimApp, addr sdk.AccAddress, s string) {
t.Helper()
balance := app.BankKeeper.GetAllBalances(ctx, addr)
require.Equal(t, s, balance.String())
}
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 suite for account abstraction seems comprehensive and covers a variety of scenarios. However, there are a few points that could be improved for better maintainability and readability:

  • The intoAny and coins helper functions are used to convert messages and coin amounts to the required types. These functions are called multiple times with similar parameters. Consider refactoring these functions to reduce redundancy and improve code clarity.
  • The test cases use hardcoded strings for error messages, such as "this account does not allow bank send messages". It's better to use constants for such strings to avoid duplication and ease future changes.
  • The test cases use hardcoded coin denominations like "stake" and "atom". It would be more maintainable to define these as constants at the beginning of the test file.
  • The balanceIs function asserts the balance of an account. It would be beneficial to include a comment explaining the expected state of the balance for clarity.
  • The test cases are well-named, indicating the scenario being tested. However, adding comments to each test case explaining the scenario in more detail would be helpful for future maintainers or other developers looking at the tests.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
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 31cd9e3 and 8d8b75a.
Files selected for processing (1)
  • x/accounts/internal/implementation/api_builder.go (1 hunks)

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

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 8d8b75a and 32a58f0.
Files selected for processing (3)
  • baseapp/msg_service_router.go (3 hunks)
  • x/accounts/keeper.go (12 hunks)
  • x/accounts/utils_test.go (1 hunks)
Additional comments: 14
baseapp/msg_service_router.go (1)
  • 97-115: The registerHybridHandler method has been updated to populate the responseByRequest map and to potentially wrap the hybrid handler with a circuit breaker. This is a critical section of code that needs to ensure that the mapping and the circuit breaker logic are correctly implemented. It's important to verify that the inputName and outputName are being correctly determined and that the circuit breaker is being applied as intended. Additionally, the error handling within this method should be reviewed to ensure that it is consistent and that any errors are properly reported and handled.
x/accounts/keeper.go (6)
  • 103-114: The Keeper struct has been extended with new fields. Ensure that these fields are properly encapsulated and that their access is controlled to maintain the integrity of the Keeper state.

  • 163-170: The Init method sets up mappings between account addresses and types, as well as account numbers and addresses. Ensure that these mappings are consistent and that there are no potential conflicts or overwrites that could occur.

  • 246-252: The makeAccountContext function creates a context with various capabilities based on whether it is a query or not. Ensure that the permissions and capabilities granted by the context are appropriate and secure for the intended operations.

  • 272-291: The sendAnyMessages helper function executes a series of anypb.Any messages. Ensure that the messages are validated and that the execution is secure, especially since the messages can belong to any module.

  • 313-335: The sendModuleMessage function sends a message to a module and expects the caller to know the response type. Ensure that the sender verification logic is robust and that there is no way for a sender to bypass the authorization checks.

  • 337-355: The queryModule function and getMessageName utility function are introduced. Ensure that the query routing logic is secure and that there is no ambiguity in the handling of multiple query handlers.

x/accounts/utils_test.go (7)
  • 3-15: The import section is well-organized and follows the convention of grouping standard library imports separately from third-party libraries. This is good for readability and maintainability.

  • 17-22: The addressCodec struct correctly implements the address.Codec interface. The methods StringToBytes and BytesToString are simple and appear to be correct, assuming that the string representation of the address is the same as its byte representation. However, in a real-world scenario, address encoding and decoding might require more complex logic to handle different address formats and potential validation.

  • 24-36: The eventService struct implements the event.Manager interface with stub methods that do nothing and return nil. This is acceptable for testing purposes, but it's important to ensure that these stubs are not used in production code where actual event handling logic is required.

  • 38-43: The newKeeper function is a test helper that creates a Keeper instance for testing. It uses the colltest.MockStore() to create a mock store and context, which is good for isolating tests. The use of require.NoError ensures that the test will fail immediately if an error occurs during the creation of the Keeper, which is a good practice for test clarity and debugging.

  • 46-54: The mockQuery type is a function type that implements the QueryRouter interface. The HybridHandlerByRequestName method returns a slice of handler functions that cast the protoiface.MessageV1 to proto.Message and call the mockQuery function. This is a clever way to mock the query routing for testing purposes, but it assumes that the req and resp arguments can always be safely cast to proto.Message. This should be fine for tests, but it's important to ensure that the actual implementation handles type assertions safely.

  • 56-66: The mockSigner type is a function type that implements the SignerProvider interface. The GetSigners method calls the mockSigner function and wraps the result in a slice of byte slices. This is a simple and effective way to mock the signer for testing. However, it's important to ensure that the actual signer implementation handles errors and edge cases appropriately.

  • 68-80: The mockExec type is a function type that implements the MsgRouter interface. The HybridHandlerByMsgName method returns a handler function that casts the protoiface.MessageV1 to proto.Message and calls the mockExec function. The ResponseNameByRequestName method appends "Response" to the request name to generate the response name. This is a simple and effective way to mock message execution for testing. However, it's important to ensure that the actual message execution logic handles message routing and response generation correctly.

baseapp/msg_service_router.go Show resolved Hide resolved
baseapp/msg_service_router.go Show resolved Hide resolved
x/accounts/keeper.go Show resolved Hide resolved
x/accounts/keeper.go Show resolved Hide resolved
x/accounts/keeper.go Show resolved Hide resolved
Comment on lines +234 to 237
func (k Keeper) makeAddress(accNum uint64) ([]byte, error) {
// TODO: better address scheme, ref: https://github.com/cosmos/cosmos-sdk/issues/17516
addr := sha256.Sum256(append([]byte("x/accounts"), binary.BigEndian.AppendUint64(nil, num)...))
addr := sha256.Sum256(append([]byte("x/accounts"), binary.BigEndian.AppendUint64(nil, accNum)...))
return addr[:], 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 makeAddress function uses a SHA-256 hash to generate an address. This approach may not be collision-resistant if the account number space is large. Consider using a more robust scheme for address generation, as noted in the TODO 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.

Review Status

Actionable comments generated: 2

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 32a58f0 and d8e1c94.
Files selected for processing (1)
  • x/accounts/keeper_account_abstraction.go (1 hunks)

x/accounts/keeper_account_abstraction.go Outdated Show resolved Hide resolved
x/accounts/keeper_account_abstraction.go Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Review Status

Actionable comments generated: 2

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between d8e1c94 and c798130.
Files selected for processing (1)
  • x/accounts/keeper_account_abstraction.go (1 hunks)

x/accounts/keeper_account_abstraction.go Show resolved Hide resolved
x/accounts/keeper_account_abstraction.go Show resolved Hide resolved
Copy link
Member

@tac0turtle tac0turtle left a comment

Choose a reason for hiding this comment

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

left two comments but the design is confusing me a bit. What is the difference between aa and accounts now? why does aa have to be native to accounts? i thought the point of accounts is that nothing needs to be native? what are the tradeoffs?

Could a README be added to accounts explaining the design and some docs on it

@@ -221,3 +221,16 @@ func RequestFullNameFromMethodDesc(sd *grpc.ServiceDesc, method grpc.MethodDesc)
}
return methodDesc.Input().FullName(), nil
}

Copy link
Member

Choose a reason for hiding this comment

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

missing godoc

@@ -31,6 +31,7 @@ type MsgServiceRouter struct {
interfaceRegistry codectypes.InterfaceRegistry
routes map[string]MsgServiceHandler
hybridHandlers map[string]func(ctx context.Context, req, resp protoiface.MessageV1) error
responseByRequest map[string]string
Copy link
Member

Choose a reason for hiding this comment

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

why is this needed?

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 c798130 and 02c2b8a.
Files selected for processing (1)
  • baseapp/internal/protocompat/protocompat.go (2 hunks)
Additional comments: 2
baseapp/internal/protocompat/protocompat.go (2)
  • 26-30: The implementation of MakeHybridHandler looks correct and handles both gogo and protov2 messages as intended.

  • 223-224: The changes to RequestFullNameFromMethodDesc look correct and should properly return the fully-qualified name of the request message.

baseapp/internal/protocompat/protocompat.go Show resolved Hide resolved
Comment on lines 163 to +167
if err := k.AccountsByType.Set(ctx, accountAddr, accountType); err != nil {
return nil, nil, err
}
// map account number to account address
if err := k.AccountByNumber.Set(ctx, accountAddr, num); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

nit: would it make sense to merge these 2 into a single map?

@facundomedica
Copy link
Member

Question, in practice what are the cases in which the response can be known/unknown? (moduleExec and moduleExecUntyped)

I need to go over the entire thing again as I don't fully understand it 😅.

Copy link
Member

@tac0turtle tac0turtle left a comment

Choose a reason for hiding this comment

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

utACK.

we should add the submessage checking of messages in the utils as discussed in the team call

Copy link
Member

@facundomedica facundomedica left a comment

Choose a reason for hiding this comment

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

utACK

@testinginprod testinginprod added this pull request to the merge queue Dec 4, 2023
Merged via the queue into main with commit d3b30e9 Dec 4, 2023
63 of 65 checks passed
@testinginprod testinginprod deleted the tip/accounts/aa/executor branch December 4, 2023 11:43
@testinginprod testinginprod mentioned this pull request Dec 19, 2023
44 tasks
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