From 3c234844d0c00c7807ec8fc56892379c59270c48 Mon Sep 17 00:00:00 2001 From: Denys S <150304777+dssei@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:48:54 -0800 Subject: [PATCH] basic cli and first draft command for ct module (#1929) * basic cli and first draft command for ct module * add second command draft * draft of init account * close account update * lint errors --- app/app.go | 2 +- x/confidentialtransfers/client/cli/tx.go | 175 ++++++++++++++++++ x/confidentialtransfers/keeper/genesis.go | 1 + x/confidentialtransfers/keeper/keeper.go | 1 + x/confidentialtransfers/keeper/msg_server.go | 8 +- x/confidentialtransfers/module.go | 20 +- x/confidentialtransfers/types/account.go | 3 +- .../types/close_account.go | 1 + .../types/initialize_account.go | 1 + x/confidentialtransfers/types/keys.go | 2 + x/confidentialtransfers/types/transfer.go | 3 +- x/confidentialtransfers/types/withdraw.go | 3 +- 12 files changed, 201 insertions(+), 19 deletions(-) create mode 100644 x/confidentialtransfers/client/cli/tx.go diff --git a/app/app.go b/app/app.go index 9aa8b1c0ca..addea52b7c 100644 --- a/app/app.go +++ b/app/app.go @@ -562,7 +562,7 @@ func New( app.ConfidentialTransfersKeeper = ctkeeper.NewKeeper( appCodec, - app.keys[(cttypes.StoreKey)], + app.keys[cttypes.StoreKey], app.GetSubspace(cttypes.ModuleName), app.AccountKeeper, app.BankKeeper) diff --git a/x/confidentialtransfers/client/cli/tx.go b/x/confidentialtransfers/client/cli/tx.go new file mode 100644 index 0000000000..961b212407 --- /dev/null +++ b/x/confidentialtransfers/client/cli/tx.go @@ -0,0 +1,175 @@ +package cli + +import ( + "context" + "crypto/ecdsa" + "encoding/hex" + "errors" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/codec/legacy" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/ethereum/go-ethereum/crypto" + "github.com/sei-protocol/sei-chain/x/confidentialtransfers/types" + "github.com/spf13/cobra" +) + +const ( + FlagPrivateKey = "private-key" +) + +// NewTxCmd returns a root CLI command handler for all x/confidentialtransfers transaction commands. +func NewTxCmd() *cobra.Command { + txCmd := &cobra.Command{ + Use: types.ShortModuleName, + Short: "Confidential transfers transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + txCmd.AddCommand(NewInitializeAccountTxCmd()) + txCmd.AddCommand(NewCloseAccountTxCmd()) + + return txCmd +} + +// NewInitializeAccountTxCmd returns a CLI command handler for creating a MsgInitializeAccount transaction. +func NewInitializeAccountTxCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "init-account [denom] [flags]", + Short: "Initialize confidential transfers account", + Long: `Initialize confidential transfers command creates account for the specified denomination and address + passed in --from flag.`, + Args: cobra.ExactArgs(1), + RunE: makeInitializeAccountCmd, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +func makeInitializeAccountCmd(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + privKey, err := getPrivateKey(cmd) + if err != nil { + return err + } + initializeAccount, err := types.NewInitializeAccount(clientCtx.GetFromAddress().String(), args[0], *privKey) + if err != nil { + return err + } + + msg := types.NewMsgInitializeAccountProto(initializeAccount) + + if err = msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) +} + +func getPrivateKey(cmd *cobra.Command) (*ecdsa.PrivateKey, error) { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return nil, err + } + txf := tx.NewFactoryCLI(clientCtx, cmd.Flags()) + kb := txf.Keybase() + info, err := kb.Key(clientCtx.GetFromName()) + if err != nil { + return nil, err + } + localInfo, ok := info.(keyring.LocalInfo) + if !ok { + return nil, errors.New("can only associate address for local keys") + } + if localInfo.GetAlgo() != hd.Secp256k1Type { + return nil, errors.New("can only use addresses using secp256k1") + } + priv, err := legacy.PrivKeyFromBytes([]byte(localInfo.PrivKeyArmor)) + if err != nil { + return nil, err + } + privHex := hex.EncodeToString(priv.Bytes()) + key, _ := crypto.HexToECDSA(privHex) + return key, nil +} + +// NewCloseAccountTxCmd returns a CLI command handler for creating a MsgCloseAccount transaction. +func NewCloseAccountTxCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "close-account [denom] [flags]", + Short: "Close confidential transfers account", + Long: `Close confidential transfers command closes (deletes) account for the specified denomination and address + passed in --from flag.`, + Args: cobra.ExactArgs(1), + RunE: makeCloseAccountCmd, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +func makeCloseAccountCmd(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + queryClientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(queryClientCtx) + + privKey, err := getPrivateKey(cmd) + if err != nil { + return err + } + + req := &types.GetCtAccountRequest{ + Address: clientCtx.GetFromAddress().String(), + Denom: args[0], + } + + ctAccount, err := queryClient.GetCtAccount(context.Background(), req) + if err != nil { + return err + } + + account, err := ctAccount.GetAccount().FromProto() + if err != nil { + return err + } + + closeAccount, err := types.NewCloseAccount( + *privKey, + clientCtx.GetFromAddress().String(), + args[0], + account.PendingBalanceLo, + account.PendingBalanceHi, + account.AvailableBalance) + + if err != nil { + return err + } + + msg := types.NewMsgCloseAccountProto(closeAccount) + + if err = msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) +} diff --git a/x/confidentialtransfers/keeper/genesis.go b/x/confidentialtransfers/keeper/genesis.go index aab049a744..4d0af9867f 100644 --- a/x/confidentialtransfers/keeper/genesis.go +++ b/x/confidentialtransfers/keeper/genesis.go @@ -2,6 +2,7 @@ package keeper import ( "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" diff --git a/x/confidentialtransfers/keeper/keeper.go b/x/confidentialtransfers/keeper/keeper.go index 312ea8353d..455d6470c6 100644 --- a/x/confidentialtransfers/keeper/keeper.go +++ b/x/confidentialtransfers/keeper/keeper.go @@ -2,6 +2,7 @@ package keeper import ( "fmt" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/cosmos/cosmos-sdk/store/prefix" diff --git a/x/confidentialtransfers/keeper/msg_server.go b/x/confidentialtransfers/keeper/msg_server.go index 78ec9f94a1..416e07fb21 100644 --- a/x/confidentialtransfers/keeper/msg_server.go +++ b/x/confidentialtransfers/keeper/msg_server.go @@ -2,13 +2,14 @@ package keeper import ( "context" + "math" + sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/sei-protocol/sei-chain/x/confidentialtransfers/types" "github.com/sei-protocol/sei-chain/x/confidentialtransfers/utils" "github.com/sei-protocol/sei-cryptography/pkg/encryption/elgamal" "github.com/sei-protocol/sei-cryptography/pkg/zkproofs" - "math" ) type msgServer struct { @@ -282,7 +283,10 @@ func (m msgServer) ApplyPendingBalance(goCtx context.Context, req *types.MsgAppl account.PendingBalanceCreditCounter = 0 // Save the changes to the account state - m.Keeper.SetAccount(ctx, req.Address, req.Denom, account) + err = m.Keeper.SetAccount(ctx, req.Address, req.Denom, account) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "error setting account") + } // Emit any required events ctx.EventManager().EmitEvents(sdk.Events{ diff --git a/x/confidentialtransfers/module.go b/x/confidentialtransfers/module.go index 537479607f..50f94e4f08 100644 --- a/x/confidentialtransfers/module.go +++ b/x/confidentialtransfers/module.go @@ -15,23 +15,19 @@ import ( "fmt" "math/rand" - "github.com/grpc-ecosystem/grpc-gateway/runtime" - "github.com/sei-protocol/sei-chain/x/confidentialtransfers/keeper" - "github.com/spf13/cobra" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/gorilla/mux" - abci "github.com/tendermint/tendermint/abci/types" - - //"github.com/sei-protocol/sei-chain/x/tokenfactory/client/cli" - //"github.com/sei-protocol/sei-chain/x/tokenfactory/keeper" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/sei-protocol/sei-chain/x/confidentialtransfers/client/cli" + "github.com/sei-protocol/sei-chain/x/confidentialtransfers/keeper" "github.com/sei-protocol/sei-chain/x/confidentialtransfers/types" - - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/spf13/cobra" + abci "github.com/tendermint/tendermint/abci/types" ) var ( @@ -100,11 +96,9 @@ func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *r types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) //nolint:errcheck } -// TODO: Implement this when we add the CLI methods // GetTxCmd returns the x/confidentialtransfers module's root tx command. func (am AppModuleBasic) GetTxCmd() *cobra.Command { - //return cli.GetTxCmd() - return nil + return cli.NewTxCmd() } // TODO: Implement this when we add the CLI methods diff --git a/x/confidentialtransfers/types/account.go b/x/confidentialtransfers/types/account.go index 9ab3a7183d..b19e2facfd 100644 --- a/x/confidentialtransfers/types/account.go +++ b/x/confidentialtransfers/types/account.go @@ -1,9 +1,10 @@ package types import ( + "math/big" + "github.com/coinbase/kryptology/pkg/core/curves" "github.com/sei-protocol/sei-cryptography/pkg/encryption/elgamal" - "math/big" ) type Account struct { diff --git a/x/confidentialtransfers/types/close_account.go b/x/confidentialtransfers/types/close_account.go index 97c4949093..4c070739ab 100644 --- a/x/confidentialtransfers/types/close_account.go +++ b/x/confidentialtransfers/types/close_account.go @@ -2,6 +2,7 @@ package types import ( "crypto/ecdsa" + "github.com/sei-protocol/sei-cryptography/pkg/encryption/elgamal" "github.com/sei-protocol/sei-cryptography/pkg/zkproofs" ) diff --git a/x/confidentialtransfers/types/initialize_account.go b/x/confidentialtransfers/types/initialize_account.go index ed789c78ac..9e50f8ffeb 100644 --- a/x/confidentialtransfers/types/initialize_account.go +++ b/x/confidentialtransfers/types/initialize_account.go @@ -2,6 +2,7 @@ package types import ( "crypto/ecdsa" + "github.com/coinbase/kryptology/pkg/core/curves" "github.com/sei-protocol/sei-cryptography/pkg/encryption" "github.com/sei-protocol/sei-cryptography/pkg/encryption/elgamal" diff --git a/x/confidentialtransfers/types/keys.go b/x/confidentialtransfers/types/keys.go index 30d0db5223..312c67f779 100644 --- a/x/confidentialtransfers/types/keys.go +++ b/x/confidentialtransfers/types/keys.go @@ -10,6 +10,8 @@ const ( // ModuleName defines the module name ModuleName = "confidentialtransfers" + ShortModuleName = "ct" + // StoreKey defines the primary module store key StoreKey = ModuleName diff --git a/x/confidentialtransfers/types/transfer.go b/x/confidentialtransfers/types/transfer.go index 2d98447303..8ca7e32947 100644 --- a/x/confidentialtransfers/types/transfer.go +++ b/x/confidentialtransfers/types/transfer.go @@ -3,12 +3,13 @@ package types import ( "crypto/ecdsa" "errors" + "math/big" + "github.com/coinbase/kryptology/pkg/core/curves" "github.com/sei-protocol/sei-chain/x/confidentialtransfers/utils" "github.com/sei-protocol/sei-cryptography/pkg/encryption" "github.com/sei-protocol/sei-cryptography/pkg/encryption/elgamal" "github.com/sei-protocol/sei-cryptography/pkg/zkproofs" - "math/big" ) type Transfer struct { diff --git a/x/confidentialtransfers/types/withdraw.go b/x/confidentialtransfers/types/withdraw.go index 8cb19ae8f3..660e774a08 100644 --- a/x/confidentialtransfers/types/withdraw.go +++ b/x/confidentialtransfers/types/withdraw.go @@ -3,11 +3,12 @@ package types import ( "crypto/ecdsa" "errors" + "math/big" + "github.com/coinbase/kryptology/pkg/core/curves" "github.com/sei-protocol/sei-cryptography/pkg/encryption" "github.com/sei-protocol/sei-cryptography/pkg/encryption/elgamal" "github.com/sei-protocol/sei-cryptography/pkg/zkproofs" - "math/big" ) type Withdraw struct {