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

Problem: no end-to-end encryption module #1407

Merged
merged 9 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ import (
icaauthkeeper "github.com/crypto-org-chain/cronos/v2/x/icaauth/keeper"
icaauthtypes "github.com/crypto-org-chain/cronos/v2/x/icaauth/types"

e2ee "github.com/crypto-org-chain/cronos/v2/x/e2ee"
e2eekeeper "github.com/crypto-org-chain/cronos/v2/x/e2ee/keeper"
e2eetypes "github.com/crypto-org-chain/cronos/v2/x/e2ee/types"

// force register the extension json-rpc.
_ "github.com/crypto-org-chain/cronos/v2/x/cronos/rpc"
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
Expand Down Expand Up @@ -250,6 +254,8 @@ func StoreKeys() (
icahosttypes.StoreKey,
// ethermint keys
evmtypes.StoreKey, feemarkettypes.StoreKey,
// e2ee keys
e2eetypes.StoreKey,
// this line is used by starport scaffolding # stargate/app/storeKey
cronostypes.StoreKey,
}
Expand Down Expand Up @@ -320,6 +326,9 @@ type App struct {
EvmKeeper *evmkeeper.Keeper
FeeMarketKeeper feemarketkeeper.Keeper

// e2ee keeper
E2EEKeeper e2eekeeper.Keeper

// this line is used by starport scaffolding # stargate/app/keeperDeclaration

CronosKeeper cronoskeeper.Keeper
Expand Down Expand Up @@ -704,6 +713,8 @@ func New(
// If evidence needs to be handled for the app, set routes in router here and seal
app.EvidenceKeeper = *evidenceKeeper

app.E2EEKeeper = e2eekeeper.NewKeeper(keys[e2eetypes.StoreKey], app.AccountKeeper.AddressCodec())

/**** Module Options ****/

// NOTE: we may consider parsing `appOpts` inside module constructors. For the moment
Expand Down Expand Up @@ -754,6 +765,7 @@ func New(
// Ethermint app modules
feemarket.NewAppModule(app.FeeMarketKeeper, feeMarketS),
evm.NewAppModule(app.EvmKeeper, app.AccountKeeper, evmS),
e2ee.NewAppModule(app.E2EEKeeper),

// Cronos app modules
cronosModule,
Expand Down
2 changes: 2 additions & 0 deletions app/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/cosmos/cosmos-sdk/types/module"
icahosttypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host/types"
clientkeeper "github.com/cosmos/ibc-go/v8/modules/core/02-client/keeper"
e2eetypes "github.com/crypto-org-chain/cronos/v2/x/e2ee/types"
)

func (app *App) RegisterUpgradeHandlers(cdc codec.BinaryCodec, clientKeeper clientkeeper.Keeper) {
Expand Down Expand Up @@ -39,6 +40,7 @@ func (app *App) RegisterUpgradeHandlers(cdc codec.BinaryCodec, clientKeeper clie
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storetypes.StoreUpgrades{
Added: []string{
icahosttypes.StoreKey,
e2eetypes.StoreKey,
},
}))
}
Expand Down
18 changes: 18 additions & 0 deletions proto/e2ee/genesis.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
syntax = "proto3";
package e2ee;

import "gogoproto/gogo.proto";

option go_package = "github.com/crypto-org-chain/cronos/v2/x/e2ee/types";

// EncryptionKeyEntry is a type that contains the owner and the public key.
message EncryptionKeyEntry {
string address = 1;
bytes key = 2;
}

// GenesisState defines the e2ee module's genesis state.
message GenesisState {
// params defines all the paramaters of the module.
repeated EncryptionKeyEntry keys = 1 [(gogoproto.nullable) = false];
}
25 changes: 25 additions & 0 deletions proto/e2ee/query.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
syntax = "proto3";
package e2ee;

import "gogoproto/gogo.proto";
import "google/api/annotations.proto";

option go_package = "github.com/crypto-org-chain/cronos/v2/x/e2ee/types";

// Query defines the gRPC querier service.
service Query {
// Key queries the encryption key of a given address
rpc Key(KeyRequest) returns (KeyResponse) {
option (google.api.http).get = "/e2ee/v1/key/{address}";
}
}

// KeyRequest is the request type for the Query/Key RPC method.
message KeyRequest {
string address = 1;
}

// KeyResponse is the response type for the Query/Key RPC method.
message KeyResponse {
bytes key = 1;
}
27 changes: 27 additions & 0 deletions proto/e2ee/tx.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
syntax = "proto3";
package e2ee;

import "cosmos/msg/v1/msg.proto";
import "gogoproto/gogo.proto";

option go_package = "github.com/crypto-org-chain/cronos/v2/x/e2ee/types";

// Msg defines the e2ee Msg service
service Msg {
option (cosmos.msg.v1.service) = true;

// RegisterEncryptionKey registers a new encryption key to a specific account
rpc RegisterEncryptionKey(MsgRegisterEncryptionKey) returns (MsgRegisterEncryptionKeyResponse);
}

// MsgRegisterEncryptionKey defines the Msg/RegisterEncryptionKey request type
message MsgRegisterEncryptionKey {
option (cosmos.msg.v1.signer) = "address";

string address = 1;
bytes key = 2;
}

// MsgRegisterEncryptionKeyResponse defines the Msg/RegisterEncryptionKey response type
message MsgRegisterEncryptionKeyResponse {
}
2 changes: 2 additions & 0 deletions x/e2ee/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
e2ee a module for end-to-end encrypted messaging, user can register encryption keys on chain, and receive encrypted
messages on/off chain.
yihuang marked this conversation as resolved.
Show resolved Hide resolved
22 changes: 22 additions & 0 deletions x/e2ee/autocli.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package e2ee

import (
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
)

// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface.
func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
return &autocliv1.ModuleOptions{
Query: &autocliv1.ServiceCommandDescriptor{
Service: "e2ee.Query",
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
{
RpcMethod: "Key",
Use: "key [address]",
Short: "Query an encryption key by address",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address"}},
},
},
},
}
}
87 changes: 87 additions & 0 deletions x/e2ee/keeper/keeper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package keeper

import (
"context"

"cosmossdk.io/core/address"
"cosmossdk.io/store/prefix"
storetypes "cosmossdk.io/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/crypto-org-chain/cronos/v2/x/e2ee/types"
)

type Keeper struct {
storeKey storetypes.StoreKey
addressCodec address.Codec
}

var (
_ types.MsgServer = Keeper{}
_ types.QueryServer = Keeper{}
)

func NewKeeper(storeKey storetypes.StoreKey, addressCodec address.Codec) Keeper {
return Keeper{
storeKey: storeKey,
addressCodec: addressCodec,
}
}

func (k Keeper) RegisterEncryptionKey(
ctx context.Context,
req *types.MsgRegisterEncryptionKey,
) (*types.MsgRegisterEncryptionKeyResponse, error) {
bz, err := k.addressCodec.StringToBytes(req.Address)
if err != nil {
return nil, err
}
sdkCtx := sdk.UnwrapSDKContext(ctx)
sdkCtx.KVStore(k.storeKey).Set(types.KeyPrefix(bz), req.Key)
return &types.MsgRegisterEncryptionKeyResponse{}, nil
}

func (k Keeper) InitGenesis(
ctx context.Context,
state *types.GenesisState,
) error {
for _, key := range state.Keys {
if _, err := k.RegisterEncryptionKey(ctx, &types.MsgRegisterEncryptionKey{
Address: key.Address,
Key: key.Key,
}); err != nil {
return err
}
}
return nil
}

func (k Keeper) ExportGenesis(ctx context.Context) (*types.GenesisState, error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
iter := prefix.NewStore(sdkCtx.KVStore(k.storeKey), types.KeyPrefixEncryptionKey).Iterator(nil, nil)
defer iter.Close()

var keys []types.EncryptionKeyEntry
for ; iter.Valid(); iter.Next() {
address, err := k.addressCodec.BytesToString(iter.Key())
if err != nil {
return nil, err
}
key := iter.Value()
keys = append(keys, types.EncryptionKeyEntry{
Address: address,
Key: key,
})
}
return &types.GenesisState{Keys: keys}, nil
}
yihuang marked this conversation as resolved.
Show resolved Hide resolved

func (k Keeper) Key(ctx context.Context, req *types.KeyRequest) (*types.KeyResponse, error) {
bz, err := k.addressCodec.StringToBytes(req.Address)
if err != nil {
return nil, err
}
sdkCtx := sdk.UnwrapSDKContext(ctx)
value := sdkCtx.KVStore(k.storeKey).Get(types.KeyPrefix(bz))
return &types.KeyResponse{Key: value}, nil
}
135 changes: 135 additions & 0 deletions x/e2ee/module.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package e2ee

import (
"encoding/json"
"fmt"

abci "github.com/cometbft/cometbft/abci/types"
"github.com/gorilla/mux"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"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"

"github.com/crypto-org-chain/cronos/v2/x/e2ee/keeper"
"github.com/crypto-org-chain/cronos/v2/x/e2ee/types"
)

var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.HasGenesisBasics = AppModuleBasic{}
// this line is used by starport scaffolding # ibc/module/interface
)

// ----------------------------------------------------------------------------
// AppModuleBasic
// ----------------------------------------------------------------------------

// AppModuleBasic implements the AppModuleBasic interface for the capability module.
type AppModuleBasic struct{}

func NewAppModuleBasic() AppModuleBasic {
return AppModuleBasic{}
}

// AddModuleInitFlags implements servertypes.ModuleInitFlags interface.
func AddModuleInitFlags(startCmd *cobra.Command) {
}

// Name returns the capability module's name.
func (AppModuleBasic) Name() string {
return types.ModuleName
}

func (AppModuleBasic) RegisterCodec(cdc *codec.LegacyAmino) {
}

func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
}

// RegisterInterfaces registers the module's interface types
func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) {
}

// DefaultGenesis returns the capability module's default genesis state.
func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {
return cdc.MustMarshalJSON(types.DefaultGenesis())
}

// ValidateGenesis performs genesis state validation for the capability module.
func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error {
var genState types.GenesisState
if err := cdc.UnmarshalJSON(bz, &genState); err != nil {
return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)
}
return genState.Validate()
}

// RegisterRESTRoutes registers the capability module's REST service handlers.
func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) {
}

// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the module.
func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
}

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

// AppModule implements the AppModule interface for the capability module.
type AppModule struct {
AppModuleBasic

keeper keeper.Keeper
}

func NewAppModule(keeper keeper.Keeper) AppModule {
return AppModule{
AppModuleBasic: NewAppModuleBasic(),
keeper: keeper,
}
}

func (am AppModule) RegisterServices(cfg module.Configurator) {
types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
types.RegisterMsgServer(cfg.MsgServer(), am.keeper)
}

func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate {
var genState types.GenesisState
// Initialize global index to index in genesis state
cdc.MustUnmarshalJSON(gs, &genState)
if err := am.keeper.InitGenesis(ctx, &genState); err != nil {
panic(err)
}
return []abci.ValidatorUpdate{}
}

// ExportGenesis returns the capability module's exported genesis state as raw JSON bytes.
func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage {
genState, err := am.keeper.ExportGenesis(ctx)
if err != nil {
panic(err)
}
return cdc.MustMarshalJSON(genState)
}

// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }

// Name returns the capability module's name.
func (am AppModule) Name() string {
return am.AppModuleBasic.Name()
}

// IsAppModule implements the appmodule.AppModule interface.
func (am AppModule) IsAppModule() {}

// IsOnePerModuleType implements the depinject.OnePerModuleType interface.
func (am AppModule) IsOnePerModuleType() {}
12 changes: 12 additions & 0 deletions x/e2ee/types/genesis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package types

// DefaultGenesis returns the default Capability genesis state
func DefaultGenesis() *GenesisState {
return &GenesisState{}
}

// Validate performs basic genesis state validation returning an error upon any
// failure.
func (gs GenesisState) Validate() error {
return nil
}
Loading
Loading