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): add interfaces and mock impls for account abstraction #18404

Merged
merged 3 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
4,299 changes: 4,299 additions & 0 deletions api/cosmos/accounts/interfaces/account_abstraction/v1/interface.pulsar.go

Large diffs are not rendered by default.

1,853 changes: 1,853 additions & 0 deletions api/cosmos/accounts/testing/rotation/v1/partial.pulsar.go

Large diffs are not rendered by default.

2,180 changes: 2,180 additions & 0 deletions api/cosmos/accounts/v1/account_abstraction.pulsar.go

Large diffs are not rendered by default.

1,314 changes: 1,253 additions & 61 deletions api/cosmos/accounts/v1/tx.pulsar.go

Large diffs are not rendered by default.

45 changes: 43 additions & 2 deletions api/cosmos/accounts/v1/tx_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
syntax = "proto3";
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is the account abstraction interface messages and query messages.


package cosmos.accounts.interfaces.account_abstraction.v1;

import "google/protobuf/any.proto";
import "cosmos/accounts/v1/account_abstraction.proto";

// MsgAuthenticate is a message that an x/account account abstraction implementer
// must handle to authenticate a state transition.
message MsgAuthenticate {
// 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;
}

// MsgAuthenticateResponse is the response to MsgAuthenticate.
// The authentication either fails or succeeds, this is why
// there are no auxiliary fields to the response.
message MsgAuthenticateResponse {}

// MsgPayBundler is a message that an x/account account abstraction implementer
// can optionally implement in case it wants to further refine control over
// the bundler payment messages.
// The account must ensure the caller of this message is the x/accounts module itself.
message MsgPayBundler {
// 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;
}

// MsgPayBundlerResponse is the response to MsgPayBundler.
message MsgPayBundlerResponse {
// bundler_payment_messages_response are the messages that the bundler will pay for.
repeated google.protobuf.Any bundler_payment_messages_response = 1;
}

// MsgExecute is a message that an x/account account abstraction implementer
// can optionally implement in case it wants to further refine control over
// the execution messages. It can be used to extend the execution flow, possibly
// block certain messages, or modify them.
// The account must ensure the caller of this message is the x/accounts module itself.
message MsgExecute {
// 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;
}

// MsgExecuteResponse is the response to MsgExecute.
message MsgExecuteResponse {
// execution_messages_response are the messages that the operation sender will execute.
repeated google.protobuf.Any execution_messages_response = 1;
}

// QueryAuthenticationMethods is a query that an x/account account abstraction implementer
// must handle to return the authentication methods that the account supports.
message QueryAuthenticationMethods {}

// QueryAuthenticationMethodsResponse is the response to QueryAuthenticationMethods.
message QueryAuthenticationMethodsResponse {
// authentication_methods are the authentication methods that the account supports.
repeated string authentication_methods = 1;
}
22 changes: 22 additions & 0 deletions proto/cosmos/accounts/testing/rotation/v1/partial.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
syntax = "proto3";
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is the proto file for a testing x/account meant to test account abstraction.

added pub key rotation to make things more spicy


package cosmos.accounts.testing.rotation.v1;

// MsgInit is the init message used to create a new account
// abstraction implementation that we use for testing, this account
// also allows for rotating the public key.
message MsgInit {
bytes pub_key_bytes = 1;
}

// MsgInitResponse is the init message response.
message MsgInitResponse {}

// MsgRotatePubKey is the message used to swap the public key
// of the account.
message MsgRotatePubKey {
bytes new_pub_key_bytes = 1;
}

// MsgRotatePubKeyResponse is the MsgRotatePubKey response.
message MsgRotatePubKeyResponse {}
63 changes: 63 additions & 0 deletions proto/cosmos/accounts/v1/account_abstraction.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
syntax = "proto3";
Copy link
Contributor Author

Choose a reason for hiding this comment

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

defines account abstraction core types used by the x/accounts module


package cosmos.accounts.v1;

option go_package = "cosmossdk.io/x/accounts/v1";

import "google/protobuf/any.proto";

// UserOperation defines the type used to define a state transition that
// an account wants to make.
message UserOperation {
// sender defines the account that is sending the UserOperation.
string sender = 1;
// authentication_method defines the authentication strategy the account wants to use.
// since accounts can have multiple authentication methods, this field is used to
// instruct the account on what auth method to use.
string authentication_method = 2;
// 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;
// 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,
// the handshake for submitting the UserOperation might have happened off-chain.
// Bundlers and accounts are free to use any form of payment, in fact the payment can
// either be empty or be expressed as:
// - NFT payment
// - IBC Token payment.
// - Payment through delegations.
repeated google.protobuf.Any bundler_payment_messages = 6;
// 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;
// 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;
// execution_gas_limit defines the gas limit to be used for the execution of the UserOperation's
// execution messages.
uint64 execution_gas_limit = 9;
}

// UserOperationResponse defines the response of a UserOperation.
message UserOperationResponse {
// authentication_gas_used defines the gas used for the authentication part of the UserOperation.
uint64 authentication_gas_used = 1;
// bundler_payment_gas_used defines the gas used for the bundler payment part of the UserOperation.
uint64 bundler_payment_gas_used = 2;
// bundler_payment_responses defines the responses of the bundler payment messages.
// It can be empty if the bundler does not need any form of payment.
repeated google.protobuf.Any bundler_payment_responses = 3;
// execution_gas_used defines the gas used for the execution part of the UserOperation.
uint64 execution_gas_used = 4;
// execution_responses defines the responses of the execution messages.
repeated google.protobuf.Any execution_responses = 5;
}
23 changes: 23 additions & 0 deletions proto/cosmos/accounts/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package cosmos.accounts.v1;
option go_package = "cosmossdk.io/x/accounts/v1";

import "cosmos/msg/v1/msg.proto";
import "cosmos/accounts/v1/account_abstraction.proto";

// Msg defines the Msg service for the x/accounts module.
service Msg {
Expand All @@ -15,6 +16,10 @@ service Msg {

// Execute executes a message to the target account.
rpc Execute(MsgExecute) returns (MsgExecuteResponse);

// ExecuteBundle pertains account abstraction, it is used by the bundler
// to execute multiple UserOperations in a single transaction message.
rpc ExecuteBundle(MsgExecuteBundle) returns (MsgExecuteBundleResponse);
}

// MsgInit defines the Create request type for the Msg/Create RPC method.
Expand Down Expand Up @@ -55,3 +60,21 @@ message MsgExecuteResponse {
// response is the response returned by the account implementation.
bytes response = 1;
}

// -------- Account Abstraction ---------
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved

// MsgExecuteBundle defines the ExecuteBundle request type for the Msg/ExecuteBundle RPC method.
message MsgExecuteBundle {
option (cosmos.msg.v1.signer) = "bundler";
// bundler defines the entity going through the standard TX flow
// to execute one or multiple UserOperations on behalf of others.
string bundler = 1;
// operations is the list of operations to be executed.
repeated UserOperation operations = 2;
}

// MsgExecuteBundleResponse defines the ExecuteBundle response type for the Msg/ExecuteBundle RPC method.
message MsgExecuteBundleResponse {
// responses is the list of responses returned by the account implementations.
repeated UserOperationResponse responses = 1;
}
7 changes: 7 additions & 0 deletions x/accounts/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package accounts
import (
"context"

"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

"cosmossdk.io/core/event"
v1 "cosmossdk.io/x/accounts/v1"
)
Expand Down Expand Up @@ -116,3 +119,7 @@ func (m msgServer) Execute(ctx context.Context, execute *v1.MsgExecute) (*v1.Msg
Response: respBytes,
}, nil
}

func (m msgServer) ExecuteBundle(ctx context.Context, req *v1.MsgExecuteBundle) (*v1.MsgExecuteBundleResponse, error) {
return nil, status.New(codes.Unimplemented, "not implemented").Err()
}
68 changes: 68 additions & 0 deletions x/accounts/testing/account_abstraction/partial_account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package account_abstraction
Copy link
Contributor Author

Choose a reason for hiding this comment

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

implements the dummy account meant to test account abstraction + pub key rotation (pub key rotation is for spiciness)


import (
"context"
"fmt"

account_abstractionv1 "cosmossdk.io/api/cosmos/accounts/interfaces/account_abstraction/v1"
rotationv1 "cosmossdk.io/api/cosmos/accounts/testing/rotation/v1"
"cosmossdk.io/api/cosmos/crypto/secp256k1"
"cosmossdk.io/collections"
"cosmossdk.io/x/accounts/accountstd"

"github.com/cosmos/cosmos-sdk/codec"
)

var (
PubKeyPrefix = collections.NewPrefix(0)
SequencePrefix = collections.NewPrefix(1)
)

var _ accountstd.Interface = (*PartialAccount)(nil)

func NewPartialAccount(d accountstd.Dependencies) (PartialAccount, error) {
return PartialAccount{
PubKey: collections.NewItem(d.SchemaBuilder, PubKeyPrefix, "pubkey", codec.CollValueV2[secp256k1.PubKey]()),
Sequence: collections.NewItem(d.SchemaBuilder, SequencePrefix, "sequence", collections.Uint64Value),
}, nil
}

// PartialAccount implements the Account interface. It also
// implements the account_abstraction interface, it only implements
// the minimum methods required to be a valid account_abstraction
// implementer.
type PartialAccount struct {
PubKey collections.Item[*secp256k1.PubKey]
Sequence collections.Item[uint64]
}

func (a PartialAccount) Init(ctx context.Context, msg *rotationv1.MsgInit) (*rotationv1.MsgInitResponse, error) {
return nil, fmt.Errorf("not implemented")
}

func (a PartialAccount) RotatePubKey(ctx context.Context, msg *rotationv1.MsgRotatePubKey) (*rotationv1.MsgRotatePubKeyResponse, error) {
return nil, fmt.Errorf("not implemented")
}

// Authenticate authenticates the account.
func (a PartialAccount) Authenticate(ctx context.Context, msg *account_abstractionv1.MsgAuthenticate) (*account_abstractionv1.MsgAuthenticateResponse, error) {
return nil, fmt.Errorf("not implemented")
}

// QueryAuthenticateMethods queries the authentication methods of the account.
func (a PartialAccount) QueryAuthenticateMethods(ctx context.Context, req *account_abstractionv1.QueryAuthenticationMethods) (*account_abstractionv1.QueryAuthenticationMethodsResponse, error) {
return nil, fmt.Errorf("not implemented")
}

func (a PartialAccount) RegisterInitHandler(builder *accountstd.InitBuilder) {
accountstd.RegisterInitHandler(builder, a.Init)
}

func (a PartialAccount) RegisterExecuteHandlers(builder *accountstd.ExecuteBuilder) {
accountstd.RegisterExecuteHandler(builder, a.RotatePubKey)
accountstd.RegisterExecuteHandler(builder, a.Authenticate) // implements account_abstraction
}

func (a PartialAccount) RegisterQueryHandlers(builder *accountstd.QueryBuilder) {
accountstd.RegisterQueryHandler(builder, a.QueryAuthenticateMethods) // implements account_abstraction
}
Loading
Loading