Skip to content

Commit d3b30e9

Browse files
testinginprodunknown unknowncoderabbitai[bot]
authored
feat(accounts): implement account abstraction execution (cosmos#18499)
Co-authored-by: unknown unknown <unknown@unknown> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent 0a7567d commit d3b30e9

File tree

28 files changed

+1781
-704
lines changed

28 files changed

+1781
-704
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
5252
* (x/auth/vesting) [#17810](https://github.com/cosmos/cosmos-sdk/pull/17810) Add the ability to specify a start time for continuous vesting accounts.
5353
* (runtime) [#18475](https://github.com/cosmos/cosmos-sdk/pull/18475) Adds an implementation for core.branch.Service.
5454
* (server) [#18478](https://github.com/cosmos/cosmos-sdk/pull/18478) CMD flag to disable colored logs.
55+
* (baseapp) [#18499](https://github.com/cosmos/cosmos-sdk/pull/18499) Add `MsgRouter` response type from message name function.
5556

5657
### Improvements
5758

api/cosmos/accounts/interfaces/account_abstraction/v1/interface.pulsar.go

Lines changed: 316 additions & 220 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/cosmos/accounts/v1/account_abstraction.pulsar.go

Lines changed: 181 additions & 161 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

baseapp/internal/protocompat/protocompat.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ var (
2323

2424
type Handler = func(ctx context.Context, request, response protoiface.MessageV1) error
2525

26+
// MakeHybridHandler returns a handler that can handle both gogo and protov2 messages, no matter
27+
// if the handler is a gogo or protov2 handler.
2628
func MakeHybridHandler(cdc codec.BinaryCodec, sd *grpc.ServiceDesc, method grpc.MethodDesc, handler interface{}) (Handler, error) {
2729
methodFullName := protoreflect.FullName(fmt.Sprintf("%s.%s", sd.ServiceName, method.MethodName))
2830
desc, err := gogoproto.HybridResolver.FindDescriptorByName(methodFullName)
@@ -221,3 +223,17 @@ func RequestFullNameFromMethodDesc(sd *grpc.ServiceDesc, method grpc.MethodDesc)
221223
}
222224
return methodDesc.Input().FullName(), nil
223225
}
226+
227+
// ResponseFullNameFromMethodDesc returns the fully-qualified name of the response message of the provided service's method.
228+
func ResponseFullNameFromMethodDesc(sd *grpc.ServiceDesc, method grpc.MethodDesc) (protoreflect.FullName, error) {
229+
methodFullName := protoreflect.FullName(fmt.Sprintf("%s.%s", sd.ServiceName, method.MethodName))
230+
desc, err := gogoproto.HybridResolver.FindDescriptorByName(methodFullName)
231+
if err != nil {
232+
return "", fmt.Errorf("cannot find method descriptor %s", methodFullName)
233+
}
234+
methodDesc, ok := desc.(protoreflect.MethodDescriptor)
235+
if !ok {
236+
return "", fmt.Errorf("invalid method descriptor %s", methodFullName)
237+
}
238+
return methodDesc.Output().FullName(), nil
239+
}

baseapp/msg_service_router.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type MsgServiceRouter struct {
3131
interfaceRegistry codectypes.InterfaceRegistry
3232
routes map[string]MsgServiceHandler
3333
hybridHandlers map[string]func(ctx context.Context, req, resp protoiface.MessageV1) error
34+
responseByRequest map[string]string
3435
circuitBreaker CircuitBreaker
3536
}
3637

@@ -39,8 +40,10 @@ var _ gogogrpc.Server = &MsgServiceRouter{}
3940
// NewMsgServiceRouter creates a new MsgServiceRouter.
4041
func NewMsgServiceRouter() *MsgServiceRouter {
4142
return &MsgServiceRouter{
42-
routes: map[string]MsgServiceHandler{},
43-
hybridHandlers: map[string]func(ctx context.Context, req, resp protoiface.MessageV1) error{},
43+
routes: map[string]MsgServiceHandler{},
44+
hybridHandlers: map[string]func(ctx context.Context, req, resp protoiface.MessageV1) error{},
45+
responseByRequest: map[string]string{},
46+
circuitBreaker: nil,
4447
}
4548
}
4649

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

93+
func (msr *MsgServiceRouter) ResponseNameByRequestName(msgName string) string {
94+
return msr.responseByRequest[msgName]
95+
}
96+
9097
func (msr *MsgServiceRouter) registerHybridHandler(sd *grpc.ServiceDesc, method grpc.MethodDesc, handler interface{}) error {
9198
inputName, err := protocompat.RequestFullNameFromMethodDesc(sd, method)
9299
if err != nil {
93100
return err
94101
}
102+
outputName, err := protocompat.ResponseFullNameFromMethodDesc(sd, method)
103+
if err != nil {
104+
return err
105+
}
95106
cdc := codec.NewProtoCodec(msr.interfaceRegistry)
96107
hybridHandler, err := protocompat.MakeHybridHandler(cdc, sd, method, handler)
97108
if err != nil {
98109
return err
99110
}
111+
// map input name to output name
112+
msr.responseByRequest[string(inputName)] = string(outputName)
100113
// if circuit breaker is not nil, then we decorate the hybrid handler with the circuit breaker
101114
if msr.circuitBreaker == nil {
102115
msr.hybridHandlers[string(inputName)] = hybridHandler

proto/cosmos/accounts/interfaces/account_abstraction/v1/interface.proto

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ import "cosmos/accounts/v1/account_abstraction.proto";
88
// MsgAuthenticate is a message that an x/account account abstraction implementer
99
// must handle to authenticate a state transition.
1010
message MsgAuthenticate {
11+
// bundler defines the address of the bundler that sent the operation.
12+
// NOTE: in case the operation was sent directly by the user, this field will reflect
13+
// the user address.
14+
string bundler = 1;
1115
// user_operation is the operation that the user is trying to perform.
1216
// it also contains authentication information.
13-
cosmos.accounts.v1.UserOperation user_operation = 1;
14-
// chain_id defines the network identifier.
15-
string chain_id = 2;
16-
// account_number is the account number of the user_operation.
17-
uint64 account_number = 3;
17+
cosmos.accounts.v1.UserOperation user_operation = 2;
1818
}
1919

2020
// MsgAuthenticateResponse is the response to MsgAuthenticate.
@@ -27,9 +27,13 @@ message MsgAuthenticateResponse {}
2727
// the bundler payment messages.
2828
// The account must ensure the caller of this message is the x/accounts module itself.
2929
message MsgPayBundler {
30+
// bundler is the address of the bundler.
31+
// NOTE: in case the operation was sent directly by the user, this field will
32+
// reflect the user address.
33+
string bundler = 1;
3034
// bundler_payment_messages are the messages that the operation sender will execute.
3135
// The account can modify the messages as it sees fit.
32-
repeated google.protobuf.Any bundler_payment_messages = 1;
36+
repeated google.protobuf.Any bundler_payment_messages = 2;
3337
}
3438

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

5260
// MsgExecuteResponse is the response to MsgExecute.

proto/cosmos/accounts/v1/account_abstraction.proto

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,9 @@ message UserOperation {
1818
// authentication_data defines the authentication data associated with the authentication method.
1919
// It is the account implementer duty to assess that the UserOperation is properly signed.
2020
bytes authentication_data = 3;
21-
// sequence defines the sequence number of the account, the authentication method might require this
22-
// to ensure non-replayability.
23-
uint64 sequence = 4;
2421
// authentication_gas_limit expresses the gas limit to be used for the authentication part of the
2522
// UserOperation.
26-
uint64 authentication_gas_limit = 5;
23+
uint64 authentication_gas_limit = 4;
2724
// bundler_payment_messages expresses a list of messages that the account
2825
// executes to pay the bundler for submitting the UserOperation.
2926
// It can be empty if the bundler does not need any form of payment,
@@ -33,21 +30,22 @@ message UserOperation {
3330
// - NFT payment
3431
// - IBC Token payment.
3532
// - Payment through delegations.
36-
repeated google.protobuf.Any bundler_payment_messages = 6;
33+
repeated google.protobuf.Any bundler_payment_messages = 5;
3734
// bundler_payment_gas_limit defines the gas limit to be used for the bundler payment.
3835
// This ensures that, since the bundler executes a list of UserOperations and there needs to
3936
// be minimal trust between bundler and UserOperation sender, the sender cannot consume
4037
// the whole bundle gas.
41-
uint64 bundler_payment_gas_limit = 7;
38+
uint64 bundler_payment_gas_limit = 6;
4239
// execution_messages expresses a list of messages that the account wants to execute.
4340
// This concretely is the intent of the transaction expressed as a UserOperation.
44-
repeated google.protobuf.Any execution_messages = 8;
41+
repeated google.protobuf.Any execution_messages = 7;
4542
// execution_gas_limit defines the gas limit to be used for the execution of the UserOperation's
4643
// execution messages.
47-
uint64 execution_gas_limit = 9;
44+
uint64 execution_gas_limit = 8;
4845
}
4946

5047
// UserOperationResponse defines the response of a UserOperation.
48+
// If the operation fails the error field will be populated.
5149
message UserOperationResponse {
5250
// authentication_gas_used defines the gas used for the authentication part of the UserOperation.
5351
uint64 authentication_gas_used = 1;
@@ -60,4 +58,10 @@ message UserOperationResponse {
6058
uint64 execution_gas_used = 4;
6159
// execution_responses defines the responses of the execution messages.
6260
repeated google.protobuf.Any execution_responses = 5;
61+
// error defines the error that occurred during the execution of the UserOperation.
62+
// If the error is not empty, the UserOperation failed.
63+
// Other fields might be populated even if the error is not empty, for example
64+
// if the operation fails after the authentication step, the authentication_gas_used
65+
// field will be populated.
66+
string error = 6;
6367
}

simapp/app.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
storetypes "cosmossdk.io/store/types"
2323
"cosmossdk.io/x/accounts"
2424
"cosmossdk.io/x/accounts/accountstd"
25+
"cosmossdk.io/x/accounts/testing/account_abstraction"
2526
"cosmossdk.io/x/accounts/testing/counter"
2627
"cosmossdk.io/x/auth"
2728
"cosmossdk.io/x/auth/ante"
@@ -284,11 +285,14 @@ func NewSimApp(
284285
accountsKeeper, err := accounts.NewKeeper(
285286
runtime.NewKVStoreService(keys[accounts.StoreKey]),
286287
runtime.EventService{},
288+
runtime.BranchService{},
287289
app.AuthKeeper.AddressCodec(),
288290
appCodec.InterfaceRegistry().SigningContext(),
289291
app.MsgServiceRouter(),
290292
app.GRPCQueryRouter(),
291293
accountstd.AddAccount("counter", counter.NewAccount),
294+
accountstd.AddAccount("aa_minimal", account_abstraction.NewMinimalAbstractedAccount),
295+
accountstd.AddAccount("aa_full", account_abstraction.NewFullAbstractedAccount),
292296
)
293297
if err != nil {
294298
panic(err)

0 commit comments

Comments
 (0)