diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/accountplus/tx.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/accountplus/tx.ts index bf7b78452a..92840d1662 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/accountplus/tx.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/accountplus/tx.ts @@ -71,13 +71,15 @@ export interface MsgRemoveAuthenticatorResponseSDKType { /** MsgSetActiveState sets the active state of the module. */ export interface MsgSetActiveState { - sender: string; + /** Authority is the address that may send this message. */ + authority: string; active: boolean; } /** MsgSetActiveState sets the active state of the module. */ export interface MsgSetActiveStateSDKType { - sender: string; + /** Authority is the address that may send this message. */ + authority: string; active: boolean; } /** MsgSetActiveStateResponse defines the Msg/SetActiveState response type. */ @@ -323,15 +325,15 @@ export const MsgRemoveAuthenticatorResponse = { function createBaseMsgSetActiveState(): MsgSetActiveState { return { - sender: "", + authority: "", active: false }; } export const MsgSetActiveState = { encode(message: MsgSetActiveState, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.sender !== "") { - writer.uint32(10).string(message.sender); + if (message.authority !== "") { + writer.uint32(10).string(message.authority); } if (message.active === true) { @@ -351,7 +353,7 @@ export const MsgSetActiveState = { switch (tag >>> 3) { case 1: - message.sender = reader.string(); + message.authority = reader.string(); break; case 2: @@ -369,7 +371,7 @@ export const MsgSetActiveState = { fromPartial(object: DeepPartial): MsgSetActiveState { const message = createBaseMsgSetActiveState(); - message.sender = object.sender ?? ""; + message.authority = object.authority ?? ""; message.active = object.active ?? false; return message; } diff --git a/proto/dydxprotocol/accountplus/tx.proto b/proto/dydxprotocol/accountplus/tx.proto index 9f901688d2..30ff59f33b 100644 --- a/proto/dydxprotocol/accountplus/tx.proto +++ b/proto/dydxprotocol/accountplus/tx.proto @@ -1,6 +1,7 @@ syntax = "proto3"; package dydxprotocol.accountplus; +import "cosmos_proto/cosmos.proto"; import "cosmos/msg/v1/msg.proto"; import "amino/amino.proto"; @@ -50,9 +51,10 @@ message MsgRemoveAuthenticatorResponse { bool success = 1; } // MsgSetActiveState sets the active state of the module. message MsgSetActiveState { option (amino.name) = "osmosis/smartaccount/set-active-state"; - option (cosmos.msg.v1.signer) = "sender"; + option (cosmos.msg.v1.signer) = "authority"; - string sender = 1; + // Authority is the address that may send this message. + string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; bool active = 2; } diff --git a/protocol/app/app.go b/protocol/app/app.go index 6b5dbdd0fb..d06428fb23 100644 --- a/protocol/app/app.go +++ b/protocol/app/app.go @@ -1225,6 +1225,9 @@ func New( appCodec, keys[accountplusmoduletypes.StoreKey], app.AuthenticatorManager, + []string{ + lib.GovModuleAddress.String(), + }, ) accountplusModule := accountplusmodule.NewAppModule(appCodec, app.AccountPlusKeeper) diff --git a/protocol/testutil/ante/testutil.go b/protocol/testutil/ante/testutil.go index a245fe4e89..e49442d42e 100644 --- a/protocol/testutil/ante/testutil.go +++ b/protocol/testutil/ante/testutil.go @@ -16,6 +16,7 @@ import ( txtestutil "github.com/cosmos/cosmos-sdk/x/auth/tx/testutil" "github.com/cosmos/cosmos-sdk/x/bank" v4module "github.com/dydxprotocol/v4-chain/protocol/app/module" + "github.com/dydxprotocol/v4-chain/protocol/lib" "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/authenticator" accountpluskeeper "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/keeper" accountplustypes "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/types" @@ -116,6 +117,9 @@ func SetupTestSuite(t testing.TB, isCheckTx bool) *AnteTestSuite { suite.EncCfg.Codec, keys[accountplustypes.StoreKey], authenticator.NewAuthenticatorManager(), + []string{ + lib.GovModuleAddress.String(), + }, ) // We're using TestMsg encoding in some tests, so register it here. diff --git a/protocol/testutil/keeper/accountplus.go b/protocol/testutil/keeper/accountplus.go index 6b1ea4c6ab..d518aace3f 100644 --- a/protocol/testutil/keeper/accountplus.go +++ b/protocol/testutil/keeper/accountplus.go @@ -6,6 +6,7 @@ import ( dbm "github.com/cosmos/cosmos-db" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/dydxprotocol/v4-chain/protocol/lib" "github.com/dydxprotocol/v4-chain/protocol/x/revshare/types" storetypes "cosmossdk.io/store/types" @@ -57,6 +58,9 @@ func createTimestampNonceKeeper( cdc, storeKey, authenticator.NewAuthenticatorManager(), + []string{ + lib.GovModuleAddress.String(), + }, ) return k, storeKey, mockTimeProvider diff --git a/protocol/x/accountplus/keeper/authenticators.go b/protocol/x/accountplus/keeper/authenticators.go new file mode 100644 index 0000000000..4d604206c1 --- /dev/null +++ b/protocol/x/accountplus/keeper/authenticators.go @@ -0,0 +1,108 @@ +package keeper + +import ( + "fmt" + "strconv" + + "cosmossdk.io/errors" + "cosmossdk.io/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + gogotypes "github.com/cosmos/gogoproto/types" + "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/types" +) + +// AddAuthenticator adds an authenticator to an account, this function is used to add multiple +// authenticators such as SignatureVerifications and AllOfs +func (k Keeper) AddAuthenticator( + ctx sdk.Context, + account sdk.AccAddress, + authenticatorType string, + config []byte, +) (uint64, error) { + impl := k.authenticatorManager.GetAuthenticatorByType(authenticatorType) + if impl == nil { + return 0, fmt.Errorf("authenticator type %s is not registered", authenticatorType) + } + + // Get the next global id value for authenticators from the store + id := k.InitializeOrGetNextAuthenticatorId(ctx) + + // Each authenticator has a custom OnAuthenticatorAdded function + err := impl.OnAuthenticatorAdded(ctx, account, config, strconv.FormatUint(id, 10)) + if err != nil { + return 0, errors.Wrapf(err, "`OnAuthenticatorAdded` failed on authenticator type %s", authenticatorType) + } + + k.SetNextAuthenticatorId(ctx, id+1) + + store := prefix.NewStore( + ctx.KVStore(k.storeKey), + []byte(types.AuthenticatorKeyPrefix), + ) + authenticator := types.AccountAuthenticator{ + Id: id, + Type: authenticatorType, + Config: config, + } + b := k.cdc.MustMarshal(&authenticator) + store.Set(types.KeyAccountId(account, id), b) + return id, nil +} + +// RemoveAuthenticator removes an authenticator from an account +func (k Keeper) RemoveAuthenticator(ctx sdk.Context, account sdk.AccAddress, authenticatorId uint64) error { + store := prefix.NewStore( + ctx.KVStore(k.storeKey), + []byte(types.AuthenticatorKeyPrefix), + ) + key := types.KeyAccountId(account, authenticatorId) + + var existing types.AccountAuthenticator + bz := store.Get(key) + if bz == nil { + return errors.Wrapf( + types.ErrAuthenticatorNotFound, + "RemoveAuthenticator: failed to get authenticator %d for address %s", + authenticatorId, + account.String(), + ) + } + k.cdc.MustUnmarshal(bz, &existing) + + impl := k.authenticatorManager.GetAuthenticatorByType(existing.Type) + if impl == nil { + return fmt.Errorf("authenticator type %s is not registered", existing.Type) + } + + // Authenticators can prevent removal. This should be used sparingly + err := impl.OnAuthenticatorRemoved(ctx, account, existing.Config, strconv.FormatUint(authenticatorId, 10)) + if err != nil { + return errors.Wrapf(err, "`OnAuthenticatorRemoved` failed on authenticator type %s", existing.Type) + } + + store.Delete(key) + return nil +} + +// InitializeOrGetNextAuthenticatorId returns the next authenticator id. +func (k Keeper) InitializeOrGetNextAuthenticatorId(ctx sdk.Context) uint64 { + store := ctx.KVStore(k.storeKey) + + b := store.Get([]byte(types.AuthenticatorIdKeyPrefix)) + if b == nil { + return 0 + } + + result := gogotypes.UInt64Value{Value: 0} + k.cdc.MustUnmarshal(b, &result) + return result.Value +} + +// SetNextAuthenticatorId sets next authenticator id. +func (k Keeper) SetNextAuthenticatorId(ctx sdk.Context, authenticatorId uint64) { + value := gogotypes.UInt64Value{Value: authenticatorId} + b := k.cdc.MustMarshal(&value) + + store := ctx.KVStore(k.storeKey) + store.Set([]byte(types.AuthenticatorIdKeyPrefix), b) +} diff --git a/protocol/x/accountplus/keeper/keeper.go b/protocol/x/accountplus/keeper/keeper.go index e330826f02..def0ced51e 100644 --- a/protocol/x/accountplus/keeper/keeper.go +++ b/protocol/x/accountplus/keeper/keeper.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/dydxprotocol/v4-chain/protocol/lib" "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/authenticator" "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/types" ) @@ -18,18 +19,20 @@ type Keeper struct { storeKey storetypes.StoreKey authenticatorManager *authenticator.AuthenticatorManager + authorities map[string]struct{} } func NewKeeper( cdc codec.BinaryCodec, key storetypes.StoreKey, authenticatorManager *authenticator.AuthenticatorManager, + authorities []string, ) *Keeper { return &Keeper{ - cdc: cdc, - storeKey: key, - + cdc: cdc, + storeKey: key, authenticatorManager: authenticatorManager, + authorities: lib.UniqueSliceToSet(authorities), } } @@ -118,3 +121,8 @@ func (k Keeper) SetAccountState( bz := k.cdc.MustMarshal(&accountState) store.Set(address.Bytes(), bz) } + +func (k Keeper) HasAuthority(authority string) bool { + _, ok := k.authorities[authority] + return ok +} diff --git a/protocol/x/accountplus/keeper/keeper_test.go b/protocol/x/accountplus/keeper/keeper_test.go index 07c3f212a8..89deb898df 100644 --- a/protocol/x/accountplus/keeper/keeper_test.go +++ b/protocol/x/accountplus/keeper/keeper_test.go @@ -1,4 +1,137 @@ package keeper_test +import ( + "encoding/hex" + "testing" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/stretchr/testify/suite" + + testapp "github.com/dydxprotocol/v4-chain/protocol/testutil/app" + "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/authenticator" + "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/testutils" + "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/types" +) + // TODO: add explicit unit tests for Get and Set funcs // https://linear.app/dydx/issue/OTE-633/add-explicit-unit-tests-for-get-and-set-methods-for-accountplus-keeper + +type KeeperTestSuite struct { + suite.Suite + + tApp *testapp.TestApp + Ctx sdk.Context +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestSuite)) +} + +func (s *KeeperTestSuite) SetupTest() { + s.tApp = testapp.NewTestAppBuilder(s.T()).Build() + s.Ctx = s.tApp.InitChain() + + s.tApp.App.AuthenticatorManager.ResetAuthenticators() + s.tApp.App.AuthenticatorManager.InitializeAuthenticators( + []authenticator.Authenticator{ + authenticator.SignatureVerification{}, + authenticator.MessageFilter{}, + testutils.TestingAuthenticator{ + Approve: testutils.Always, + GasConsumption: 10, + Confirm: testutils.Always, + }, + }, + ) + s.tApp.App.AccountPlusKeeper.SetParams( + s.Ctx, + types.Params{ + IsSmartAccountActive: true, + }, + ) +} + +func (s *KeeperTestSuite) TestKeeper_AddAuthenticator() { + ctx := s.Ctx + + // Set up account + key := "6cf5103c60c939a5f38e383b52239c5296c968579eec1c68a47d70fbf1d19159" + bz, _ := hex.DecodeString(key) + priv := &secp256k1.PrivKey{Key: bz} + accAddress := sdk.AccAddress(priv.PubKey().Address()) + + id, err := s.tApp.App.AccountPlusKeeper.AddAuthenticator( + ctx, + accAddress, + "SignatureVerification", + priv.PubKey().Bytes(), + ) + s.Require().NoError(err, "Should successfully add a SignatureVerification") + s.Require().Equal(id, uint64(0), "Adding authenticator returning incorrect id") + + id, err = s.tApp.App.AccountPlusKeeper.AddAuthenticator( + ctx, + accAddress, + "MessageFilter", + []byte("/cosmos.bank.v1beta1.MsgSend"), + ) + s.Require().NoError(err, "Should successfully add a MessageFilter") + s.Require().Equal(id, uint64(1), "Adding authenticator returning incorrect id") + + _, err = s.tApp.App.AccountPlusKeeper.AddAuthenticator( + ctx, + accAddress, + "SignatureVerification", + []byte("BrokenBytes"), + ) + s.Require().Error(err, "Should have failed as OnAuthenticatorAdded fails") + + s.tApp.App.AuthenticatorManager.ResetAuthenticators() + _, err = s.tApp.App.AccountPlusKeeper.AddAuthenticator( + ctx, + accAddress, + "MessageFilter", + []byte("/cosmos.bank.v1beta1.MsgSend"), + ) + s.Require().Error(err, "Authenticator not registered so should fail") +} + +func (s *KeeperTestSuite) TestKeeper_GetAndSetAuthenticatorId() { + ctx := s.Ctx + + authenticatorId := s.tApp.App.AccountPlusKeeper.InitializeOrGetNextAuthenticatorId(ctx) + s.Require().Equal(uint64(0), authenticatorId, "Initialize/Get authenticator id returned incorrect id") + + authenticatorId = s.tApp.App.AccountPlusKeeper.InitializeOrGetNextAuthenticatorId(ctx) + s.Require().Equal(uint64(0), authenticatorId, "Initialize/Get authenticator id returned incorrect id") + + // Set up account + key := "6cf5103c60c939a5f38e383b52239c5296c968579eec1c68a47d70fbf1d19159" + bz, _ := hex.DecodeString(key) + priv := &secp256k1.PrivKey{Key: bz} + accAddress := sdk.AccAddress(priv.PubKey().Address()) + + _, err := s.tApp.App.AccountPlusKeeper.AddAuthenticator( + ctx, + accAddress, + "SignatureVerification", + priv.PubKey().Bytes(), + ) + s.Require().NoError(err, "Should successfully add a SignatureVerification") + + authenticatorId = s.tApp.App.AccountPlusKeeper.InitializeOrGetNextAuthenticatorId(ctx) + s.Require().Equal(authenticatorId, uint64(1), "Initialize/Get authenticator id returned incorrect id") + + _, err = s.tApp.App.AccountPlusKeeper.AddAuthenticator( + ctx, + accAddress, + "SignatureVerification", + priv.PubKey().Bytes(), + ) + s.Require().NoError(err, "Should successfully add a MessageFilter") + + authenticatorId = s.tApp.App.AccountPlusKeeper.InitializeOrGetNextAuthenticatorId(ctx) + s.Require().Equal(authenticatorId, uint64(2), "Initialize/Get authenticator id returned incorrect id") +} diff --git a/protocol/x/accountplus/keeper/msg_server.go b/protocol/x/accountplus/keeper/msg_server.go new file mode 100644 index 0000000000..ed490ffd44 --- /dev/null +++ b/protocol/x/accountplus/keeper/msg_server.go @@ -0,0 +1,103 @@ +package keeper + +import ( + "context" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/types" +) + +type msgServer struct { + Keeper +} + +// NewMsgServerImpl returns an implementation of the MsgServer interface +// for the provided Keeper. +func NewMsgServerImpl(keeper Keeper) types.MsgServer { + return &msgServer{Keeper: keeper} +} + +var _ types.MsgServer = msgServer{} + +// AddAuthenticator allows the addition of various types of authenticators to an account. +// This method serves as a versatile function for adding diverse authenticator types +// to an account, making it highly adaptable for different use cases. +func (m msgServer) AddAuthenticator( + goCtx context.Context, + msg *types.MsgAddAuthenticator, +) (*types.MsgAddAuthenticatorResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + isSmartAccountActive := m.GetIsSmartAccountActive(ctx) + if !isSmartAccountActive { + return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "smart account authentication flow is not active") + } + + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, errorsmod.Wrap(err, "invalid sender address") + } + + // Finally, add the authenticator to the store. + _, err = m.Keeper.AddAuthenticator(ctx, sender, msg.AuthenticatorType, msg.Data) + if err != nil { + return nil, err + } + + return &types.MsgAddAuthenticatorResponse{ + Success: true, + }, nil +} + +// RemoveAuthenticator removes an authenticator from the store. The message specifies a sender address and an index. +func (m msgServer) RemoveAuthenticator( + goCtx context.Context, + msg *types.MsgRemoveAuthenticator, +) (*types.MsgRemoveAuthenticatorResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + isSmartAccountActive := m.GetIsSmartAccountActive(ctx) + if !isSmartAccountActive { + return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "smart account authentication flow is not active") + } + + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, errorsmod.Wrap(err, "invalid sender address") + } + + // At this point, we assume that verification has occurred on the account, and we + // proceed to remove the authenticator from the store. + err = m.Keeper.RemoveAuthenticator(ctx, sender, msg.Id) + if err != nil { + return nil, err + } + + return &types.MsgRemoveAuthenticatorResponse{ + Success: true, + }, nil +} + +// SetActiveState sets the active state of the smart account authentication flow. +func (m msgServer) SetActiveState( + goCtx context.Context, + msg *types.MsgSetActiveState, +) (*types.MsgSetActiveStateResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + if !m.Keeper.HasAuthority(msg.GetAuthority()) { + return nil, errorsmod.Wrapf( + sdkerrors.ErrUnauthorized, + "%v is not recognized as a valid authority for setting smart account active state", + msg.GetAuthority(), + ) + } + + // Set the active state of the authenticator + m.Keeper.SetActiveState(ctx, msg.Active) + + return &types.MsgSetActiveStateResponse{}, nil +} diff --git a/protocol/x/accountplus/keeper/msg_server_test.go b/protocol/x/accountplus/keeper/msg_server_test.go new file mode 100644 index 0000000000..355dedabf0 --- /dev/null +++ b/protocol/x/accountplus/keeper/msg_server_test.go @@ -0,0 +1,186 @@ +package keeper_test + +import ( + "encoding/hex" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/dydxprotocol/v4-chain/protocol/lib" + "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/authenticator" + "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/keeper" + "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/types" +) + +func (s *KeeperTestSuite) TestMsgServer_AddAuthenticator() { + msgServer := keeper.NewMsgServerImpl(s.tApp.App.AccountPlusKeeper) + ctx := s.Ctx + + // Ensure the SigVerificationAuthenticator type is registered + s.Require().True( + s.tApp.App.AuthenticatorManager.IsAuthenticatorTypeRegistered( + authenticator.SignatureVerification{}.Type(), + ), + ) + + // Set up account + key := "6cf5103c60c939a5f38e383b52239c5296c968579eec1c68a47d70fbf1d19159" + bz, _ := hex.DecodeString(key) + priv := &secp256k1.PrivKey{Key: bz} + accAddress := sdk.AccAddress(priv.PubKey().Address()) + + // Create a test message + msg := &types.MsgAddAuthenticator{ + Sender: accAddress.String(), + AuthenticatorType: authenticator.SignatureVerification{}.Type(), + Data: priv.PubKey().Bytes(), + } + + resp, err := msgServer.AddAuthenticator(ctx, msg) + s.Require().NoError(err) + s.Require().True(resp.Success) +} + +func (s *KeeperTestSuite) TestMsgServer_AddAuthenticatorFail() { + msgServer := keeper.NewMsgServerImpl(s.tApp.App.AccountPlusKeeper) + ctx := s.Ctx + + // Ensure the SigVerificationAuthenticator type is registered + s.Require().True( + s.tApp.App.AuthenticatorManager.IsAuthenticatorTypeRegistered( + authenticator.SignatureVerification{}.Type(), + ), + ) + + // Set up account + key := "6cf5103c60c939a5f38e383b52239c5296c968579eec1c68a47d70fbf1d19159" + bz, _ := hex.DecodeString(key) + priv := &secp256k1.PrivKey{Key: bz} + accAddress := sdk.AccAddress(priv.PubKey().Address()) + + // Create a test message + msg := &types.MsgAddAuthenticator{ + Sender: accAddress.String(), + AuthenticatorType: authenticator.SignatureVerification{}.Type(), + Data: priv.PubKey().Bytes(), + } + + msg.AuthenticatorType = "PassKeyAuthenticator" + _, err := msgServer.AddAuthenticator(ctx, msg) + s.Require().Error(err) +} + +func (s *KeeperTestSuite) TestMsgServer_RemoveAuthenticator() { + msgServer := keeper.NewMsgServerImpl(s.tApp.App.AccountPlusKeeper) + ctx := s.Ctx + + // Set up account + key := "6cf5103c60c939a5f38e383b52239c5296c968579eec1c68a47d70fbf1d19159" + bz, _ := hex.DecodeString(key) + priv := &secp256k1.PrivKey{Key: bz} + accAddress := sdk.AccAddress(priv.PubKey().Address()) + + // Create a test message + addMsg := &types.MsgAddAuthenticator{ + Sender: accAddress.String(), + AuthenticatorType: authenticator.SignatureVerification{}.Type(), + Data: priv.PubKey().Bytes(), + } + _, err := msgServer.AddAuthenticator(ctx, addMsg) + s.Require().NoError(err) + + // Now attempt to remove it + removeMsg := &types.MsgRemoveAuthenticator{ + Sender: accAddress.String(), + Id: 0, + } + + resp, err := msgServer.RemoveAuthenticator(ctx, removeMsg) + s.Require().NoError(err) + s.Require().True(resp.Success) +} + +func (s *KeeperTestSuite) TestMsgServer_SetActiveState() { + ak := s.tApp.App.AccountPlusKeeper + msgServer := keeper.NewMsgServerImpl(ak) + ctx := s.Ctx + + // Set up account + key := "0dd4d1506e18a5712080708c338eb51ecf2afdceae01e8162e890b126ac190fe" + bz, _ := hex.DecodeString(key) + priv := &secp256k1.PrivKey{Key: bz} + unauthorizedAccAddress := sdk.AccAddress(priv.PubKey().Address()) + + // activated by default + initialParams := s.tApp.App.AccountPlusKeeper.GetParams(ctx) + s.Require().True(initialParams.IsSmartAccountActive) + + // deactivate by unauthorized account + _, err := msgServer.SetActiveState( + ctx, + &types.MsgSetActiveState{ + Authority: unauthorizedAccAddress.String(), + Active: false, + }) + + s.Require().Error(err) + s.Require().Equal( + err.Error(), + "dydx1jns2dl6u55vy72g7r76l6cse7kmlj4me87xj2j is not recognized as a valid authority "+ + "for setting smart account active state: unauthorized", + ) + + // deactivate + _, err = msgServer.SetActiveState( + ctx, + &types.MsgSetActiveState{ + Authority: lib.GovModuleAddress.String(), + Active: false, + }) + + s.Require().NoError(err) + + // active state should be false + params := ak.GetParams(ctx) + s.Require().False(params.IsSmartAccountActive) + + // reactivate by gov + _, err = msgServer.SetActiveState( + ctx, + &types.MsgSetActiveState{ + Authority: lib.GovModuleAddress.String(), + Active: true, + }) + s.Require().NoError(err) + + // active state should be true + params = ak.GetParams(ctx) + s.Require().True(params.IsSmartAccountActive) +} + +func (s *KeeperTestSuite) TestMsgServer_SmartAccountsNotActive() { + msgServer := keeper.NewMsgServerImpl(s.tApp.App.AccountPlusKeeper) + ctx := s.Ctx + + s.tApp.App.AccountPlusKeeper.SetParams(s.Ctx, types.Params{IsSmartAccountActive: false}) + + // Create a test message + msg := &types.MsgAddAuthenticator{ + Sender: "", + AuthenticatorType: authenticator.SignatureVerification{}.Type(), + Data: []byte(""), + } + + _, err := msgServer.AddAuthenticator(ctx, msg) + s.Require().Error(err) + s.Require().Equal(err.Error(), "smart account authentication flow is not active: unauthorized") + + removeMsg := &types.MsgRemoveAuthenticator{ + Sender: "", + Id: 1, + } + + _, err = msgServer.RemoveAuthenticator(ctx, removeMsg) + s.Require().Error(err) + s.Require().Equal(err.Error(), "smart account authentication flow is not active: unauthorized") +} diff --git a/protocol/x/accountplus/keeper/params.go b/protocol/x/accountplus/keeper/params.go new file mode 100644 index 0000000000..fd69f9c100 --- /dev/null +++ b/protocol/x/accountplus/keeper/params.go @@ -0,0 +1,41 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/types" +) + +// GetParams get all parameters as types.Params +func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { + store := ctx.KVStore(k.storeKey) + bz := store.Get([]byte(types.ParamsKeyPrefix)) + if bz == nil { + return types.Params{ + IsSmartAccountActive: false, + } + } + + k.cdc.MustUnmarshal(bz, ¶ms) + return params +} + +// SetParams set the params +func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(¶ms) + store.Set([]byte(types.ParamsKeyPrefix), bz) +} + +// GetIsSmartAccountActive returns the value of the isSmartAccountActive parameter. +// If the value has not been set, it will return false. +func (k *Keeper) GetIsSmartAccountActive(ctx sdk.Context) bool { + return k.GetParams(ctx).IsSmartAccountActive +} + +// SetActiveState sets the active state of the smart account module. +func (k Keeper) SetActiveState(ctx sdk.Context, active bool) { + params := k.GetParams(ctx) + params.IsSmartAccountActive = active + k.SetParams(ctx, params) +} diff --git a/protocol/x/accountplus/types/errors.go b/protocol/x/accountplus/types/errors.go new file mode 100644 index 0000000000..48ad01cbd6 --- /dev/null +++ b/protocol/x/accountplus/types/errors.go @@ -0,0 +1,21 @@ +package types + +import errorsmod "cosmossdk.io/errors" + +var ( + ErrAuthenticatorNotFound = errorsmod.Register( + ModuleName, + 1, + "Authenticator is not found", + ) + ErrInvalidAccountAddress = errorsmod.Register( + ModuleName, + 2, + "Invalid account address", + ) + ErrAuthenticatorDataExceedsMaximumLength = errorsmod.Register( + ModuleName, + 3, + "Authenticator data exceeds maximum length", + ) +) diff --git a/protocol/x/accountplus/types/keys.go b/protocol/x/accountplus/types/keys.go index 3dbc04fc89..3844749bf3 100644 --- a/protocol/x/accountplus/types/keys.go +++ b/protocol/x/accountplus/types/keys.go @@ -1,5 +1,12 @@ package types +import ( + fmt "fmt" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + // Module name and store keys. const ( // The Account module uses "acc" as its module name. @@ -9,3 +16,31 @@ const ( // StoreKey defines the primary module store key. StoreKey = ModuleName ) + +// Below key prefixes are for smart account implementation. +const ( + // SmartAccountKeyPrefix is the prefix key for all smart account store state. + SmartAccountKeyPrefix = "SA/" + + // ParamsKeyPrefix is the prefix key for smart account params. + ParamsKeyPrefix = SmartAccountKeyPrefix + "P/" + + // AuthenticatorKeyPrefix is the prefix key for all authenticators. + AuthenticatorKeyPrefix = SmartAccountKeyPrefix + "A/" + + // AuthenticatorIdKeyPrefix is the prefix key for the next authenticator id. + AuthenticatorIdKeyPrefix = SmartAccountKeyPrefix + "ID/" +) + +func KeyAccountId(account sdk.AccAddress, id uint64) []byte { + return BuildKey(account.String(), id) +} + +// BuildKey creates a key by concatenating the provided elements with the key separator. +func BuildKey(elements ...interface{}) []byte { + strElements := make([]string, len(elements)) + for i, element := range elements { + strElements[i] = fmt.Sprint(element) + } + return []byte(strings.Join(strElements, "/") + "/") +} diff --git a/protocol/x/accountplus/types/message_add_authenticator.go b/protocol/x/accountplus/types/message_add_authenticator.go new file mode 100644 index 0000000000..557d3796a8 --- /dev/null +++ b/protocol/x/accountplus/types/message_add_authenticator.go @@ -0,0 +1,23 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const AUTHENTICATOR_DATA_MAX_LENGTH = 256 + +// ValidateBasic performs stateless validation for the `MsgAddAuthenticator` msg. +func (msg *MsgAddAuthenticator) ValidateBasic() (err error) { + // Validate account sender. + _, err = sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return ErrInvalidAccountAddress + } + + // Make sure that the authenticator data does not exceed the maximum length. + if len(msg.Data) > AUTHENTICATOR_DATA_MAX_LENGTH { + return ErrAuthenticatorDataExceedsMaximumLength + } + + return nil +} diff --git a/protocol/x/accountplus/types/message_add_authenticator_test.go b/protocol/x/accountplus/types/message_add_authenticator_test.go new file mode 100644 index 0000000000..cc818ffad2 --- /dev/null +++ b/protocol/x/accountplus/types/message_add_authenticator_test.go @@ -0,0 +1,74 @@ +package types_test + +import ( + fmt "fmt" + "testing" + + "github.com/dydxprotocol/v4-chain/protocol/testutil/constants" + "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/types" + "github.com/stretchr/testify/require" +) + +func TestMsgCompleteBridge_ValidateBasic(t *testing.T) { + const messageFilterData = "/cosmos.bank.v1beta1.MsgMultiSend,/cosmos.bank.v1beta1.MsgSend" + + tests := map[string]struct { + msg types.MsgAddAuthenticator + expectedErr error + }{ + "Success": { + msg: types.MsgAddAuthenticator{ + Sender: constants.AliceAccAddress.String(), + AuthenticatorType: "MessageFilter", + Data: []byte(messageFilterData), + }, + }, + "Failure: Not an address": { + msg: types.MsgAddAuthenticator{ + Sender: "invalid", + }, + expectedErr: types.ErrInvalidAccountAddress, + }, + "Failure: Data exceeds max length": { + msg: types.MsgAddAuthenticator{ + Sender: constants.AliceAccAddress.String(), + AuthenticatorType: "AllOf", + Data: []byte( + fmt.Sprintf( + `[ + {"Type":"MessageFilter","Config":"%s"}, + { + "Type":"AnyOf", + "Config":" + [ + {"Type":"SignatureVerification","Config":"%s"}, + {"Type":"SignatureVerification","Config":"%s"}, + {"Type":"SignatureVerification","Config":"%s"}, + {"Type":"SignatureVerification","Config":"%s"} + ] + " + }, + ]`, + messageFilterData, + constants.AlicePrivateKey.PubKey().String(), + constants.BobPrivateKey.PubKey().String(), + constants.CarlPrivateKey.PubKey().String(), + constants.DavePrivateKey.PubKey().String(), + ), + ), + }, + expectedErr: types.ErrAuthenticatorDataExceedsMaximumLength, + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.expectedErr == nil { + require.NoError(t, err) + } else { + require.ErrorIs(t, err, tc.expectedErr) + } + }) + } +} diff --git a/protocol/x/accountplus/types/tx.pb.go b/protocol/x/accountplus/types/tx.pb.go index 7f908acf0f..b813711a49 100644 --- a/protocol/x/accountplus/types/tx.pb.go +++ b/protocol/x/accountplus/types/tx.pb.go @@ -6,6 +6,7 @@ package types import ( context "context" fmt "fmt" + _ "github.com/cosmos/cosmos-proto" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" grpc1 "github.com/cosmos/gogoproto/grpc" @@ -237,8 +238,9 @@ func (m *MsgRemoveAuthenticatorResponse) GetSuccess() bool { // MsgSetActiveState sets the active state of the module. type MsgSetActiveState struct { - Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` - Active bool `protobuf:"varint,2,opt,name=active,proto3" json:"active,omitempty"` + // Authority is the address that may send this message. + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + Active bool `protobuf:"varint,2,opt,name=active,proto3" json:"active,omitempty"` } func (m *MsgSetActiveState) Reset() { *m = MsgSetActiveState{} } @@ -274,9 +276,9 @@ func (m *MsgSetActiveState) XXX_DiscardUnknown() { var xxx_messageInfo_MsgSetActiveState proto.InternalMessageInfo -func (m *MsgSetActiveState) GetSender() string { +func (m *MsgSetActiveState) GetAuthority() string { if m != nil { - return m.Sender + return m.Authority } return "" } @@ -386,39 +388,42 @@ func init() { func init() { proto.RegisterFile("dydxprotocol/accountplus/tx.proto", fileDescriptor_2d1c240983fd17d6) } var fileDescriptor_2d1c240983fd17d6 = []byte{ - // 511 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x94, 0xcf, 0x6a, 0xdb, 0x40, - 0x10, 0xc6, 0x2d, 0xdb, 0xb8, 0xe9, 0xb6, 0x84, 0x5a, 0x01, 0xc7, 0x75, 0x40, 0xa4, 0x82, 0x82, - 0x71, 0x91, 0xd4, 0x36, 0x0d, 0x29, 0x82, 0x1c, 0x5c, 0x68, 0x6f, 0xbe, 0x28, 0x81, 0x42, 0x2f, - 0x61, 0xb3, 0x3b, 0xc8, 0x02, 0x4b, 0x2b, 0x34, 0x2b, 0x23, 0xf7, 0x52, 0xda, 0x63, 0x4f, 0x7d, - 0x90, 0x1e, 0xf2, 0x18, 0x3d, 0xe6, 0xd8, 0x63, 0xb1, 0x0f, 0x79, 0x84, 0x5e, 0x83, 0xd7, 0x7f, - 0xb0, 0x1c, 0x39, 0xc4, 0x17, 0x5b, 0x3b, 0xf3, 0xcd, 0xcc, 0x6f, 0x56, 0x1f, 0x22, 0x2f, 0xf8, - 0x88, 0x67, 0x71, 0x22, 0xa4, 0x60, 0x62, 0xe0, 0x50, 0xc6, 0x44, 0x1a, 0xc9, 0x78, 0x90, 0xa2, - 0x23, 0x33, 0x5b, 0xc5, 0xf5, 0xe6, 0xaa, 0xc4, 0x5e, 0x91, 0xb4, 0xf6, 0x99, 0xc0, 0x50, 0xa0, - 0x13, 0xa2, 0xef, 0x0c, 0xdf, 0x4c, 0xff, 0x66, 0x25, 0xad, 0x3a, 0x0d, 0x83, 0x48, 0x38, 0xea, - 0x77, 0x16, 0x32, 0x7f, 0x6b, 0x64, 0xaf, 0x87, 0x7e, 0x97, 0xf3, 0x6e, 0x2a, 0xfb, 0x10, 0xc9, - 0x80, 0x51, 0x29, 0x12, 0xbd, 0x41, 0x6a, 0x08, 0x11, 0x87, 0xa4, 0xa9, 0x1d, 0x6a, 0xed, 0xc7, - 0xde, 0xfc, 0xa4, 0x5b, 0x44, 0xa7, 0xab, 0xc2, 0x0b, 0x39, 0x8a, 0xa1, 0x59, 0x56, 0x9a, 0x7a, - 0x2e, 0x73, 0x3e, 0x8a, 0x41, 0xd7, 0x49, 0x95, 0x53, 0x49, 0x9b, 0x95, 0x43, 0xad, 0xfd, 0xd4, - 0x53, 0xcf, 0xae, 0xfb, 0xe3, 0xe6, 0xaa, 0x33, 0xef, 0xf7, 0xf3, 0xe6, 0xaa, 0xd3, 0xd9, 0xb8, - 0x2b, 0xe5, 0xdc, 0xca, 0xf5, 0x34, 0x4f, 0xc8, 0x41, 0x01, 0xad, 0x07, 0x18, 0x8b, 0x08, 0x41, - 0x6f, 0x92, 0x47, 0x98, 0x32, 0x06, 0x88, 0x0a, 0x7b, 0xc7, 0x5b, 0x1c, 0xcd, 0x6f, 0xa4, 0xd1, - 0x43, 0xdf, 0x83, 0x50, 0x0c, 0xe1, 0x61, 0x9b, 0xee, 0x92, 0x72, 0xc0, 0xd5, 0x66, 0x55, 0xaf, - 0x1c, 0x70, 0xf7, 0x74, 0x0d, 0xdb, 0xda, 0x88, 0x9d, 0xa8, 0x29, 0x6b, 0xe4, 0x2e, 0x31, 0x8a, - 0x01, 0x1e, 0x00, 0xff, 0x95, 0xd4, 0x7b, 0xe8, 0x9f, 0x81, 0xec, 0x32, 0x19, 0x0c, 0xe1, 0x4c, - 0x52, 0x09, 0x1b, 0xb9, 0x1b, 0xa4, 0x46, 0x95, 0x4c, 0xb1, 0xef, 0x78, 0xf3, 0x93, 0x7b, 0xbc, - 0xc6, 0xff, 0x52, 0x99, 0x24, 0x40, 0x07, 0x43, 0x9a, 0xc8, 0x39, 0xbf, 0x83, 0x20, 0xad, 0x59, - 0x81, 0x85, 0xd3, 0x31, 0xe6, 0x01, 0x79, 0x7e, 0x67, 0xf6, 0x02, 0xd9, 0xfc, 0x44, 0x9e, 0x9c, - 0x67, 0x1f, 0x33, 0x09, 0x11, 0x06, 0x22, 0xd2, 0x4f, 0xc8, 0x3e, 0xc2, 0x00, 0x98, 0x04, 0x7e, - 0x91, 0xdb, 0x7e, 0xba, 0x51, 0xa5, 0x5d, 0xf5, 0x1a, 0x8b, 0x74, 0xee, 0x06, 0xf0, 0xed, 0xff, - 0x32, 0xa9, 0xf4, 0xd0, 0xd7, 0x33, 0xf2, 0xec, 0x8e, 0x13, 0x2d, 0x7b, 0x93, 0xd1, 0xed, 0x02, - 0x2b, 0xb4, 0x8e, 0xb7, 0x92, 0x2f, 0x2f, 0xff, 0xbb, 0x46, 0xf6, 0x8a, 0xdc, 0xf1, 0xfa, 0xde, - 0x76, 0x05, 0x15, 0xad, 0xf7, 0xdb, 0x56, 0x2c, 0x19, 0x12, 0xb2, 0xbb, 0xf6, 0x8e, 0x5f, 0xdd, - 0xdb, 0x2b, 0x2f, 0x6e, 0x1d, 0x6d, 0x21, 0x5e, 0xcc, 0xfc, 0xf0, 0xf9, 0xcf, 0xd8, 0xd0, 0xae, - 0xc7, 0x86, 0xf6, 0x6f, 0x6c, 0x68, 0xbf, 0x26, 0x46, 0xe9, 0x7a, 0x62, 0x94, 0xfe, 0x4e, 0x8c, - 0xd2, 0x97, 0x53, 0x3f, 0x90, 0xfd, 0xf4, 0xd2, 0x66, 0x22, 0x74, 0x72, 0x56, 0x1f, 0xbe, 0xb3, - 0x58, 0x9f, 0x06, 0x91, 0xb3, 0x8c, 0x64, 0xf9, 0x2f, 0xd4, 0x28, 0x06, 0xbc, 0xac, 0xa9, 0xec, - 0xd1, 0x6d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x6f, 0xd1, 0xf0, 0xf4, 0xca, 0x04, 0x00, 0x00, + // 557 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x31, 0x6b, 0xdb, 0x40, + 0x14, 0x8e, 0x6c, 0x93, 0x26, 0xd7, 0x12, 0x6a, 0xa5, 0x38, 0x8a, 0x03, 0x22, 0x35, 0x14, 0x8c, + 0x8b, 0xac, 0xb6, 0x69, 0x9b, 0x60, 0xc8, 0xe0, 0x40, 0xbb, 0x79, 0x91, 0x03, 0x85, 0x2e, 0xe6, + 0x72, 0x77, 0xc8, 0x07, 0x96, 0x4e, 0xe8, 0x9d, 0x8d, 0x3c, 0x95, 0x76, 0xec, 0xd4, 0x3f, 0xd0, + 0x7f, 0xd0, 0x21, 0x43, 0x7f, 0x44, 0xc7, 0xd0, 0xa9, 0x63, 0xb1, 0x87, 0xfc, 0x84, 0xae, 0x45, + 0x27, 0xd9, 0xb1, 0x1c, 0x39, 0xc4, 0x8b, 0xad, 0x77, 0xef, 0x7b, 0xdf, 0xfb, 0xbe, 0xa7, 0x77, + 0x42, 0x4f, 0xe9, 0x98, 0x46, 0x41, 0x28, 0xa4, 0x20, 0x62, 0x60, 0x63, 0x42, 0xc4, 0xd0, 0x97, + 0xc1, 0x60, 0x08, 0xb6, 0x8c, 0x9a, 0xea, 0x5c, 0x37, 0x16, 0x21, 0xcd, 0x05, 0x48, 0x75, 0x9f, + 0x08, 0xf0, 0x04, 0xf4, 0x54, 0xd2, 0x4e, 0x82, 0xa4, 0xa8, 0xba, 0x97, 0x44, 0xb6, 0x07, 0xae, + 0x3d, 0x7a, 0x19, 0xff, 0xa5, 0x89, 0x32, 0xf6, 0xb8, 0x2f, 0x6c, 0xf5, 0x9b, 0x1c, 0xd5, 0x7e, + 0x68, 0x68, 0xb7, 0x03, 0x6e, 0x9b, 0xd2, 0xf6, 0x50, 0xf6, 0x99, 0x2f, 0x39, 0xc1, 0x52, 0x84, + 0x7a, 0x05, 0x6d, 0x02, 0xf3, 0x29, 0x0b, 0x0d, 0xed, 0x50, 0xab, 0x6f, 0x3b, 0x69, 0xa4, 0x5b, + 0x48, 0xc7, 0x8b, 0xc0, 0x9e, 0x1c, 0x07, 0xcc, 0x28, 0x28, 0x4c, 0x39, 0x93, 0x39, 0x1f, 0x07, + 0x4c, 0xd7, 0x51, 0x89, 0x62, 0x89, 0x8d, 0xe2, 0xa1, 0x56, 0x7f, 0xe4, 0xa8, 0xe7, 0x56, 0xeb, + 0xcb, 0xf5, 0x65, 0x23, 0xe5, 0xfb, 0x7a, 0x7d, 0xd9, 0x68, 0xac, 0x1c, 0x03, 0xa6, 0xd4, 0xca, + 0x70, 0xd6, 0x8e, 0xd1, 0x41, 0x8e, 0x5a, 0x87, 0x41, 0x20, 0x7c, 0x60, 0xba, 0x81, 0x1e, 0xc0, + 0x90, 0x10, 0x06, 0xa0, 0x64, 0x6f, 0x39, 0xb3, 0xb0, 0xf6, 0x09, 0x55, 0x3a, 0xe0, 0x3a, 0xcc, + 0x13, 0x23, 0x76, 0x3f, 0xa7, 0x3b, 0xa8, 0xc0, 0xa9, 0x72, 0x56, 0x72, 0x0a, 0x9c, 0xb6, 0x4e, + 0x97, 0x64, 0x5b, 0x2b, 0x65, 0x87, 0xaa, 0xcb, 0x92, 0xf2, 0x16, 0x32, 0xf3, 0x05, 0xdc, 0x43, + 0xfc, 0x77, 0x0d, 0x95, 0x3b, 0xe0, 0x76, 0x99, 0x6c, 0x13, 0xc9, 0x47, 0xac, 0x2b, 0xb1, 0x64, + 0xfa, 0x5b, 0xb4, 0x1d, 0xb7, 0x10, 0x21, 0x97, 0xe3, 0x44, 0xfb, 0x99, 0xf1, 0xfb, 0xa7, 0xf5, + 0x24, 0xdd, 0x85, 0x36, 0xa5, 0x21, 0x03, 0xe8, 0xca, 0x90, 0xfb, 0xae, 0x73, 0x03, 0x8d, 0x0d, + 0x63, 0x45, 0xa3, 0xcc, 0x6d, 0x39, 0x69, 0xd4, 0x3a, 0x89, 0x0d, 0xde, 0xe0, 0x62, 0x8f, 0xcf, + 0x14, 0x15, 0x07, 0x1b, 0x3c, 0x1c, 0xca, 0xd4, 0xa3, 0x0d, 0x4c, 0x5a, 0x49, 0x8d, 0x05, 0xb1, + 0x92, 0xda, 0x01, 0xda, 0xbf, 0x25, 0x6f, 0x66, 0xab, 0xf6, 0x1e, 0x3d, 0x3c, 0x8f, 0xde, 0x45, + 0x92, 0xf9, 0xc0, 0x85, 0xaf, 0x1f, 0xa3, 0x3d, 0x60, 0x03, 0x46, 0x24, 0xa3, 0xbd, 0xcc, 0x84, + 0x62, 0xd7, 0xc5, 0x7a, 0xc9, 0xa9, 0xcc, 0xd2, 0x99, 0x29, 0xc1, 0xab, 0x7f, 0x05, 0x54, 0xec, + 0x80, 0xab, 0x47, 0xe8, 0xf1, 0xad, 0x6d, 0xb5, 0x9a, 0xab, 0xee, 0x49, 0x33, 0x67, 0x5d, 0xaa, + 0x6f, 0xd6, 0x82, 0xcf, 0x5f, 0xd0, 0x67, 0x0d, 0xed, 0xe6, 0x6d, 0xd0, 0x8b, 0x3b, 0xe9, 0x72, + 0x2a, 0xaa, 0x27, 0xeb, 0x56, 0xcc, 0x35, 0x84, 0x68, 0x67, 0x69, 0x0d, 0x9e, 0xdf, 0xc9, 0x95, + 0x05, 0x57, 0x8f, 0xd6, 0x00, 0xcf, 0x7a, 0x9e, 0x7d, 0xf8, 0x35, 0x31, 0xb5, 0xab, 0x89, 0xa9, + 0xfd, 0x9d, 0x98, 0xda, 0xb7, 0xa9, 0xb9, 0x71, 0x35, 0x35, 0x37, 0xfe, 0x4c, 0xcd, 0x8d, 0x8f, + 0xa7, 0x2e, 0x97, 0xfd, 0xe1, 0x45, 0x93, 0x08, 0xcf, 0xce, 0x5c, 0x87, 0xd1, 0x6b, 0x8b, 0xf4, + 0x31, 0xf7, 0xed, 0xf9, 0x49, 0x94, 0xfd, 0xc0, 0x8d, 0x03, 0x06, 0x17, 0x9b, 0x2a, 0x7b, 0xf4, + 0x3f, 0x00, 0x00, 0xff, 0xff, 0x67, 0x49, 0xc8, 0xe0, 0x09, 0x05, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -756,10 +761,10 @@ func (m *MsgSetActiveState) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x10 } - if len(m.Sender) > 0 { - i -= len(m.Sender) - copy(dAtA[i:], m.Sender) - i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) i-- dAtA[i] = 0xa } @@ -908,7 +913,7 @@ func (m *MsgSetActiveState) Size() (n int) { } var l int _ = l - l = len(m.Sender) + l = len(m.Authority) if l > 0 { n += 1 + l + sovTx(uint64(l)) } @@ -1369,7 +1374,7 @@ func (m *MsgSetActiveState) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1397,7 +1402,7 @@ func (m *MsgSetActiveState) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Sender = string(dAtA[iNdEx:postIndex]) + m.Authority = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 0 {