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
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (x/auth/vesting) [#17810](https://github.com/cosmos/cosmos-sdk/pull/17810) Add the ability to specify a start time for continuous vesting accounts.
* (runtime) [#18475](https://github.com/cosmos/cosmos-sdk/pull/18475) Adds an implementation for core.branch.Service.
* (server) [#18478](https://github.com/cosmos/cosmos-sdk/pull/18478) CMD flag to disable colored logs.
* (baseapp) [#18499](https://github.com/cosmos/cosmos-sdk/pull/18499) Add `MsgRouter` response type from message name function.

### Improvements

Expand Down

Large diffs are not rendered by default.

342 changes: 181 additions & 161 deletions api/cosmos/accounts/v1/account_abstraction.pulsar.go

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions baseapp/internal/protocompat/protocompat.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

func ResponseFullNameFromMethodDesc(sd *grpc.ServiceDesc, method grpc.MethodDesc) (protoreflect.FullName, error) {
methodFullName := protoreflect.FullName(fmt.Sprintf("%s.%s", sd.ServiceName, method.MethodName))
desc, err := gogoproto.HybridResolver.FindDescriptorByName(methodFullName)
if err != nil {
return "", fmt.Errorf("cannot find method descriptor %s", methodFullName)
}
methodDesc, ok := desc.(protoreflect.MethodDescriptor)
if !ok {
return "", fmt.Errorf("invalid method descriptor %s", methodFullName)
}
return methodDesc.Output().FullName(), nil
}
17 changes: 15 additions & 2 deletions baseapp/msg_service_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -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?

circuitBreaker CircuitBreaker
}
testinginprod marked this conversation as resolved.
Show resolved Hide resolved

Expand All @@ -39,8 +40,10 @@ var _ gogogrpc.Server = &MsgServiceRouter{}
// NewMsgServiceRouter creates a new MsgServiceRouter.
func NewMsgServiceRouter() *MsgServiceRouter {
return &MsgServiceRouter{
routes: map[string]MsgServiceHandler{},
hybridHandlers: map[string]func(ctx context.Context, req, resp protoiface.MessageV1) error{},
routes: map[string]MsgServiceHandler{},
hybridHandlers: map[string]func(ctx context.Context, req, resp protoiface.MessageV1) error{},
responseByRequest: map[string]string{},
circuitBreaker: nil,
}
}

Expand Down Expand Up @@ -87,16 +90,26 @@ func (msr *MsgServiceRouter) HybridHandlerByMsgName(msgName string) func(ctx con
return msr.hybridHandlers[msgName]
}

func (msr *MsgServiceRouter) ResponseNameByRequestName(msgName string) string {
return msr.responseByRequest[msgName]
}
testinginprod marked this conversation as resolved.
Show resolved Hide resolved

func (msr *MsgServiceRouter) registerHybridHandler(sd *grpc.ServiceDesc, method grpc.MethodDesc, handler interface{}) error {
inputName, err := protocompat.RequestFullNameFromMethodDesc(sd, method)
if err != nil {
return err
}
outputName, err := protocompat.ResponseFullNameFromMethodDesc(sd, method)
if err != nil {
return err
}
cdc := codec.NewProtoCodec(msr.interfaceRegistry)
hybridHandler, err := protocompat.MakeHybridHandler(cdc, sd, method, handler)
if err != nil {
return err
}
// map input name to output name
msr.responseByRequest[string(inputName)] = string(outputName)
// if circuit breaker is not nil, then we decorate the hybrid handler with the circuit breaker
if msr.circuitBreaker == nil {
msr.hybridHandlers[string(inputName)] = hybridHandler
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@

// MsgAuthenticate is a message that an x/account account abstraction implementer
// must handle to authenticate a state transition.
message MsgAuthenticate {

Check failure on line 10 in proto/cosmos/accounts/interfaces/account_abstraction/v1/interface.proto

View workflow job for this annotation

GitHub Actions / break-check

Previously present field "3" with name "account_number" on message "MsgAuthenticate" was deleted.
// bundler defines the address of the bundler that sent the operation.
// NOTE: in case the operation was sent directly by the user, this field will reflect
// the user address.
string bundler = 1;

Check failure on line 14 in proto/cosmos/accounts/interfaces/account_abstraction/v1/interface.proto

View workflow job for this annotation

GitHub Actions / break-check

Field "1" with name "bundler" on message "MsgAuthenticate" changed option "json_name" from "userOperation" to "bundler".

Check failure on line 14 in proto/cosmos/accounts/interfaces/account_abstraction/v1/interface.proto

View workflow job for this annotation

GitHub Actions / break-check

Field "1" on message "MsgAuthenticate" changed type from "message" to "string".

Check failure on line 14 in proto/cosmos/accounts/interfaces/account_abstraction/v1/interface.proto

View workflow job for this annotation

GitHub Actions / break-check

Field "1" on message "MsgAuthenticate" changed name from "user_operation" to "bundler".
// user_operation is the operation that the user is trying to perform.
// it also contains authentication information.
cosmos.accounts.v1.UserOperation user_operation = 1;
// chain_id defines the network identifier.
string chain_id = 2;
// account_number is the account number of the user_operation.
uint64 account_number = 3;
cosmos.accounts.v1.UserOperation user_operation = 2;

Check failure on line 17 in proto/cosmos/accounts/interfaces/account_abstraction/v1/interface.proto

View workflow job for this annotation

GitHub Actions / break-check

Field "2" with name "user_operation" on message "MsgAuthenticate" changed option "json_name" from "chainId" to "userOperation".

Check failure on line 17 in proto/cosmos/accounts/interfaces/account_abstraction/v1/interface.proto

View workflow job for this annotation

GitHub Actions / break-check

Field "2" on message "MsgAuthenticate" changed type from "string" to "message".

Check failure on line 17 in proto/cosmos/accounts/interfaces/account_abstraction/v1/interface.proto

View workflow job for this annotation

GitHub Actions / break-check

Field "2" on message "MsgAuthenticate" changed name from "chain_id" to "user_operation".
}

// MsgAuthenticateResponse is the response to MsgAuthenticate.
Expand All @@ -27,9 +27,13 @@
// the bundler payment messages.
// The account must ensure the caller of this message is the x/accounts module itself.
message MsgPayBundler {
// bundler is the address of the bundler.
// NOTE: in case the operation was sent directly by the user, this field will
// reflect the user address.
string bundler = 1;

Check failure on line 33 in proto/cosmos/accounts/interfaces/account_abstraction/v1/interface.proto

View workflow job for this annotation

GitHub Actions / break-check

Field "1" with name "bundler" on message "MsgPayBundler" changed option "json_name" from "bundlerPaymentMessages" to "bundler".

Check failure on line 33 in proto/cosmos/accounts/interfaces/account_abstraction/v1/interface.proto

View workflow job for this annotation

GitHub Actions / break-check

Field "1" on message "MsgPayBundler" changed label from "repeated" to "optional".

Check failure on line 33 in proto/cosmos/accounts/interfaces/account_abstraction/v1/interface.proto

View workflow job for this annotation

GitHub Actions / break-check

Field "1" on message "MsgPayBundler" changed type from "message" to "string".
// bundler_payment_messages are the messages that the operation sender will execute.
// The account can modify the messages as it sees fit.
repeated google.protobuf.Any bundler_payment_messages = 1;
repeated google.protobuf.Any bundler_payment_messages = 2;
}

// MsgPayBundlerResponse is the response to MsgPayBundler.
Expand All @@ -44,9 +48,13 @@
// block certain messages, or modify them.
// The account must ensure the caller of this message is the x/accounts module itself.
message MsgExecute {
// bundler is the address of the bundler.
// NOTE: in case the operation was sent directly by the user, this field will
// reflect the user address.
string bundler = 1;
// execution_messages are the messages that the operation sender will execute.
// The account can modify the messages as it sees fit.
repeated google.protobuf.Any execution_messages = 1;
repeated google.protobuf.Any execution_messages = 2;
}

// MsgExecuteResponse is the response to MsgExecute.
Expand Down
20 changes: 12 additions & 8 deletions proto/cosmos/accounts/v1/account_abstraction.proto
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,9 @@ message UserOperation {
// authentication_data defines the authentication data associated with the authentication method.
// It is the account implementer duty to assess that the UserOperation is properly signed.
bytes authentication_data = 3;
// sequence defines the sequence number of the account, the authentication method might require this
// to ensure non-replayability.
uint64 sequence = 4;
// authentication_gas_limit expresses the gas limit to be used for the authentication part of the
// UserOperation.
uint64 authentication_gas_limit = 5;
uint64 authentication_gas_limit = 4;
// bundler_payment_messages expresses a list of messages that the account
// executes to pay the bundler for submitting the UserOperation.
// It can be empty if the bundler does not need any form of payment,
Expand All @@ -33,21 +30,22 @@ message UserOperation {
// - NFT payment
// - IBC Token payment.
// - Payment through delegations.
repeated google.protobuf.Any bundler_payment_messages = 6;
repeated google.protobuf.Any bundler_payment_messages = 5;
// bundler_payment_gas_limit defines the gas limit to be used for the bundler payment.
// This ensures that, since the bundler executes a list of UserOperations and there needs to
// be minimal trust between bundler and UserOperation sender, the sender cannot consume
// the whole bundle gas.
uint64 bundler_payment_gas_limit = 7;
uint64 bundler_payment_gas_limit = 6;
// execution_messages expresses a list of messages that the account wants to execute.
// This concretely is the intent of the transaction expressed as a UserOperation.
repeated google.protobuf.Any execution_messages = 8;
repeated google.protobuf.Any execution_messages = 7;
// execution_gas_limit defines the gas limit to be used for the execution of the UserOperation's
// execution messages.
uint64 execution_gas_limit = 9;
uint64 execution_gas_limit = 8;
}

// UserOperationResponse defines the response of a UserOperation.
// If the operation fails the error field will be populated.
message UserOperationResponse {
// authentication_gas_used defines the gas used for the authentication part of the UserOperation.
uint64 authentication_gas_used = 1;
Expand All @@ -60,4 +58,10 @@ message UserOperationResponse {
uint64 execution_gas_used = 4;
// execution_responses defines the responses of the execution messages.
repeated google.protobuf.Any execution_responses = 5;
// error defines the error that occurred during the execution of the UserOperation.
// If the error is not empty, the UserOperation failed.
// Other fields might be populated even if the error is not empty, for example
// if the operation fails after the authentication step, the authentication_gas_used
// field will be populated.
string error = 6;
}
4 changes: 4 additions & 0 deletions simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
storetypes "cosmossdk.io/store/types"
"cosmossdk.io/x/accounts"
"cosmossdk.io/x/accounts/accountstd"
"cosmossdk.io/x/accounts/testing/account_abstraction"
"cosmossdk.io/x/accounts/testing/counter"
"cosmossdk.io/x/auth"
"cosmossdk.io/x/auth/ante"
Expand Down Expand Up @@ -284,11 +285,14 @@ func NewSimApp(
accountsKeeper, err := accounts.NewKeeper(
runtime.NewKVStoreService(keys[accounts.StoreKey]),
runtime.EventService{},
runtime.BranchService{},
app.AuthKeeper.AddressCodec(),
appCodec.InterfaceRegistry().SigningContext(),
app.MsgServiceRouter(),
app.GRPCQueryRouter(),
accountstd.AddAccount("counter", counter.NewAccount),
accountstd.AddAccount("aa_minimal", account_abstraction.NewMinimalAbstractedAccount),
accountstd.AddAccount("aa_full", account_abstraction.NewFullAbstractedAccount),
)
if err != nil {
panic(err)
Expand Down
Loading
Loading