refactor(accounts): Remove UserOperation in favour of using Tx for abstracted accounts (#19395)
This commit is contained in:
parent
e46d526b46
commit
4a88a58e1b
@ -28,6 +28,7 @@ COPY api/go.mod api/go.sum ./api/
|
||||
COPY core/go.mod core/go.sum ./core/
|
||||
COPY collections/go.mod collections/go.sum ./collections/
|
||||
COPY store/go.mod store/go.sum ./store/
|
||||
COPY x/accounts/go.mod x/accounts/go.sum ./x/accounts/
|
||||
COPY x/tx/go.mod x/tx/go.sum /x/tx/
|
||||
COPY x/protocolpool/go.mod x/protocolpool/go.sum ./x/protocolpool/
|
||||
COPY x/gov/go.mod x/gov/go.sum ./x/gov/
|
||||
|
||||
2705
api/cosmos/accounts/defaults/base/v1/base.pulsar.go
Normal file
2705
api/cosmos/accounts/defaults/base/v1/base.pulsar.go
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -19,11 +19,10 @@ import (
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
const (
|
||||
Query_AccountQuery_FullMethodName = "/cosmos.accounts.v1.Query/AccountQuery"
|
||||
Query_Schema_FullMethodName = "/cosmos.accounts.v1.Query/Schema"
|
||||
Query_AccountType_FullMethodName = "/cosmos.accounts.v1.Query/AccountType"
|
||||
Query_AccountNumber_FullMethodName = "/cosmos.accounts.v1.Query/AccountNumber"
|
||||
Query_SimulateUserOperation_FullMethodName = "/cosmos.accounts.v1.Query/SimulateUserOperation"
|
||||
Query_AccountQuery_FullMethodName = "/cosmos.accounts.v1.Query/AccountQuery"
|
||||
Query_Schema_FullMethodName = "/cosmos.accounts.v1.Query/Schema"
|
||||
Query_AccountType_FullMethodName = "/cosmos.accounts.v1.Query/AccountType"
|
||||
Query_AccountNumber_FullMethodName = "/cosmos.accounts.v1.Query/AccountNumber"
|
||||
)
|
||||
|
||||
// QueryClient is the client API for Query service.
|
||||
@ -38,8 +37,6 @@ type QueryClient interface {
|
||||
AccountType(ctx context.Context, in *AccountTypeRequest, opts ...grpc.CallOption) (*AccountTypeResponse, error)
|
||||
// AccountNumber returns the account number given the account address.
|
||||
AccountNumber(ctx context.Context, in *AccountNumberRequest, opts ...grpc.CallOption) (*AccountNumberResponse, error)
|
||||
// SimulateUserOperation simulates a user operation.
|
||||
SimulateUserOperation(ctx context.Context, in *SimulateUserOperationRequest, opts ...grpc.CallOption) (*SimulateUserOperationResponse, error)
|
||||
}
|
||||
|
||||
type queryClient struct {
|
||||
@ -86,15 +83,6 @@ func (c *queryClient) AccountNumber(ctx context.Context, in *AccountNumberReques
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *queryClient) SimulateUserOperation(ctx context.Context, in *SimulateUserOperationRequest, opts ...grpc.CallOption) (*SimulateUserOperationResponse, error) {
|
||||
out := new(SimulateUserOperationResponse)
|
||||
err := c.cc.Invoke(ctx, Query_SimulateUserOperation_FullMethodName, in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// QueryServer is the server API for Query service.
|
||||
// All implementations must embed UnimplementedQueryServer
|
||||
// for forward compatibility
|
||||
@ -107,8 +95,6 @@ type QueryServer interface {
|
||||
AccountType(context.Context, *AccountTypeRequest) (*AccountTypeResponse, error)
|
||||
// AccountNumber returns the account number given the account address.
|
||||
AccountNumber(context.Context, *AccountNumberRequest) (*AccountNumberResponse, error)
|
||||
// SimulateUserOperation simulates a user operation.
|
||||
SimulateUserOperation(context.Context, *SimulateUserOperationRequest) (*SimulateUserOperationResponse, error)
|
||||
mustEmbedUnimplementedQueryServer()
|
||||
}
|
||||
|
||||
@ -128,9 +114,6 @@ func (UnimplementedQueryServer) AccountType(context.Context, *AccountTypeRequest
|
||||
func (UnimplementedQueryServer) AccountNumber(context.Context, *AccountNumberRequest) (*AccountNumberResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AccountNumber not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) SimulateUserOperation(context.Context, *SimulateUserOperationRequest) (*SimulateUserOperationResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SimulateUserOperation not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {}
|
||||
|
||||
// UnsafeQueryServer may be embedded to opt out of forward compatibility for this service.
|
||||
@ -216,24 +199,6 @@ func _Query_AccountNumber_Handler(srv interface{}, ctx context.Context, dec func
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Query_SimulateUserOperation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SimulateUserOperationRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(QueryServer).SimulateUserOperation(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Query_SimulateUserOperation_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(QueryServer).SimulateUserOperation(ctx, req.(*SimulateUserOperationRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Query_ServiceDesc is the grpc.ServiceDesc for Query service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@ -257,10 +222,6 @@ var Query_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "AccountNumber",
|
||||
Handler: _Query_AccountNumber_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SimulateUserOperation",
|
||||
Handler: _Query_SimulateUserOperation_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "cosmos/accounts/v1/query.proto",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -164,6 +164,8 @@ require (
|
||||
pgregory.net/rapid v1.1.0 // indirect
|
||||
)
|
||||
|
||||
require cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
|
||||
require github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
|
||||
|
||||
replace github.com/cosmos/cosmos-sdk => ./../../
|
||||
@ -171,6 +173,7 @@ replace github.com/cosmos/cosmos-sdk => ./../../
|
||||
replace (
|
||||
cosmossdk.io/core => ./../../core
|
||||
cosmossdk.io/depinject => ./../../depinject
|
||||
cosmossdk.io/x/accounts => ./../../x/accounts
|
||||
cosmossdk.io/x/auth => ./../../x/auth
|
||||
cosmossdk.io/x/bank => ./../../x/bank
|
||||
cosmossdk.io/x/distribution => ./../../x/distribution
|
||||
|
||||
@ -20,6 +20,7 @@ COPY x/auth/go.mod x/auth/go.sum /work/x/auth/
|
||||
COPY x/authz/go.mod x/authz/go.sum /work/x/authz/
|
||||
COPY x/bank/go.mod x/bank/go.sum /work/x/bank/
|
||||
COPY x/mint/go.mod x/mint/go.sum /work/x/mint/
|
||||
COPY x/accounts/go.mod x/accounts/go.sum /work/x/accounts/
|
||||
RUN go mod download
|
||||
|
||||
COPY ./ /work
|
||||
|
||||
2
go.mod
2
go.mod
@ -66,6 +66,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
|
||||
github.com/DataDog/datadog-go v4.8.3+incompatible // indirect
|
||||
@ -180,6 +181,7 @@ replace (
|
||||
cosmossdk.io/api => ./api
|
||||
cosmossdk.io/core => ./core
|
||||
cosmossdk.io/depinject => ./depinject
|
||||
cosmossdk.io/x/accounts => ./x/accounts
|
||||
cosmossdk.io/x/auth => ./x/auth
|
||||
cosmossdk.io/x/bank => ./x/bank
|
||||
cosmossdk.io/x/staking => ./x/staking
|
||||
|
||||
34
proto/cosmos/accounts/defaults/base/v1/base.proto
Normal file
34
proto/cosmos/accounts/defaults/base/v1/base.proto
Normal file
@ -0,0 +1,34 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package cosmos.accounts.defaults.base.v1;
|
||||
|
||||
option go_package = "cosmossdk.io/x/accounts/defaults/base/v1";
|
||||
|
||||
// MsgInit is used to initialize a base account.
|
||||
message MsgInit {
|
||||
// pub_key defines the secp256k1 pubkey for the account.
|
||||
bytes pub_key = 1;
|
||||
}
|
||||
|
||||
// MsgInitResponse is the response returned after base account initialization.
|
||||
// This is empty.
|
||||
message MsgInitResponse {}
|
||||
|
||||
// MsgSwapPubKey is used to change the pubkey for the account.
|
||||
message MsgSwapPubKey {
|
||||
// new_pub_key defines the secp256k1 pubkey to swap the account to.
|
||||
bytes new_pub_key = 1;
|
||||
}
|
||||
|
||||
// MsgSwapPubKeyResponse is the response for the MsgSwapPubKey message.
|
||||
// This is empty.
|
||||
message MsgSwapPubKeyResponse {}
|
||||
|
||||
// QuerySequence is the request for the account sequence.
|
||||
message QuerySequence {}
|
||||
|
||||
// QuerySequenceResponse returns the sequence of the account.
|
||||
message QuerySequenceResponse {
|
||||
// sequence is the current sequence of the account.
|
||||
uint64 sequence = 1;
|
||||
}
|
||||
@ -3,20 +3,25 @@ syntax = "proto3";
|
||||
package cosmos.accounts.interfaces.account_abstraction.v1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "cosmos/accounts/v1/account_abstraction.proto";
|
||||
import "cosmos/tx/v1beta1/tx.proto";
|
||||
|
||||
option go_package = "cosmossdk.io/x/accounts/interfaces/account_abstraction/v1";
|
||||
|
||||
// MsgAuthenticate is a message that an x/account account abstraction implementer
|
||||
// must handle to authenticate a state transition.
|
||||
// must handle to authenticate a transaction. Always ensure the caller is the Accounts module.
|
||||
message MsgAuthenticate {
|
||||
// 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;
|
||||
// user_operation is the operation that the user is trying to perform.
|
||||
// it also contains authentication information.
|
||||
cosmos.accounts.v1.UserOperation user_operation = 2;
|
||||
// raw_tx defines the raw version of the tx, this is useful to compute the signature quickly.
|
||||
cosmos.tx.v1beta1.TxRaw raw_tx = 2;
|
||||
// tx defines the decoded version of the tx, coming from raw_tx.
|
||||
cosmos.tx.v1beta1.Tx tx = 3;
|
||||
// signer_index defines the index of the signer in the tx.
|
||||
// Specifically this can be used to extract the signature at the correct
|
||||
// index.
|
||||
uint32 signer_index = 4;
|
||||
}
|
||||
|
||||
// MsgAuthenticateResponse is the response to MsgAuthenticate.
|
||||
@ -24,47 +29,6 @@ message MsgAuthenticate {
|
||||
// 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 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;
|
||||
// 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 = 2;
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// 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 = 2;
|
||||
}
|
||||
|
||||
// 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 {}
|
||||
|
||||
@ -1,86 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
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.
|
||||
google.protobuf.Any authentication_data = 3;
|
||||
// authentication_gas_limit expresses the gas limit to be used for the authentication part of the
|
||||
// UserOperation.
|
||||
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,
|
||||
// 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 = 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 = 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 = 7;
|
||||
// execution_gas_limit defines the gas limit to be used for the execution of the UserOperation's
|
||||
// execution messages.
|
||||
uint64 execution_gas_limit = 8;
|
||||
|
||||
// tx_compat is populated only when the operation is composed from a raw tx.
|
||||
// In fact if a TX comes and the sender of the TX is an abstracted account,
|
||||
// we convert the TX into a user operation, and try to authenticate using the
|
||||
// x/accounts authenticate method. If a bundler tries to send a UserOperation
|
||||
// with a populated tx_compat, the operation will immediately yield a failure.
|
||||
TxCompat tx_compat = 9;
|
||||
}
|
||||
|
||||
// TxCompat provides compatibility for x/accounts abstracted account with the cosmos-sdk's Txs.
|
||||
// In fact TxCompat contains fields coming from the Tx in raw and decoded format. The Raw format
|
||||
// is mainly needed for proper sig verification.
|
||||
message TxCompat {
|
||||
// auth_info_bytes contains the auth info bytes of the tx.
|
||||
// Must not be modified.
|
||||
bytes auth_info_bytes = 1;
|
||||
// body_bytes contains the body bytes of the tx.
|
||||
// must not be modified.
|
||||
bytes body_bytes = 2;
|
||||
}
|
||||
|
||||
// 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;
|
||||
// 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;
|
||||
// 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;
|
||||
}
|
||||
@ -5,7 +5,6 @@ package cosmos.accounts.v1;
|
||||
option go_package = "cosmossdk.io/x/accounts/v1";
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "cosmos/accounts/v1/account_abstraction.proto";
|
||||
|
||||
// Query defines the Query service for the x/accounts module.
|
||||
service Query {
|
||||
@ -17,8 +16,6 @@ service Query {
|
||||
rpc AccountType(AccountTypeRequest) returns (AccountTypeResponse) {};
|
||||
// AccountNumber returns the account number given the account address.
|
||||
rpc AccountNumber(AccountNumberRequest) returns (AccountNumberResponse) {};
|
||||
// SimulateUserOperation simulates a user operation.
|
||||
rpc SimulateUserOperation(SimulateUserOperationRequest) returns (SimulateUserOperationResponse) {};
|
||||
}
|
||||
|
||||
// AccountQueryRequest is the request type for the Query/AccountQuery RPC
|
||||
@ -84,20 +81,3 @@ message AccountNumberResponse {
|
||||
// number is the account number of the provided address.
|
||||
uint64 number = 1;
|
||||
}
|
||||
|
||||
// SimulateUserOperationRequest is the query request used to simulate a
|
||||
// UserOperation.
|
||||
message SimulateUserOperationRequest {
|
||||
// bundler can be filled to simulate the address of the bundler.
|
||||
string bundler = 1;
|
||||
// user_operation defines the user operation that we want to simulate.
|
||||
// Gas limit fields are ignored.
|
||||
UserOperation user_operation = 2;
|
||||
}
|
||||
|
||||
// SimulateUserOperationResponse is the query response returned by the simulation.
|
||||
// It will populate the gas limits fields.
|
||||
message SimulateUserOperationResponse {
|
||||
// UserOperationResponse is the response of the simulation.
|
||||
UserOperationResponse user_operation_response = 1;
|
||||
}
|
||||
@ -6,8 +6,8 @@ option go_package = "cosmossdk.io/x/accounts/v1";
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "cosmos/msg/v1/msg.proto";
|
||||
import "cosmos/accounts/v1/account_abstraction.proto";
|
||||
import "cosmos/base/v1beta1/coin.proto";
|
||||
import "cosmos/tx/v1beta1/tx.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
|
||||
// Msg defines the Msg service for the x/accounts module.
|
||||
@ -78,12 +78,18 @@ message MsgExecuteBundle {
|
||||
// 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;
|
||||
// txs defines the txs to execute on behalf of other users.
|
||||
repeated cosmos.tx.v1beta1.TxRaw txs = 2;
|
||||
}
|
||||
|
||||
// BundledTxResponse defines the response of a bundled tx.
|
||||
message BundledTxResponse {
|
||||
google.protobuf.Any exec_responses = 1;
|
||||
string error = 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;
|
||||
repeated BundledTxResponse responses = 1;
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
||||
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
|
||||
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
|
||||
ante.NewValidateSigCountDecorator(options.AccountKeeper),
|
||||
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler, options.SigGasConsumer),
|
||||
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler, options.SigGasConsumer, options.AccountAbstractionKeeper),
|
||||
}
|
||||
|
||||
return sdk.ChainAnteDecorators(anteDecorators...), nil
|
||||
|
||||
@ -22,6 +22,7 @@ import (
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
"cosmossdk.io/x/accounts"
|
||||
"cosmossdk.io/x/accounts/accountstd"
|
||||
baseaccount "cosmossdk.io/x/accounts/defaults/base"
|
||||
"cosmossdk.io/x/accounts/testing/account_abstraction"
|
||||
"cosmossdk.io/x/accounts/testing/counter"
|
||||
"cosmossdk.io/x/auth"
|
||||
@ -297,9 +298,11 @@ func NewSimApp(
|
||||
app.MsgServiceRouter(),
|
||||
app.GRPCQueryRouter(),
|
||||
appCodec.InterfaceRegistry(),
|
||||
// TESTING: do not add
|
||||
accountstd.AddAccount("counter", counter.NewAccount),
|
||||
accountstd.AddAccount("aa_minimal", account_abstraction.NewMinimalAbstractedAccount),
|
||||
accountstd.AddAccount("aa_full", account_abstraction.NewFullAbstractedAccount),
|
||||
// PRODUCTION: add
|
||||
baseaccount.NewAccount("base", txConfig.SignModeHandler()),
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -598,11 +601,12 @@ func (app *SimApp) setAnteHandler(txConfig client.TxConfig) {
|
||||
anteHandler, err := NewAnteHandler(
|
||||
HandlerOptions{
|
||||
ante.HandlerOptions{
|
||||
AccountKeeper: app.AuthKeeper,
|
||||
BankKeeper: app.BankKeeper,
|
||||
SignModeHandler: txConfig.SignModeHandler(),
|
||||
FeegrantKeeper: app.FeeGrantKeeper,
|
||||
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
|
||||
AccountAbstractionKeeper: app.AccountsKeeper,
|
||||
AccountKeeper: app.AuthKeeper,
|
||||
BankKeeper: app.BankKeeper,
|
||||
SignModeHandler: txConfig.SignModeHandler(),
|
||||
FeegrantKeeper: app.FeeGrantKeeper,
|
||||
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
|
||||
},
|
||||
&app.CircuitKeeper,
|
||||
app.UnorderedTxManager,
|
||||
|
||||
@ -7,13 +7,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/simapp"
|
||||
"cosmossdk.io/x/accounts"
|
||||
rotationv1 "cosmossdk.io/x/accounts/testing/rotation/v1"
|
||||
accountsv1 "cosmossdk.io/x/accounts/v1"
|
||||
"cosmossdk.io/x/bank/testutil"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
"cosmossdk.io/x/nft"
|
||||
stakingtypes "cosmossdk.io/x/staking/types"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
@ -28,6 +21,7 @@ var (
|
||||
aliceAddr = secp256k1.GenPrivKey().PubKey().Address()
|
||||
)
|
||||
|
||||
/*
|
||||
func TestAccountAbstraction(t *testing.T) {
|
||||
app := setupApp(t)
|
||||
ak := app.AccountsKeeper
|
||||
@ -59,316 +53,23 @@ func TestAccountAbstraction(t *testing.T) {
|
||||
aliceAddrStr, err := app.AuthKeeper.AddressCodec().BytesToString(aliceAddr)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("fail - tx compat in bundle is not allowed", func(t *testing.T) {
|
||||
resp := ak.ExecuteUserOperation(ctx, bundlerAddrStr, &accountsv1.UserOperation{
|
||||
Sender: aaAddrStr,
|
||||
AuthenticationMethod: "secp256k1",
|
||||
AuthenticationData: mockSignature,
|
||||
ExecutionMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: aaAddrStr,
|
||||
ToAddress: bundlerAddrStr,
|
||||
Amount: coins(t, "1stake"), // the sender is the AA, so it has the coins and wants to pay the bundler for the gas
|
||||
}),
|
||||
TxCompat: &accountsv1.TxCompat{},
|
||||
})
|
||||
require.Contains(t, resp.Error, accounts.ErrDisallowedTxCompatInBundle.Error())
|
||||
})
|
||||
t.Run("ok - pay bundler not implemented", func(t *testing.T) {})
|
||||
t.Run("pay bundle impersonation", func(t *testing.T) {})
|
||||
t.Run("auth failure", func(t *testing.T) {})
|
||||
t.Run("pay bundle failure", func(t *testing.T) {})
|
||||
t.Run("exec message failure", func(t *testing.T) {})
|
||||
|
||||
t.Run("ok - pay bundler and exec not implemented", func(t *testing.T) {
|
||||
// we simulate executing an user operation in an abstracted account
|
||||
// which only implements the authentication.
|
||||
resp := ak.ExecuteUserOperation(ctx, bundlerAddrStr, &accountsv1.UserOperation{
|
||||
Sender: aaAddrStr,
|
||||
AuthenticationMethod: "secp256k1",
|
||||
AuthenticationData: mockSignature,
|
||||
AuthenticationGasLimit: 10000,
|
||||
BundlerPaymentMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: aaAddrStr,
|
||||
ToAddress: bundlerAddrStr,
|
||||
Amount: coins(t, "1stake"), // the sender is the AA, so it has the coins and wants to pay the bundler for the gas
|
||||
}),
|
||||
BundlerPaymentGasLimit: 50000,
|
||||
ExecutionMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: aaAddrStr,
|
||||
ToAddress: aliceAddrStr,
|
||||
Amount: coins(t, "2000stake"), // as the real action the sender wants to send coins to alice
|
||||
}),
|
||||
ExecutionGasLimit: 38000,
|
||||
})
|
||||
require.Empty(t, resp.Error) // no error
|
||||
require.Len(t, resp.BundlerPaymentResponses, 1)
|
||||
require.Len(t, resp.ExecutionResponses, 1)
|
||||
require.NotZero(t, resp.ExecutionGasUsed)
|
||||
require.NotZero(t, resp.BundlerPaymentGasUsed)
|
||||
require.NotZero(t, resp.AuthenticationGasUsed)
|
||||
// assert there were state changes
|
||||
balanceIs(t, ctx, app, bundlerAddr.Bytes(), "1stake") // pay bundler state change
|
||||
balanceIs(t, ctx, app, aliceAddr.Bytes(), "2000stake") // execute messages state change.
|
||||
})
|
||||
t.Run("pay bundle impersonation", func(t *testing.T) {
|
||||
// we simulate the execution of an abstracted account
|
||||
// which only implements authentication and tries in the pay
|
||||
// bundler messages the account tries to impersonate another one.
|
||||
resp := ak.ExecuteUserOperation(ctx, bundlerAddrStr, &accountsv1.UserOperation{
|
||||
Sender: aaAddrStr,
|
||||
AuthenticationMethod: "secp256k1",
|
||||
AuthenticationData: mockSignature,
|
||||
AuthenticationGasLimit: 10000,
|
||||
BundlerPaymentMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: bundlerAddrStr, // abstracted account tries to send money from bundler to itself.
|
||||
ToAddress: aaAddrStr,
|
||||
Amount: coins(t, "1stake"),
|
||||
}),
|
||||
BundlerPaymentGasLimit: 50000,
|
||||
ExecutionMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: aaAddrStr,
|
||||
ToAddress: aliceAddrStr,
|
||||
Amount: coins(t, "2000stake"), // as the real action the sender wants to send coins to alice
|
||||
}),
|
||||
ExecutionGasLimit: 36000,
|
||||
})
|
||||
require.Contains(t, resp.Error, accounts.ErrUnauthorized.Error()) // error is unauthorized
|
||||
require.Empty(t, resp.BundlerPaymentResponses) // no bundler payment responses, since the atomic exec failed
|
||||
require.Empty(t, resp.ExecutionResponses) // no execution responses, since the atomic exec failed
|
||||
require.Zero(t, resp.ExecutionGasUsed) // no execution gas used, since the atomic exec failed
|
||||
require.NotZero(t, resp.BundlerPaymentGasUsed) // bundler payment gas used, even if the atomic exec failed
|
||||
})
|
||||
t.Run("exec message impersonation", func(t *testing.T) {
|
||||
// we simulate a case in which the abstracted account tries to impersonate
|
||||
// someone else in the execution of messages.
|
||||
resp := ak.ExecuteUserOperation(ctx, bundlerAddrStr, &accountsv1.UserOperation{
|
||||
Sender: aaAddrStr,
|
||||
AuthenticationMethod: "secp256k1",
|
||||
AuthenticationData: mockSignature,
|
||||
AuthenticationGasLimit: 10000,
|
||||
BundlerPaymentMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: aaAddrStr,
|
||||
ToAddress: bundlerAddrStr,
|
||||
Amount: coins(t, "1stake"),
|
||||
}),
|
||||
BundlerPaymentGasLimit: 50000,
|
||||
ExecutionMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: aliceAddrStr, // abstracted account attempts to send money from alice to itself
|
||||
ToAddress: aaAddrStr,
|
||||
Amount: coins(t, "2000stake"),
|
||||
}),
|
||||
ExecutionGasLimit: 36000,
|
||||
})
|
||||
require.Contains(t, resp.Error, accounts.ErrUnauthorized.Error()) // error is unauthorized
|
||||
require.NotEmpty(t, resp.BundlerPaymentResponses) // bundler payment responses, since the bundler payment succeeded
|
||||
require.Empty(t, resp.ExecutionResponses) // no execution responses, since the atomic exec failed
|
||||
require.NotZero(t, resp.ExecutionGasUsed) // execution gas used, even if the atomic exec failed
|
||||
require.NotZero(t, resp.BundlerPaymentGasUsed) // bundler payment gas used, even if the atomic exec failed
|
||||
})
|
||||
t.Run("auth failure", func(t *testing.T) {
|
||||
// if auth fails nothing more should be attempted, the authentication
|
||||
// should have spent gas and the error should be returned.
|
||||
// we simulate a case in which the abstracted account tries to impersonate
|
||||
// someone else in the execution of messages.
|
||||
resp := ak.ExecuteUserOperation(ctx, bundlerAddrStr, &accountsv1.UserOperation{
|
||||
Sender: aaAddrStr,
|
||||
AuthenticationMethod: "invalid",
|
||||
AuthenticationData: mockSignature,
|
||||
AuthenticationGasLimit: 10000,
|
||||
BundlerPaymentMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: aaAddrStr,
|
||||
ToAddress: bundlerAddrStr,
|
||||
Amount: coins(t, "1stake"),
|
||||
}),
|
||||
BundlerPaymentGasLimit: 50000,
|
||||
ExecutionMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: aliceAddrStr, // abstracted account attempts to send money from alice to itself
|
||||
ToAddress: aaAddrStr,
|
||||
Amount: coins(t, "2000stake"),
|
||||
}),
|
||||
ExecutionGasLimit: 36000,
|
||||
})
|
||||
require.Contains(t, resp.Error, accounts.ErrAuthentication.Error()) // error is authentication
|
||||
require.Empty(t, resp.BundlerPaymentResponses) // no bundler payment responses, since the atomic exec failed
|
||||
require.Empty(t, resp.ExecutionResponses) // no execution responses, since the atomic exec failed
|
||||
require.Zero(t, resp.ExecutionGasUsed) // no execution gas used, since the atomic exec failed
|
||||
require.Zero(t, resp.BundlerPaymentGasUsed) // no bundler payment gas used, since the atomic exec failed
|
||||
require.NotZero(t, resp.AuthenticationGasUsed) // authentication gas used, even if the atomic exec failed
|
||||
})
|
||||
t.Run("pay bundle failure", func(t *testing.T) {
|
||||
// pay bundler fails, nothing more should be attempted, the authentication
|
||||
// succeeded. We expect gas used in auth and pay bundler step.
|
||||
// we simulate a case in which the abstracted account tries to impersonate
|
||||
// someone else in the execution of messages.
|
||||
resp := ak.ExecuteUserOperation(ctx, bundlerAddrStr, &accountsv1.UserOperation{
|
||||
Sender: aaAddrStr,
|
||||
AuthenticationMethod: "secp256k1",
|
||||
AuthenticationData: mockSignature,
|
||||
AuthenticationGasLimit: 10000,
|
||||
BundlerPaymentMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: aaAddrStr,
|
||||
ToAddress: bundlerAddrStr,
|
||||
Amount: coins(t, "1atom"), // abstracted account does not have enough money to pay the bundler, since it does not hold atom
|
||||
}),
|
||||
BundlerPaymentGasLimit: 50000,
|
||||
ExecutionMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: aliceAddrStr, // abstracted account attempts to send money from alice to itself
|
||||
ToAddress: aaAddrStr,
|
||||
Amount: coins(t, "2000stake"),
|
||||
}),
|
||||
ExecutionGasLimit: 36000,
|
||||
})
|
||||
require.Contains(t, resp.Error, accounts.ErrBundlerPayment.Error()) // error is bundler payment
|
||||
require.Empty(t, resp.BundlerPaymentResponses) // no bundler payment responses, since the atomic exec failed
|
||||
require.Empty(t, resp.ExecutionResponses) // no execution responses, since the atomic exec failed
|
||||
require.Zero(t, resp.ExecutionGasUsed) // no execution gas used, since the atomic exec failed
|
||||
require.NotZero(t, resp.BundlerPaymentGasUsed) // bundler payment gas used, even if the atomic exec failed
|
||||
require.NotZero(t, resp.AuthenticationGasUsed) // authentication gas used, even if the atomic exec failed
|
||||
})
|
||||
t.Run("exec message failure", func(t *testing.T) {
|
||||
// execution message fails, nothing more should be attempted, the authentication
|
||||
// and pay bundler succeeded. We expect gas used in auth, pay bundler and
|
||||
// execution step.
|
||||
resp := ak.ExecuteUserOperation(ctx, bundlerAddrStr, &accountsv1.UserOperation{
|
||||
Sender: aaAddrStr,
|
||||
AuthenticationMethod: "secp256k1",
|
||||
AuthenticationData: mockSignature,
|
||||
AuthenticationGasLimit: 10000,
|
||||
BundlerPaymentMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: aaAddrStr,
|
||||
ToAddress: bundlerAddrStr,
|
||||
Amount: coins(t, "1stake"),
|
||||
}),
|
||||
BundlerPaymentGasLimit: 50000,
|
||||
ExecutionMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: aaAddrStr,
|
||||
ToAddress: aliceAddrStr,
|
||||
Amount: coins(t, "2000atom"), // abstracted account does not have enough money to pay alice, since it does not hold atom
|
||||
}),
|
||||
ExecutionGasLimit: 36000,
|
||||
})
|
||||
require.Contains(t, resp.Error, accounts.ErrExecution.Error()) // error is execution
|
||||
require.Len(t, resp.BundlerPaymentResponses, 1) // bundler payment response, since the pay bundler succeeded
|
||||
require.Empty(t, resp.ExecutionResponses) // no execution responses, since the atomic exec failed
|
||||
require.NotZero(t, resp.ExecutionGasUsed) // execution gas used, even if the atomic exec failed
|
||||
require.NotZero(t, resp.BundlerPaymentGasUsed) // bundler payment gas used, even if the atomic exec failed
|
||||
require.NotZero(t, resp.AuthenticationGasUsed) // authentication gas used, even if the atomic exec failed
|
||||
})
|
||||
t.Run("implements bundler payment - fail ", func(t *testing.T) {})
|
||||
|
||||
t.Run("implements bundler payment - fail ", func(t *testing.T) {
|
||||
// we assert that if an aa implements the bundler payment interface, then
|
||||
// that is called.
|
||||
resp := ak.ExecuteUserOperation(ctx, bundlerAddrStr, &accountsv1.UserOperation{
|
||||
Sender: aaFullAddrStr,
|
||||
AuthenticationMethod: "secp256k1",
|
||||
AuthenticationData: mockSignature,
|
||||
AuthenticationGasLimit: 10000,
|
||||
BundlerPaymentMessages: intoAny(t, &banktypes.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, &banktypes.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) {})
|
||||
|
||||
t.Run("implements execution - fail", func(t *testing.T) {
|
||||
resp := ak.ExecuteUserOperation(ctx, bundlerAddrStr, &accountsv1.UserOperation{
|
||||
Sender: aaFullAddrStr,
|
||||
AuthenticationMethod: "secp256k1",
|
||||
AuthenticationData: mockSignature,
|
||||
AuthenticationGasLimit: 10000,
|
||||
BundlerPaymentMessages: nil,
|
||||
BundlerPaymentGasLimit: 50000,
|
||||
ExecutionMessages: intoAny(t, &stakingtypes.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) {})
|
||||
|
||||
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))
|
||||
t.Run("Simulate - OK", func(t *testing.T) {})
|
||||
|
||||
resp := ak.ExecuteUserOperation(ctx, bundlerAddrStr, &accountsv1.UserOperation{
|
||||
Sender: aaFullAddrStr,
|
||||
AuthenticationMethod: "secp256k1",
|
||||
AuthenticationData: mockSignature,
|
||||
AuthenticationGasLimit: 10000,
|
||||
BundlerPaymentMessages: intoAny(t, &nft.MsgSend{
|
||||
ClassId: "omega-rare",
|
||||
Id: "the-most-rare",
|
||||
Sender: aaFullAddrStr,
|
||||
Receiver: bundlerAddrStr,
|
||||
}),
|
||||
BundlerPaymentGasLimit: 50000,
|
||||
ExecutionMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: aaFullAddrStr,
|
||||
ToAddress: aliceAddrStr,
|
||||
Amount: coins(t, "2000stake"),
|
||||
}),
|
||||
ExecutionGasLimit: 38000,
|
||||
})
|
||||
require.Empty(t, resp.Error) // no error
|
||||
})
|
||||
|
||||
t.Run("Simulate - OK", func(t *testing.T) {
|
||||
queryServer := accounts.NewQueryServer(ak)
|
||||
|
||||
// gas in unspecified
|
||||
op := &accountsv1.UserOperation{
|
||||
Sender: aaAddrStr,
|
||||
AuthenticationMethod: "secp256k1",
|
||||
AuthenticationData: mockSignature,
|
||||
BundlerPaymentMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: aaAddrStr,
|
||||
ToAddress: bundlerAddrStr,
|
||||
Amount: coins(t, "1stake"),
|
||||
}),
|
||||
ExecutionMessages: intoAny(t, &banktypes.MsgSend{
|
||||
FromAddress: aaAddrStr,
|
||||
ToAddress: aliceAddrStr,
|
||||
Amount: coins(t, "2000stake"),
|
||||
}),
|
||||
}
|
||||
queryResp, err := queryServer.SimulateUserOperation(ctx, &accountsv1.SimulateUserOperationRequest{
|
||||
Bundler: bundlerAddrStr,
|
||||
UserOperation: op,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
resp := queryResp.UserOperationResponse
|
||||
require.Empty(t, resp.Error) // no error
|
||||
require.Len(t, resp.BundlerPaymentResponses, 1)
|
||||
require.Len(t, resp.ExecutionResponses, 1)
|
||||
// assess gas is filled
|
||||
require.NotZero(t, resp.ExecutionGasUsed)
|
||||
require.NotZero(t, resp.BundlerPaymentGasUsed)
|
||||
require.NotZero(t, resp.AuthenticationGasUsed)
|
||||
})
|
||||
|
||||
t.Run("Simulate - Fail empty user operation", func(t *testing.T) {
|
||||
queryServer := accounts.NewQueryServer(ak)
|
||||
_, err := queryServer.SimulateUserOperation(ctx, &accountsv1.SimulateUserOperationRequest{})
|
||||
require.Error(t, err)
|
||||
})
|
||||
t.Run("Simulate - Fail empty user operation", func(t *testing.T) {})
|
||||
}
|
||||
*/
|
||||
|
||||
func intoAny(t *testing.T, msgs ...gogoproto.Message) (anys []*codectypes.Any) {
|
||||
t.Helper()
|
||||
|
||||
84
tests/e2e/accounts/base_account_test.go
Normal file
84
tests/e2e/accounts/base_account_test.go
Normal file
@ -0,0 +1,84 @@
|
||||
//go:build app_v1
|
||||
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/simapp"
|
||||
baseaccountv1 "cosmossdk.io/x/accounts/defaults/base/v1"
|
||||
"cosmossdk.io/x/bank/testutil"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestBaseAccount(t *testing.T) {
|
||||
app := setupApp(t)
|
||||
ak := app.AccountsKeeper
|
||||
ctx := sdk.NewContext(app.CommitMultiStore(), false, app.Logger())
|
||||
|
||||
_, baseAccountAddr, err := ak.Init(ctx, "base", accCreator, &baseaccountv1.MsgInit{
|
||||
PubKey: privKey.PubKey().Bytes(),
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// fund base account! this will also cause an auth base account to be created
|
||||
// by the bank module.
|
||||
// TODO: fixed by letting x/auth rely on x/accounts for acc existence checks.
|
||||
fundAccount(t, app, ctx, baseAccountAddr, "1000000stake")
|
||||
|
||||
// now we make the account send a tx, public key not present.
|
||||
// so we know it will default to x/accounts calling.
|
||||
msg := &banktypes.MsgSend{
|
||||
FromAddress: bechify(t, app, baseAccountAddr),
|
||||
ToAddress: bechify(t, app, []byte("random-addr")),
|
||||
Amount: coins(t, "100stake"),
|
||||
}
|
||||
sendTx(t, ctx, app, baseAccountAddr, msg)
|
||||
}
|
||||
|
||||
func sendTx(t *testing.T, ctx sdk.Context, app *simapp.SimApp, sender []byte, msg sdk.Msg) {
|
||||
tx := sign(t, ctx, app, sender, privKey, msg)
|
||||
res, _, err := app.SimDeliver(app.TxEncode, tx)
|
||||
require.NoError(t, err)
|
||||
t.Log(res)
|
||||
}
|
||||
|
||||
func sign(t *testing.T, ctx sdk.Context, app *simapp.SimApp, from sdk.AccAddress, privKey cryptotypes.PrivKey, msg sdk.Msg) sdk.Tx {
|
||||
r := rand.New(rand.NewSource(0))
|
||||
|
||||
accNum, err := app.AccountsKeeper.AccountByNumber.Get(ctx, from)
|
||||
require.NoError(t, err)
|
||||
accSeq, err := app.AccountsKeeper.Query(ctx, from, &baseaccountv1.QuerySequence{})
|
||||
require.NoError(t, err)
|
||||
|
||||
tx, err := sims.GenSignedMockTx(
|
||||
r,
|
||||
app.TxConfig(),
|
||||
[]sdk.Msg{msg},
|
||||
coins(t, "100stake"),
|
||||
1_000_000,
|
||||
app.ChainID(),
|
||||
[]uint64{accNum},
|
||||
[]uint64{accSeq.(*baseaccountv1.QuerySequenceResponse).Sequence},
|
||||
privKey,
|
||||
)
|
||||
|
||||
require.NoError(t, err)
|
||||
return tx
|
||||
}
|
||||
|
||||
func bechify(t *testing.T, app *simapp.SimApp, addr []byte) string {
|
||||
bech32, err := app.AuthKeeper.AddressCodec().BytesToString(addr)
|
||||
require.NoError(t, err)
|
||||
return bech32
|
||||
}
|
||||
|
||||
func fundAccount(t *testing.T, app *simapp.SimApp, ctx sdk.Context, addr sdk.AccAddress, amt string) {
|
||||
require.NoError(t, testutil.FundAccount(ctx, app.BankKeeper, addr, coins(t, amt)))
|
||||
|
||||
}
|
||||
@ -73,6 +73,14 @@ func Sender(ctx context.Context) []byte {
|
||||
return implementation.Sender(ctx)
|
||||
}
|
||||
|
||||
// HasSender checks if the execution context was sent from the provided sender
|
||||
func HasSender(ctx context.Context, wantSender []byte) bool {
|
||||
return bytes.Equal(Sender(ctx), wantSender)
|
||||
}
|
||||
|
||||
// SenderIsSelf checks if the sender of the request is the account itself.
|
||||
func SenderIsSelf(ctx context.Context) bool { return HasSender(ctx, Whoami(ctx)) }
|
||||
|
||||
// SenderIsAccountsModule returns true if the sender of the execution request is the accounts module.
|
||||
func SenderIsAccountsModule(ctx context.Context) bool {
|
||||
return bytes.Equal(Sender(ctx), accountsModuleAddress)
|
||||
|
||||
@ -11,6 +11,16 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// coinsTransferMsgFunc defines a function that creates a message to send coins from one
|
||||
// address to the other, and also a message that parses such response.
|
||||
// This in most cases will be implemented as a bank.MsgSend creator, but we keep x/accounts independent of bank.
|
||||
type coinsTransferMsgFunc = func(from, to []byte, coins sdk.Coins) (implementation.ProtoMsg, implementation.ProtoMsg, error)
|
||||
|
||||
type gogoProtoPlusV2 interface {
|
||||
proto.Message
|
||||
implementation.ProtoMsg
|
||||
}
|
||||
|
||||
// protoV2GogoWrapper is a wrapper of a protov2 message into a gogo message.
|
||||
// this is exceptionally allowed to enable accounts to be decoupled from
|
||||
// the SDK, since x/accounts can support only protov1 in its APIs.
|
||||
|
||||
216
x/accounts/defaults/base/account.go
Normal file
216
x/accounts/defaults/base/account.go
Normal file
@ -0,0 +1,216 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
dcrd_secp256k1 "github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
|
||||
signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1"
|
||||
txv1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1"
|
||||
"cosmossdk.io/collections"
|
||||
"cosmossdk.io/core/address"
|
||||
"cosmossdk.io/core/header"
|
||||
"cosmossdk.io/x/accounts/accountstd"
|
||||
v1 "cosmossdk.io/x/accounts/defaults/base/v1"
|
||||
aa_interface_v1 "cosmossdk.io/x/accounts/interfaces/account_abstraction/v1"
|
||||
accountsv1 "cosmossdk.io/x/accounts/v1"
|
||||
"cosmossdk.io/x/tx/signing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||
)
|
||||
|
||||
var (
|
||||
PubKeyPrefix = collections.NewPrefix(0)
|
||||
SequencePrefix = collections.NewPrefix(1)
|
||||
)
|
||||
|
||||
func NewAccount(name string, handlerMap *signing.HandlerMap) accountstd.AccountCreatorFunc {
|
||||
return func(deps accountstd.Dependencies) (string, accountstd.Interface, error) {
|
||||
return name, Account{
|
||||
PubKey: collections.NewItem(deps.SchemaBuilder, PubKeyPrefix, "pub_key", codec.CollValue[secp256k1.PubKey](deps.LegacyStateCodec)),
|
||||
Sequence: collections.NewSequence(deps.SchemaBuilder, SequencePrefix, "sequence"),
|
||||
addrCodec: deps.AddressCodec,
|
||||
hs: deps.HeaderService,
|
||||
signingHandlers: handlerMap,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Account implements a base account.
|
||||
type Account struct {
|
||||
PubKey collections.Item[secp256k1.PubKey]
|
||||
Sequence collections.Sequence
|
||||
|
||||
addrCodec address.Codec
|
||||
hs header.Service
|
||||
|
||||
signingHandlers *signing.HandlerMap
|
||||
}
|
||||
|
||||
func (a Account) Init(ctx context.Context, msg *v1.MsgInit) (*v1.MsgInitResponse, error) {
|
||||
return &v1.MsgInitResponse{}, a.verifyAndSetPubKey(ctx, msg.PubKey)
|
||||
}
|
||||
|
||||
func (a Account) SwapPubKey(ctx context.Context, msg *v1.MsgSwapPubKey) (*v1.MsgSwapPubKeyResponse, error) {
|
||||
if !accountstd.SenderIsSelf(ctx) {
|
||||
return nil, fmt.Errorf("unauthorized")
|
||||
}
|
||||
|
||||
return &v1.MsgSwapPubKeyResponse{}, a.verifyAndSetPubKey(ctx, msg.NewPubKey)
|
||||
}
|
||||
|
||||
func (a Account) verifyAndSetPubKey(ctx context.Context, key []byte) error {
|
||||
_, err := dcrd_secp256k1.ParsePubKey(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return a.PubKey.Set(ctx, secp256k1.PubKey{Key: key})
|
||||
}
|
||||
|
||||
// Authenticate implements the authentication flow of an abstracted base account.
|
||||
func (a Account) Authenticate(ctx context.Context, msg *aa_interface_v1.MsgAuthenticate) (*aa_interface_v1.MsgAuthenticateResponse, error) {
|
||||
if !accountstd.SenderIsAccountsModule(ctx) {
|
||||
return nil, fmt.Errorf("unauthorized: only accounts module is allowed to call this")
|
||||
}
|
||||
|
||||
pubKey, signerData, err := a.computeSignerData(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txData, err := a.getTxData(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gotSeq := msg.Tx.AuthInfo.SignerInfos[msg.SignerIndex].Sequence
|
||||
if gotSeq != signerData.Sequence {
|
||||
return nil, fmt.Errorf("unexpected sequence number, wanted: %d, got: %d", signerData.Sequence, gotSeq)
|
||||
}
|
||||
|
||||
signMode, err := parseSignMode(msg.Tx.AuthInfo.SignerInfos[msg.SignerIndex].ModeInfo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse sign mode: %w", err)
|
||||
}
|
||||
|
||||
signature := msg.Tx.Signatures[msg.SignerIndex]
|
||||
|
||||
signBytes, err := a.signingHandlers.GetSignBytes(ctx, signMode, signerData, txData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !pubKey.VerifySignature(signBytes, signature) {
|
||||
return nil, fmt.Errorf("signature verification failed")
|
||||
}
|
||||
|
||||
return &aa_interface_v1.MsgAuthenticateResponse{}, nil
|
||||
}
|
||||
|
||||
func parseSignMode(info *tx.ModeInfo) (signingv1beta1.SignMode, error) {
|
||||
single, ok := info.Sum.(*tx.ModeInfo_Single_)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("only sign mode single accepted got: %v", info.Sum)
|
||||
}
|
||||
return signingv1beta1.SignMode(single.Single.Mode), nil
|
||||
}
|
||||
|
||||
// computeSignerData will populate signer data and also increase the sequence.
|
||||
func (a Account) computeSignerData(ctx context.Context) (secp256k1.PubKey, signing.SignerData, error) {
|
||||
addrStr, err := a.addrCodec.BytesToString(accountstd.Whoami(ctx))
|
||||
if err != nil {
|
||||
return secp256k1.PubKey{}, signing.SignerData{}, err
|
||||
}
|
||||
chainID := a.hs.GetHeaderInfo(ctx).ChainID
|
||||
|
||||
wantSequence, err := a.Sequence.Next(ctx)
|
||||
if err != nil {
|
||||
return secp256k1.PubKey{}, signing.SignerData{}, err
|
||||
}
|
||||
|
||||
pk, err := a.PubKey.Get(ctx)
|
||||
if err != nil {
|
||||
return secp256k1.PubKey{}, signing.SignerData{}, err
|
||||
}
|
||||
|
||||
pkAny, err := codectypes.NewAnyWithValue(&pk)
|
||||
if err != nil {
|
||||
return secp256k1.PubKey{}, signing.SignerData{}, err
|
||||
}
|
||||
|
||||
accNum, err := a.getNumber(ctx, addrStr)
|
||||
if err != nil {
|
||||
return secp256k1.PubKey{}, signing.SignerData{}, err
|
||||
}
|
||||
|
||||
return pk, signing.SignerData{
|
||||
Address: addrStr,
|
||||
ChainID: chainID,
|
||||
AccountNumber: accNum,
|
||||
Sequence: wantSequence,
|
||||
PubKey: &anypb.Any{
|
||||
TypeUrl: pkAny.TypeUrl,
|
||||
Value: pkAny.Value,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a Account) getNumber(ctx context.Context, addrStr string) (uint64, error) {
|
||||
accNum, err := accountstd.QueryModule[accountsv1.AccountNumberResponse](ctx, &accountsv1.AccountNumberRequest{Address: addrStr})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return accNum.Number, nil
|
||||
}
|
||||
|
||||
func (a Account) getTxData(msg *aa_interface_v1.MsgAuthenticate) (signing.TxData, error) {
|
||||
// TODO: add a faster way to do this, we can avoid unmarshalling but we need
|
||||
// to write a function that converts this into the protov2 counterparty.
|
||||
txBody := new(txv1beta1.TxBody)
|
||||
err := proto.Unmarshal(msg.RawTx.BodyBytes, txBody)
|
||||
if err != nil {
|
||||
return signing.TxData{}, err
|
||||
}
|
||||
|
||||
authInfo := new(txv1beta1.AuthInfo)
|
||||
err = proto.Unmarshal(msg.RawTx.AuthInfoBytes, authInfo)
|
||||
if err != nil {
|
||||
return signing.TxData{}, err
|
||||
}
|
||||
|
||||
return signing.TxData{
|
||||
Body: txBody,
|
||||
AuthInfo: authInfo,
|
||||
BodyBytes: msg.RawTx.BodyBytes,
|
||||
AuthInfoBytes: msg.RawTx.AuthInfoBytes,
|
||||
BodyHasUnknownNonCriticals: false, // NOTE: amino signing must be disabled.
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a Account) QuerySequence(ctx context.Context, _ *v1.QuerySequence) (*v1.QuerySequenceResponse, error) {
|
||||
seq, err := a.Sequence.Peek(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &v1.QuerySequenceResponse{Sequence: seq}, nil
|
||||
}
|
||||
|
||||
func (a Account) RegisterInitHandler(builder *accountstd.InitBuilder) {
|
||||
accountstd.RegisterInitHandler(builder, a.Init)
|
||||
}
|
||||
|
||||
func (a Account) RegisterExecuteHandlers(builder *accountstd.ExecuteBuilder) {
|
||||
accountstd.RegisterExecuteHandler(builder, a.SwapPubKey)
|
||||
accountstd.RegisterExecuteHandler(builder, a.Authenticate) // account abstraction
|
||||
}
|
||||
|
||||
func (a Account) RegisterQueryHandlers(builder *accountstd.QueryBuilder) {
|
||||
accountstd.RegisterQueryHandler(builder, a.QuerySequence)
|
||||
}
|
||||
1018
x/accounts/defaults/base/v1/base.pb.go
Normal file
1018
x/accounts/defaults/base/v1/base.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,8 +7,10 @@ require (
|
||||
cosmossdk.io/collections v0.4.0
|
||||
cosmossdk.io/core v0.12.1-0.20231114100755-569e3ff6a0d7
|
||||
cosmossdk.io/depinject v1.0.0-alpha.4
|
||||
cosmossdk.io/x/tx v0.13.0
|
||||
github.com/cosmos/cosmos-sdk v0.51.0
|
||||
github.com/cosmos/gogoproto v1.4.11
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
@ -23,7 +25,6 @@ require (
|
||||
cosmossdk.io/math v1.2.0 // indirect
|
||||
cosmossdk.io/store v1.0.2 // indirect
|
||||
cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/tx v0.13.0 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
|
||||
github.com/99designs/keyring v1.2.2 // indirect
|
||||
@ -53,7 +54,6 @@ require (
|
||||
github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect
|
||||
github.com/danieljoos/wincred v1.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.1 // indirect
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -40,11 +40,6 @@ var (
|
||||
AccountByNumber = collections.NewPrefix(2)
|
||||
)
|
||||
|
||||
// coinsTransferMsgFunc defines a function that creates a message to send coins from one
|
||||
// address to the other, and also a message that parses such response.
|
||||
// This in most cases will be implemented as a bank.MsgSend creator, but we keep x/accounts independent of bank.
|
||||
type coinsTransferMsgFunc = func(from, to []byte, coins sdk.Coins) (implementation.ProtoMsg, implementation.ProtoMsg, error)
|
||||
|
||||
// QueryRouter represents a router which can be used to route queries to the correct module.
|
||||
// It returns the handler given the message name, if multiple handlers are returned, then
|
||||
// it is up to the caller to choose which one to call.
|
||||
@ -150,44 +145,75 @@ func (k Keeper) Init(
|
||||
initRequest implementation.ProtoMsg,
|
||||
funds sdk.Coins,
|
||||
) (implementation.ProtoMsg, []byte, error) {
|
||||
impl, err := k.getImplementation(accountType)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// get the next account number
|
||||
num, err := k.AccountNumber.Next(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// make a new account address
|
||||
// create address
|
||||
accountAddr, err := k.makeAddress(num)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// send funds, if provided
|
||||
err = k.maybeSendFunds(ctx, creator, accountAddr, funds)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to transfer funds: %w", err)
|
||||
}
|
||||
// make the context and init the account
|
||||
ctx = k.makeAccountContext(ctx, num, accountAddr, creator, funds, false)
|
||||
resp, err := impl.Init(ctx, initRequest)
|
||||
initResp, err := k.init(ctx, accountType, creator, num, accountAddr, initRequest, funds)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return initResp, accountAddr, nil
|
||||
}
|
||||
|
||||
// init initializes the account, given the type, the creator the newly created account number, its address and the
|
||||
// initialization message.
|
||||
func (k Keeper) init(
|
||||
ctx context.Context,
|
||||
accountType string,
|
||||
creator []byte,
|
||||
accountNum uint64,
|
||||
accountAddr []byte,
|
||||
initRequest implementation.ProtoMsg,
|
||||
funds sdk.Coins,
|
||||
) (implementation.ProtoMsg, error) {
|
||||
impl, ok := k.accounts[accountType]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%w: not found %s", errAccountTypeNotFound, accountType)
|
||||
}
|
||||
|
||||
// send funds, if provided
|
||||
err := k.maybeSendFunds(ctx, creator, accountAddr, funds)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to transfer funds: %w", err)
|
||||
}
|
||||
// make the context and init the account
|
||||
ctx = k.makeAccountContext(ctx, accountNum, accountAddr, creator, funds, false)
|
||||
resp, err := impl.Init(ctx, initRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// map account address to account type
|
||||
if err := k.AccountsByType.Set(ctx, accountAddr, accountType); err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
// map account number to account address
|
||||
if err := k.AccountByNumber.Set(ctx, accountAddr, num); err != nil {
|
||||
return nil, nil, err
|
||||
if err := k.AccountByNumber.Set(ctx, accountAddr, accountNum); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, accountAddr, nil
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// MigrateLegacyAccount is used to migrate a legacy account to x/accounts.
|
||||
// Concretely speaking this works like Init, but with a custom account number provided,
|
||||
// Where the creator is the account itself. This can be used by the x/auth module to
|
||||
// gradually migrate base accounts to x/accounts.
|
||||
// NOTE: this assumes the calling module checks for account overrides.
|
||||
func (k Keeper) MigrateLegacyAccount(
|
||||
ctx context.Context,
|
||||
addr []byte, // The current address of the account
|
||||
accNum uint64, // The current account number
|
||||
accType string, // The account type to migrate to
|
||||
msg implementation.ProtoMsg, // The init msg of the account type we're migrating to
|
||||
) (implementation.ProtoMsg, error) {
|
||||
return k.init(ctx, accType, addr, accNum, addr, msg, nil)
|
||||
}
|
||||
|
||||
// Execute executes a state transition on the given account.
|
||||
@ -198,14 +224,8 @@ func (k Keeper) Execute(
|
||||
execRequest implementation.ProtoMsg,
|
||||
funds sdk.Coins,
|
||||
) (implementation.ProtoMsg, error) {
|
||||
// get account type
|
||||
accountType, err := k.AccountsByType.Get(ctx, accountAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// get account implementation
|
||||
impl, err := k.getImplementation(accountType)
|
||||
impl, err := k.getImplementation(ctx, accountAddr)
|
||||
if err != nil {
|
||||
// this means the account was initialized with an implementation
|
||||
// that the chain does not know about, in theory should never happen,
|
||||
@ -235,14 +255,8 @@ func (k Keeper) Query(
|
||||
accountAddr []byte,
|
||||
queryRequest implementation.ProtoMsg,
|
||||
) (implementation.ProtoMsg, error) {
|
||||
// get account type
|
||||
accountType, err := k.AccountsByType.Get(ctx, accountAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// get account implementation
|
||||
impl, err := k.getImplementation(accountType)
|
||||
impl, err := k.getImplementation(ctx, accountAddr)
|
||||
if err != nil {
|
||||
// this means the account was initialized with an implementation
|
||||
// that the chain does not know about, in theory should never happen,
|
||||
@ -260,7 +274,11 @@ func (k Keeper) Query(
|
||||
return impl.Query(ctx, queryRequest)
|
||||
}
|
||||
|
||||
func (k Keeper) getImplementation(accountType string) (implementation.Implementation, error) {
|
||||
func (k Keeper) getImplementation(ctx context.Context, addr []byte) (implementation.Implementation, error) {
|
||||
accountType, err := k.AccountsByType.Get(ctx, addr)
|
||||
if err != nil {
|
||||
return implementation.Implementation{}, err
|
||||
}
|
||||
impl, ok := k.accounts[accountType]
|
||||
if !ok {
|
||||
return implementation.Implementation{}, fmt.Errorf("%w: %s", errAccountTypeNotFound, accountType)
|
||||
@ -312,6 +330,7 @@ func (k Keeper) makeAccountContext(ctx context.Context, accountNumber uint64, ac
|
||||
|
||||
// sendAnyMessages it a helper function that executes untyped codectypes.Any messages
|
||||
// The messages must all belong to a module.
|
||||
// nolint: unused // TODO: remove nolint when we bring back bundler payments
|
||||
func (k Keeper) sendAnyMessages(ctx context.Context, sender []byte, anyMessages []*implementation.Any) ([]*implementation.Any, error) {
|
||||
anyResponses := make([]*implementation.Any, len(anyMessages))
|
||||
for i := range anyMessages {
|
||||
@ -408,11 +427,6 @@ func (k Keeper) maybeSendFunds(ctx context.Context, from, to []byte, amt sdk.Coi
|
||||
return nil
|
||||
}
|
||||
|
||||
type gogoProtoPlusV2 interface {
|
||||
proto.Message
|
||||
implementation.ProtoMsg
|
||||
}
|
||||
|
||||
const msgInterfaceName = "cosmos.accounts.v1.MsgInterface"
|
||||
|
||||
// creates a new interface type which is an alias of the proto message interface to avoid conflicts with sdk.Msg
|
||||
|
||||
@ -5,9 +5,10 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
account_abstractionv1 "cosmossdk.io/x/accounts/interfaces/account_abstraction/v1"
|
||||
"cosmossdk.io/x/accounts/internal/implementation"
|
||||
v1 "cosmossdk.io/x/accounts/v1"
|
||||
"cosmossdk.io/collections"
|
||||
aa_interface_v1 "cosmossdk.io/x/accounts/interfaces/account_abstraction/v1"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types/address"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -17,228 +18,29 @@ var (
|
||||
ErrBundlerPayment = errors.New("bundler payment failed")
|
||||
// ErrExecution is returned when the execution fails.
|
||||
ErrExecution = errors.New("execution failed")
|
||||
// ErrDisallowedTxCompatInBundle is returned when the tx compat
|
||||
// is populated in a bundle.
|
||||
ErrDisallowedTxCompatInBundle = errors.New("tx compat field populated in bundle")
|
||||
)
|
||||
|
||||
// ExecuteUserOperation handles the execution of an abstracted account UserOperation.
|
||||
func (k Keeper) ExecuteUserOperation(
|
||||
ctx context.Context,
|
||||
bundler string,
|
||||
op *v1.UserOperation,
|
||||
) *v1.UserOperationResponse {
|
||||
// TxCompat field must not be allowed in a UserOperation sent from a bundle.
|
||||
// Only the runtime can populate this field when an abstracted account sends
|
||||
// a tx (not from a bundle) and this is converted into a UserOperation.
|
||||
if op.TxCompat != nil {
|
||||
return &v1.UserOperationResponse{Error: ErrDisallowedTxCompatInBundle.Error()}
|
||||
}
|
||||
|
||||
resp := &v1.UserOperationResponse{}
|
||||
|
||||
// authenticate
|
||||
authGas, err := k.Authenticate(ctx, bundler, op)
|
||||
resp.AuthenticationGasUsed = authGas
|
||||
if err != nil {
|
||||
resp.Error = err.Error()
|
||||
return resp
|
||||
}
|
||||
resp.AuthenticationGasUsed = authGas
|
||||
|
||||
// pay bundler
|
||||
bundlerPayGas, bundlerPayResp, err := k.PayBundler(ctx, bundler, op)
|
||||
resp.BundlerPaymentGasUsed = bundlerPayGas
|
||||
if err != nil {
|
||||
resp.Error = err.Error()
|
||||
return resp
|
||||
}
|
||||
resp.BundlerPaymentResponses = bundlerPayResp
|
||||
|
||||
// execute messages, the real operation intent
|
||||
executeGas, executeResp, err := k.OpExecuteMessages(ctx, bundler, op)
|
||||
resp.ExecutionGasUsed = executeGas
|
||||
if err != nil {
|
||||
resp.Error = err.Error()
|
||||
return resp
|
||||
}
|
||||
resp.ExecutionResponses = executeResp
|
||||
|
||||
// done!
|
||||
return resp
|
||||
}
|
||||
|
||||
// Authenticate handles the authentication flow of an abstracted account.
|
||||
// Authentication happens in an isolated context with the authentication gas limit.
|
||||
// If the authentication is successful, then the state is committed.
|
||||
func (k Keeper) Authenticate(
|
||||
ctx context.Context,
|
||||
bundler string,
|
||||
op *v1.UserOperation,
|
||||
) (gasUsed uint64, err error) {
|
||||
// authenticate
|
||||
gasUsed, err = k.branchExecutor.ExecuteWithGasLimit(ctx, op.AuthenticationGasLimit, func(ctx context.Context) error {
|
||||
return k.authenticate(ctx, bundler, op)
|
||||
})
|
||||
if err != nil {
|
||||
return gasUsed, fmt.Errorf("%v: %w", ErrAuthentication, err)
|
||||
}
|
||||
return gasUsed, nil
|
||||
}
|
||||
|
||||
// authenticate handles the authentication flow of an abstracted account.
|
||||
func (k Keeper) authenticate(
|
||||
ctx context.Context,
|
||||
bundler string,
|
||||
op *v1.UserOperation,
|
||||
) error {
|
||||
senderAddr, err := k.addressCodec.StringToBytes(op.Sender)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// create an isolated context in which we execute authentication
|
||||
// without affecting the parent context and with the authentication gas limit.
|
||||
_, err = k.Execute(ctx, senderAddr, ModuleAccountAddress, &account_abstractionv1.MsgAuthenticate{
|
||||
Bundler: bundler,
|
||||
UserOperation: op,
|
||||
}, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// OpExecuteMessages handles the execution of the messages in a given v1.UserOperation.
|
||||
// It executes in an isolated branch, in an atomic way, if all the messages pass then
|
||||
// the execution is deemed successful and the state is committed.
|
||||
// An account abstraction implementer can choose to handle execution messages or not,
|
||||
// if it does not expose the execution messages method, then this method will simply
|
||||
// execute the provided messages on behalf of the sender and return.
|
||||
func (k Keeper) OpExecuteMessages(
|
||||
ctx context.Context,
|
||||
bundler string,
|
||||
op *v1.UserOperation,
|
||||
) (gasUsed uint64, responses []*implementation.Any, err error) {
|
||||
// execute messages, the real operation intent
|
||||
gasUsed, err = k.branchExecutor.ExecuteWithGasLimit(ctx, op.ExecutionGasLimit, func(ctx context.Context) error {
|
||||
responses, err = k.opExecuteMessages(ctx, bundler, op)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return gasUsed, nil, fmt.Errorf("%v: %w", ErrExecution, err)
|
||||
}
|
||||
return gasUsed, responses, nil
|
||||
}
|
||||
|
||||
func (k Keeper) opExecuteMessages(
|
||||
ctx context.Context,
|
||||
bundler string,
|
||||
op *v1.UserOperation,
|
||||
) (messagesResponse []*implementation.Any, err error) {
|
||||
senderAddr, err := k.addressCodec.StringToBytes(op.Sender)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := k.Execute(ctx, senderAddr, ModuleAccountAddress, &account_abstractionv1.MsgExecute{
|
||||
Bundler: bundler,
|
||||
ExecutionMessages: op.ExecutionMessages,
|
||||
}, nil)
|
||||
// here is where we check if the account handles execution messages
|
||||
// if it does not, then we simply execute the provided messages on behalf of the sender
|
||||
// IsAbstractedAccount returns if the provided address is an abstracted account or not.
|
||||
func (k Keeper) IsAbstractedAccount(ctx context.Context, addr []byte) (bool, error) {
|
||||
accType, err := k.AccountsByType.Get(ctx, addr)
|
||||
switch {
|
||||
case err == nil:
|
||||
// all is ok, so parse responses.
|
||||
executeResp, err := parseExecuteResponse(resp)
|
||||
return executeResp, err
|
||||
case implementation.IsRoutingError(err):
|
||||
// if it is a routing error, it means the account does not handle execution messages,
|
||||
// in this case we attempt to execute the provided messages on behalf of the op sender.
|
||||
return k.sendAnyMessages(ctx, senderAddr, op.ExecutionMessages)
|
||||
default:
|
||||
// some other error
|
||||
return nil, err
|
||||
case errors.Is(err, collections.ErrNotFound):
|
||||
return false, nil
|
||||
case err != nil:
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
// PayBundler handles the payment of the bundler in a given v1.UserOperation.
|
||||
// Must be called after Authenticate.
|
||||
// It gets executed in an isolated context with the bundler payment gas limit.
|
||||
// If the payment is successful, then the state is committed.
|
||||
// Since for an abstracted account the bundler payment method is optional,
|
||||
// if the account does not handle bundler payment messages, then this method
|
||||
// will simply execute the provided messages on behalf of the sender and return.
|
||||
func (k Keeper) PayBundler(
|
||||
ctx context.Context,
|
||||
bundler string,
|
||||
op *v1.UserOperation,
|
||||
) (gasUsed uint64, responses []*implementation.Any, err error) {
|
||||
// pay bundler
|
||||
gasUsed, err = k.branchExecutor.ExecuteWithGasLimit(ctx, op.BundlerPaymentGasLimit, func(ctx context.Context) error {
|
||||
responses, err = k.payBundler(ctx, bundler, op)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return gasUsed, nil, fmt.Errorf("%v: %w", ErrBundlerPayment, err)
|
||||
}
|
||||
return gasUsed, responses, nil
|
||||
}
|
||||
|
||||
func (k Keeper) payBundler(
|
||||
ctx context.Context,
|
||||
bundler string,
|
||||
op *v1.UserOperation,
|
||||
) (paymentResponses []*implementation.Any, err error) {
|
||||
// if messages are empty, then there is nothing to do
|
||||
if len(op.BundlerPaymentMessages) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
// pay bundler
|
||||
senderAddr, err := k.addressCodec.StringToBytes(op.Sender)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := k.Execute(ctx, senderAddr, ModuleAccountAddress, &account_abstractionv1.MsgPayBundler{
|
||||
Bundler: bundler,
|
||||
BundlerPaymentMessages: op.BundlerPaymentMessages,
|
||||
}, nil)
|
||||
// here is where we check if the account handles bundler payment messages
|
||||
// if it does not, then we simply execute the provided messages on behalf of the sender
|
||||
switch {
|
||||
case err == nil:
|
||||
// if no error, execution went fine, so parse responses.
|
||||
payBundlerResp, err := parsePayBundlerResponse(resp)
|
||||
return payBundlerResp, err
|
||||
case implementation.IsRoutingError(err):
|
||||
// if we get a routing message error it means the account does not handle bundler payment messages,
|
||||
// in this case we attempt to execute the provided messages on behalf of the op sender.
|
||||
return k.sendAnyMessages(ctx, senderAddr, op.BundlerPaymentMessages)
|
||||
default:
|
||||
// some other execution error.
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// parsePayBundlerResponse parses the bundler response as any into a slice of
|
||||
// responses on payment messages.
|
||||
func parsePayBundlerResponse(resp any) ([]*implementation.Any, error) {
|
||||
payBundlerResp, ok := resp.(*account_abstractionv1.MsgPayBundlerResponse)
|
||||
// this means the account does not properly implement account abstraction.
|
||||
if payBundlerResp == nil {
|
||||
return nil, fmt.Errorf("account does not implement account abstraction correctly: wanted %T, got nil", &account_abstractionv1.MsgPayBundlerResponse{})
|
||||
}
|
||||
impl, ok := k.accounts[accType]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("account does not implement account abstraction correctly: wanted %T, got %T", &account_abstractionv1.MsgPayBundlerResponse{}, resp)
|
||||
return false, fmt.Errorf("%w: %s", errAccountTypeNotFound, accType)
|
||||
}
|
||||
return payBundlerResp.BundlerPaymentMessagesResponse, nil
|
||||
return impl.HasExec(&aa_interface_v1.MsgAuthenticate{}), nil
|
||||
}
|
||||
|
||||
// parseExecuteResponse parses the execute response as any into a slice of
|
||||
// responses on execution messages.
|
||||
func parseExecuteResponse(resp any) ([]*implementation.Any, error) {
|
||||
executeResp, ok := resp.(*account_abstractionv1.MsgExecuteResponse)
|
||||
// this means the account does not properly implement account abstraction.
|
||||
if executeResp == nil {
|
||||
return nil, fmt.Errorf("account does not implement account abstraction correctly: wanted %T, got nil", &account_abstractionv1.MsgExecuteResponse{})
|
||||
func (k Keeper) AuthenticateAccount(ctx context.Context, addr []byte, msg *aa_interface_v1.MsgAuthenticate) error {
|
||||
_, err := k.Execute(ctx, addr, address.Module("accounts"), msg, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %w", ErrAuthentication, err)
|
||||
}
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("account does not implement account abstraction correctly: wanted %T, got %T", &account_abstractionv1.MsgExecuteResponse{}, resp)
|
||||
}
|
||||
return executeResp.ExecutionMessagesResponse, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -96,15 +96,5 @@ func (m msgServer) Execute(ctx context.Context, execute *v1.MsgExecute) (*v1.Msg
|
||||
}
|
||||
|
||||
func (m msgServer) ExecuteBundle(ctx context.Context, req *v1.MsgExecuteBundle) (*v1.MsgExecuteBundleResponse, error) {
|
||||
_, err := m.k.addressCodec.StringToBytes(req.Bundler)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := &v1.MsgExecuteBundleResponse{Responses: make([]*v1.UserOperationResponse, len(req.Operations))}
|
||||
for i, op := range req.Operations {
|
||||
resp.Responses[i] = m.k.ExecuteUserOperation(ctx, req.Bundler, op)
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
panic("impl")
|
||||
}
|
||||
|
||||
@ -90,21 +90,3 @@ const (
|
||||
SimulateBundlerPaymentGasLimit = SimulateAuthenticateGasLimit
|
||||
ExecuteGasLimit = SimulateAuthenticateGasLimit
|
||||
)
|
||||
|
||||
func (q queryServer) SimulateUserOperation(ctx context.Context, request *v1.SimulateUserOperationRequest) (*v1.SimulateUserOperationResponse, error) {
|
||||
_, err := q.k.addressCodec.StringToBytes(request.Bundler)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if request.UserOperation == nil {
|
||||
return nil, fmt.Errorf("nil user operation")
|
||||
}
|
||||
|
||||
request.UserOperation.AuthenticationGasLimit = SimulateAuthenticateGasLimit
|
||||
request.UserOperation.BundlerPaymentGasLimit = SimulateBundlerPaymentGasLimit
|
||||
request.UserOperation.ExecutionGasLimit = ExecuteGasLimit
|
||||
|
||||
resp := q.k.ExecuteUserOperation(ctx, request.Bundler, request.UserOperation)
|
||||
return &v1.SimulateUserOperationResponse{UserOperationResponse: resp}, nil
|
||||
}
|
||||
|
||||
@ -1,77 +0,0 @@
|
||||
package account_abstraction
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/x/accounts/accountstd"
|
||||
account_abstractionv1 "cosmossdk.io/x/accounts/interfaces/account_abstraction/v1"
|
||||
)
|
||||
|
||||
// FullAbstractedAccount is an account abstraction that implements
|
||||
// the account abstraction interface fully. It is used for testing.
|
||||
type FullAbstractedAccount struct {
|
||||
m *MinimalAbstractedAccount
|
||||
}
|
||||
|
||||
func NewFullAbstractedAccount(d accountstd.Dependencies) (FullAbstractedAccount, error) {
|
||||
m, err := NewMinimalAbstractedAccount(d)
|
||||
if err != nil {
|
||||
return FullAbstractedAccount{}, err
|
||||
}
|
||||
return FullAbstractedAccount{m: &m}, nil
|
||||
}
|
||||
|
||||
func (a FullAbstractedAccount) ExecuteMessages(ctx context.Context, msg *account_abstractionv1.MsgExecute) (*account_abstractionv1.MsgExecuteResponse, error) {
|
||||
// we always want to ensure that this is called by the x/accounts module, it's the only trusted entrypoint.
|
||||
// if we do not do this check then someone could call this method directly and bypass the authentication.
|
||||
if !accountstd.SenderIsAccountsModule(ctx) {
|
||||
return nil, fmt.Errorf("sender is not the x/accounts module")
|
||||
}
|
||||
// we simulate this account does not allow delegation messages to be executed.
|
||||
for _, m := range msg.ExecutionMessages {
|
||||
if m.TypeUrl == "/cosmos.staking.v1beta1.MsgDelegate" { // NOTE: this is not a safe way to check the typeUrl, it's just for testing.
|
||||
return nil, fmt.Errorf("this account does not allow delegation messages")
|
||||
}
|
||||
}
|
||||
// execute messages
|
||||
responses, err := accountstd.ExecModuleAnys(ctx, msg.ExecutionMessages)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &account_abstractionv1.MsgExecuteResponse{ExecutionMessagesResponse: responses}, nil
|
||||
}
|
||||
|
||||
func (a FullAbstractedAccount) PayBundler(ctx context.Context, msg *account_abstractionv1.MsgPayBundler) (*account_abstractionv1.MsgPayBundlerResponse, error) {
|
||||
// we always want to ensure that this is called by the x/accounts module, it's the only trusted entrypoint.
|
||||
// if we do not do this check then someone could call this method directly and bypass the authentication.
|
||||
if !accountstd.SenderIsAccountsModule(ctx) {
|
||||
return nil, fmt.Errorf("sender is not the x/accounts module")
|
||||
}
|
||||
// we check if it's a bank send, if it is we reject it.
|
||||
for _, m := range msg.BundlerPaymentMessages {
|
||||
if m.TypeUrl == "/cosmos.bank.v1beta1.MsgSend" { // NOTE: this is not a safe way to check the typeUrl, it's just for testing.
|
||||
return nil, fmt.Errorf("this account does not allow bank send messages")
|
||||
}
|
||||
}
|
||||
// execute messages
|
||||
responses, err := accountstd.ExecModuleAnys(ctx, msg.BundlerPaymentMessages)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &account_abstractionv1.MsgPayBundlerResponse{BundlerPaymentMessagesResponse: responses}, nil
|
||||
}
|
||||
|
||||
func (a FullAbstractedAccount) RegisterInitHandler(builder *accountstd.InitBuilder) {
|
||||
a.m.RegisterInitHandler(builder) // registers same init message as MinimalAbstractedAccount
|
||||
}
|
||||
|
||||
func (a FullAbstractedAccount) RegisterExecuteHandlers(builder *accountstd.ExecuteBuilder) {
|
||||
accountstd.RegisterExecuteHandler(builder, a.ExecuteMessages) // implements accounts_abstraction
|
||||
accountstd.RegisterExecuteHandler(builder, a.PayBundler) // implements account_abstraction
|
||||
a.m.RegisterExecuteHandlers(builder) // note: MinimalAbstractedAccount implements account_abstraction, and we're calling its RegisterExecuteHandlers
|
||||
}
|
||||
|
||||
func (a FullAbstractedAccount) RegisterQueryHandlers(builder *accountstd.QueryBuilder) {
|
||||
a.m.RegisterQueryHandlers(builder)
|
||||
}
|
||||
@ -44,9 +44,6 @@ func (a MinimalAbstractedAccount) RotatePubKey(ctx context.Context, msg *rotatio
|
||||
|
||||
// Authenticate authenticates the account, auth always passess.
|
||||
func (a MinimalAbstractedAccount) Authenticate(ctx context.Context, msg *account_abstractionv1.MsgAuthenticate) (*account_abstractionv1.MsgAuthenticateResponse, error) {
|
||||
if msg.UserOperation.AuthenticationMethod != "secp256k1" {
|
||||
return nil, fmt.Errorf("authentication method not supported")
|
||||
}
|
||||
_, err := a.Sequence.Next(ctx)
|
||||
return &account_abstractionv1.MsgAuthenticateResponse{}, err
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -481,110 +481,6 @@ func (m *AccountNumberResponse) GetNumber() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// SimulateUserOperationRequest is the query request used to simulate a
|
||||
// UserOperation.
|
||||
type SimulateUserOperationRequest struct {
|
||||
// bundler can be filled to simulate the address of the bundler.
|
||||
Bundler string `protobuf:"bytes,1,opt,name=bundler,proto3" json:"bundler,omitempty"`
|
||||
// user_operation defines the user operation that we want to simulate.
|
||||
// Gas limit fields are ignored.
|
||||
UserOperation *UserOperation `protobuf:"bytes,2,opt,name=user_operation,json=userOperation,proto3" json:"user_operation,omitempty"`
|
||||
}
|
||||
|
||||
func (m *SimulateUserOperationRequest) Reset() { *m = SimulateUserOperationRequest{} }
|
||||
func (m *SimulateUserOperationRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*SimulateUserOperationRequest) ProtoMessage() {}
|
||||
func (*SimulateUserOperationRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_16ad14c22e3080d2, []int{8}
|
||||
}
|
||||
func (m *SimulateUserOperationRequest) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *SimulateUserOperationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_SimulateUserOperationRequest.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *SimulateUserOperationRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_SimulateUserOperationRequest.Merge(m, src)
|
||||
}
|
||||
func (m *SimulateUserOperationRequest) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *SimulateUserOperationRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_SimulateUserOperationRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_SimulateUserOperationRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *SimulateUserOperationRequest) GetBundler() string {
|
||||
if m != nil {
|
||||
return m.Bundler
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *SimulateUserOperationRequest) GetUserOperation() *UserOperation {
|
||||
if m != nil {
|
||||
return m.UserOperation
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SimulateUserOperationResponse is the query response returned by the simulation.
|
||||
// It will populate the gas limits fields.
|
||||
type SimulateUserOperationResponse struct {
|
||||
// UserOperationResponse is the response of the simulation.
|
||||
UserOperationResponse *UserOperationResponse `protobuf:"bytes,1,opt,name=user_operation_response,json=userOperationResponse,proto3" json:"user_operation_response,omitempty"`
|
||||
}
|
||||
|
||||
func (m *SimulateUserOperationResponse) Reset() { *m = SimulateUserOperationResponse{} }
|
||||
func (m *SimulateUserOperationResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*SimulateUserOperationResponse) ProtoMessage() {}
|
||||
func (*SimulateUserOperationResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_16ad14c22e3080d2, []int{9}
|
||||
}
|
||||
func (m *SimulateUserOperationResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *SimulateUserOperationResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_SimulateUserOperationResponse.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *SimulateUserOperationResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_SimulateUserOperationResponse.Merge(m, src)
|
||||
}
|
||||
func (m *SimulateUserOperationResponse) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *SimulateUserOperationResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_SimulateUserOperationResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_SimulateUserOperationResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *SimulateUserOperationResponse) GetUserOperationResponse() *UserOperationResponse {
|
||||
if m != nil {
|
||||
return m.UserOperationResponse
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*AccountQueryRequest)(nil), "cosmos.accounts.v1.AccountQueryRequest")
|
||||
proto.RegisterType((*AccountQueryResponse)(nil), "cosmos.accounts.v1.AccountQueryResponse")
|
||||
@ -595,52 +491,44 @@ func init() {
|
||||
proto.RegisterType((*AccountTypeResponse)(nil), "cosmos.accounts.v1.AccountTypeResponse")
|
||||
proto.RegisterType((*AccountNumberRequest)(nil), "cosmos.accounts.v1.AccountNumberRequest")
|
||||
proto.RegisterType((*AccountNumberResponse)(nil), "cosmos.accounts.v1.AccountNumberResponse")
|
||||
proto.RegisterType((*SimulateUserOperationRequest)(nil), "cosmos.accounts.v1.SimulateUserOperationRequest")
|
||||
proto.RegisterType((*SimulateUserOperationResponse)(nil), "cosmos.accounts.v1.SimulateUserOperationResponse")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("cosmos/accounts/v1/query.proto", fileDescriptor_16ad14c22e3080d2) }
|
||||
|
||||
var fileDescriptor_16ad14c22e3080d2 = []byte{
|
||||
// 608 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0xcf, 0x6f, 0x12, 0x41,
|
||||
0x14, 0x66, 0x69, 0xa5, 0xfa, 0x28, 0xd5, 0x8c, 0xa5, 0xe2, 0x46, 0x37, 0xb0, 0x07, 0x4b, 0x8d,
|
||||
0x99, 0x05, 0xf4, 0xe0, 0xcd, 0xe0, 0x89, 0xc4, 0x44, 0xc3, 0xd6, 0x5e, 0x4c, 0x0c, 0x2e, 0xcb,
|
||||
0x94, 0x12, 0x61, 0x97, 0xce, 0xec, 0x34, 0xe5, 0xe2, 0xc1, 0x9b, 0x37, 0xff, 0xac, 0x1e, 0x7b,
|
||||
0xf4, 0x68, 0xe0, 0x1f, 0x31, 0xcc, 0x0f, 0xd8, 0xad, 0x5b, 0x28, 0xb7, 0x79, 0xf3, 0xde, 0xfb,
|
||||
0xbe, 0xb7, 0xef, 0x7d, 0x6f, 0x16, 0x2c, 0x3f, 0x64, 0xa3, 0x90, 0x39, 0x9e, 0xef, 0x87, 0x3c,
|
||||
0x88, 0x98, 0x73, 0x51, 0x77, 0xce, 0x39, 0xa1, 0x13, 0x3c, 0xa6, 0x61, 0x14, 0x22, 0x24, 0xfd,
|
||||
0x58, 0xfb, 0xf1, 0x45, 0xdd, 0x7c, 0xda, 0x0f, 0xc3, 0xfe, 0x90, 0x38, 0x22, 0xa2, 0xcb, 0x4f,
|
||||
0x1d, 0x2f, 0x50, 0xe1, 0xe6, 0xab, 0x14, 0x38, 0x75, 0xee, 0x78, 0x5d, 0x16, 0x51, 0xcf, 0x8f,
|
||||
0x06, 0x61, 0x20, 0xa3, 0xed, 0xaf, 0xf0, 0xb8, 0x29, 0x9d, 0xed, 0x39, 0xa5, 0x4b, 0xce, 0x39,
|
||||
0x61, 0x11, 0x3a, 0x80, 0x5c, 0xe4, 0xd1, 0x3e, 0x89, 0x4a, 0x46, 0xd9, 0xa8, 0x3e, 0x70, 0x95,
|
||||
0x85, 0x30, 0xec, 0x50, 0x19, 0x52, 0xca, 0x96, 0x8d, 0x6a, 0xbe, 0xb1, 0x8f, 0x65, 0x25, 0x58,
|
||||
0x57, 0x82, 0x9b, 0xc1, 0xc4, 0xd5, 0x41, 0x76, 0x0b, 0xf6, 0x93, 0xf0, 0x6c, 0x1c, 0x06, 0x8c,
|
||||
0xa0, 0x1a, 0xdc, 0xa7, 0xea, 0x2c, 0x18, 0x6e, 0x03, 0x5a, 0x44, 0xd9, 0x0d, 0x28, 0x1c, 0xfb,
|
||||
0x67, 0x64, 0xe4, 0xe9, 0x12, 0x2b, 0xb0, 0xab, 0x3f, 0x2b, 0x9a, 0x8c, 0x89, 0x2a, 0x34, 0xaf,
|
||||
0xee, 0x3e, 0x4f, 0xc6, 0xc4, 0xbe, 0xca, 0xc2, 0x9e, 0x4e, 0x52, 0xc4, 0x1f, 0x20, 0x3f, 0x08,
|
||||
0x06, 0x51, 0x87, 0x89, 0x6b, 0xc5, 0xfd, 0x12, 0xff, 0xdf, 0x62, 0x9c, 0x4c, 0xc4, 0x2d, 0x2f,
|
||||
0xe8, 0x0d, 0x09, 0x75, 0x61, 0x9e, 0x2e, 0x7d, 0xe8, 0x04, 0x1e, 0x91, 0x4b, 0xe2, 0xf3, 0x88,
|
||||
0x74, 0xce, 0xa4, 0x9b, 0x95, 0xb2, 0xe5, 0xad, 0x0d, 0x11, 0x1f, 0x2a, 0x0c, 0x65, 0x33, 0xd4,
|
||||
0x86, 0x3d, 0x31, 0xff, 0x25, 0xe8, 0xd6, 0xc6, 0xa0, 0x05, 0x81, 0xa0, 0x21, 0xcd, 0x77, 0xb0,
|
||||
0xa3, 0xce, 0xa8, 0xb4, 0x1c, 0xa1, 0x6c, 0x99, 0x36, 0x91, 0x19, 0x1b, 0x4a, 0x56, 0xb8, 0x96,
|
||||
0xed, 0xc7, 0x80, 0x9a, 0xcb, 0xce, 0xea, 0x19, 0x94, 0x60, 0xc7, 0xeb, 0xf5, 0x28, 0x61, 0x4c,
|
||||
0x63, 0x29, 0xd3, 0x7e, 0xbb, 0xd0, 0x95, 0x8c, 0x57, 0xed, 0xbf, 0xc3, 0xd0, 0x6a, 0x0b, 0xc9,
|
||||
0x7c, 0xe4, 0xa3, 0x2e, 0xa1, 0xeb, 0xb9, 0x1c, 0x28, 0xde, 0xc8, 0x50, 0x6c, 0x07, 0x90, 0x0b,
|
||||
0xc4, 0x8d, 0xc8, 0xd8, 0x76, 0x95, 0x65, 0xff, 0x34, 0xe0, 0xd9, 0xf1, 0x60, 0xc4, 0x87, 0x5e,
|
||||
0x44, 0x4e, 0x18, 0xa1, 0x9f, 0xc6, 0x84, 0x7a, 0xf3, 0xa5, 0x88, 0x71, 0x75, 0xb9, 0x68, 0x97,
|
||||
0xe6, 0x52, 0x26, 0x6a, 0xc1, 0x1e, 0x67, 0x84, 0x76, 0x42, 0x9d, 0xa2, 0xf6, 0xa0, 0x92, 0x36,
|
||||
0x9b, 0x24, 0x76, 0x81, 0xc7, 0xcd, 0x79, 0x11, 0xcf, 0x6f, 0x29, 0x42, 0x95, 0xef, 0xc1, 0x93,
|
||||
0x24, 0x57, 0xe7, 0xc6, 0xce, 0x1c, 0xad, 0x27, 0x55, 0x09, 0x6e, 0x91, 0xa7, 0x5d, 0x37, 0x7e,
|
||||
0x6d, 0xc3, 0x3d, 0xb1, 0x99, 0xc8, 0x87, 0xdd, 0xf8, 0xa6, 0xa2, 0xc3, 0x34, 0xec, 0x94, 0xa7,
|
||||
0xc2, 0xac, 0xae, 0x0f, 0x54, 0x1a, 0xca, 0xa0, 0x36, 0xe4, 0xd4, 0xea, 0x54, 0x56, 0x69, 0x59,
|
||||
0x02, 0xdb, 0xeb, 0xe5, 0x6e, 0x67, 0xd0, 0x37, 0xc8, 0xc7, 0x84, 0x86, 0x5e, 0xac, 0xa8, 0x26,
|
||||
0xa6, 0x5c, 0xf3, 0x70, 0x6d, 0xdc, 0x82, 0xe1, 0x14, 0x0a, 0x09, 0x79, 0xa1, 0x55, 0x5f, 0x9c,
|
||||
0xd0, 0xac, 0x79, 0x74, 0x87, 0xc8, 0x05, 0xcf, 0x0f, 0x28, 0xa6, 0xea, 0x01, 0xd5, 0x52, 0x1b,
|
||||
0xb1, 0x42, 0xbf, 0x66, 0x7d, 0x83, 0x0c, 0xcd, 0xff, 0xfe, 0xcd, 0xd5, 0xd4, 0x32, 0xae, 0xa7,
|
||||
0x96, 0xf1, 0x77, 0x6a, 0x19, 0xbf, 0x67, 0x56, 0xe6, 0x7a, 0x66, 0x65, 0xfe, 0xcc, 0xac, 0xcc,
|
||||
0x17, 0x53, 0xa2, 0xb1, 0xde, 0x77, 0x3c, 0x08, 0x9d, 0xcb, 0xf8, 0xaf, 0xa5, 0x9b, 0x13, 0xef,
|
||||
0xf5, 0xeb, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xcd, 0xc0, 0xe6, 0x63, 0xc6, 0x06, 0x00, 0x00,
|
||||
// 497 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xc1, 0x6e, 0xd3, 0x40,
|
||||
0x10, 0xb5, 0x13, 0x48, 0x60, 0xd2, 0x14, 0x34, 0x94, 0xca, 0xf8, 0x60, 0xa5, 0x3e, 0xd0, 0xc0,
|
||||
0x61, 0xdd, 0x06, 0x0e, 0xdc, 0x50, 0x38, 0x55, 0x42, 0x42, 0x8a, 0x81, 0x0b, 0x12, 0x0a, 0x8e,
|
||||
0xb3, 0x4d, 0x23, 0x1a, 0x6f, 0xea, 0xb5, 0xab, 0xe6, 0x13, 0xb8, 0xf1, 0x59, 0x3d, 0xf6, 0xc8,
|
||||
0x11, 0x25, 0x3f, 0x82, 0xba, 0x3b, 0x9b, 0x38, 0x50, 0xe2, 0xf6, 0xe6, 0xd9, 0x79, 0xf3, 0xde,
|
||||
0xfa, 0xbd, 0xb1, 0xc1, 0x8b, 0x85, 0x9c, 0x08, 0x19, 0x44, 0x71, 0x2c, 0xf2, 0x24, 0x93, 0xc1,
|
||||
0xf9, 0x61, 0x70, 0x96, 0xf3, 0x74, 0xc6, 0xa6, 0xa9, 0xc8, 0x04, 0xa2, 0xee, 0x33, 0xd3, 0x67,
|
||||
0xe7, 0x87, 0xee, 0xb3, 0x91, 0x10, 0xa3, 0x53, 0x1e, 0x28, 0xc4, 0x20, 0x3f, 0x0e, 0xa2, 0x84,
|
||||
0xe0, 0xfe, 0x57, 0x78, 0xd2, 0xd5, 0xc8, 0xde, 0x35, 0x49, 0xc8, 0xcf, 0x72, 0x2e, 0x33, 0xdc,
|
||||
0x85, 0x5a, 0x16, 0xa5, 0x23, 0x9e, 0x39, 0x76, 0xcb, 0x6e, 0x3f, 0x0c, 0xa9, 0x42, 0x06, 0xf5,
|
||||
0x54, 0x43, 0x9c, 0x4a, 0xcb, 0x6e, 0x37, 0x3a, 0x3b, 0x4c, 0x73, 0x33, 0xc3, 0xcd, 0xba, 0xc9,
|
||||
0x2c, 0x34, 0x20, 0xff, 0x08, 0x76, 0xd6, 0xe9, 0xe5, 0x54, 0x24, 0x92, 0xe3, 0x01, 0x3c, 0x48,
|
||||
0xe9, 0x59, 0x29, 0xfc, 0x8f, 0x68, 0x89, 0xf2, 0x3b, 0xd0, 0xfc, 0x18, 0x9f, 0xf0, 0x49, 0x64,
|
||||
0xae, 0xb8, 0x07, 0x5b, 0xf4, 0x8e, 0xfd, 0x6c, 0x36, 0xe5, 0x74, 0xd1, 0x06, 0x9d, 0x7d, 0x9a,
|
||||
0x4d, 0xb9, 0x7f, 0x59, 0x81, 0x6d, 0x33, 0x44, 0xc2, 0xef, 0xa1, 0x31, 0x4e, 0xc6, 0x59, 0x5f,
|
||||
0xaa, 0x63, 0xd2, 0x7e, 0xc9, 0xfe, 0x35, 0x8d, 0xad, 0x0f, 0xb2, 0xa3, 0x28, 0x19, 0x9e, 0xf2,
|
||||
0x34, 0x84, 0xeb, 0x71, 0xdd, 0xc3, 0xcf, 0xf0, 0x98, 0x5f, 0xf0, 0x38, 0xcf, 0x78, 0xff, 0x44,
|
||||
0xb7, 0xa5, 0x53, 0x69, 0x55, 0xef, 0xc8, 0xf8, 0x88, 0x38, 0xa8, 0x96, 0xd8, 0x83, 0x6d, 0x95,
|
||||
0xe8, 0x8a, 0xb4, 0x7a, 0x67, 0xd2, 0xa6, 0x62, 0x30, 0x94, 0xee, 0x5b, 0xa8, 0xd3, 0x33, 0x3a,
|
||||
0xab, 0x08, 0xb5, 0x65, 0xa6, 0x44, 0xb7, 0x10, 0x4a, 0x45, 0xb5, 0x56, 0xf6, 0x33, 0xc0, 0xee,
|
||||
0xca, 0x59, 0x93, 0x81, 0x03, 0xf5, 0x68, 0x38, 0x4c, 0xb9, 0x94, 0x86, 0x8b, 0x4a, 0xff, 0xcd,
|
||||
0x72, 0xaf, 0x34, 0x9e, 0xec, 0xbf, 0x45, 0x68, 0x07, 0xcb, 0x95, 0xf9, 0x90, 0x4f, 0x06, 0x3c,
|
||||
0x2d, 0xd7, 0x0a, 0xe0, 0xe9, 0x5f, 0x13, 0xa4, 0xb6, 0x0b, 0xb5, 0x44, 0x9d, 0xa8, 0x89, 0x7b,
|
||||
0x21, 0x55, 0x9d, 0x1f, 0x55, 0xb8, 0xaf, 0xf6, 0x11, 0x63, 0xd8, 0x2a, 0xee, 0x27, 0xee, 0xdf,
|
||||
0x64, 0xf1, 0x0d, 0x1f, 0x88, 0xdb, 0x2e, 0x07, 0x92, 0x73, 0x16, 0xf6, 0xa0, 0x46, 0x0b, 0xb3,
|
||||
0xb7, 0x29, 0x41, 0x4d, 0xec, 0x97, 0x87, 0xec, 0x5b, 0xf8, 0x0d, 0x1a, 0x05, 0x7b, 0xf1, 0xf9,
|
||||
0x86, 0xdb, 0x14, 0xf2, 0x72, 0xf7, 0x4b, 0x71, 0x4b, 0x85, 0x63, 0x68, 0xae, 0x99, 0x8a, 0x9b,
|
||||
0xde, 0x78, 0x2d, 0x29, 0xf7, 0xc5, 0x2d, 0x90, 0x46, 0xe7, 0xdd, 0xeb, 0xcb, 0xb9, 0x67, 0x5f,
|
||||
0xcd, 0x3d, 0xfb, 0xf7, 0xdc, 0xb3, 0x7f, 0x2e, 0x3c, 0xeb, 0x6a, 0xe1, 0x59, 0xbf, 0x16, 0x9e,
|
||||
0xf5, 0xc5, 0xd5, 0x2c, 0x72, 0xf8, 0x9d, 0x8d, 0x45, 0x70, 0x51, 0xfc, 0xe3, 0x0d, 0x6a, 0xea,
|
||||
0x2f, 0xf1, 0xea, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xea, 0x75, 0x93, 0xfa, 0x0e, 0x05, 0x00,
|
||||
0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@ -663,8 +551,6 @@ type QueryClient interface {
|
||||
AccountType(ctx context.Context, in *AccountTypeRequest, opts ...grpc.CallOption) (*AccountTypeResponse, error)
|
||||
// AccountNumber returns the account number given the account address.
|
||||
AccountNumber(ctx context.Context, in *AccountNumberRequest, opts ...grpc.CallOption) (*AccountNumberResponse, error)
|
||||
// SimulateUserOperation simulates a user operation.
|
||||
SimulateUserOperation(ctx context.Context, in *SimulateUserOperationRequest, opts ...grpc.CallOption) (*SimulateUserOperationResponse, error)
|
||||
}
|
||||
|
||||
type queryClient struct {
|
||||
@ -711,15 +597,6 @@ func (c *queryClient) AccountNumber(ctx context.Context, in *AccountNumberReques
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *queryClient) SimulateUserOperation(ctx context.Context, in *SimulateUserOperationRequest, opts ...grpc.CallOption) (*SimulateUserOperationResponse, error) {
|
||||
out := new(SimulateUserOperationResponse)
|
||||
err := c.cc.Invoke(ctx, "/cosmos.accounts.v1.Query/SimulateUserOperation", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// QueryServer is the server API for Query service.
|
||||
type QueryServer interface {
|
||||
// AccountQuery runs an account query.
|
||||
@ -730,8 +607,6 @@ type QueryServer interface {
|
||||
AccountType(context.Context, *AccountTypeRequest) (*AccountTypeResponse, error)
|
||||
// AccountNumber returns the account number given the account address.
|
||||
AccountNumber(context.Context, *AccountNumberRequest) (*AccountNumberResponse, error)
|
||||
// SimulateUserOperation simulates a user operation.
|
||||
SimulateUserOperation(context.Context, *SimulateUserOperationRequest) (*SimulateUserOperationResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedQueryServer can be embedded to have forward compatible implementations.
|
||||
@ -750,9 +625,6 @@ func (*UnimplementedQueryServer) AccountType(ctx context.Context, req *AccountTy
|
||||
func (*UnimplementedQueryServer) AccountNumber(ctx context.Context, req *AccountNumberRequest) (*AccountNumberResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AccountNumber not implemented")
|
||||
}
|
||||
func (*UnimplementedQueryServer) SimulateUserOperation(ctx context.Context, req *SimulateUserOperationRequest) (*SimulateUserOperationResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SimulateUserOperation not implemented")
|
||||
}
|
||||
|
||||
func RegisterQueryServer(s grpc1.Server, srv QueryServer) {
|
||||
s.RegisterService(&_Query_serviceDesc, srv)
|
||||
@ -830,24 +702,6 @@ func _Query_AccountNumber_Handler(srv interface{}, ctx context.Context, dec func
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Query_SimulateUserOperation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SimulateUserOperationRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(QueryServer).SimulateUserOperation(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/cosmos.accounts.v1.Query/SimulateUserOperation",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(QueryServer).SimulateUserOperation(ctx, req.(*SimulateUserOperationRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Query_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "cosmos.accounts.v1.Query",
|
||||
HandlerType: (*QueryServer)(nil),
|
||||
@ -868,10 +722,6 @@ var _Query_serviceDesc = grpc.ServiceDesc{
|
||||
MethodName: "AccountNumber",
|
||||
Handler: _Query_AccountNumber_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SimulateUserOperation",
|
||||
Handler: _Query_SimulateUserOperation_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "cosmos/accounts/v1/query.proto",
|
||||
@ -1202,83 +1052,6 @@ func (m *AccountNumberResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *SimulateUserOperationRequest) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *SimulateUserOperationRequest) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *SimulateUserOperationRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.UserOperation != nil {
|
||||
{
|
||||
size, err := m.UserOperation.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintQuery(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if len(m.Bundler) > 0 {
|
||||
i -= len(m.Bundler)
|
||||
copy(dAtA[i:], m.Bundler)
|
||||
i = encodeVarintQuery(dAtA, i, uint64(len(m.Bundler)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *SimulateUserOperationResponse) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *SimulateUserOperationResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *SimulateUserOperationResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.UserOperationResponse != nil {
|
||||
{
|
||||
size, err := m.UserOperationResponse.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintQuery(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintQuery(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovQuery(v)
|
||||
base := offset
|
||||
@ -1426,36 +1199,6 @@ func (m *AccountNumberResponse) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *SimulateUserOperationRequest) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Bundler)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovQuery(uint64(l))
|
||||
}
|
||||
if m.UserOperation != nil {
|
||||
l = m.UserOperation.Size()
|
||||
n += 1 + l + sovQuery(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *SimulateUserOperationResponse) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.UserOperationResponse != nil {
|
||||
l = m.UserOperationResponse.Size()
|
||||
n += 1 + l + sovQuery(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovQuery(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
@ -2331,210 +2074,6 @@ func (m *AccountNumberResponse) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *SimulateUserOperationRequest) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: SimulateUserOperationRequest: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: SimulateUserOperationRequest: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Bundler", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Bundler = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field UserOperation", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.UserOperation == nil {
|
||||
m.UserOperation = &UserOperation{}
|
||||
}
|
||||
if err := m.UserOperation.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipQuery(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *SimulateUserOperationResponse) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: SimulateUserOperationResponse: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: SimulateUserOperationResponse: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field UserOperationResponse", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.UserOperationResponse == nil {
|
||||
m.UserOperationResponse = &UserOperationResponse{}
|
||||
}
|
||||
if err := m.UserOperationResponse.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipQuery(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipQuery(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types"
|
||||
types1 "github.com/cosmos/cosmos-sdk/types"
|
||||
_ "github.com/cosmos/cosmos-sdk/types/msgservice"
|
||||
tx "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
_ "github.com/cosmos/gogoproto/gogoproto"
|
||||
grpc1 "github.com/cosmos/gogoproto/grpc"
|
||||
proto "github.com/cosmos/gogoproto/proto"
|
||||
@ -286,8 +287,8 @@ type MsgExecuteBundle struct {
|
||||
// bundler defines the entity going through the standard TX flow
|
||||
// to execute one or multiple UserOperations on behalf of others.
|
||||
Bundler string `protobuf:"bytes,1,opt,name=bundler,proto3" json:"bundler,omitempty"`
|
||||
// operations is the list of operations to be executed.
|
||||
Operations []*UserOperation `protobuf:"bytes,2,rep,name=operations,proto3" json:"operations,omitempty"`
|
||||
// txs defines the txs to execute on behalf of other users.
|
||||
Txs []*tx.TxRaw `protobuf:"bytes,2,rep,name=txs,proto3" json:"txs,omitempty"`
|
||||
}
|
||||
|
||||
func (m *MsgExecuteBundle) Reset() { *m = MsgExecuteBundle{} }
|
||||
@ -330,24 +331,77 @@ func (m *MsgExecuteBundle) GetBundler() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *MsgExecuteBundle) GetOperations() []*UserOperation {
|
||||
func (m *MsgExecuteBundle) GetTxs() []*tx.TxRaw {
|
||||
if m != nil {
|
||||
return m.Operations
|
||||
return m.Txs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BundledTxResponse defines the response of a bundled tx.
|
||||
type BundledTxResponse struct {
|
||||
ExecResponses *types.Any `protobuf:"bytes,1,opt,name=exec_responses,json=execResponses,proto3" json:"exec_responses,omitempty"`
|
||||
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (m *BundledTxResponse) Reset() { *m = BundledTxResponse{} }
|
||||
func (m *BundledTxResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*BundledTxResponse) ProtoMessage() {}
|
||||
func (*BundledTxResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_29c2b6d8a13d4189, []int{5}
|
||||
}
|
||||
func (m *BundledTxResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *BundledTxResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_BundledTxResponse.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *BundledTxResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_BundledTxResponse.Merge(m, src)
|
||||
}
|
||||
func (m *BundledTxResponse) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *BundledTxResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_BundledTxResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_BundledTxResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *BundledTxResponse) GetExecResponses() *types.Any {
|
||||
if m != nil {
|
||||
return m.ExecResponses
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *BundledTxResponse) GetError() string {
|
||||
if m != nil {
|
||||
return m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// MsgExecuteBundleResponse defines the ExecuteBundle response type for the Msg/ExecuteBundle RPC method.
|
||||
type MsgExecuteBundleResponse struct {
|
||||
// responses is the list of responses returned by the account implementations.
|
||||
Responses []*UserOperationResponse `protobuf:"bytes,1,rep,name=responses,proto3" json:"responses,omitempty"`
|
||||
Responses []*BundledTxResponse `protobuf:"bytes,1,rep,name=responses,proto3" json:"responses,omitempty"`
|
||||
}
|
||||
|
||||
func (m *MsgExecuteBundleResponse) Reset() { *m = MsgExecuteBundleResponse{} }
|
||||
func (m *MsgExecuteBundleResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*MsgExecuteBundleResponse) ProtoMessage() {}
|
||||
func (*MsgExecuteBundleResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_29c2b6d8a13d4189, []int{5}
|
||||
return fileDescriptor_29c2b6d8a13d4189, []int{6}
|
||||
}
|
||||
func (m *MsgExecuteBundleResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@ -376,7 +430,7 @@ func (m *MsgExecuteBundleResponse) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_MsgExecuteBundleResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *MsgExecuteBundleResponse) GetResponses() []*UserOperationResponse {
|
||||
func (m *MsgExecuteBundleResponse) GetResponses() []*BundledTxResponse {
|
||||
if m != nil {
|
||||
return m.Responses
|
||||
}
|
||||
@ -389,50 +443,53 @@ func init() {
|
||||
proto.RegisterType((*MsgExecute)(nil), "cosmos.accounts.v1.MsgExecute")
|
||||
proto.RegisterType((*MsgExecuteResponse)(nil), "cosmos.accounts.v1.MsgExecuteResponse")
|
||||
proto.RegisterType((*MsgExecuteBundle)(nil), "cosmos.accounts.v1.MsgExecuteBundle")
|
||||
proto.RegisterType((*BundledTxResponse)(nil), "cosmos.accounts.v1.BundledTxResponse")
|
||||
proto.RegisterType((*MsgExecuteBundleResponse)(nil), "cosmos.accounts.v1.MsgExecuteBundleResponse")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("cosmos/accounts/v1/tx.proto", fileDescriptor_29c2b6d8a13d4189) }
|
||||
|
||||
var fileDescriptor_29c2b6d8a13d4189 = []byte{
|
||||
// 583 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0xcd, 0x6e, 0xd3, 0x40,
|
||||
0x10, 0x8e, 0x9b, 0x36, 0xa1, 0x9b, 0x42, 0xd1, 0xaa, 0x2a, 0xae, 0x2b, 0xb9, 0x69, 0x40, 0x10,
|
||||
0xaa, 0xb2, 0x6e, 0x02, 0xa7, 0xde, 0x12, 0xc4, 0xdf, 0x21, 0x42, 0x58, 0x70, 0xe1, 0x82, 0xfc,
|
||||
0xb3, 0x5d, 0xac, 0x26, 0xde, 0xc8, 0xb3, 0x8e, 0x92, 0x03, 0x12, 0xe2, 0x01, 0x10, 0xcf, 0xc1,
|
||||
0xa9, 0x8f, 0xd1, 0x63, 0x8f, 0x1c, 0x10, 0xa0, 0x04, 0xa9, 0xaf, 0x81, 0x6c, 0xef, 0x3a, 0x01,
|
||||
0x9a, 0xd0, 0x23, 0xa7, 0xec, 0xce, 0x7c, 0xf3, 0xcd, 0x7c, 0x5f, 0x66, 0x8d, 0xb6, 0x3d, 0x0e,
|
||||
0x3d, 0x0e, 0x96, 0xe3, 0x79, 0x3c, 0x0e, 0x05, 0x58, 0x83, 0x86, 0x25, 0x86, 0xa4, 0x1f, 0x71,
|
||||
0xc1, 0x31, 0xce, 0x92, 0x44, 0x25, 0xc9, 0xa0, 0x61, 0x6c, 0x31, 0xce, 0x59, 0x97, 0x5a, 0x29,
|
||||
0xc2, 0x8d, 0x8f, 0x2c, 0x27, 0x1c, 0x65, 0x70, 0xe3, 0x86, 0xe4, 0xea, 0x01, 0x4b, 0x68, 0x7a,
|
||||
0xc0, 0x64, 0x62, 0xff, 0x82, 0x26, 0xf2, 0xfc, 0xc6, 0x71, 0x41, 0x44, 0x8e, 0x27, 0x02, 0x1e,
|
||||
0x4a, 0xb4, 0x29, 0xd1, 0xae, 0x03, 0xd4, 0x1a, 0x34, 0x5c, 0x2a, 0x9c, 0x86, 0xe5, 0xf1, 0x40,
|
||||
0xe5, 0x37, 0x18, 0x67, 0x3c, 0x3d, 0x5a, 0xc9, 0x29, 0x8b, 0xd6, 0x7e, 0x6a, 0xa8, 0xdc, 0x01,
|
||||
0xf6, 0x2c, 0x0c, 0x04, 0xde, 0x44, 0x25, 0xa0, 0xa1, 0x4f, 0x23, 0x5d, 0xab, 0x6a, 0xf5, 0x55,
|
||||
0x5b, 0xde, 0xf0, 0x2e, 0x5a, 0x53, 0x6d, 0xc5, 0xa8, 0x4f, 0xf5, 0xa5, 0x34, 0x5b, 0x91, 0xb1,
|
||||
0x97, 0xa3, 0x3e, 0xc5, 0x04, 0x95, 0x7b, 0x14, 0xc0, 0x61, 0x54, 0x2f, 0x56, 0xb5, 0x7a, 0xa5,
|
||||
0xb9, 0x41, 0x32, 0xc1, 0x44, 0x09, 0x26, 0xad, 0x70, 0x64, 0x2b, 0x10, 0x76, 0xd0, 0xca, 0x51,
|
||||
0x1c, 0xfa, 0xa0, 0x2f, 0x57, 0x8b, 0xf5, 0x4a, 0x73, 0x8b, 0x48, 0xcb, 0x92, 0xe1, 0x89, 0x1c,
|
||||
0x9e, 0x3c, 0xe4, 0x41, 0xd8, 0x3e, 0x38, 0xfd, 0xb6, 0x53, 0xf8, 0xfc, 0x7d, 0xa7, 0xce, 0x02,
|
||||
0xf1, 0x36, 0x76, 0x89, 0xc7, 0x7b, 0x96, 0x54, 0x9a, 0xfd, 0xdc, 0x03, 0xff, 0xd8, 0x4a, 0xe6,
|
||||
0x82, 0xb4, 0x00, 0xec, 0x8c, 0xf9, 0xb0, 0xf2, 0xe1, 0xfc, 0x64, 0x4f, 0x4a, 0xa8, 0x75, 0xd1,
|
||||
0xba, 0x54, 0x69, 0x53, 0xe8, 0xf3, 0x10, 0x28, 0xbe, 0x83, 0xd6, 0x73, 0x33, 0x7d, 0x3f, 0xa2,
|
||||
0x00, 0x52, 0xf6, 0x35, 0x19, 0x6e, 0x65, 0x51, 0x7c, 0x80, 0xae, 0x44, 0xb2, 0x28, 0x95, 0x3e,
|
||||
0x4f, 0x5c, 0x8e, 0xaa, 0x7d, 0xd5, 0x10, 0xea, 0x00, 0x7b, 0x34, 0xa4, 0x5e, 0x2c, 0xe8, 0x5c,
|
||||
0x5f, 0x37, 0x51, 0x49, 0x38, 0x11, 0xa3, 0x42, 0x3a, 0x2a, 0x6f, 0xff, 0xbd, 0x99, 0x8f, 0x11,
|
||||
0x9e, 0xaa, 0xcb, 0xfd, 0x9c, 0xb5, 0x49, 0xbb, 0x94, 0x4d, 0xef, 0xd0, 0xf5, 0x29, 0x4f, 0x3b,
|
||||
0x0e, 0xfd, 0x2e, 0xc5, 0x3a, 0x2a, 0xbb, 0xe9, 0x49, 0x99, 0xa5, 0xae, 0xb8, 0x85, 0x10, 0xef,
|
||||
0xd3, 0xc8, 0x49, 0x56, 0x1e, 0xf4, 0xa5, 0x54, 0xea, 0x2e, 0xf9, 0xfb, 0xa9, 0x91, 0x57, 0x40,
|
||||
0xa3, 0xe7, 0x0a, 0x69, 0xcf, 0x14, 0x1d, 0xae, 0x25, 0x2a, 0x14, 0x61, 0xcd, 0x43, 0xfa, 0x9f,
|
||||
0xed, 0x73, 0x31, 0x4f, 0xd0, 0xaa, 0x1a, 0x33, 0x59, 0x8b, 0xa4, 0xd7, 0xdd, 0x7f, 0xf7, 0x92,
|
||||
0x15, 0xf6, 0xb4, 0xb6, 0xf9, 0x71, 0x09, 0x15, 0x3b, 0xc0, 0xf0, 0x53, 0xb4, 0x9c, 0xbe, 0xb1,
|
||||
0xed, 0x8b, 0x58, 0xe4, 0x6a, 0x1a, 0x37, 0x17, 0x24, 0xf3, 0xd1, 0x5e, 0xa0, 0xb2, 0x5a, 0x2c,
|
||||
0x73, 0x0e, 0x5e, 0xe6, 0x8d, 0xdb, 0x8b, 0xf3, 0x39, 0xa5, 0x87, 0xae, 0xfe, 0xfe, 0x2f, 0xdc,
|
||||
0x5a, 0x5c, 0x98, 0xa1, 0x8c, 0xfd, 0xcb, 0xa0, 0x54, 0x13, 0x63, 0xe5, 0xfd, 0xf9, 0xc9, 0x9e,
|
||||
0xd6, 0x7e, 0x70, 0x3a, 0x36, 0xb5, 0xb3, 0xb1, 0xa9, 0xfd, 0x18, 0x9b, 0xda, 0xa7, 0x89, 0x59,
|
||||
0x38, 0x9b, 0x98, 0x85, 0x2f, 0x13, 0xb3, 0xf0, 0xda, 0xc8, 0xd8, 0xc0, 0x3f, 0x26, 0x01, 0xb7,
|
||||
0x86, 0xb3, 0x9f, 0x3d, 0xb7, 0x94, 0xae, 0xd0, 0xfd, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x16,
|
||||
0x7f, 0x4c, 0xfa, 0x78, 0x05, 0x00, 0x00,
|
||||
// 609 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0xcd, 0x6e, 0xd3, 0x4c,
|
||||
0x14, 0x8d, 0x9b, 0xb6, 0xf9, 0x7a, 0xd3, 0x9f, 0x8f, 0x51, 0x55, 0x5c, 0x57, 0x72, 0x4b, 0xf8,
|
||||
0x8b, 0x2a, 0x18, 0x37, 0x85, 0x55, 0x59, 0xb5, 0x15, 0x08, 0x16, 0x5d, 0x60, 0x75, 0xc5, 0xa6,
|
||||
0xf2, 0xcf, 0x64, 0x88, 0xda, 0x78, 0x22, 0xdf, 0x71, 0x71, 0x76, 0x88, 0x07, 0x40, 0x3c, 0x07,
|
||||
0xab, 0x3e, 0x46, 0x97, 0x5d, 0xb2, 0x40, 0x80, 0x1a, 0xa4, 0xbe, 0x06, 0xb2, 0x3d, 0xe3, 0x04,
|
||||
0x4a, 0xa2, 0x2e, 0x59, 0x65, 0xe6, 0x9e, 0x73, 0xef, 0x9c, 0x73, 0xc6, 0x19, 0x58, 0x0b, 0x04,
|
||||
0x76, 0x05, 0x3a, 0x5e, 0x10, 0x88, 0x24, 0x92, 0xe8, 0x9c, 0xb6, 0x1c, 0x99, 0xd2, 0x5e, 0x2c,
|
||||
0xa4, 0x20, 0xa4, 0x00, 0xa9, 0x06, 0xe9, 0x69, 0xcb, 0x5a, 0xe5, 0x42, 0xf0, 0x13, 0xe6, 0xe4,
|
||||
0x0c, 0x3f, 0x69, 0x3b, 0x5e, 0xd4, 0x2f, 0xe8, 0xd6, 0x6d, 0x35, 0xab, 0x8b, 0x3c, 0x1b, 0xd3,
|
||||
0x45, 0xae, 0x00, 0x5b, 0x01, 0xbe, 0x87, 0xcc, 0x39, 0x6d, 0xf9, 0x4c, 0x7a, 0x2d, 0x27, 0x10,
|
||||
0x9d, 0x48, 0xe1, 0x96, 0xc2, 0x65, 0x5a, 0xa2, 0x5a, 0x83, 0xb5, 0xcc, 0x05, 0x17, 0xf9, 0xd2,
|
||||
0xc9, 0x56, 0x45, 0xb5, 0xf1, 0xd3, 0x80, 0xda, 0x01, 0xf2, 0x57, 0x51, 0x47, 0x92, 0x15, 0x98,
|
||||
0x45, 0x16, 0x85, 0x2c, 0x36, 0x8d, 0x0d, 0xa3, 0x39, 0xe7, 0xaa, 0x1d, 0xb9, 0x03, 0xf3, 0x4a,
|
||||
0xf8, 0x91, 0xec, 0xf7, 0x98, 0x39, 0x95, 0xa3, 0x75, 0x55, 0x3b, 0xec, 0xf7, 0x18, 0xa1, 0x50,
|
||||
0xeb, 0x32, 0x44, 0x8f, 0x33, 0xb3, 0xba, 0x61, 0x34, 0xeb, 0xdb, 0xcb, 0xb4, 0xb0, 0x47, 0xb5,
|
||||
0x3d, 0xba, 0x1b, 0xf5, 0x5d, 0x4d, 0x22, 0x1e, 0xcc, 0xb4, 0x93, 0x28, 0x44, 0x73, 0x7a, 0xa3,
|
||||
0xda, 0xac, 0x6f, 0xaf, 0x52, 0x15, 0x50, 0x66, 0x8c, 0x2a, 0xe9, 0x74, 0x5f, 0x74, 0xa2, 0xbd,
|
||||
0xad, 0xf3, 0x6f, 0xeb, 0x95, 0xcf, 0xdf, 0xd7, 0x9b, 0xbc, 0x23, 0xdf, 0x26, 0x3e, 0x0d, 0x44,
|
||||
0xd7, 0x51, 0x2e, 0x8b, 0x9f, 0xc7, 0x18, 0x1e, 0x3b, 0x99, 0x2e, 0xcc, 0x1b, 0xd0, 0x2d, 0x26,
|
||||
0xef, 0xd4, 0x3f, 0x5c, 0x9d, 0x6d, 0x2a, 0x0b, 0x8d, 0x13, 0x58, 0x52, 0x2e, 0x5d, 0x86, 0x3d,
|
||||
0x11, 0x21, 0x23, 0x0f, 0x61, 0x49, 0xbb, 0xf2, 0xc2, 0x30, 0x66, 0x88, 0xca, 0xf6, 0xa2, 0x2a,
|
||||
0xef, 0x16, 0x55, 0xb2, 0x05, 0xff, 0xc5, 0xaa, 0x29, 0xb7, 0x3e, 0xce, 0x5c, 0xc9, 0x6a, 0x7c,
|
||||
0x35, 0x00, 0x0e, 0x90, 0x3f, 0x4f, 0x59, 0x90, 0x48, 0x36, 0x36, 0xd7, 0x15, 0x98, 0x95, 0x5e,
|
||||
0xcc, 0x99, 0x54, 0x89, 0xaa, 0xdd, 0x3f, 0x1f, 0xe6, 0x0b, 0x20, 0x43, 0x77, 0x65, 0x9e, 0xa3,
|
||||
0x31, 0x19, 0x37, 0x8a, 0xa9, 0x0d, 0xff, 0x0f, 0xe7, 0xec, 0x25, 0x51, 0x78, 0xc2, 0x88, 0x09,
|
||||
0x35, 0x3f, 0x5f, 0xe9, 0xb0, 0xf4, 0x96, 0x6c, 0x42, 0x55, 0xa6, 0x68, 0x4e, 0xe5, 0x1e, 0x4d,
|
||||
0xed, 0x51, 0xa6, 0xa5, 0xc3, 0xc3, 0xd4, 0xf5, 0xde, 0xb9, 0x19, 0x69, 0x67, 0x3e, 0x93, 0xab,
|
||||
0x3b, 0x1b, 0x6d, 0xb8, 0x55, 0x4c, 0x0f, 0x0f, 0xd3, 0x52, 0xee, 0x33, 0x58, 0x64, 0x29, 0x0b,
|
||||
0x8e, 0xb4, 0x1a, 0x9c, 0x28, 0x7a, 0x21, 0xe3, 0xea, 0x5e, 0x24, 0xcb, 0x30, 0xc3, 0xe2, 0x58,
|
||||
0xc4, 0xea, 0xe2, 0x8a, 0x4d, 0xe3, 0x08, 0xcc, 0x3f, 0xfd, 0x94, 0xc7, 0xed, 0xc3, 0xdc, 0xe8,
|
||||
0x49, 0x99, 0x87, 0xfb, 0xf4, 0xfa, 0xab, 0x40, 0xaf, 0x09, 0x75, 0x87, 0x7d, 0xdb, 0x1f, 0xa7,
|
||||
0xa0, 0x7a, 0x80, 0x9c, 0xbc, 0x84, 0xe9, 0xfc, 0x0f, 0xbb, 0xf6, 0xb7, 0x09, 0xea, 0x3b, 0xb7,
|
||||
0xee, 0x4e, 0x00, 0x4b, 0x59, 0xaf, 0xa1, 0xa6, 0xbf, 0x52, 0x7b, 0x0c, 0x5f, 0xe1, 0xd6, 0x83,
|
||||
0xc9, 0x78, 0x39, 0x32, 0x80, 0x85, 0xdf, 0xaf, 0xf4, 0xde, 0xe4, 0xc6, 0x82, 0x65, 0x3d, 0xba,
|
||||
0x09, 0x4b, 0x1f, 0x62, 0xcd, 0xbc, 0xbf, 0x3a, 0xdb, 0x34, 0xf6, 0x9e, 0x9e, 0x5f, 0xda, 0xc6,
|
||||
0xc5, 0xa5, 0x6d, 0xfc, 0xb8, 0xb4, 0x8d, 0x4f, 0x03, 0xbb, 0x72, 0x31, 0xb0, 0x2b, 0x5f, 0x06,
|
||||
0x76, 0xe5, 0x8d, 0x7a, 0x09, 0x31, 0x3c, 0xa6, 0x1d, 0xe1, 0xa4, 0xa3, 0xcf, 0xb2, 0x3f, 0x9b,
|
||||
0x5f, 0xed, 0x93, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xc4, 0x6a, 0x98, 0xb0, 0xb3, 0x05, 0x00,
|
||||
0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@ -818,10 +875,10 @@ func (m *MsgExecuteBundle) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Operations) > 0 {
|
||||
for iNdEx := len(m.Operations) - 1; iNdEx >= 0; iNdEx-- {
|
||||
if len(m.Txs) > 0 {
|
||||
for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
size, err := m.Operations[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||
size, err := m.Txs[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -842,6 +899,48 @@ func (m *MsgExecuteBundle) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *BundledTxResponse) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *BundledTxResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *BundledTxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Error) > 0 {
|
||||
i -= len(m.Error)
|
||||
copy(dAtA[i:], m.Error)
|
||||
i = encodeVarintTx(dAtA, i, uint64(len(m.Error)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if m.ExecResponses != nil {
|
||||
{
|
||||
size, err := m.ExecResponses.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintTx(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *MsgExecuteBundleResponse) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
@ -984,8 +1083,8 @@ func (m *MsgExecuteBundle) Size() (n int) {
|
||||
if l > 0 {
|
||||
n += 1 + l + sovTx(uint64(l))
|
||||
}
|
||||
if len(m.Operations) > 0 {
|
||||
for _, e := range m.Operations {
|
||||
if len(m.Txs) > 0 {
|
||||
for _, e := range m.Txs {
|
||||
l = e.Size()
|
||||
n += 1 + l + sovTx(uint64(l))
|
||||
}
|
||||
@ -993,6 +1092,23 @@ func (m *MsgExecuteBundle) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *BundledTxResponse) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.ExecResponses != nil {
|
||||
l = m.ExecResponses.Size()
|
||||
n += 1 + l + sovTx(uint64(l))
|
||||
}
|
||||
l = len(m.Error)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovTx(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *MsgExecuteBundleResponse) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
@ -1649,7 +1765,7 @@ func (m *MsgExecuteBundle) Unmarshal(dAtA []byte) error {
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Operations", wireType)
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Txs", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
@ -1676,8 +1792,8 @@ func (m *MsgExecuteBundle) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Operations = append(m.Operations, &UserOperation{})
|
||||
if err := m.Operations[len(m.Operations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
m.Txs = append(m.Txs, &tx.TxRaw{})
|
||||
if err := m.Txs[len(m.Txs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
@ -1702,6 +1818,124 @@ func (m *MsgExecuteBundle) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *BundledTxResponse) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTx
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: BundledTxResponse: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: BundledTxResponse: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ExecResponses", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTx
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.ExecResponses == nil {
|
||||
m.ExecResponses = &types.Any{}
|
||||
}
|
||||
if err := m.ExecResponses.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTx
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Error = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipTx(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *MsgExecuteBundleResponse) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
@ -1760,7 +1994,7 @@ func (m *MsgExecuteBundleResponse) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Responses = append(m.Responses, &UserOperationResponse{})
|
||||
m.Responses = append(m.Responses, &BundledTxResponse{})
|
||||
if err := m.Responses[len(m.Responses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -13,13 +13,14 @@ import (
|
||||
|
||||
// HandlerOptions are the options required for constructing a default SDK AnteHandler.
|
||||
type HandlerOptions struct {
|
||||
AccountKeeper AccountKeeper
|
||||
BankKeeper types.BankKeeper
|
||||
ExtensionOptionChecker ExtensionOptionChecker
|
||||
FeegrantKeeper FeegrantKeeper
|
||||
SignModeHandler *txsigning.HandlerMap
|
||||
SigGasConsumer func(meter storetypes.GasMeter, sig signing.SignatureV2, params types.Params) error
|
||||
TxFeeChecker TxFeeChecker
|
||||
AccountKeeper AccountKeeper
|
||||
AccountAbstractionKeeper AccountAbstractionKeeper
|
||||
BankKeeper types.BankKeeper
|
||||
ExtensionOptionChecker ExtensionOptionChecker
|
||||
FeegrantKeeper FeegrantKeeper
|
||||
SignModeHandler *txsigning.HandlerMap
|
||||
SigGasConsumer func(meter storetypes.GasMeter, sig signing.SignatureV2, params types.Params) error
|
||||
TxFeeChecker TxFeeChecker
|
||||
}
|
||||
|
||||
// NewAnteHandler returns an AnteHandler that checks and increments sequence
|
||||
@ -47,7 +48,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
||||
NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
|
||||
NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
|
||||
NewValidateSigCountDecorator(options.AccountKeeper),
|
||||
NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler, options.SigGasConsumer),
|
||||
NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler, options.SigGasConsumer, options.AccountAbstractionKeeper),
|
||||
}
|
||||
|
||||
return sdk.ChainAnteDecorators(anteDecorators...), nil
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
@ -11,6 +12,7 @@ import (
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
aa_interface_v1 "cosmossdk.io/x/accounts/interfaces/account_abstraction/v1"
|
||||
authsigning "cosmossdk.io/x/auth/signing"
|
||||
"cosmossdk.io/x/auth/types"
|
||||
txsigning "cosmossdk.io/x/tx/signing"
|
||||
@ -24,6 +26,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
)
|
||||
|
||||
@ -46,6 +49,11 @@ func init() {
|
||||
// This is where apps can define their own PubKey
|
||||
type SignatureVerificationGasConsumer = func(meter storetypes.GasMeter, sig signing.SignatureV2, params types.Params) error
|
||||
|
||||
type AccountAbstractionKeeper interface {
|
||||
IsAbstractedAccount(ctx context.Context, addr []byte) (bool, error)
|
||||
AuthenticateAccount(ctx context.Context, addr []byte, msg *aa_interface_v1.MsgAuthenticate) error
|
||||
}
|
||||
|
||||
// SigVerificationDecorator verifies all signatures for a tx and returns an
|
||||
// error if any are invalid.
|
||||
// It will populate an account's public key if that is not present only if
|
||||
@ -61,12 +69,14 @@ type SignatureVerificationGasConsumer = func(meter storetypes.GasMeter, sig sign
|
||||
// CONTRACT: Tx must implement SigVerifiableTx interface
|
||||
type SigVerificationDecorator struct {
|
||||
ak AccountKeeper
|
||||
aaKeeper AccountAbstractionKeeper
|
||||
signModeHandler *txsigning.HandlerMap
|
||||
sigGasConsumer SignatureVerificationGasConsumer
|
||||
}
|
||||
|
||||
func NewSigVerificationDecorator(ak AccountKeeper, signModeHandler *txsigning.HandlerMap, sigGasConsumer SignatureVerificationGasConsumer) SigVerificationDecorator {
|
||||
func NewSigVerificationDecorator(ak AccountKeeper, signModeHandler *txsigning.HandlerMap, sigGasConsumer SignatureVerificationGasConsumer, aaKeeper AccountAbstractionKeeper) SigVerificationDecorator {
|
||||
return SigVerificationDecorator{
|
||||
aaKeeper: aaKeeper,
|
||||
ak: ak,
|
||||
signModeHandler: signModeHandler,
|
||||
sigGasConsumer: sigGasConsumer,
|
||||
@ -176,7 +186,7 @@ func (svd SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
|
||||
}
|
||||
|
||||
for i := range signers {
|
||||
err = svd.authenticate(ctx, sigTx, signers[i], signatures[i], pubKeys[i])
|
||||
err = svd.authenticate(ctx, sigTx, signers[i], signatures[i], pubKeys[i], i)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
@ -209,7 +219,20 @@ func (svd SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
|
||||
}
|
||||
|
||||
// authenticate the authentication of the TX for a specific tx signer.
|
||||
func (svd SigVerificationDecorator) authenticate(ctx sdk.Context, tx authsigning.Tx, signer []byte, sig signing.SignatureV2, txPubKey cryptotypes.PubKey) error {
|
||||
func (svd SigVerificationDecorator) authenticate(ctx sdk.Context, tx authsigning.Tx, signer []byte, sig signing.SignatureV2, txPubKey cryptotypes.PubKey, signerIndex int) error {
|
||||
// first we check if it's an AA
|
||||
if svd.aaKeeper != nil {
|
||||
isAa, err := svd.aaKeeper.IsAbstractedAccount(ctx, signer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if isAa {
|
||||
return svd.authenticateAbstractedAccount(ctx, tx, signer, signerIndex)
|
||||
}
|
||||
}
|
||||
|
||||
// not an AA, proceed with standard auth flow.
|
||||
|
||||
// newlyCreated is a flag that indicates if the account was newly created.
|
||||
// This is only the case when the user is sending their first tx.
|
||||
newlyCreated := false
|
||||
@ -401,6 +424,27 @@ func (svd SigVerificationDecorator) increaseSequence(tx authsigning.Tx, acc sdk.
|
||||
return acc.SetSequence(acc.GetSequence() + 1)
|
||||
}
|
||||
|
||||
// authenticateAbstractedAccount computes an AA authentication instruction and invokes the auth flow on the AA.
|
||||
func (svd SigVerificationDecorator) authenticateAbstractedAccount(ctx sdk.Context, authTx authsigning.Tx, signer []byte, index int) error {
|
||||
// the bundler is the AA itself.
|
||||
selfBundler, err := svd.ak.AddressCodec().BytesToString(signer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
infoTx := authTx.(interface {
|
||||
GetRawTx() *tx.TxRaw
|
||||
GetProtoTx() *tx.Tx
|
||||
})
|
||||
|
||||
return svd.aaKeeper.AuthenticateAccount(ctx, signer, &aa_interface_v1.MsgAuthenticate{
|
||||
Bundler: selfBundler,
|
||||
RawTx: infoTx.GetRawTx(),
|
||||
Tx: infoTx.GetProtoTx(),
|
||||
SignerIndex: uint32(index),
|
||||
})
|
||||
}
|
||||
|
||||
// ValidateSigCountDecorator takes in Params and returns errors if there are too many signatures in the tx for the given params
|
||||
// otherwise it calls next AnteHandler
|
||||
// Use this decorator to set parameterized limit on number of signatures in tx
|
||||
|
||||
@ -145,7 +145,7 @@ func TestSigVerification(t *testing.T) {
|
||||
)
|
||||
require.NoError(t, err)
|
||||
noOpGasConsume := func(_ storetypes.GasMeter, _ signing.SignatureV2, _ types.Params) error { return nil }
|
||||
svd := ante.NewSigVerificationDecorator(suite.accountKeeper, anteTxConfig.SignModeHandler(), noOpGasConsume)
|
||||
svd := ante.NewSigVerificationDecorator(suite.accountKeeper, anteTxConfig.SignModeHandler(), noOpGasConsume, nil)
|
||||
antehandler := sdk.ChainAnteDecorators(svd)
|
||||
defaultSignMode, err := authsign.APISignModeToInternal(anteTxConfig.SignModeHandler().DefaultMode())
|
||||
require.NoError(t, err)
|
||||
@ -279,7 +279,7 @@ func runSigDecorators(t *testing.T, params types.Params, _ bool, privs ...crypto
|
||||
tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT)
|
||||
require.NoError(t, err)
|
||||
|
||||
svd := ante.NewSigVerificationDecorator(suite.accountKeeper, suite.clientCtx.TxConfig.SignModeHandler(), ante.DefaultSigVerificationGasConsumer)
|
||||
svd := ante.NewSigVerificationDecorator(suite.accountKeeper, suite.clientCtx.TxConfig.SignModeHandler(), ante.DefaultSigVerificationGasConsumer, nil)
|
||||
antehandler := sdk.ChainAnteDecorators(svd)
|
||||
|
||||
txBytes, err := suite.clientCtx.TxConfig.TxEncoder()(tx)
|
||||
@ -335,7 +335,7 @@ func TestAnteHandlerChecks(t *testing.T) {
|
||||
accs[i] = acc
|
||||
}
|
||||
|
||||
sigVerificationDecorator := ante.NewSigVerificationDecorator(suite.accountKeeper, anteTxConfig.SignModeHandler(), ante.DefaultSigVerificationGasConsumer)
|
||||
sigVerificationDecorator := ante.NewSigVerificationDecorator(suite.accountKeeper, anteTxConfig.SignModeHandler(), ante.DefaultSigVerificationGasConsumer, nil)
|
||||
|
||||
anteHandler := sdk.ChainAnteDecorators(sigVerificationDecorator)
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ require (
|
||||
cosmossdk.io/log v1.3.1
|
||||
cosmossdk.io/math v1.2.0
|
||||
cosmossdk.io/store v1.0.2
|
||||
cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/x/bank v0.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/x/tx v0.13.0
|
||||
@ -168,6 +169,7 @@ replace github.com/cosmos/cosmos-sdk => ../../.
|
||||
replace (
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
cosmossdk.io/x/staking => ../staking
|
||||
cosmossdk.io/x/tx => ../tx
|
||||
|
||||
@ -423,6 +423,14 @@ func (w *wrapper) GetProtoTx() *tx.Tx {
|
||||
return w.tx
|
||||
}
|
||||
|
||||
func (w *wrapper) GetRawTx() *tx.TxRaw {
|
||||
return &tx.TxRaw{
|
||||
BodyBytes: w.bodyBz,
|
||||
AuthInfoBytes: w.authInfoBz,
|
||||
Signatures: w.tx.Signatures,
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated: AsAny extracts proto Tx and wraps it into Any.
|
||||
// NOTE: You should probably use `GetProtoTx` if you want to serialize the transaction.
|
||||
func (w *wrapper) AsAny() *codectypes.Any {
|
||||
|
||||
@ -27,6 +27,8 @@ require (
|
||||
google.golang.org/protobuf v1.32.0
|
||||
)
|
||||
|
||||
require cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
|
||||
require github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
|
||||
|
||||
require (
|
||||
@ -170,6 +172,7 @@ replace (
|
||||
cosmossdk.io/api => ../../api
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/auth => ../auth
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
cosmossdk.io/x/staking => ../staking
|
||||
|
||||
@ -26,6 +26,8 @@ require (
|
||||
gotest.tools/v3 v3.5.1
|
||||
)
|
||||
|
||||
require cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
|
||||
require github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
|
||||
|
||||
require (
|
||||
@ -168,6 +170,7 @@ replace github.com/cosmos/cosmos-sdk => ../../.
|
||||
replace (
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/auth => ../auth
|
||||
cosmossdk.io/x/staking => ../staking
|
||||
cosmossdk.io/x/tx => ../tx
|
||||
|
||||
@ -23,6 +23,7 @@ require (
|
||||
|
||||
require (
|
||||
cosmossdk.io/math v1.2.0 // indirect
|
||||
cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/bank v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/tx v0.13.0 // indirect
|
||||
@ -167,6 +168,7 @@ replace github.com/cosmos/cosmos-sdk => ../../.
|
||||
replace (
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/auth => ../auth
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
cosmossdk.io/x/staking => ../staking
|
||||
|
||||
@ -31,6 +31,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
|
||||
github.com/cometbft/cometbft v0.38.5 // indirect
|
||||
)
|
||||
@ -171,6 +172,7 @@ replace github.com/cosmos/cosmos-sdk => ../../.
|
||||
replace (
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/auth => ../auth
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
cosmossdk.io/x/staking => ../staking
|
||||
|
||||
@ -26,6 +26,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/bank v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect
|
||||
@ -167,6 +168,7 @@ replace github.com/cosmos/cosmos-sdk => ../../.
|
||||
replace (
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/auth => ../auth
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
cosmossdk.io/x/staking => ../staking
|
||||
|
||||
@ -28,6 +28,8 @@ require (
|
||||
gotest.tools/v3 v3.5.1
|
||||
)
|
||||
|
||||
require cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
|
||||
require github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
|
||||
|
||||
require (
|
||||
@ -171,6 +173,7 @@ replace github.com/cosmos/cosmos-sdk => ../../.
|
||||
replace (
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/auth => ../auth
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
cosmossdk.io/x/gov => ../gov
|
||||
|
||||
@ -33,6 +33,8 @@ require (
|
||||
gotest.tools/v3 v3.5.1
|
||||
)
|
||||
|
||||
require cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
|
||||
require github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
|
||||
|
||||
require (
|
||||
@ -172,6 +174,7 @@ replace (
|
||||
cosmossdk.io/api => ../../api
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/auth => ../auth
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
cosmossdk.io/x/staking => ../staking
|
||||
|
||||
@ -37,6 +37,7 @@ require (
|
||||
|
||||
require (
|
||||
cosmossdk.io/collections v0.4.0 // indirect
|
||||
cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/tx v0.13.0 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
|
||||
@ -174,6 +175,7 @@ replace (
|
||||
cosmossdk.io/api => ../../api
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/auth => ../auth
|
||||
cosmossdk.io/x/authz => ../authz
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
|
||||
@ -23,6 +23,8 @@ require (
|
||||
gotest.tools/v3 v3.5.1
|
||||
)
|
||||
|
||||
require cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
|
||||
require github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
|
||||
|
||||
require (
|
||||
@ -169,6 +171,7 @@ replace github.com/cosmos/cosmos-sdk => ../../.
|
||||
replace (
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/auth => ../auth
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
cosmossdk.io/x/staking => ../staking
|
||||
|
||||
@ -23,6 +23,7 @@ require (
|
||||
|
||||
require (
|
||||
cosmossdk.io/collections v0.4.0 // indirect
|
||||
cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/bank v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect
|
||||
@ -167,6 +168,7 @@ replace github.com/cosmos/cosmos-sdk => ../../.
|
||||
replace (
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/auth => ../auth
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
cosmossdk.io/x/staking => ../staking
|
||||
|
||||
@ -27,6 +27,7 @@ require (
|
||||
|
||||
require (
|
||||
cosmossdk.io/collections v0.4.0 // indirect
|
||||
cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/bank v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect
|
||||
@ -168,6 +169,7 @@ replace github.com/cosmos/cosmos-sdk => ../..
|
||||
replace (
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/auth => ../auth
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
cosmossdk.io/x/distribution => ../distribution
|
||||
|
||||
@ -26,6 +26,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/bank v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/tx v0.13.0 // indirect
|
||||
@ -167,6 +168,7 @@ replace github.com/cosmos/cosmos-sdk => ../../.
|
||||
replace (
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/auth => ../auth
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
cosmossdk.io/x/staking => ../staking
|
||||
|
||||
@ -30,6 +30,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/bank v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/tx v0.13.0 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
@ -169,6 +170,7 @@ replace github.com/cosmos/cosmos-sdk => ../../.
|
||||
replace (
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/auth => ../auth
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
cosmossdk.io/x/staking => ../staking
|
||||
|
||||
@ -29,6 +29,8 @@ require (
|
||||
gotest.tools/v3 v3.5.1
|
||||
)
|
||||
|
||||
require cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
|
||||
require github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
|
||||
|
||||
require (
|
||||
@ -168,6 +170,7 @@ replace github.com/cosmos/cosmos-sdk => ../../.
|
||||
replace (
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/auth => ../auth
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
cosmossdk.io/x/tx => ../tx
|
||||
|
||||
@ -38,6 +38,7 @@ require (
|
||||
cloud.google.com/go/storage v1.36.0 // indirect
|
||||
cosmossdk.io/collections v0.4.0 // indirect
|
||||
cosmossdk.io/math v1.2.0 // indirect
|
||||
cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/bank v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect
|
||||
cosmossdk.io/x/tx v0.13.0 // indirect
|
||||
@ -202,6 +203,7 @@ replace github.com/cosmos/cosmos-sdk => ../../.
|
||||
replace (
|
||||
cosmossdk.io/core => ../../core
|
||||
cosmossdk.io/depinject => ../../depinject
|
||||
cosmossdk.io/x/accounts => ../accounts
|
||||
cosmossdk.io/x/auth => ../auth
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
cosmossdk.io/x/gov => ../gov
|
||||
|
||||
Loading…
Reference in New Issue
Block a user