Skip to content

Commit

Permalink
[CT-1195] add keeper methods and msg server implementation (#2285)
Browse files Browse the repository at this point in the history
  • Loading branch information
jayy04 committed Sep 20, 2024
1 parent 82598aa commit 63802c6
Show file tree
Hide file tree
Showing 16 changed files with 808 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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) {
Expand All @@ -351,7 +353,7 @@ export const MsgSetActiveState = {

switch (tag >>> 3) {
case 1:
message.sender = reader.string();
message.authority = reader.string();
break;

case 2:
Expand All @@ -369,7 +371,7 @@ export const MsgSetActiveState = {

fromPartial(object: DeepPartial<MsgSetActiveState>): MsgSetActiveState {
const message = createBaseMsgSetActiveState();
message.sender = object.sender ?? "";
message.authority = object.authority ?? "";
message.active = object.active ?? false;
return message;
}
Expand Down
6 changes: 4 additions & 2 deletions proto/dydxprotocol/accountplus/tx.proto
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
syntax = "proto3";
package dydxprotocol.accountplus;

import "cosmos_proto/cosmos.proto";
import "cosmos/msg/v1/msg.proto";
import "amino/amino.proto";

Expand Down Expand Up @@ -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;
}

Expand Down
3 changes: 3 additions & 0 deletions protocol/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -1225,6 +1225,9 @@ func New(
appCodec,
keys[accountplusmoduletypes.StoreKey],
app.AuthenticatorManager,
[]string{
lib.GovModuleAddress.String(),
},
)
accountplusModule := accountplusmodule.NewAppModule(appCodec, app.AccountPlusKeeper)

Expand Down
4 changes: 4 additions & 0 deletions protocol/testutil/ante/testutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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.
Expand Down
4 changes: 4 additions & 0 deletions protocol/testutil/keeper/accountplus.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -57,6 +58,9 @@ func createTimestampNonceKeeper(
cdc,
storeKey,
authenticator.NewAuthenticatorManager(),
[]string{
lib.GovModuleAddress.String(),
},
)

return k, storeKey, mockTimeProvider
Expand Down
108 changes: 108 additions & 0 deletions protocol/x/accountplus/keeper/authenticators.go
Original file line number Diff line number Diff line change
@@ -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)
}
14 changes: 11 additions & 3 deletions protocol/x/accountplus/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand All @@ -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),
}
}

Expand Down Expand Up @@ -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
}
Loading

0 comments on commit 63802c6

Please sign in to comment.