Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add confidential transfer queries to seid #1931

Merged
merged 14 commits into from
Nov 15, 2024
3 changes: 2 additions & 1 deletion app/apptesting/test_suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package apptesting
import (
"context"
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/crypto"
"time"

"github.com/ethereum/go-ethereum/crypto"

"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
Expand Down
94 changes: 94 additions & 0 deletions x/confidentialtransfers/client/cli/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package cli

import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/sei-protocol/sei-chain/x/confidentialtransfers/types"
"github.com/spf13/cobra"
)

// GetQueryCmd returns the cli query commands for the minting module.
func GetQueryCmd() *cobra.Command {
confidentialTransfersQueryCmd := &cobra.Command{
Use: types.ModuleName,
Short: "Querying commands for the confidential transfer module",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}

confidentialTransfersQueryCmd.AddCommand(
GetCmdQueryAccount(),
GetCmdQueryAllAccount(),
)

return confidentialTransfersQueryCmd
}

// GetCmdQueryAccount implements a command to return an account asssociated with the address and denom
func GetCmdQueryAccount() *cobra.Command {
cmd := &cobra.Command{
Use: "account [address] [denom]",
Short: "Query the account state",
Args: cobra.ExactArgs(2),
mj850 marked this conversation as resolved.
Show resolved Hide resolved
RunE: func(cmd *cobra.Command, args []string) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I think we were moving those functions to separate methods in tx. Might make our code consistent

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved to separate functions for both

clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)

res, err := queryClient.GetCtAccount(cmd.Context(), &types.GetCtAccountRequest{
Address: args[0],
Denom: args[1],
})

if err != nil {
return err
}

return clientCtx.PrintProto(res.Account)
},
}

flags.AddQueryFlagsToCmd(cmd)

return cmd
}

// GetCmdQueryAccount implements a command to return an account asssociated with the address and denom
func GetCmdQueryAllAccount() *cobra.Command {
cmd := &cobra.Command{
Use: "accounts [address]",
Short: "Query all the confidential token accounts associated with the address",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)

res, err := queryClient.GetAllCtAccounts(cmd.Context(), &types.GetAllCtAccountsRequest{
Address: args[0],
})

if err != nil {
return err
}

for i := range res.Accounts {
err = clientCtx.PrintProto(&res.Accounts[i])
if err != nil {
return err
}
}

return nil
},
}

flags.AddQueryFlagsToCmd(cmd)

return cmd
}
12 changes: 3 additions & 9 deletions x/confidentialtransfers/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ type Keeper interface {
GetParams(ctx sdk.Context) types.Params
SetParams(ctx sdk.Context, params types.Params)

// TODO: See if there's a way to put this somewhere else
SendTokens(ctx sdk.Context, to sdk.AccAddress, amount sdk.Coins) error
ReceiveTokens(ctx sdk.Context, from sdk.AccAddress, amount sdk.Coins) error
BankKeeper() types.BankKeeper

CreateModuleAccount(ctx sdk.Context)

Expand Down Expand Up @@ -177,12 +175,8 @@ func (k BaseKeeper) SetParams(ctx sdk.Context, params types.Params) {
k.paramSpace.SetParamSet(ctx, &params)
}

func (k BaseKeeper) SendTokens(ctx sdk.Context, to sdk.AccAddress, amount sdk.Coins) error {
return k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, to, amount)
}

func (k BaseKeeper) ReceiveTokens(ctx sdk.Context, from sdk.AccAddress, amount sdk.Coins) error {
return k.bankKeeper.SendCoinsFromAccountToModule(ctx, from, types.ModuleName, amount)
func (k BaseKeeper) BankKeeper() types.BankKeeper {
return k.bankKeeper
}

func (k BaseKeeper) getAccountStore(ctx sdk.Context) prefix.Store {
Expand Down
5 changes: 2 additions & 3 deletions x/confidentialtransfers/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func (m msgServer) Deposit(goCtx context.Context, req *types.MsgDeposit) (*types
coins := sdk.NewCoins(sdk.NewCoin(req.Denom, sdk.NewIntFromUint64(req.Amount)))

// Transfer the amount from the sender's account to the module account
if err := m.Keeper.ReceiveTokens(ctx, address, coins); err != nil {
if err := m.Keeper.BankKeeper().SendCoinsFromAccountToModule(ctx, address, types.ModuleName, coins); err != nil {
return nil, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "insufficient funds to deposit %d %s", req.Amount, req.Denom)
}

Expand Down Expand Up @@ -228,7 +228,7 @@ func (m msgServer) Withdraw(goCtx context.Context, req *types.MsgWithdraw) (*typ

// Return the tokens to the sender
coins := sdk.NewCoins(sdk.NewCoin(instruction.Denom, sdk.NewIntFromUint64(instruction.Amount)))
if err := m.Keeper.SendTokens(ctx, address, coins); err != nil {
if err := m.Keeper.BankKeeper().SendCoinsFromModuleToAccount(ctx, types.ModuleName, address, coins); err != nil {
return nil, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "insufficient funds to withdraw %d %s", req.Amount, req.Denom)
}

Expand Down Expand Up @@ -408,7 +408,6 @@ func (m msgServer) Transfer(goCtx context.Context, req *types.MsgTransfer) (*typ
}

// Calculate and Update the account states.
// TODO: Is there a possibility for a race condition here if multiple Transfer transactions are made to the same account at the same time?
recipientPendingBalanceLo, err := elgamal.AddCiphertext(recipientAccount.PendingBalanceLo, instruction.RecipientTransferAmountLo)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "error adding recipient transfer amount lo")
Expand Down
9 changes: 1 addition & 8 deletions x/confidentialtransfers/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,9 @@ func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config clien
return nil
}

// TODO: Look into whether we require REST endpoints
// RegisterRESTRoutes registers the capability module's REST service handlers.
func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {}

// TODO: Look into whether we require gRPC Gateway support
// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the module.
func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) //nolint:errcheck
Expand All @@ -101,26 +99,22 @@ func (am AppModuleBasic) GetTxCmd() *cobra.Command {
return cli.NewTxCmd()
}

// TODO: Implement this when we add the CLI methods
// GetQueryCmd returns the x/confidentialtransfers module's root query command.
func (AppModuleBasic) GetQueryCmd() *cobra.Command {
//return cli.GetQueryCmd()
return nil
return cli.GetQueryCmd()
}

// ----------------------------------------------------------------------------
// AppModule
// ----------------------------------------------------------------------------

// TODO: Add any required keepers here
// AppModule implements the AppModule interface for the capability module.
type AppModule struct {
AppModuleBasic

keeper keeper.Keeper
}

// TODO: Revisit if any other keepers are required.
func NewAppModule(
keeper keeper.Keeper,
) AppModule {
Expand Down Expand Up @@ -178,7 +172,6 @@ func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.Ra
// ExportGenesis returns the x/confidentialtransfers module's exported genesis state as raw
// JSON bytes.
func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage {
// TODO: Implement once we implement keeper/Genesis
genState := am.keeper.ExportGenesis(ctx)
return cdc.MustMarshalJSON(genState)
}
Expand Down
8 changes: 8 additions & 0 deletions x/confidentialtransfers/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ func RegisterCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&MsgInitializeAccount{}, "confidentialtransfers/MsgInitializeAccount", nil)
cdc.RegisterConcrete(&MsgDeposit{}, "confidentialtransfers/MsgDeposit", nil)
cdc.RegisterConcrete(&MsgWithdraw{}, "confidentialtransfers/MsgWithdraw", nil)
cdc.RegisterConcrete(&MsgCloseAccount{}, "confidentialtransfers/MsgCloseAccount", nil)
cdc.RegisterConcrete(&MsgApplyPendingBalance{}, "confidentialtransfers/MsgApplyPendingBalance", nil)
}

func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
Expand All @@ -27,6 +29,12 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
registry.RegisterImplementations((*sdk.Msg)(nil),
&MsgWithdraw{},
)
registry.RegisterImplementations((*sdk.Msg)(nil),
&MsgCloseAccount{},
)
registry.RegisterImplementations((*sdk.Msg)(nil),
&MsgApplyPendingBalance{},
)

msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
}
Expand Down
4 changes: 0 additions & 4 deletions x/confidentialtransfers/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"github.com/cosmos/cosmos-sdk/types/address"
)

// TODO: Remove keys that are eventually not required
const (
// ModuleName defines the module name
ModuleName = "confidentialtransfers"
Expand All @@ -20,9 +19,6 @@ const (

// QuerierRoute defines the module's query routing key
QuerierRoute = ModuleName

// MemStoreKey defines the in-memory store key
MemStoreKey = "mem_confidential"
)

var (
Expand Down
4 changes: 2 additions & 2 deletions x/confidentialtransfers/types/msgs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ func TestMsgTransfer_ValidateBasic(t *testing.T) {
Denom: validDenom,
},
wantErr: true,
errMsg: "FromAmountLo is required",
errMsg: "from amount lo is required",
},
{
name: "missing from amount hi",
Expand All @@ -325,7 +325,7 @@ func TestMsgTransfer_ValidateBasic(t *testing.T) {
FromAmountLo: &Ciphertext{},
},
wantErr: true,
errMsg: sdkerrors.ErrInvalidRequest.Error(),
errMsg: "from amount hi is required",
},
{
name: "missing to amount lo",
Expand Down
26 changes: 13 additions & 13 deletions x/confidentialtransfers/types/transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,27 +271,27 @@ func VerifyTransferProofs(params *Transfer, senderPubkey *curves.Point, recipien
// Verify the validity proofs that the ciphertexts sent are valid (encrypted with the correct pubkey).
ok := zkproofs.VerifyCiphertextValidity(params.Proofs.RemainingBalanceCommitmentValidityProof, *senderPubkey, params.RemainingBalanceCommitment)
if !ok {
return errors.New("Failed to verify remaining balance commitment")
return errors.New("failed to verify remaining balance commitment")
}

ok = zkproofs.VerifyCiphertextValidity(params.Proofs.SenderTransferAmountLoValidityProof, *senderPubkey, params.SenderTransferAmountLo)
if !ok {
return errors.New("Failed to verify senderTransferAmountLo")
return errors.New("failed to verify senderTransferAmountLo")
}

ok = zkproofs.VerifyCiphertextValidity(params.Proofs.SenderTransferAmountHiValidityProof, *senderPubkey, params.SenderTransferAmountHi)
if !ok {
return errors.New("Failed to verify senderTransferAmountHi")
return errors.New("failed to verify senderTransferAmountHi")
}

ok = zkproofs.VerifyCiphertextValidity(params.Proofs.RecipientTransferAmountLoValidityProof, *recipientPubkey, params.RecipientTransferAmountLo)
if !ok {
return errors.New("Failed to verify recipientTransferAmountLo")
return errors.New("failed to verify recipientTransferAmountLo")
}

ok = zkproofs.VerifyCiphertextValidity(params.Proofs.RecipientTransferAmountHiValidityProof, *recipientPubkey, params.RecipientTransferAmountHi)
if !ok {
return errors.New("Failed to verify recipientTransferAmountHi")
return errors.New("failed to verify recipientTransferAmountHi")
}

// Verify that the account's remaining balance is greater than zero after this transfer.
Expand All @@ -301,24 +301,24 @@ func VerifyTransferProofs(params *Transfer, senderPubkey *curves.Point, recipien
return err
}
if !ok {
return errors.New("Range proof verification failed")
return errors.New("range proof verification failed")
}

// As part of the range proof above, we verify that the RemainingBalanceCommitment sent by the user is equal to the remaining balance calculated by the server.
ok = zkproofs.VerifyCiphertextCommitmentEquality(params.Proofs.RemainingBalanceEqualityProof, senderPubkey, newBalanceCiphertext, &params.RemainingBalanceCommitment.C)
if !ok {
return errors.New("Ciphertext Commitment equality verification failed")
return errors.New("ciphertext commitment equality verification failed")
}

// Lastly verify that the transferAmount ciphertexts encode the same value
ok = zkproofs.VerifyCiphertextCiphertextEquality(params.Proofs.TransferAmountLoEqualityProof, senderPubkey, recipientPubkey, params.SenderTransferAmountLo, params.RecipientTransferAmountLo)
if !ok {
return errors.New("Ciphertext Ciphertext equality verification on transferAmountLo failed")
return errors.New("ciphertext ciphertext equality verification on transferAmountLo failed")
}

ok = zkproofs.VerifyCiphertextCiphertextEquality(params.Proofs.TransferAmountHiEqualityProof, senderPubkey, recipientPubkey, params.SenderTransferAmountHi, params.RecipientTransferAmountHi)
if !ok {
return errors.New("Ciphertext Ciphertext equality verification on transferAmountHi failed")
return errors.New("ciphertext ciphertext equality verification on transferAmountHi failed")
}

return nil
Expand All @@ -334,23 +334,23 @@ func VerifyAuditorProof(
// Verify that the transfer amounts are valid (encrypted with the correct pubkey).
ok := zkproofs.VerifyCiphertextValidity(auditorParams.TransferAmountLoValidityProof, *auditorPubkey, auditorParams.EncryptedTransferAmountLo)
if !ok {
return errors.New("Failed to verify auditor TransferAmountLo")
return errors.New("failed to verify auditor transfer amoun lo")
}

ok = zkproofs.VerifyCiphertextValidity(auditorParams.TransferAmountHiValidityProof, *auditorPubkey, auditorParams.EncryptedTransferAmountHi)
if !ok {
return errors.New("Failed to verify auditor TransferAmountHi")
return errors.New("failed to verify auditor transfer amount hi")
}

// Then, verify that the transferAmount ciphertexts encode the same value
ok = zkproofs.VerifyCiphertextCiphertextEquality(auditorParams.TransferAmountLoEqualityProof, senderPubkey, auditorPubkey, senderTransferAmountLo, auditorParams.EncryptedTransferAmountLo)
if !ok {
return errors.New("Ciphertext Ciphertext equality verification on auditor transferAmountLo failed")
return errors.New("ciphertext ciphertext equality verification on auditor transfer amount lo failed")
}

ok = zkproofs.VerifyCiphertextCiphertextEquality(auditorParams.TransferAmountHiEqualityProof, senderPubkey, auditorPubkey, senderTransferAmountHi, auditorParams.EncryptedTransferAmountHi)
if !ok {
return errors.New("Ciphertext Ciphertext equality verification on auditor transferAmountHi failed")
return errors.New("ciphertext ciphertext equality verification on auditor transfer amount hi failed")
}

return nil
Expand Down
Loading