From 3258b5b26c473d311afc578a6da555de361acfef Mon Sep 17 00:00:00 2001 From: yihuang Date: Fri, 26 Apr 2024 16:33:09 +0800 Subject: [PATCH 01/24] Problem: e2ee module is not backported Problem: no end-to-end encryption module (#1407) * Problem: no end-to-end encryption module add keeper add grpc query signer option getter/setter genesis init/export fix lint * fix proto lint * fix test * register codec * changelog * fix build * Update x/e2ee/types/keys.go Co-authored-by: mmsqe Signed-off-by: yihuang * Update x/e2ee/types/codec.go Co-authored-by: mmsqe Signed-off-by: yihuang --------- Signed-off-by: yihuang Co-authored-by: mmsqe Problem: encryption-key cmd is not supported (#1409) * Problem: encryption-key cmd is not supported * gen doc * add validate Problem: no keyring interface for e2ee to store arbitrary payload (#1413) changelo add age encrypt/decrypt in unit test Update x/e2ee/keyring/keyring.go Signed-off-by: yihuang fix lint fix build Problem: no encrypt and decrypt cmds for message (#1411) * Problem: no encrypt and decrypt cmds for message * fix doc * add gen * test * cleanup * move command to e2ee module move encrypt cmd to e2ee module move decrypt cmd to e2ee update integration test store key as string, to make autocli better fix integration test Update x/e2ee/client/cli/encrypt.go Signed-off-by: yihuang fix lint --------- Signed-off-by: yihuang Co-authored-by: yihuang Co-authored-by: yihuang Problem: no efficient batch query for encryption keys (#1415) Update CHANGELOG.md Signed-off-by: yihuang update swagger typo fix build proposal handler update version check exist Problem: proto-gen fails in CI (#1392) * Problem: proto-gen fails in CI * Apply suggestions from code review add cronos msg add store-block-list cmd refresh block list add handler update deps add handler lint fix cmd test store list set with ante move to util fix ibc Revert "set with ante" This reverts commit c2700f546f84709ed8bff0c28fda9b8b85148c1b. reject on err fix prepare proposal fix proto lint --- .github/workflows/proto.yml | 4 +- CHANGELOG.md | 16 + Makefile | 5 + app/app.go | 90 +- app/proposal.go | 117 +++ app/upgrades.go | 21 +- client/docs/config.json | 3 + client/docs/swagger-ui/swagger.yaml | 115 +++ cmd/cronosd/cmd/root.go | 8 + default.nix | 2 +- go.mod | 7 +- go.sum | 6 +- gomod2nix.toml | 7 +- integration_tests/configs/default.jsonnet | 9 + integration_tests/configs/ibc.jsonnet | 14 +- .../configs/upgrade-test-package.nix | 2 +- integration_tests/cosmoscli.py | 109 +- integration_tests/ibc_utils.py | 3 +- integration_tests/test_e2ee.py | 12 + integration_tests/test_gov_update_params.py | 27 +- integration_tests/test_upgrade.py | 2 +- integration_tests/utils.py | 25 + proto/cronos/query.proto | 13 +- proto/cronos/tx.proto | 13 +- proto/e2ee/genesis.proto | 18 + proto/e2ee/query.proto | 42 + proto/e2ee/tx.proto | 24 + x/cronos/client/cli/tx.go | 40 + x/cronos/handler.go | 3 + x/cronos/keeper/grpc_query.go | 8 + x/cronos/keeper/keeper.go | 4 + x/cronos/keeper/msg_server.go | 10 + x/cronos/rpc/api.go | 2 +- x/cronos/types/keys.go | 2 + x/cronos/types/messages.go | 25 + x/cronos/types/query.pb.go | 435 +++++++- x/cronos/types/query.pb.gw.go | 65 ++ x/cronos/types/tx.pb.go | 469 ++++++++- x/e2ee/README.md | 2 + x/e2ee/client/cli/cmd.go | 18 + x/e2ee/client/cli/decrypt.go | 108 ++ x/e2ee/client/cli/encrypt.go | 106 ++ x/e2ee/client/cli/generate.go | 56 + x/e2ee/client/cli/query.go | 78 ++ x/e2ee/client/cli/tx.go | 50 + x/e2ee/keeper/keeper.go | 96 ++ x/e2ee/keyring/keyring.go | 202 ++++ x/e2ee/keyring/keyring_test.go | 47 + x/e2ee/module.go | 148 +++ x/e2ee/types/codec.go | 20 + x/e2ee/types/genesis.go | 17 + x/e2ee/types/genesis.pb.go | 555 ++++++++++ x/e2ee/types/keys.go | 46 + x/e2ee/types/msg.go | 31 + x/e2ee/types/query.pb.go | 973 ++++++++++++++++++ x/e2ee/types/query.pb.gw.go | 270 +++++ x/e2ee/types/tx.pb.go | 580 +++++++++++ 57 files changed, 5053 insertions(+), 127 deletions(-) create mode 100644 app/proposal.go create mode 100644 integration_tests/test_e2ee.py create mode 100644 proto/e2ee/genesis.proto create mode 100644 proto/e2ee/query.proto create mode 100644 proto/e2ee/tx.proto create mode 100644 x/e2ee/README.md create mode 100644 x/e2ee/client/cli/cmd.go create mode 100644 x/e2ee/client/cli/decrypt.go create mode 100644 x/e2ee/client/cli/encrypt.go create mode 100644 x/e2ee/client/cli/generate.go create mode 100644 x/e2ee/client/cli/query.go create mode 100644 x/e2ee/client/cli/tx.go create mode 100644 x/e2ee/keeper/keeper.go create mode 100644 x/e2ee/keyring/keyring.go create mode 100644 x/e2ee/keyring/keyring_test.go create mode 100644 x/e2ee/module.go create mode 100644 x/e2ee/types/codec.go create mode 100644 x/e2ee/types/genesis.go create mode 100644 x/e2ee/types/genesis.pb.go create mode 100644 x/e2ee/types/keys.go create mode 100644 x/e2ee/types/msg.go create mode 100644 x/e2ee/types/query.pb.go create mode 100644 x/e2ee/types/query.pb.gw.go create mode 100644 x/e2ee/types/tx.pb.go diff --git a/.github/workflows/proto.yml b/.github/workflows/proto.yml index b27f60b9e8..a37e08977a 100644 --- a/.github/workflows/proto.yml +++ b/.github/workflows/proto.yml @@ -40,10 +40,10 @@ jobs: with: PATTERNS: | **/**.proto - - name: proto-gen + - name: proto-gen-ci if: env.GIT_DIFF run: | - make proto-gen # proto-swagger-gen FIXME swagger-gen result is not reproducible in CI + make proto-gen-ci # proto-swagger-gen FIXME swagger-gen result is not reproducible in CI git checkout -- go.mod go.sum docs/api/proto-docs.md # FIXME doc gen not reproducible in CI - name: check working directory is clean uses: numtide/clean-git-action@main diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cb47ea598..85fab28148 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## UNRELEASED + +### State Machine Breaking + +* [#1407](https://github.com/crypto-org-chain/cronos/pull/1407) Add end-to-end encryption module. + +### Improvements + +* [#1413](https://github.com/crypto-org-chain/cronos/pull/1413) Add custom keyring implementation for e2ee module. +* (e2ee)[#1415](https://github.com/crypto-org-chain/cronos/pull/1415) Add batch keys query for e2ee module. + *April 22, 2024* ## v1.2.1 @@ -13,6 +24,11 @@ * (rpc) [#1397](https://github.com/crypto-org-chain/cronos/pull/1397) Avoid panic on invalid elasticity_multiplier. +### Features + +* [#1406](https://github.com/crypto-org-chain/cronos/pull/1406) Add set-encryption-key for encryption module. +* [#1411](https://github.com/crypto-org-chain/cronos/pull/1411) Add encrypt and decrypt cmds for message. + *April 8, 2024* ## v1.2.0 diff --git a/Makefile b/Makefile index 057281c06c..784248ea05 100644 --- a/Makefile +++ b/Makefile @@ -272,6 +272,7 @@ endif HTTPS_GIT := https://github.com/crypto-org-chain/cronos.git protoVer=0.11.6 protoImageName=ghcr.io/cosmos/proto-builder:$(protoVer) +protoImageCi=$(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace --user root $(protoImageName) protoImage=$(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace $(protoImageName) # ------ @@ -280,6 +281,10 @@ protoImage=$(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace $(pro # proto-all: proto-format proto-lint proto-gen +proto-gen-ci: + @echo "Generating Protobuf files" + $(protoImageCi) sh ./scripts/protocgen.sh + proto-gen: @echo "Generating Protobuf files" $(protoImage) sh ./scripts/protocgen.sh diff --git a/app/app.go b/app/app.go index 1533139bd9..8cddb2032a 100644 --- a/app/app.go +++ b/app/app.go @@ -15,6 +15,7 @@ import ( autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1" + "filippo.io/age" runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services" "golang.org/x/exp/slices" @@ -23,6 +24,7 @@ import ( tmjson "github.com/cometbft/cometbft/libs/json" "github.com/cometbft/cometbft/libs/log" tmos "github.com/cometbft/cometbft/libs/os" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec/types" "github.com/gorilla/mux" @@ -123,6 +125,7 @@ import ( icaauthkeeper "github.com/crypto-org-chain/cronos/v2/x/icaauth/keeper" icaauthtypes "github.com/crypto-org-chain/cronos/v2/x/icaauth/types" + clientflags "github.com/cosmos/cosmos-sdk/client/flags" evmante "github.com/evmos/ethermint/app/ante" srvflags "github.com/evmos/ethermint/server/flags" ethermint "github.com/evmos/ethermint/types" @@ -159,6 +162,11 @@ import ( _ "github.com/ethereum/go-ethereum/eth/tracers/native" ethparams "github.com/ethereum/go-ethereum/params" + e2ee "github.com/crypto-org-chain/cronos/v2/x/e2ee" + e2eekeeper "github.com/crypto-org-chain/cronos/v2/x/e2ee/keeper" + e2eekeyring "github.com/crypto-org-chain/cronos/v2/x/e2ee/keyring" + 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" ) @@ -260,6 +268,7 @@ func GenModuleBasics() module.BasicManager { ibcfee.AppModuleBasic{}, evm.AppModuleBasic{}, feemarket.AppModuleBasic{}, + e2ee.AppModuleBasic{}, // this line is used by starport scaffolding # stargate/app/moduleBasic gravity.AppModuleBasic{}, cronos.AppModuleBasic{}, @@ -286,6 +295,8 @@ func StoreKeys(skipGravity bool) ( icaauthtypes.StoreKey, // ethermint keys evmtypes.StoreKey, feemarkettypes.StoreKey, + // e2ee keys + e2eetypes.StoreKey, // this line is used by starport scaffolding # stargate/app/storeKey cronostypes.StoreKey, } @@ -357,6 +368,9 @@ type App struct { // Gravity module GravityKeeper gravitykeeper.Keeper + // e2ee keeper + E2EEKeeper e2eekeeper.Keeper + // this line is used by starport scaffolding # stargate/app/keeperDeclaration CronosKeeper cronoskeeper.Keeper @@ -371,6 +385,8 @@ type App struct { configurator module.Configurator qms storetypes.MultiStore + + blockProposalHandler *ProposalHandler } // New returns a reference to an initialized chain. @@ -385,15 +401,37 @@ func New( cdc := encodingConfig.Amino interfaceRegistry := encodingConfig.InterfaceRegistry + var identity age.Identity + { + if cast.ToString(appOpts.Get("mode")) == "validator" { + krBackend := cast.ToString(appOpts.Get(clientflags.FlagKeyringBackend)) + kr, err := e2eekeyring.New("cronosd", krBackend, homePath, os.Stdin) + if err != nil { + panic(err) + } + bz, err := kr.Get(e2eetypes.DefaultKeyringName) + if err != nil { + logger.Error("e2ee identity for validator not found", "error", err) + } else { + identity, err = age.ParseX25519Identity(string(bz)) + if err != nil { + panic(err) + } + } + } + } + baseAppOptions = memiavlstore.SetupMemIAVL(logger, homePath, appOpts, false, false, baseAppOptions) + + blockProposalHandler := NewProposalHandler(encodingConfig.TxConfig.TxDecoder(), identity) + // NOTE we use custom transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx // Setup Mempool and Proposal Handlers baseAppOptions = append(baseAppOptions, func(app *baseapp.BaseApp) { mempool := mempool.NoOpMempool{} app.SetMempool(mempool) - handler := baseapp.NewDefaultProposalHandler(mempool, app) - app.SetPrepareProposal(handler.PrepareProposalHandler()) - app.SetProcessProposal(handler.ProcessProposalHandler()) + app.SetPrepareProposal(blockProposalHandler.PrepareProposalHandler()) + app.SetProcessProposal(blockProposalHandler.ProcessProposalHandler()) }) bApp := baseapp.NewBaseApp(Name, logger, db, encodingConfig.TxConfig.TxDecoder(), baseAppOptions...) @@ -404,14 +442,15 @@ func New( keys, memKeys, tkeys := StoreKeys(skipGravity) app := &App{ - BaseApp: bApp, - cdc: cdc, - appCodec: appCodec, - interfaceRegistry: interfaceRegistry, - invCheckPeriod: invCheckPeriod, - keys: keys, - tkeys: tkeys, - memKeys: memKeys, + BaseApp: bApp, + cdc: cdc, + appCodec: appCodec, + interfaceRegistry: interfaceRegistry, + invCheckPeriod: invCheckPeriod, + keys: keys, + tkeys: tkeys, + memKeys: memKeys, + blockProposalHandler: blockProposalHandler, } // init params keeper and subspaces @@ -666,6 +705,8 @@ func New( // this line is used by starport scaffolding # ibc/app/router app.IBCKeeper.SetRouter(ibcRouter) + app.E2EEKeeper = e2eekeeper.NewKeeper(keys[e2eetypes.StoreKey]) + /**** Module Options ****/ // NOTE: we may consider parsing `appOpts` inside module constructors. For the moment @@ -709,6 +750,9 @@ func New( feeModule, feemarket.NewAppModule(app.FeeMarketKeeper, feeMarketS), evm.NewAppModule(app.EvmKeeper, app.AccountKeeper, evmS), + e2ee.NewAppModule(app.E2EEKeeper), + + // Cronos app modules cronosModule, } @@ -737,6 +781,7 @@ func New( vestingtypes.ModuleName, cronostypes.ModuleName, consensusparamtypes.ModuleName, + e2eetypes.ModuleName, } endBlockersOrder := []string{ crisistypes.ModuleName, govtypes.ModuleName, stakingtypes.ModuleName, @@ -760,6 +805,7 @@ func New( vestingtypes.ModuleName, cronostypes.ModuleName, consensusparamtypes.ModuleName, + e2eetypes.ModuleName, } // NOTE: The genutils module must occur after staking so that pools are // properly initialized with tokens from genesis accounts. @@ -795,6 +841,7 @@ func New( consensusparamtypes.ModuleName, // NOTE: crisis module must go at the end to check for invariants on each module crisistypes.ModuleName, + e2eetypes.ModuleName, } if !skipGravity { @@ -908,6 +955,10 @@ func New( tmos.Exit(fmt.Sprintf("versiondb version %d lag behind iavl version %d", v1, v2)) } } + + if err := app.RefreshBlockList(app.NewUncachedContext(false, tmproto.Header{})); err != nil { + panic(err) + } } app.ScopedIBCKeeper = scopedIBCKeeper @@ -1002,7 +1053,22 @@ func (app *App) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.R // EndBlocker application updates every end block func (app *App) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { - return app.mm.EndBlock(ctx, req) + rsp := app.mm.EndBlock(ctx, req) + + if err := app.RefreshBlockList(ctx); err != nil { + app.Logger().Error("failed to update blocklist", "error", err) + } + + return rsp +} + +func (app *App) RefreshBlockList(ctx sdk.Context) error { + if app.blockProposalHandler.Identity == nil { + return nil + } + + // refresh blocklist + return app.blockProposalHandler.SetBlockList(app.CronosKeeper.GetBlockList(ctx)) } // InitChainer application update at chain initialization diff --git a/app/proposal.go b/app/proposal.go new file mode 100644 index 0000000000..fe23975ba8 --- /dev/null +++ b/app/proposal.go @@ -0,0 +1,117 @@ +package app + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + + "filippo.io/age" + + abci "github.com/cometbft/cometbft/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/signing" +) + +type BlockList struct { + Addresses []string `mapstructure:"addresses"` +} + +type ProposalHandler struct { + TxDecoder sdk.TxDecoder + Identity age.Identity + Blocklist map[string]struct{} + LastBlockList []byte +} + +func NewProposalHandler(txDecoder sdk.TxDecoder, identity age.Identity) *ProposalHandler { + return &ProposalHandler{ + TxDecoder: txDecoder, + Identity: identity, + Blocklist: make(map[string]struct{}), + } +} + +func (h *ProposalHandler) SetBlockList(blob []byte) error { + if h.Identity == nil { + return nil + } + + if bytes.Equal(h.LastBlockList, blob) { + return nil + } + h.LastBlockList = blob + + reader, err := age.Decrypt(bytes.NewBuffer(blob), h.Identity) + if err != nil { + return err + } + + data, err := io.ReadAll(reader) + if err != nil { + return err + } + + var blocklist BlockList + if err := json.Unmarshal(data, &blocklist); err != nil { + return err + } + + // convert to map + m := make(map[string]struct{}, len(blocklist.Addresses)) + for _, s := range blocklist.Addresses { + addr, err := sdk.AccAddressFromBech32(s) + if err != nil { + return fmt.Errorf("invalid bech32 address: %s, err: %w", s, err) + } + m[addr.String()] = struct{}{} + } + + h.Blocklist = m + return nil +} + +func (h *ProposalHandler) ValidateTransaction(txBz []byte) error { + tx, err := h.TxDecoder(txBz) + if err != nil { + return err + } + + sigTx, ok := tx.(signing.SigVerifiableTx) + if !ok { + return fmt.Errorf("tx of type %T does not implement SigVerifiableTx", tx) + } + + for _, signer := range sigTx.GetSigners() { + if _, ok := h.Blocklist[signer.String()]; ok { + return fmt.Errorf("signer is blocked: %s", signer.String()) + } + } + return nil +} + +func (h *ProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { + return func(ctx sdk.Context, req abci.RequestPrepareProposal) abci.ResponsePrepareProposal { + txs := make([][]byte, 0, len(req.Txs)) + for _, txBz := range req.Txs { + if err := h.ValidateTransaction(txBz); err != nil { + continue + } + txs = append(txs, txBz) + } + + return abci.ResponsePrepareProposal{Txs: txs} + } +} + +func (h *ProposalHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { + return func(ctx sdk.Context, req abci.RequestProcessProposal) abci.ResponseProcessProposal { + for _, txBz := range req.Txs { + if err := h.ValidateTransaction(txBz); err != nil { + return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT} + } + } + + return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT} + } +} diff --git a/app/upgrades.go b/app/upgrades.go index 76bbff4227..2211ea414c 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -1,15 +1,20 @@ package app import ( + "fmt" + "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" clientkeeper "github.com/cosmos/ibc-go/v7/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) { - planName := "v1.2" + planName := "v1.3" app.UpgradeKeeper.SetUpgradeHandler(planName, func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { m, err := app.mm.RunMigrations(ctx, app.configurator, fromVM) if err != nil { @@ -17,4 +22,18 @@ func (app *App) RegisterUpgradeHandlers(cdc codec.BinaryCodec, clientKeeper clie } return m, nil }) + + upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk() + if err != nil { + panic(fmt.Sprintf("failed to read upgrade info from disk %s", err)) + } + if !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { + if upgradeInfo.Name == planName { + app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storetypes.StoreUpgrades{ + Added: []string{ + e2eetypes.StoreKey, + }, + })) + } + } } diff --git a/client/docs/config.json b/client/docs/config.json index 59927bc19f..9c76549202 100644 --- a/client/docs/config.json +++ b/client/docs/config.json @@ -14,6 +14,9 @@ } } }, + { + "url": "./tmp-swagger-gen/e2ee/query.swagger.json" + }, { "url": "./tmp-swagger-gen/ethermint/evm/v1/query.swagger.json", "operationIds": { diff --git a/client/docs/swagger-ui/swagger.yaml b/client/docs/swagger-ui/swagger.yaml index c69312786a..ea9557515d 100644 --- a/client/docs/swagger-ui/swagger.yaml +++ b/client/docs/swagger-ui/swagger.yaml @@ -864,6 +864,99 @@ paths: type: string tags: - Query + /e2ee/v1/key/{address}: + get: + summary: Key queries the encryption key of a given address + operationId: Key + responses: + '200': + description: A successful response. + schema: + type: object + properties: + key: + type: string + description: KeyResponse is the response type for the Query/Key RPC method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + parameters: + - name: address + in: path + required: true + type: string + tags: + - Query + /e2ee/v1/keys: + post: + summary: Keys queries the encryption keys for a batch of addresses + operationId: Keys + responses: + '200': + description: A successful response. + schema: + type: object + properties: + keys: + type: array + items: + type: string + description: KeysResponse is the response type for the Query/Key RPC method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + parameters: + - name: body + in: body + required: true + schema: + type: object + properties: + addresses: + type: array + items: + type: string + description: KeysRequest is the request type for the Query/Key RPC method. + tags: + - Query /ethermint/evm/v1/account/{address}: get: summary: Account queries an Ethereum account. @@ -43217,6 +43310,28 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + e2ee.KeyResponse: + type: object + properties: + key: + type: string + description: KeyResponse is the response type for the Query/Key RPC method. + e2ee.KeysRequest: + type: object + properties: + addresses: + type: array + items: + type: string + description: KeysRequest is the request type for the Query/Key RPC method. + e2ee.KeysResponse: + type: object + properties: + keys: + type: array + items: + type: string + description: KeysResponse is the response type for the Query/Key RPC method. ethermint.evm.v1.ChainConfig: type: object properties: diff --git a/cmd/cronosd/cmd/root.go b/cmd/cronosd/cmd/root.go index 0e1d63f5a1..97610a2e59 100644 --- a/cmd/cronosd/cmd/root.go +++ b/cmd/cronosd/cmd/root.go @@ -37,12 +37,14 @@ import ( "github.com/evmos/ethermint/crypto/hd" ethermintserver "github.com/evmos/ethermint/server" servercfg "github.com/evmos/ethermint/server/config" + srvflags "github.com/evmos/ethermint/server/flags" ethermint "github.com/evmos/ethermint/types" memiavlcfg "github.com/crypto-org-chain/cronos/store/config" "github.com/crypto-org-chain/cronos/v2/app" "github.com/crypto-org-chain/cronos/v2/cmd/cronosd/opendb" "github.com/crypto-org-chain/cronos/v2/x/cronos" + e2eecli "github.com/crypto-org-chain/cronos/v2/x/e2ee/client/cli" // this line is used by starport scaffolding # stargate/root/import ) @@ -150,8 +152,14 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig ethermint.EncodingConfig queryCommand(), txCommand(), ethermintclient.KeyCommands(app.DefaultNodeHome), + e2eecli.E2EECommand(), ) + rootCmd, err := srvflags.AddTxFlags(rootCmd) + if err != nil { + panic(err) + } + // add rosetta rootCmd.AddCommand(rosettaCmd.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Codec)) } diff --git a/default.nix b/default.nix index 4516138d6a..4501d75db8 100644 --- a/default.nix +++ b/default.nix @@ -11,7 +11,7 @@ , nativeByteOrder ? true # nativeByteOrder mode will panic on big endian machines }: let - version = "v1.2.1"; + version = "v1.3.0"; pname = "cronosd"; tags = [ "ledger" "netgo" network "rocksdb" "grocksdb_no_link" ] ++ lib.optionals nativeByteOrder [ "nativebyteorder" ]; ldflags = lib.concatStringsSep "\n" ([ diff --git a/go.mod b/go.mod index 4d76629af9..bd67b768cd 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,8 @@ require ( cosmossdk.io/math v1.2.0 cosmossdk.io/simapp v0.0.0-20230608160436-666c345ad23d cosmossdk.io/tools/rosetta v0.2.1 + filippo.io/age v1.1.1 + github.com/99designs/keyring v1.2.1 github.com/armon/go-metrics v0.4.1 github.com/cometbft/cometbft v0.37.4 github.com/cometbft/cometbft-db v0.8.0 @@ -31,6 +33,7 @@ require ( github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.4 + golang.org/x/crypto v0.17.0 golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 google.golang.org/grpc v1.60.1 @@ -49,7 +52,6 @@ require ( cosmossdk.io/log v1.3.1 // indirect filippo.io/edwards25519 v1.0.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect - github.com/99designs/keyring v1.2.1 // indirect github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect github.com/DataDog/zstd v1.5.2 // indirect github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect @@ -208,7 +210,6 @@ require ( go.opentelemetry.io/otel v1.19.0 // indirect go.opentelemetry.io/otel/metric v1.19.0 // indirect go.opentelemetry.io/otel/trace v1.19.0 // indirect - golang.org/x/crypto v0.17.0 // indirect golang.org/x/net v0.19.0 // indirect golang.org/x/oauth2 v0.13.0 // indirect golang.org/x/sync v0.4.0 // indirect @@ -239,7 +240,7 @@ replace ( // TODO: remove it: https://github.com/cosmos/cosmos-sdk/issues/13134 github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2 github.com/ethereum/go-ethereum => github.com/crypto-org-chain/go-ethereum v1.10.20-0.20231207063621-43cf32d91c3e - github.com/evmos/ethermint => github.com/crypto-org-chain/ethermint v0.6.1-0.20240419022701-412115d02b10 + github.com/evmos/ethermint => github.com/crypto-org-chain/ethermint v0.6.1-0.20240502043119-814fcacedf60 // Fix upstream GHSA-h395-qcrw-5vmq and GHSA-3vp4-m3rf-835h vulnerabilities. // TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409 github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.0 diff --git a/go.sum b/go.sum index 207627b180..3d827976a6 100644 --- a/go.sum +++ b/go.sum @@ -212,6 +212,8 @@ cosmossdk.io/simapp v0.0.0-20230608160436-666c345ad23d/go.mod h1:xbjky3L3DJEylah cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw= cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/age v1.1.1 h1:pIpO7l151hCnQ4BdyBujnGP2YlUo0uj6sAVNHGBvXHg= +filippo.io/age v1.1.1/go.mod h1:l03SrzDUrBkdBx8+IILdnn2KZysqQdbEBUQ4p3sqEQE= filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -488,8 +490,8 @@ github.com/crypto-org-chain/cometbft-db v0.0.0-20231011055109-57922ac52a63 h1:R1 github.com/crypto-org-chain/cometbft-db v0.0.0-20231011055109-57922ac52a63/go.mod h1:rocwIfnS+kA060x64gkSIRvWB9StSppIkJuo5MWzL24= github.com/crypto-org-chain/cosmos-sdk v0.46.0-beta2.0.20240228013111-9bd1e035ed1d h1:ihUBUAEwQYHZEqf7lXrJithNCUJTjB8q3oSQA6Nevco= github.com/crypto-org-chain/cosmos-sdk v0.46.0-beta2.0.20240228013111-9bd1e035ed1d/go.mod h1:cmAawe8FV/52oPKbgeHLt4UpNkrNu8R5KD+kw0kxJFc= -github.com/crypto-org-chain/ethermint v0.6.1-0.20240419022701-412115d02b10 h1:6uN0+FzbTTFbGAlqdrKjcJt/geaK6zveGtm2p33tXJg= -github.com/crypto-org-chain/ethermint v0.6.1-0.20240419022701-412115d02b10/go.mod h1:zJYmx1D+tDggzvXmdJ0/I62TeIykdCMfJBjBxOcniAU= +github.com/crypto-org-chain/ethermint v0.6.1-0.20240502043119-814fcacedf60 h1:wyqbGGnU3FzSWbu72wrg0RJ1lD25EpYBnVrYTUH9lqk= +github.com/crypto-org-chain/ethermint v0.6.1-0.20240502043119-814fcacedf60/go.mod h1:zJYmx1D+tDggzvXmdJ0/I62TeIykdCMfJBjBxOcniAU= github.com/crypto-org-chain/go-ethereum v1.10.20-0.20231207063621-43cf32d91c3e h1:vnyepPQ/m25+19xcTuBUdRxmltZ/EjVWNqEjhg7Ummk= github.com/crypto-org-chain/go-ethereum v1.10.20-0.20231207063621-43cf32d91c3e/go.mod h1:+a8pUj1tOyJ2RinsNQD4326YS+leSoKGiG/uVVb0x6Y= github.com/crypto-org-chain/gravity-bridge/module/v2 v2.0.1-0.20230825054824-75403cd90c6e h1:rSTc35OBjjCBx47rHPWBCIHNGPbMnEj8f7fNcK2TjVI= diff --git a/gomod2nix.toml b/gomod2nix.toml index 36f7081834..dd5d363ba9 100644 --- a/gomod2nix.toml +++ b/gomod2nix.toml @@ -40,6 +40,9 @@ schema = 3 [mod."cosmossdk.io/tools/rosetta"] version = "v0.2.1" hash = "sha256-TrkXwA1ZdwSyu3te0DLMBynCb7CGEtefo2wzFvxeyU8=" + [mod."filippo.io/age"] + version = "v1.1.1" + hash = "sha256-LRxxJQLQkzoCNYGS/XBixVmYXoZ1mPHKvFicPGXYLcw=" [mod."filippo.io/edwards25519"] version = "v1.0.0" hash = "sha256-APnPAcmItvtJ5Zsy863lzR2TjEBF9Y66TY1e4M1ap98=" @@ -216,8 +219,8 @@ schema = 3 hash = "sha256-lDIqRLUrXYCb9mmFBY/+WW+ee69+IkxOgqjHVyo4ij0=" replaced = "github.com/crypto-org-chain/go-ethereum" [mod."github.com/evmos/ethermint"] - version = "v0.6.1-0.20240419022701-412115d02b10" - hash = "sha256-wuXg0oZlIHc+x9tSmxZxGNoBa521p+o/Nk4ynJHKlRU=" + version = "v0.6.1-0.20240502043119-814fcacedf60" + hash = "sha256-dPO5F/J8XKGLUHiPTpSLBiZcYn42CNzRQ6Ntqcuc8kY=" replaced = "github.com/crypto-org-chain/ethermint" [mod."github.com/felixge/httpsnoop"] version = "v1.0.2" diff --git a/integration_tests/configs/default.jsonnet b/integration_tests/configs/default.jsonnet index 24cd3d4540..41b0364d56 100644 --- a/integration_tests/configs/default.jsonnet +++ b/integration_tests/configs/default.jsonnet @@ -61,6 +61,9 @@ name: 'signer2', coins: '30000000000000000000000basetcro', mnemonic: '${SIGNER2_MNEMONIC}', + }, { + name: 'user', + coins: '10000000000000000000000basetcro', }], genesis: { consensus_params: { @@ -82,6 +85,12 @@ ibc_cro_denom: '${IBC_CRO_DENOM}', }, }, + e2ee: { + keys: [{ + address: 'crc16z0herz998946wr659lr84c8c556da55dc34hh', + key: std.base64('key'), + }], + }, gov: { params: { voting_period: '10s', diff --git a/integration_tests/configs/ibc.jsonnet b/integration_tests/configs/ibc.jsonnet index d63860e654..42ddb56ccd 100644 --- a/integration_tests/configs/ibc.jsonnet +++ b/integration_tests/configs/ibc.jsonnet @@ -5,8 +5,18 @@ config { 'account-prefix': 'crc', 'coin-type': 60, key_name: 'signer1', - accounts: super.accounts[:std.length(super.accounts) - 1] + [super.accounts[std.length(super.accounts) - 1] { - coins: super.coins + ',100000000000ibcfee', + accounts: [{ + name: 'community', + coins: '10000000000000000000000basetcro', + mnemonic: '${COMMUNITY_MNEMONIC}', + }, { + name: 'signer1', + coins: '20000000000000000000000basetcro', + mnemonic: '${SIGNER1_MNEMONIC}', + }, { + name: 'signer2', + coins: '30000000000000000000000basetcro,100000000000ibcfee', + mnemonic: '${SIGNER2_MNEMONIC}', }] + [ { name: 'user' + i, diff --git a/integration_tests/configs/upgrade-test-package.nix b/integration_tests/configs/upgrade-test-package.nix index 2d06b77080..ea00a05708 100644 --- a/integration_tests/configs/upgrade-test-package.nix +++ b/integration_tests/configs/upgrade-test-package.nix @@ -23,5 +23,5 @@ in pkgs.linkFarm "upgrade-test-package" [ { name = "genesis"; path = released0; } { name = "v1.1.0"; path = released; } - { name = "v1.2"; path = current; } + { name = "v1.3"; path = current; } ] diff --git a/integration_tests/cosmoscli.py b/integration_tests/cosmoscli.py index 920fe15a87..978a718e35 100644 --- a/integration_tests/cosmoscli.py +++ b/integration_tests/cosmoscli.py @@ -1,6 +1,7 @@ import binascii import enum import hashlib +import itertools import json import os import re @@ -331,9 +332,18 @@ def staking_pool(self, bonded=True): )["bonded_tokens" if bonded else "not_bonded_tokens"] ) - def transfer(self, from_, to, coins, generate_only=False, fees=None, **kwargs): + def transfer( + self, + from_, + to, + coins, + generate_only=False, + event_query_tx=True, + fees=None, + **kwargs, + ): kwargs.setdefault("gas_prices", DEFAULT_GAS_PRICE) - return json.loads( + rsp = json.loads( self.raw( "tx", "bank", @@ -348,6 +358,9 @@ def transfer(self, from_, to, coins, generate_only=False, fees=None, **kwargs): **kwargs, ) ) + if rsp["code"] == 0 and event_query_tx: + rsp = self.event_query_tx_for(rsp["txhash"]) + return rsp def get_delegated_amount(self, which_addr): return json.loads( @@ -1699,6 +1712,25 @@ def update_permissions(self, address, permissions, **kwargs): rsp = self.event_query_tx_for(rsp["txhash"]) return rsp + def store_blocklist(self, data, **kwargs): + kwargs.setdefault("gas_prices", DEFAULT_GAS_PRICE) + kwargs.setdefault("gas", DEFAULT_GAS) + rsp = json.loads( + self.raw( + "tx", + "cronos", + "store-block-list", + data, + "-y", + home=self.data_dir, + stderr=subprocess.DEVNULL, + **kwargs, + ) + ) + if rsp["code"] == 0: + rsp = self.event_query_tx_for(rsp["txhash"]) + return rsp + def rollback(self): self.raw("rollback", home=self.data_dir) @@ -1814,3 +1846,76 @@ def event_query_tx_for(self, hash): def query_bank_send(self): res = json.loads(self.raw("q", "bank", "send-enabled", home=self.data_dir)) return res["send_enabled"] + + def query_e2ee_key(self, address): + return json.loads( + self.raw( + "q", + "e2ee", + "key", + address, + home=self.data_dir, + output="json", + ) + )["key"] + + def query_e2ee_keys(self, *addresses): + return json.loads( + self.raw( + "q", + "e2ee", + "keys", + *addresses, + home=self.data_dir, + output="json", + ) + )["keys"] + + def register_e2ee_key(self, key, **kwargs): + kwargs.setdefault("gas_prices", DEFAULT_GAS_PRICE) + kwargs.setdefault("gas", DEFAULT_GAS) + rsp = json.loads( + self.raw( + "tx", + "e2ee", + "register-encryption-key", + key, + "-y", + home=self.data_dir, + **kwargs, + ) + ) + if rsp["code"] == 0: + rsp = self.event_query_tx_for(rsp["txhash"]) + return rsp + + def keygen(self, **kwargs): + return self.raw("e2ee", "keygen", home=self.data_dir, **kwargs).strip().decode() + + def encrypt(self, input, *recipients, **kwargs): + return ( + self.raw( + "e2ee", + "encrypt", + input, + *itertools.chain.from_iterable(("-r", r) for r in recipients), + home=self.data_dir, + **kwargs, + ) + .strip() + .decode() + ) + + def decrypt(self, input, identity="e2ee-identity", **kwargs): + return ( + self.raw( + "e2ee", + "decrypt", + input, + home=self.data_dir, + identity=identity, + **kwargs, + ) + .strip() + .decode() + ) diff --git a/integration_tests/ibc_utils.py b/integration_tests/ibc_utils.py index c6c0f32f30..dc4dba0a21 100644 --- a/integration_tests/ibc_utils.py +++ b/integration_tests/ibc_utils.py @@ -774,7 +774,8 @@ def funds_ica(cli, adr): assert cli.balance(adr) == 0 # send some funds to interchain account - rsp = cli.transfer("signer2", adr, "1cro", gas_prices="1000000basecro") + price = "1000000basecro" + rsp = cli.transfer("signer2", adr, "1cro", gas_prices=price, event_query_tx=False) assert rsp["code"] == 0, rsp["raw_log"] wait_for_new_blocks(cli, 1) amt = 100000000 diff --git a/integration_tests/test_e2ee.py b/integration_tests/test_e2ee.py new file mode 100644 index 0000000000..ebe6a3dcae --- /dev/null +++ b/integration_tests/test_e2ee.py @@ -0,0 +1,12 @@ +from .utils import prepare_cipherfile + + +def test_encrypt_decrypt(cronos): + cli = cronos.cosmos_cli() + cli1 = cronos.cosmos_cli(1) + name0 = "key0" + name1 = "key1" + content = "Hello World!" + cipherfile = prepare_cipherfile(cli, cli1, name0, name1, content) + assert cli.decrypt(cipherfile, identity=name0) == content + assert cli1.decrypt(cipherfile, identity=name1) == content diff --git a/integration_tests/test_gov_update_params.py b/integration_tests/test_gov_update_params.py index cc9d6651cc..69f3f41d41 100644 --- a/integration_tests/test_gov_update_params.py +++ b/integration_tests/test_gov_update_params.py @@ -2,8 +2,17 @@ import json import pytest +from pystarport import ports -from .utils import CONTRACTS, approve_proposal, deploy_contract, eth_to_bech32 +from .utils import ( + CONTRACTS, + approve_proposal, + deploy_contract, + eth_to_bech32, + prepare_cipherfile, + wait_for_new_blocks, + wait_for_port, +) pytestmark = pytest.mark.gov @@ -86,3 +95,19 @@ def test_gov_update_params(cronos, tmp_path): rsp = cli.query_params() print("params", rsp) assert rsp == params + + # gen two keys for two accounts + name = "e2ee-identity" + cli1 = cronos.cosmos_cli(1) + addr = cli.address("user") + content = json.dumps({"addresses": [addr]}) + cipherfile = prepare_cipherfile(cli, cli1, name, name, content) + cronos.supervisorctl("stop", "all") + cronos.supervisorctl("start", "cronos_777-1-node0", "cronos_777-1-node1") + wait_for_port(ports.evmrpc_port(cronos.base_port(0))) + rsp = cli.store_blocklist(cipherfile, from_="validator") + assert rsp["code"] == 0, rsp["raw_log"] + wait_for_new_blocks(cli, 2) + rsp = cli.transfer(addr, cli.address("validator"), "1basetcro") + assert rsp["code"] != 0 + assert "signer is blocked" in rsp["raw_log"] diff --git a/integration_tests/test_upgrade.py b/integration_tests/test_upgrade.py index cc8a8dded6..d07787d678 100644 --- a/integration_tests/test_upgrade.py +++ b/integration_tests/test_upgrade.py @@ -194,7 +194,7 @@ def do_upgrade(plan_name, target, mode=None): ) print("old values", old_height, old_balance, old_base_fee) - do_upgrade("v1.2", target_height1) + do_upgrade("v1.3", target_height1) cli = c.cosmos_cli() # check basic tx works diff --git a/integration_tests/utils.py b/integration_tests/utils.py index 323207d83e..fd9cfb933b 100644 --- a/integration_tests/utils.py +++ b/integration_tests/utils.py @@ -732,3 +732,28 @@ def get_send_enable(port): url = f"http://127.0.0.1:{port}/cosmos/bank/v1beta1/params" raw = requests.get(url).json() return raw["params"]["send_enabled"] + + +def prepare_cipherfile(cli0, cli1, name0, name1, content): + # gen two keys for two accounts + pubkey0 = cli0.keygen(keyring_name=name0) + pubkey1 = cli1.keygen(keyring_name=name1) + sender = "validator" + cli0.register_e2ee_key(pubkey0, _from=sender) + cli1.register_e2ee_key(pubkey1, _from=sender) + # query in batch + assert cli0.query_e2ee_keys(cli0.address(sender), cli1.address(sender)) == [ + pubkey0, + pubkey1, + ] + # prepare data file to encrypt + plainfile = cli0.data_dir / "plaintext" + plainfile.write_text(content) + cipherfile = cli0.data_dir / "ciphertext" + cli0.encrypt( + plainfile, + cli0.address(sender), + cli1.address(sender), + output=cipherfile, + ) + return cipherfile diff --git a/proto/cronos/query.proto b/proto/cronos/query.proto index 0f7c457d88..95903eda27 100644 --- a/proto/cronos/query.proto +++ b/proto/cronos/query.proto @@ -36,6 +36,11 @@ service Query { option (google.api.http).get = "/cronos/v1/permissions"; } + // BlockList + rpc BlockList(QueryBlockListRequest) returns (QueryBlockListResponse) { + option (google.api.http).get = "/cronos/v1/blocklist"; + } + // this line is used by starport scaffolding # 2 } @@ -105,4 +110,10 @@ message QueryPermissionsResponse { bool can_turn_bridge = 2; } -// this line is used by starport scaffolding # 3 +// QueryBlockListRequest +message QueryBlockListRequest { } + +// QueryBlockListResponse +message QueryBlockListResponse { + bytes blob = 1; +} diff --git a/proto/cronos/tx.proto b/proto/cronos/tx.proto index 6bb3f2dbbd..af659448d0 100644 --- a/proto/cronos/tx.proto +++ b/proto/cronos/tx.proto @@ -32,6 +32,9 @@ service Msg { // UpdatePermissions defines a method to update cronos admins permissions rpc UpdatePermissions(MsgUpdatePermissions) returns (MsgUpdatePermissionsResponse); + + // StoreBlockList + rpc StoreBlockList(MsgStoreBlockList) returns (MsgStoreBlockListResponse); } // MsgConvertVouchers represents a message to convert ibc voucher coins to @@ -102,4 +105,12 @@ message MsgUpdatePermissions { // MsgUpdatePermissionsResponse defines the response type. message MsgUpdatePermissionsResponse {} -// this line is used by starport scaffolding # proto/tx/message +// MsgStoreBlockList +message MsgStoreBlockList { + string from = 1; + bytes blob = 2; +} + +// MsgStoreBlockListResponse +message MsgStoreBlockListResponse { +} diff --git a/proto/e2ee/genesis.proto b/proto/e2ee/genesis.proto new file mode 100644 index 0000000000..12f4948149 --- /dev/null +++ b/proto/e2ee/genesis.proto @@ -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; + string 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]; +} diff --git a/proto/e2ee/query.proto b/proto/e2ee/query.proto new file mode 100644 index 0000000000..9a8ac9c56b --- /dev/null +++ b/proto/e2ee/query.proto @@ -0,0 +1,42 @@ +syntax = "proto3"; +package e2ee; + +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}"; + } + // Keys queries the encryption keys for a batch of addresses + rpc Keys(KeysRequest) returns (KeysResponse) { + option (google.api.http) = { + post: "/e2ee/v1/keys" + body: "*" + }; + } +} + +// 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 { + string key = 1; +} + + +// KeysRequest is the request type for the Query/Key RPC method. +message KeysRequest { + repeated string addresses = 1; +} + +// KeysResponse is the response type for the Query/Key RPC method. +message KeysResponse { + repeated string keys = 1; +} diff --git a/proto/e2ee/tx.proto b/proto/e2ee/tx.proto new file mode 100644 index 0000000000..b6ecee52bd --- /dev/null +++ b/proto/e2ee/tx.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; +package e2ee; + +import "cosmos/msg/v1/msg.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 { + string address = 1; + string key = 2; +} + +// MsgRegisterEncryptionKeyResponse defines the Msg/RegisterEncryptionKey response type +message MsgRegisterEncryptionKeyResponse { +} diff --git a/x/cronos/client/cli/tx.go b/x/cronos/client/cli/tx.go index 3618c8dd6b..9ff2633ff4 100644 --- a/x/cronos/client/cli/tx.go +++ b/x/cronos/client/cli/tx.go @@ -3,6 +3,8 @@ package cli import ( "encoding/json" "fmt" + "io" + "os" "strconv" "strings" @@ -46,6 +48,7 @@ func GetTxCmd() *cobra.Command { cmd.AddCommand(CmdUpdateTokenMapping()) cmd.AddCommand(CmdTurnBridge()) cmd.AddCommand(CmdUpdatePermissions()) + cmd.AddCommand(CmdStoreBlockList()) cmd.AddCommand(MigrateGenesisCmd()) return cmd } @@ -319,6 +322,43 @@ func CmdUpdatePermissions() *cobra.Command { return cmd } +// CmdStoreBlockList returns a CLI command handler for updating cronos permissions +func CmdStoreBlockList() *cobra.Command { + cmd := &cobra.Command{ + Use: "store-block-list [encrypted-block-list-file]", + Short: "Store encrypted block list", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + fp, err := os.Open(args[0]) + if err != nil { + return err + } + defer fp.Close() + + // Read the file + blob, err := io.ReadAll(fp) + if err != nil { + return err + } + + msg := types.NewMsgStoreBlockList(clientCtx.GetFromAddress().String(), blob) + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} + type ExportEvmGenesisState struct { evmtypes.GenesisState Params ExportEvmParams `json:"params"` diff --git a/x/cronos/handler.go b/x/cronos/handler.go index 92ec7db9f2..86c8d76ab8 100644 --- a/x/cronos/handler.go +++ b/x/cronos/handler.go @@ -32,6 +32,9 @@ func NewHandler(k keeper.Keeper) sdk.Handler { case *types.MsgTurnBridge: res, err := msgServer.TurnBridge(sdk.WrapSDKContext(ctx), msg) return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgStoreBlockList: + res, err := msgServer.StoreBlockList(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) default: errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg) return nil, errors.Wrap(sdkerrors.ErrUnknownRequest, errMsg) diff --git a/x/cronos/keeper/grpc_query.go b/x/cronos/keeper/grpc_query.go index 33bb7b8968..6b3b9a92ff 100644 --- a/x/cronos/keeper/grpc_query.go +++ b/x/cronos/keeper/grpc_query.go @@ -146,3 +146,11 @@ func (k Keeper) Permissions(goCtx context.Context, req *types.QueryPermissionsRe CanTurnBridge: CanTurnBridge == (permissions & CanTurnBridge), }, nil } + +func (k Keeper) BlockList(goCtx context.Context, req *types.QueryBlockListRequest) (*types.QueryBlockListResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + blob := ctx.KVStore(k.storeKey).Get(types.KeyPrefixBlockList) + return &types.QueryBlockListResponse{ + Blob: blob, + }, nil +} diff --git a/x/cronos/keeper/keeper.go b/x/cronos/keeper/keeper.go index 2b69339b53..ab6e16ffa4 100644 --- a/x/cronos/keeper/keeper.go +++ b/x/cronos/keeper/keeper.go @@ -360,3 +360,7 @@ func (k Keeper) IBCSendPacketCallback( ) error { return nil } + +func (k Keeper) GetBlockList(ctx sdk.Context) []byte { + return ctx.KVStore(k.storeKey).Get(types.KeyPrefixBlockList) +} diff --git a/x/cronos/keeper/msg_server.go b/x/cronos/keeper/msg_server.go index b2df2384df..5877bd5a28 100644 --- a/x/cronos/keeper/msg_server.go +++ b/x/cronos/keeper/msg_server.go @@ -123,3 +123,13 @@ func (k msgServer) UpdatePermissions(goCtx context.Context, msg *types.MsgUpdate return &types.MsgUpdatePermissionsResponse{}, nil } + +func (k msgServer) StoreBlockList(goCtx context.Context, msg *types.MsgStoreBlockList) (*types.MsgStoreBlockListResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + admin := k.Keeper.GetParams(ctx).CronosAdmin + if admin != msg.From { + return nil, errors.Wrap(sdkerrors.ErrUnauthorized, "msg sender is not authorized") + } + ctx.KVStore(k.storeKey).Set(types.KeyPrefixBlockList, msg.Blob) + return &types.MsgStoreBlockListResponse{}, nil +} diff --git a/x/cronos/rpc/api.go b/x/cronos/rpc/api.go index bf4fa9fb76..521996196c 100644 --- a/x/cronos/rpc/api.go +++ b/x/cronos/rpc/api.go @@ -180,7 +180,7 @@ func (api *CronosAPI) GetTransactionReceiptsByBlock(blockNrOrHash rpctypes.Block return nil, err } - logs, err := evmtypes.DecodeMsgLogsFromEvents(txResult.Data, parsedTx.MsgIndex, uint64(blockRes.Height)) + logs, err := evmtypes.DecodeMsgLogsFromEvents(txResult.Data, txResult.Events, parsedTx.MsgIndex, uint64(blockRes.Height)) if err != nil { api.logger.Debug("failed to parse logs", "block", resBlock.Block.Height, "txIndex", txIndex, "msgIndex", msgIndex, "error", err.Error()) } diff --git a/x/cronos/types/keys.go b/x/cronos/types/keys.go index 91a8b6b2e6..bf5da7a4c2 100644 --- a/x/cronos/types/keys.go +++ b/x/cronos/types/keys.go @@ -27,6 +27,7 @@ const ( prefixContractToDenom paramsKey prefixAdminToPermissions + prefixBlockList ) // KVStore key prefixes @@ -37,6 +38,7 @@ var ( // ParamsKey is the key for params. ParamsKey = []byte{paramsKey} KeyPrefixAdminToPermissions = []byte{prefixAdminToPermissions} + KeyPrefixBlockList = []byte{prefixBlockList} ) // this line is used by starport scaffolding # ibc/keys/port diff --git a/x/cronos/types/messages.go b/x/cronos/types/messages.go index d7a63da759..4981703385 100644 --- a/x/cronos/types/messages.go +++ b/x/cronos/types/messages.go @@ -23,6 +23,7 @@ var ( _ sdk.Msg = &MsgUpdateParams{} _ sdk.Msg = &MsgTurnBridge{} _ sdk.Msg = &MsgUpdatePermissions{} + _ sdk.Msg = &MsgStoreBlockList{} ) func NewMsgConvertVouchers(address string, coins sdk.Coins) *MsgConvertVouchers { @@ -318,3 +319,27 @@ func (msg *MsgUpdatePermissions) GetSignBytes() []byte { bz := ModuleCdc.MustMarshalJSON(msg) return sdk.MustSortJSON(bz) } + +func NewMsgStoreBlockList(from string, blob []byte) *MsgStoreBlockList { + return &MsgStoreBlockList{ + From: from, + Blob: blob, + } +} + +func (msg *MsgStoreBlockList) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(msg.From) + if err != nil { + return errors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid sender address (%s)", err) + } + return nil +} + +func (msg *MsgStoreBlockList) GetSigners() []sdk.AccAddress { + addr, err := sdk.AccAddressFromBech32(msg.From) + if err != nil { + panic(err) + } + + return []sdk.AccAddress{addr} +} diff --git a/x/cronos/types/query.pb.go b/x/cronos/types/query.pb.go index f929622915..2ccf06b075 100644 --- a/x/cronos/types/query.pb.go +++ b/x/cronos/types/query.pb.go @@ -478,6 +478,88 @@ func (m *QueryPermissionsResponse) GetCanTurnBridge() bool { return false } +// QueryBlockListRequest +type QueryBlockListRequest struct { +} + +func (m *QueryBlockListRequest) Reset() { *m = QueryBlockListRequest{} } +func (m *QueryBlockListRequest) String() string { return proto.CompactTextString(m) } +func (*QueryBlockListRequest) ProtoMessage() {} +func (*QueryBlockListRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_d4ed0fd688c48372, []int{10} +} +func (m *QueryBlockListRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryBlockListRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryBlockListRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryBlockListRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryBlockListRequest.Merge(m, src) +} +func (m *QueryBlockListRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryBlockListRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryBlockListRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryBlockListRequest proto.InternalMessageInfo + +// QueryBlockListResponse +type QueryBlockListResponse struct { + Blob []byte `protobuf:"bytes,1,opt,name=blob,proto3" json:"blob,omitempty"` +} + +func (m *QueryBlockListResponse) Reset() { *m = QueryBlockListResponse{} } +func (m *QueryBlockListResponse) String() string { return proto.CompactTextString(m) } +func (*QueryBlockListResponse) ProtoMessage() {} +func (*QueryBlockListResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_d4ed0fd688c48372, []int{11} +} +func (m *QueryBlockListResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryBlockListResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryBlockListResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryBlockListResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryBlockListResponse.Merge(m, src) +} +func (m *QueryBlockListResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryBlockListResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryBlockListResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryBlockListResponse proto.InternalMessageInfo + +func (m *QueryBlockListResponse) GetBlob() []byte { + if m != nil { + return m.Blob + } + return nil +} + func init() { proto.RegisterType((*ContractByDenomRequest)(nil), "cronos.ContractByDenomRequest") proto.RegisterType((*ContractByDenomResponse)(nil), "cronos.ContractByDenomResponse") @@ -489,61 +571,67 @@ func init() { proto.RegisterType((*QueryParamsResponse)(nil), "cronos.QueryParamsResponse") proto.RegisterType((*QueryPermissionsRequest)(nil), "cronos.QueryPermissionsRequest") proto.RegisterType((*QueryPermissionsResponse)(nil), "cronos.QueryPermissionsResponse") + proto.RegisterType((*QueryBlockListRequest)(nil), "cronos.QueryBlockListRequest") + proto.RegisterType((*QueryBlockListResponse)(nil), "cronos.QueryBlockListResponse") } func init() { proto.RegisterFile("cronos/query.proto", fileDescriptor_d4ed0fd688c48372) } var fileDescriptor_d4ed0fd688c48372 = []byte{ - // 780 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x54, 0x4f, 0x4f, 0xe3, 0x46, - 0x14, 0x8f, 0x21, 0xa4, 0x61, 0x02, 0x45, 0x9d, 0x50, 0x30, 0x6e, 0x6b, 0xa7, 0x6e, 0x05, 0x54, - 0x02, 0x5b, 0x84, 0x4a, 0xad, 0x7a, 0xe8, 0x21, 0x29, 0x12, 0x17, 0x50, 0x6b, 0xe5, 0x84, 0x90, - 0xac, 0x89, 0x33, 0x75, 0x2c, 0xf0, 0x8c, 0xf1, 0x8c, 0x23, 0x22, 0x84, 0x54, 0xb5, 0x97, 0x1e, - 0x91, 0xfa, 0x05, 0x38, 0xf7, 0x93, 0x70, 0x44, 0xea, 0xa5, 0xea, 0xa1, 0xbb, 0x82, 0x3d, 0xec, - 0xc7, 0x58, 0x79, 0x3c, 0x93, 0x04, 0x12, 0x76, 0x4f, 0x9e, 0xf9, 0xfd, 0xde, 0x9f, 0xdf, 0x9b, - 0xf7, 0x9e, 0x01, 0x0c, 0x52, 0x4a, 0x28, 0x73, 0x2f, 0x32, 0x9c, 0x0e, 0x9d, 0x24, 0xa5, 0x9c, - 0xc2, 0x4a, 0x81, 0x19, 0xab, 0x21, 0x0d, 0xa9, 0x80, 0xdc, 0xfc, 0x54, 0xb0, 0xc6, 0xe7, 0x21, - 0xa5, 0xe1, 0x39, 0x76, 0x51, 0x12, 0xb9, 0x88, 0x10, 0xca, 0x11, 0x8f, 0x28, 0x61, 0x92, 0xb5, - 0x24, 0x2b, 0x6e, 0xdd, 0xec, 0x57, 0x97, 0x47, 0x31, 0x66, 0x1c, 0xc5, 0x89, 0x34, 0xd8, 0xc0, - 0xbc, 0x8f, 0xd3, 0x38, 0x22, 0xdc, 0xc5, 0x83, 0xd8, 0x1d, 0xec, 0xb9, 0xfc, 0x52, 0x52, 0x75, - 0xa9, 0xa5, 0xf8, 0x14, 0xa0, 0xfd, 0x3d, 0x58, 0x6b, 0x53, 0xc2, 0x53, 0x14, 0xf0, 0xd6, 0xf0, - 0x27, 0x4c, 0x68, 0xec, 0xe1, 0x8b, 0x0c, 0x33, 0x0e, 0x57, 0xc1, 0x42, 0x2f, 0xbf, 0xeb, 0x5a, - 0x43, 0xdb, 0x5e, 0xf4, 0x8a, 0xcb, 0x0f, 0xd5, 0x3f, 0x6f, 0xad, 0xd2, 0xdb, 0x5b, 0xab, 0x64, - 0x9f, 0x80, 0xf5, 0x29, 0x4f, 0x96, 0x50, 0xc2, 0x30, 0x34, 0x40, 0x35, 0x90, 0x94, 0xf4, 0x1e, - 0xdd, 0xe1, 0x57, 0x60, 0x19, 0x65, 0x9c, 0xfa, 0x23, 0x83, 0x39, 0x61, 0xb0, 0x94, 0x83, 0x2a, - 0x9e, 0xfd, 0x23, 0x58, 0x13, 0x11, 0x5b, 0x43, 0x05, 0x29, 0x55, 0xef, 0x09, 0x3d, 0xa1, 0xcd, - 0x05, 0xeb, 0x53, 0xfe, 0x52, 0xdb, 0xcc, 0xb2, 0xec, 0xff, 0x34, 0x00, 0x3d, 0x9c, 0x9c, 0xa3, - 0x61, 0xeb, 0x9c, 0x06, 0x67, 0x2a, 0xdb, 0x3e, 0x28, 0xc7, 0x2c, 0x64, 0xba, 0xd6, 0x98, 0xdf, - 0xae, 0x35, 0x2d, 0x67, 0xf4, 0xb8, 0x0e, 0x1e, 0xc4, 0xce, 0x60, 0xcf, 0x39, 0x62, 0xe1, 0x41, - 0x8e, 0xe1, 0x2c, 0xee, 0x5c, 0x7a, 0xc2, 0x18, 0x7e, 0x09, 0x96, 0xba, 0x79, 0x10, 0x9f, 0x64, - 0x71, 0x17, 0xa7, 0xa2, 0xc0, 0x79, 0xaf, 0x26, 0xb0, 0x63, 0x01, 0xc1, 0x2f, 0x00, 0x28, 0x4c, - 0xfa, 0x88, 0xf5, 0xf5, 0x79, 0xa1, 0x64, 0x51, 0x20, 0x87, 0x88, 0xf5, 0x61, 0x5b, 0xd1, 0x79, - 0x77, 0xf5, 0x72, 0x43, 0xdb, 0xae, 0x35, 0x0d, 0xa7, 0x68, 0xbd, 0xa3, 0x5a, 0xef, 0x74, 0x54, - 0xeb, 0x5b, 0xd5, 0xbb, 0xff, 0xad, 0xd2, 0xcd, 0x2b, 0x4b, 0x93, 0x41, 0x72, 0x66, 0xe2, 0x35, - 0x4e, 0x41, 0xfd, 0x49, 0x6d, 0xf2, 0x25, 0x0e, 0xc0, 0x62, 0x2a, 0xcf, 0xaa, 0xc2, 0xad, 0x0f, - 0x55, 0x28, 0xed, 0xbd, 0xb1, 0xa7, 0xbd, 0x0a, 0xe0, 0x2f, 0xf9, 0x74, 0xff, 0x8c, 0x52, 0x14, - 0x33, 0xf9, 0x72, 0x76, 0x1b, 0xd4, 0x9f, 0xa0, 0x32, 0xe7, 0x0e, 0xa8, 0x24, 0x02, 0x11, 0xcf, - 0x5f, 0x6b, 0x7e, 0xec, 0xc8, 0x69, 0x2c, 0xec, 0x5a, 0xe5, 0xbc, 0x12, 0x4f, 0xda, 0xd8, 0xfb, - 0x60, 0xbd, 0x08, 0x92, 0x4b, 0x62, 0x2c, 0xdf, 0x03, 0xd5, 0x19, 0x1d, 0x7c, 0x84, 0x7a, 0xbd, - 0x14, 0x33, 0x26, 0x1b, 0xa9, 0xae, 0xf6, 0x15, 0xd0, 0xa7, 0x9d, 0x64, 0xfa, 0xef, 0x80, 0x1e, - 0x20, 0xe2, 0x07, 0x7d, 0x44, 0x42, 0xec, 0x73, 0x7a, 0x86, 0x89, 0x1f, 0xa3, 0x24, 0x89, 0x48, - 0x28, 0xc2, 0x54, 0xbd, 0x4f, 0x03, 0x44, 0xda, 0x82, 0xee, 0xe4, 0xec, 0x51, 0x41, 0xc2, 0x4d, - 0xb0, 0x92, 0x3b, 0xf2, 0x2c, 0x25, 0x7e, 0x37, 0x8d, 0x7a, 0x21, 0x16, 0x6d, 0xad, 0x7a, 0xcb, - 0x01, 0x22, 0x9d, 0x2c, 0x25, 0x2d, 0x01, 0x36, 0xff, 0x2e, 0x83, 0x05, 0x91, 0x1d, 0xfe, 0xa6, - 0x81, 0x95, 0x67, 0xfb, 0x01, 0x4d, 0x55, 0xed, 0xec, 0x95, 0x33, 0xac, 0x17, 0xf9, 0x42, 0xbf, - 0xbd, 0xf3, 0xfb, 0x3f, 0x6f, 0xfe, 0x9a, 0xdb, 0x84, 0x5f, 0xcb, 0x25, 0xce, 0xf7, 0x5b, 0x8d, - 0xbf, 0xdf, 0x1d, 0xfa, 0x62, 0x98, 0xdd, 0x2b, 0xf1, 0xb9, 0x86, 0x7f, 0x68, 0x60, 0xe5, 0xd9, - 0x1a, 0x8c, 0x25, 0xcc, 0xde, 0xaf, 0xb1, 0x84, 0x17, 0xf6, 0xc7, 0x76, 0x85, 0x84, 0x6f, 0xe0, - 0xd6, 0x84, 0x04, 0x91, 0x2f, 0xcf, 0xaf, 0xb4, 0xb8, 0x57, 0xea, 0x74, 0x0d, 0x0f, 0x41, 0x6d, - 0x62, 0xfa, 0xa0, 0xa1, 0x12, 0x4c, 0xaf, 0x9b, 0xf1, 0xd9, 0x4c, 0x4e, 0x26, 0x2e, 0xc1, 0x53, - 0x50, 0x29, 0xc6, 0x64, 0x1c, 0x64, 0x7a, 0xf2, 0xc6, 0x41, 0x66, 0xcc, 0x9f, 0xbd, 0x21, 0xd4, - 0xd7, 0xe1, 0x27, 0x13, 0xea, 0x8b, 0x61, 0x83, 0x09, 0xa8, 0x4d, 0x8c, 0x0c, 0xb4, 0x9e, 0x86, - 0x99, 0x9a, 0x40, 0xa3, 0xf1, 0xb2, 0x81, 0x4c, 0x66, 0x8a, 0x64, 0x3a, 0x5c, 0x9b, 0x4c, 0x36, - 0xb6, 0x6b, 0x1d, 0xdf, 0x3d, 0x98, 0xda, 0xfd, 0x83, 0xa9, 0xbd, 0x7e, 0x30, 0xb5, 0x9b, 0x47, - 0xb3, 0x74, 0xff, 0x68, 0x96, 0xfe, 0x7d, 0x34, 0x4b, 0x27, 0xdf, 0x86, 0x11, 0xef, 0x67, 0x5d, - 0x27, 0xa0, 0xb1, 0x1b, 0xa4, 0xc3, 0x84, 0xd3, 0x5d, 0x9a, 0x86, 0xbb, 0x41, 0x1f, 0x45, 0x64, - 0x14, 0xac, 0xe9, 0x5e, 0xaa, 0x33, 0x1f, 0x26, 0x98, 0x75, 0x2b, 0xe2, 0xd7, 0xb0, 0xff, 0x2e, - 0x00, 0x00, 0xff, 0xff, 0x45, 0xdb, 0x55, 0xc7, 0x75, 0x06, 0x00, 0x00, + // 840 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x54, 0x4d, 0x6f, 0xdc, 0x44, + 0x18, 0x5e, 0x37, 0x1f, 0x6c, 0xde, 0x4d, 0x89, 0x98, 0xa4, 0x1b, 0xd7, 0xb4, 0x76, 0x30, 0xa8, + 0x0d, 0x52, 0x6a, 0xab, 0x1b, 0x24, 0x10, 0x07, 0x0e, 0x1b, 0x2a, 0xf5, 0x40, 0x2b, 0xb0, 0x72, + 0xaa, 0x2a, 0x59, 0x63, 0x67, 0xb0, 0xad, 0xae, 0x67, 0x5c, 0xcf, 0x38, 0xca, 0x2a, 0xaa, 0x84, + 0xe0, 0xc2, 0xb1, 0x12, 0xfc, 0x80, 0xfe, 0x9c, 0x1e, 0x23, 0x71, 0x41, 0x1c, 0x00, 0x25, 0x1c, + 0xf8, 0x19, 0xc8, 0xe3, 0x99, 0x5d, 0x67, 0x3f, 0xe8, 0xc9, 0x33, 0xef, 0xf3, 0xce, 0xfb, 0x3c, + 0xef, 0x97, 0x01, 0xc5, 0x25, 0xa3, 0x8c, 0xfb, 0x2f, 0x2b, 0x52, 0x8e, 0xbd, 0xa2, 0x64, 0x82, + 0xa1, 0xf5, 0xc6, 0x66, 0xed, 0x24, 0x2c, 0x61, 0xd2, 0xe4, 0xd7, 0xa7, 0x06, 0xb5, 0xee, 0x24, + 0x8c, 0x25, 0x23, 0xe2, 0xe3, 0x22, 0xf3, 0x31, 0xa5, 0x4c, 0x60, 0x91, 0x31, 0xca, 0x15, 0xea, + 0x28, 0x54, 0xde, 0xa2, 0xea, 0x7b, 0x5f, 0x64, 0x39, 0xe1, 0x02, 0xe7, 0x85, 0x72, 0xb8, 0x4d, + 0x44, 0x4a, 0xca, 0x3c, 0xa3, 0xc2, 0x27, 0xa7, 0xb9, 0x7f, 0xfa, 0xd0, 0x17, 0x67, 0x0a, 0xda, + 0x56, 0x5a, 0x9a, 0x4f, 0x63, 0x74, 0xbf, 0x80, 0xfe, 0x11, 0xa3, 0xa2, 0xc4, 0xb1, 0x18, 0x8e, + 0xbf, 0x26, 0x94, 0xe5, 0x01, 0x79, 0x59, 0x11, 0x2e, 0xd0, 0x0e, 0xac, 0x9d, 0xd4, 0x77, 0xd3, + 0xd8, 0x33, 0xf6, 0x37, 0x82, 0xe6, 0xf2, 0x65, 0xf7, 0xe7, 0x37, 0x4e, 0xe7, 0xdf, 0x37, 0x4e, + 0xc7, 0x7d, 0x06, 0xbb, 0x73, 0x2f, 0x79, 0xc1, 0x28, 0x27, 0xc8, 0x82, 0x6e, 0xac, 0x20, 0xf5, + 0x7a, 0x72, 0x47, 0x1f, 0xc3, 0x4d, 0x5c, 0x09, 0x16, 0x4e, 0x1c, 0x6e, 0x48, 0x87, 0xcd, 0xda, + 0xa8, 0xe3, 0xb9, 0x5f, 0x41, 0x5f, 0x46, 0x1c, 0x8e, 0xb5, 0x49, 0xab, 0xfa, 0x9f, 0xd0, 0x2d, + 0x6d, 0x3e, 0xec, 0xce, 0xbd, 0x57, 0xda, 0x16, 0xa6, 0xe5, 0xfe, 0x61, 0x00, 0x0a, 0x48, 0x31, + 0xc2, 0xe3, 0xe1, 0x88, 0xc5, 0x2f, 0x34, 0xdb, 0x21, 0xac, 0xe6, 0x3c, 0xe1, 0xa6, 0xb1, 0xb7, + 0xb2, 0xdf, 0x1b, 0x38, 0xde, 0xa4, 0xb8, 0x1e, 0x39, 0xcd, 0xbd, 0xd3, 0x87, 0xde, 0x13, 0x9e, + 0x3c, 0xaa, 0x6d, 0xa4, 0xca, 0x8f, 0xcf, 0x02, 0xe9, 0x8c, 0x3e, 0x82, 0xcd, 0xa8, 0x0e, 0x12, + 0xd2, 0x2a, 0x8f, 0x48, 0x29, 0x13, 0x5c, 0x09, 0x7a, 0xd2, 0xf6, 0x54, 0x9a, 0xd0, 0x5d, 0x80, + 0xc6, 0x25, 0xc5, 0x3c, 0x35, 0x57, 0xa4, 0x92, 0x0d, 0x69, 0x79, 0x8c, 0x79, 0x8a, 0x8e, 0x34, + 0x5c, 0x77, 0xd7, 0x5c, 0xdd, 0x33, 0xf6, 0x7b, 0x03, 0xcb, 0x6b, 0x5a, 0xef, 0xe9, 0xd6, 0x7b, + 0xc7, 0xba, 0xf5, 0xc3, 0xee, 0xdb, 0x3f, 0x9d, 0xce, 0xeb, 0xbf, 0x1c, 0x43, 0x05, 0xa9, 0x91, + 0x56, 0x35, 0x9e, 0xc3, 0xf6, 0xb5, 0xdc, 0x54, 0x25, 0x1e, 0xc1, 0x46, 0xa9, 0xce, 0x3a, 0xc3, + 0xfb, 0xef, 0xca, 0x50, 0xf9, 0x07, 0xd3, 0x97, 0xee, 0x0e, 0xa0, 0xef, 0xea, 0xe9, 0xfe, 0x16, + 0x97, 0x38, 0xe7, 0xaa, 0x72, 0xee, 0x11, 0x6c, 0x5f, 0xb3, 0x2a, 0xce, 0x03, 0x58, 0x2f, 0xa4, + 0x45, 0x96, 0xbf, 0x37, 0x78, 0xdf, 0x53, 0xd3, 0xd8, 0xf8, 0x0d, 0x57, 0xeb, 0x4c, 0x02, 0xe5, + 0xe3, 0x1e, 0xc2, 0x6e, 0x13, 0xa4, 0x96, 0xc4, 0x79, 0xbd, 0x07, 0xba, 0x33, 0x26, 0xbc, 0x87, + 0x4f, 0x4e, 0x4a, 0xc2, 0xb9, 0x6a, 0xa4, 0xbe, 0xba, 0xe7, 0x60, 0xce, 0x3f, 0x52, 0xf4, 0x9f, + 0x83, 0x19, 0x63, 0x1a, 0xc6, 0x29, 0xa6, 0x09, 0x09, 0x05, 0x7b, 0x41, 0x68, 0x98, 0xe3, 0xa2, + 0xc8, 0x68, 0x22, 0xc3, 0x74, 0x83, 0x5b, 0x31, 0xa6, 0x47, 0x12, 0x3e, 0xae, 0xd1, 0x27, 0x0d, + 0x88, 0xee, 0xc1, 0x56, 0xfd, 0x50, 0x54, 0x25, 0x0d, 0xa3, 0x32, 0x3b, 0x49, 0x88, 0x6c, 0x6b, + 0x37, 0xb8, 0x19, 0x63, 0x7a, 0x5c, 0x95, 0x74, 0x28, 0x8d, 0xee, 0x2e, 0xdc, 0x92, 0xe4, 0xb2, + 0xd2, 0xdf, 0x64, 0x5c, 0xcf, 0xad, 0x7b, 0x00, 0xfd, 0x59, 0x40, 0x69, 0x42, 0xb0, 0x1a, 0x8d, + 0x58, 0x24, 0xf9, 0x37, 0x03, 0x79, 0x1e, 0xfc, 0xba, 0x06, 0x6b, 0xd2, 0x1d, 0xfd, 0x60, 0xc0, + 0xd6, 0xcc, 0x9a, 0x21, 0x5b, 0x17, 0x6d, 0xf1, 0xe6, 0x5a, 0xce, 0x52, 0xbc, 0xa1, 0x74, 0x0f, + 0x7e, 0xfc, 0xed, 0x9f, 0x5f, 0x6e, 0xdc, 0x43, 0x9f, 0xa8, 0x7f, 0x41, 0xfd, 0x9b, 0xd0, 0x5b, + 0x14, 0x46, 0xe3, 0x50, 0xee, 0x84, 0x7f, 0x2e, 0x3f, 0xaf, 0xd0, 0x4f, 0x06, 0x6c, 0xcd, 0x6c, + 0xd3, 0x54, 0xc2, 0xe2, 0x35, 0x9d, 0x4a, 0x58, 0xb2, 0x86, 0xae, 0x2f, 0x25, 0x7c, 0x8a, 0xee, + 0xb7, 0x24, 0x48, 0xbe, 0x9a, 0x5f, 0x6b, 0xf1, 0xcf, 0xf5, 0xe9, 0x15, 0x7a, 0x0c, 0xbd, 0xd6, + 0x10, 0x23, 0x4b, 0x13, 0xcc, 0x6f, 0xad, 0xf5, 0xe1, 0x42, 0x4c, 0x11, 0x77, 0xd0, 0x73, 0x58, + 0x6f, 0xa6, 0x6d, 0x1a, 0x64, 0x7e, 0x80, 0xa7, 0x41, 0x16, 0x8c, 0xb1, 0x7b, 0x5b, 0xaa, 0xdf, + 0x46, 0x1f, 0xb4, 0xd4, 0x37, 0x33, 0x8b, 0x0a, 0xe8, 0xb5, 0x26, 0x0f, 0x39, 0xd7, 0xc3, 0xcc, + 0x0d, 0xb2, 0xb5, 0xb7, 0xdc, 0x41, 0x91, 0xd9, 0x92, 0xcc, 0x44, 0xfd, 0x36, 0x59, 0x8b, 0x22, + 0x85, 0x8d, 0xc9, 0x54, 0xa1, 0xbb, 0xd7, 0xc2, 0xcd, 0x8e, 0xa1, 0x65, 0x2f, 0x83, 0x15, 0xd7, + 0x1d, 0xc9, 0xd5, 0x47, 0x3b, 0x2d, 0x2e, 0xf9, 0x4b, 0x19, 0x65, 0x5c, 0x0c, 0x9f, 0xbe, 0xbd, + 0xb4, 0x8d, 0x8b, 0x4b, 0xdb, 0xf8, 0xfb, 0xd2, 0x36, 0x5e, 0x5f, 0xd9, 0x9d, 0x8b, 0x2b, 0xbb, + 0xf3, 0xfb, 0x95, 0xdd, 0x79, 0xf6, 0x59, 0x92, 0x89, 0xb4, 0x8a, 0xbc, 0x98, 0xe5, 0x7e, 0x5c, + 0x8e, 0x0b, 0xc1, 0x1e, 0xb0, 0x32, 0x79, 0x10, 0xa7, 0x38, 0xa3, 0x93, 0x50, 0x03, 0xff, 0x4c, + 0x9f, 0xc5, 0xb8, 0x20, 0x3c, 0x5a, 0x97, 0xff, 0xb2, 0xc3, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, + 0x8b, 0x53, 0x98, 0x0a, 0x26, 0x07, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -569,6 +657,8 @@ type QueryClient interface { Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) // Params queries permissions for a specific address.. Permissions(ctx context.Context, in *QueryPermissionsRequest, opts ...grpc.CallOption) (*QueryPermissionsResponse, error) + // BlockList + BlockList(ctx context.Context, in *QueryBlockListRequest, opts ...grpc.CallOption) (*QueryBlockListResponse, error) } type queryClient struct { @@ -624,6 +714,15 @@ func (c *queryClient) Permissions(ctx context.Context, in *QueryPermissionsReque return out, nil } +func (c *queryClient) BlockList(ctx context.Context, in *QueryBlockListRequest, opts ...grpc.CallOption) (*QueryBlockListResponse, error) { + out := new(QueryBlockListResponse) + err := c.cc.Invoke(ctx, "/cronos.Query/BlockList", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // ContractByDenom queries contract addresses by native denom @@ -637,6 +736,8 @@ type QueryServer interface { Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) // Params queries permissions for a specific address.. Permissions(context.Context, *QueryPermissionsRequest) (*QueryPermissionsResponse, error) + // BlockList + BlockList(context.Context, *QueryBlockListRequest) (*QueryBlockListResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -658,6 +759,9 @@ func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsReq func (*UnimplementedQueryServer) Permissions(ctx context.Context, req *QueryPermissionsRequest) (*QueryPermissionsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Permissions not implemented") } +func (*UnimplementedQueryServer) BlockList(ctx context.Context, req *QueryBlockListRequest) (*QueryBlockListResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method BlockList not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -753,6 +857,24 @@ func _Query_Permissions_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } +func _Query_BlockList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryBlockListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).BlockList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cronos.Query/BlockList", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).BlockList(ctx, req.(*QueryBlockListRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "cronos.Query", HandlerType: (*QueryServer)(nil), @@ -777,6 +899,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "Permissions", Handler: _Query_Permissions_Handler, }, + { + MethodName: "BlockList", + Handler: _Query_BlockList_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "cronos/query.proto", @@ -1132,6 +1258,59 @@ func (m *QueryPermissionsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error return len(dAtA) - i, nil } +func (m *QueryBlockListRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryBlockListRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryBlockListRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryBlockListResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryBlockListResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryBlockListResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Blob) > 0 { + i -= len(m.Blob) + copy(dAtA[i:], m.Blob) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Blob))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -1286,6 +1465,28 @@ func (m *QueryPermissionsResponse) Size() (n int) { return n } +func (m *QueryBlockListRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryBlockListResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Blob) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -2209,6 +2410,140 @@ func (m *QueryPermissionsResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryBlockListRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryBlockListRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryBlockListRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryBlockListResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryBlockListResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryBlockListResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Blob", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Blob = append(m.Blob[:0], dAtA[iNdEx:postIndex]...) + if m.Blob == nil { + m.Blob = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/cronos/types/query.pb.gw.go b/x/cronos/types/query.pb.gw.go index 38bd87d332..b6e425049b 100644 --- a/x/cronos/types/query.pb.gw.go +++ b/x/cronos/types/query.pb.gw.go @@ -195,6 +195,24 @@ func local_request_Query_Permissions_0(ctx context.Context, marshaler runtime.Ma } +func request_Query_BlockList_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryBlockListRequest + var metadata runtime.ServerMetadata + + msg, err := client.BlockList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_BlockList_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryBlockListRequest + var metadata runtime.ServerMetadata + + msg, err := server.BlockList(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -293,6 +311,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_BlockList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_BlockList_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_BlockList_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -414,6 +455,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_BlockList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_BlockList_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_BlockList_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -425,6 +486,8 @@ var ( pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"cronos", "v1", "params"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_Permissions_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"cronos", "v1", "permissions"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_BlockList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"cronos", "v1", "blocklist"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -435,4 +498,6 @@ var ( forward_Query_Params_0 = runtime.ForwardResponseMessage forward_Query_Permissions_0 = runtime.ForwardResponseMessage + + forward_Query_BlockList_0 = runtime.ForwardResponseMessage ) diff --git a/x/cronos/types/tx.pb.go b/x/cronos/types/tx.pb.go index dc4c56f5c3..bd1874ea78 100644 --- a/x/cronos/types/tx.pb.go +++ b/x/cronos/types/tx.pb.go @@ -616,6 +616,96 @@ func (m *MsgUpdatePermissionsResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgUpdatePermissionsResponse proto.InternalMessageInfo +// MsgStoreBlockList +type MsgStoreBlockList struct { + From string `protobuf:"bytes,1,opt,name=from,proto3" json:"from,omitempty"` + Blob []byte `protobuf:"bytes,2,opt,name=blob,proto3" json:"blob,omitempty"` +} + +func (m *MsgStoreBlockList) Reset() { *m = MsgStoreBlockList{} } +func (m *MsgStoreBlockList) String() string { return proto.CompactTextString(m) } +func (*MsgStoreBlockList) ProtoMessage() {} +func (*MsgStoreBlockList) Descriptor() ([]byte, []int) { + return fileDescriptor_28e09e4eabb18884, []int{12} +} +func (m *MsgStoreBlockList) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgStoreBlockList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgStoreBlockList.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgStoreBlockList) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgStoreBlockList.Merge(m, src) +} +func (m *MsgStoreBlockList) XXX_Size() int { + return m.Size() +} +func (m *MsgStoreBlockList) XXX_DiscardUnknown() { + xxx_messageInfo_MsgStoreBlockList.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgStoreBlockList proto.InternalMessageInfo + +func (m *MsgStoreBlockList) GetFrom() string { + if m != nil { + return m.From + } + return "" +} + +func (m *MsgStoreBlockList) GetBlob() []byte { + if m != nil { + return m.Blob + } + return nil +} + +// MsgStoreBlockListResponse +type MsgStoreBlockListResponse struct { +} + +func (m *MsgStoreBlockListResponse) Reset() { *m = MsgStoreBlockListResponse{} } +func (m *MsgStoreBlockListResponse) String() string { return proto.CompactTextString(m) } +func (*MsgStoreBlockListResponse) ProtoMessage() {} +func (*MsgStoreBlockListResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_28e09e4eabb18884, []int{13} +} +func (m *MsgStoreBlockListResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgStoreBlockListResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgStoreBlockListResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgStoreBlockListResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgStoreBlockListResponse.Merge(m, src) +} +func (m *MsgStoreBlockListResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgStoreBlockListResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgStoreBlockListResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgStoreBlockListResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgConvertVouchers)(nil), "cronos.MsgConvertVouchers") proto.RegisterType((*MsgTransferTokens)(nil), "cronos.MsgTransferTokens") @@ -629,54 +719,59 @@ func init() { proto.RegisterType((*MsgUpdateParamsResponse)(nil), "cronos.MsgUpdateParamsResponse") proto.RegisterType((*MsgUpdatePermissions)(nil), "cronos.MsgUpdatePermissions") proto.RegisterType((*MsgUpdatePermissionsResponse)(nil), "cronos.MsgUpdatePermissionsResponse") + proto.RegisterType((*MsgStoreBlockList)(nil), "cronos.MsgStoreBlockList") + proto.RegisterType((*MsgStoreBlockListResponse)(nil), "cronos.MsgStoreBlockListResponse") } func init() { proto.RegisterFile("cronos/tx.proto", fileDescriptor_28e09e4eabb18884) } var fileDescriptor_28e09e4eabb18884 = []byte{ - // 658 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0xcd, 0x6e, 0xd3, 0x4c, - 0x14, 0x8d, 0x93, 0x34, 0x5f, 0x7b, 0xfb, 0xb5, 0x55, 0x87, 0xfe, 0x24, 0x26, 0x75, 0x82, 0x05, - 0x52, 0x16, 0x34, 0xa6, 0x81, 0x3d, 0x52, 0xba, 0x61, 0x93, 0x0a, 0xac, 0x02, 0x52, 0x25, 0x16, - 0x13, 0x7b, 0xea, 0x58, 0xad, 0x67, 0xac, 0x99, 0x49, 0xd5, 0xbc, 0x05, 0x88, 0x1d, 0x8f, 0xc0, - 0x93, 0x74, 0xd9, 0x25, 0x2b, 0x40, 0xed, 0x92, 0x97, 0x40, 0x19, 0x8f, 0x1d, 0xb7, 0x4e, 0xba, - 0x63, 0xe5, 0xb9, 0xf7, 0xcc, 0x3d, 0xe7, 0x5c, 0xcf, 0x9d, 0x81, 0x0d, 0x8f, 0x33, 0xca, 0x84, - 0x23, 0x2f, 0xbb, 0x31, 0x67, 0x92, 0xa1, 0x5a, 0x92, 0x30, 0xb7, 0x02, 0x16, 0x30, 0x95, 0x72, - 0xa6, 0xab, 0x04, 0x35, 0x2d, 0x8f, 0x89, 0x88, 0x09, 0x67, 0x88, 0x05, 0x71, 0x2e, 0x0e, 0x86, - 0x44, 0xe2, 0x03, 0xc7, 0x63, 0x21, 0xd5, 0xf8, 0x23, 0x4d, 0x97, 0x7c, 0x92, 0xa4, 0xfd, 0xc5, - 0x00, 0x34, 0x10, 0xc1, 0x21, 0xa3, 0x17, 0x84, 0xcb, 0x0f, 0x6c, 0xec, 0x8d, 0x08, 0x17, 0xa8, - 0x0e, 0xff, 0x61, 0xdf, 0xe7, 0x44, 0x88, 0xba, 0xd1, 0x36, 0x3a, 0x2b, 0x6e, 0x1a, 0x22, 0x0c, - 0x4b, 0x53, 0x4e, 0x51, 0x2f, 0xb7, 0x2b, 0x9d, 0xd5, 0x5e, 0xa3, 0x9b, 0xa8, 0x76, 0xa7, 0xaa, - 0x5d, 0xad, 0xda, 0x3d, 0x64, 0x21, 0xed, 0xbf, 0xb8, 0xfa, 0xd9, 0x2a, 0x7d, 0xff, 0xd5, 0xea, - 0x04, 0xa1, 0x1c, 0x8d, 0x87, 0x5d, 0x8f, 0x45, 0x8e, 0xb6, 0x98, 0x7c, 0xf6, 0x85, 0x7f, 0xe6, - 0xc8, 0x49, 0x4c, 0x84, 0x2a, 0x10, 0x6e, 0xc2, 0x6c, 0x7f, 0x33, 0x60, 0x73, 0x20, 0x82, 0x63, - 0x8e, 0xa9, 0x38, 0x25, 0xfc, 0x98, 0x9d, 0x11, 0x2a, 0x10, 0x82, 0xea, 0x29, 0x67, 0x91, 0xf6, - 0xa3, 0xd6, 0x68, 0x1d, 0xca, 0x92, 0xd5, 0xcb, 0x2a, 0x53, 0x96, 0x6c, 0x66, 0xae, 0xf2, 0xcf, - 0xcc, 0x35, 0xc1, 0x2c, 0xfe, 0x2f, 0x97, 0x88, 0x98, 0x51, 0x41, 0xec, 0xc7, 0xd0, 0x28, 0x38, - 0xcf, 0xc0, 0xaf, 0x06, 0x6c, 0x0f, 0x44, 0xf0, 0x3e, 0xf6, 0xb1, 0x24, 0x0a, 0x1b, 0xe0, 0x38, - 0x0e, 0x69, 0x80, 0x76, 0xa0, 0x26, 0x08, 0xf5, 0x09, 0xd7, 0xdd, 0xe9, 0x08, 0x6d, 0xc1, 0x92, - 0x4f, 0x28, 0x8b, 0x74, 0x8b, 0x49, 0x80, 0x4c, 0x58, 0xf6, 0x18, 0x95, 0x1c, 0x7b, 0xb2, 0x5e, - 0x51, 0x40, 0x16, 0x2b, 0xa6, 0x49, 0x34, 0x64, 0xe7, 0xf5, 0xaa, 0x66, 0x52, 0xd1, 0xf4, 0x40, - 0x7d, 0xe2, 0x85, 0x11, 0x3e, 0xaf, 0x2f, 0xb5, 0x8d, 0xce, 0x9a, 0x9b, 0x86, 0x76, 0x0b, 0xf6, - 0xe6, 0x9a, 0xca, 0x6c, 0xbf, 0x86, 0xb5, 0x69, 0x4f, 0x63, 0x4e, 0xfb, 0x3c, 0xf4, 0x03, 0xb2, - 0xd0, 0xed, 0x0e, 0xd4, 0x08, 0xc5, 0xc3, 0x73, 0xa2, 0xec, 0x2e, 0xbb, 0x3a, 0xb2, 0x77, 0x55, - 0xdb, 0x33, 0x82, 0x8c, 0xf9, 0x13, 0x6c, 0x64, 0xd2, 0x6f, 0x31, 0xc7, 0x91, 0x40, 0x4d, 0x58, - 0xc1, 0x63, 0x39, 0x62, 0x3c, 0x94, 0x13, 0x4d, 0x3f, 0x4b, 0xa0, 0xe7, 0x50, 0x8b, 0xd5, 0x3e, - 0xa5, 0xb0, 0xda, 0x5b, 0xef, 0xea, 0x61, 0x4e, 0xaa, 0xfb, 0xd5, 0xe9, 0xa9, 0xba, 0x7a, 0x8f, - 0xdd, 0x80, 0xdd, 0x7b, 0xf4, 0x99, 0xf2, 0x29, 0x6c, 0xcd, 0x20, 0xc2, 0xa3, 0x50, 0x88, 0x90, - 0x2d, 0x18, 0xb2, 0xdc, 0x5d, 0x28, 0xdf, 0xbd, 0x0b, 0x6d, 0x58, 0x8d, 0x67, 0xc5, 0xea, 0x2c, - 0xaa, 0x6e, 0x3e, 0x65, 0x5b, 0xd0, 0x9c, 0xa7, 0x93, 0xfa, 0xe8, 0xfd, 0xa9, 0x40, 0x65, 0x20, - 0x02, 0xf4, 0x0e, 0x36, 0xee, 0x5f, 0x41, 0x33, 0xed, 0xad, 0x38, 0x6e, 0xa6, 0xbd, 0x18, 0x4b, - 0xa9, 0xd1, 0x11, 0xac, 0xdf, 0xbb, 0x41, 0x8d, 0x5c, 0xd5, 0x5d, 0xc8, 0x7c, 0xb2, 0x10, 0xca, - 0xf8, 0x4e, 0x00, 0xcd, 0x99, 0xdc, 0xbd, 0x5c, 0x61, 0x11, 0x36, 0x9f, 0x3d, 0x08, 0x67, 0xdc, - 0x7d, 0x80, 0xdc, 0x7c, 0x6d, 0xe7, 0xcd, 0x64, 0x69, 0x73, 0x6f, 0x6e, 0x3a, 0xe3, 0x78, 0x03, - 0xff, 0xdf, 0x99, 0xa4, 0xdd, 0x82, 0x74, 0x02, 0x98, 0xad, 0x05, 0x40, 0xc6, 0xf4, 0x11, 0x36, - 0x8b, 0x93, 0xd1, 0x2c, 0x56, 0xcd, 0x50, 0xf3, 0xe9, 0x43, 0x68, 0x4a, 0xdc, 0x3f, 0xba, 0xba, - 0xb1, 0x8c, 0xeb, 0x1b, 0xcb, 0xf8, 0x7d, 0x63, 0x19, 0x9f, 0x6f, 0xad, 0xd2, 0xf5, 0xad, 0x55, - 0xfa, 0x71, 0x6b, 0x95, 0x4e, 0x5e, 0xe5, 0x9f, 0x21, 0x3e, 0x89, 0x25, 0xdb, 0x67, 0x3c, 0xd8, - 0xf7, 0x46, 0x38, 0xa4, 0xfa, 0xc1, 0x76, 0x2e, 0x7a, 0xce, 0x65, 0xba, 0x56, 0x0f, 0xd3, 0xb0, - 0xa6, 0xde, 0xf0, 0x97, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x3a, 0x67, 0xb5, 0xca, 0x29, 0x06, - 0x00, 0x00, + // 707 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xcd, 0x6e, 0xd3, 0x4a, + 0x14, 0x8e, 0x93, 0x34, 0xb7, 0x3d, 0xfd, 0x53, 0xe7, 0xf6, 0x27, 0xf1, 0x4d, 0x9d, 0x5c, 0xeb, + 0x5e, 0x29, 0x0b, 0x1a, 0xd3, 0xc0, 0x8e, 0x05, 0x52, 0xba, 0x61, 0x41, 0x2a, 0x30, 0x05, 0xa4, + 0x4a, 0x2c, 0xfc, 0x33, 0x75, 0xac, 0xc6, 0x33, 0xd6, 0xcc, 0xa4, 0x6a, 0xde, 0x02, 0xc4, 0x8e, + 0x47, 0xe0, 0x15, 0x78, 0x81, 0x2e, 0xbb, 0x64, 0x05, 0xa8, 0x7d, 0x11, 0x94, 0xf1, 0xc4, 0x71, + 0xe2, 0xa4, 0x3b, 0x56, 0x9e, 0x73, 0x3e, 0x9f, 0xef, 0x7c, 0xe3, 0xf3, 0x8d, 0x07, 0xb6, 0x3d, + 0x46, 0x09, 0xe5, 0x96, 0xb8, 0x6e, 0xc7, 0x8c, 0x0a, 0x8a, 0x2a, 0x49, 0x42, 0xdf, 0x0d, 0x68, + 0x40, 0x65, 0xca, 0x1a, 0xaf, 0x12, 0x54, 0x37, 0x3c, 0xca, 0x23, 0xca, 0x2d, 0xd7, 0xe1, 0xd8, + 0xba, 0x3a, 0x76, 0xb1, 0x70, 0x8e, 0x2d, 0x8f, 0x86, 0x44, 0xe1, 0x7f, 0x2b, 0xba, 0xe4, 0x91, + 0x24, 0xcd, 0x4f, 0x1a, 0xa0, 0x1e, 0x0f, 0x4e, 0x28, 0xb9, 0xc2, 0x4c, 0xbc, 0xa3, 0x43, 0xaf, + 0x8f, 0x19, 0x47, 0x55, 0xf8, 0xcb, 0xf1, 0x7d, 0x86, 0x39, 0xaf, 0x6a, 0x4d, 0xad, 0xb5, 0x66, + 0x4f, 0x42, 0xe4, 0xc0, 0xca, 0x98, 0x93, 0x57, 0x8b, 0xcd, 0x52, 0x6b, 0xbd, 0x53, 0x6b, 0x27, + 0x5d, 0xdb, 0xe3, 0xae, 0x6d, 0xd5, 0xb5, 0x7d, 0x42, 0x43, 0xd2, 0x7d, 0x7c, 0xf3, 0xa3, 0x51, + 0xf8, 0xfa, 0xb3, 0xd1, 0x0a, 0x42, 0xd1, 0x1f, 0xba, 0x6d, 0x8f, 0x46, 0x96, 0x92, 0x98, 0x3c, + 0x8e, 0xb8, 0x7f, 0x69, 0x89, 0x51, 0x8c, 0xb9, 0x2c, 0xe0, 0x76, 0xc2, 0x6c, 0x7e, 0xd1, 0x60, + 0xa7, 0xc7, 0x83, 0x33, 0xe6, 0x10, 0x7e, 0x81, 0xd9, 0x19, 0xbd, 0xc4, 0x84, 0x23, 0x04, 0xe5, + 0x0b, 0x46, 0x23, 0xa5, 0x47, 0xae, 0xd1, 0x16, 0x14, 0x05, 0xad, 0x16, 0x65, 0xa6, 0x28, 0xe8, + 0x54, 0x5c, 0xe9, 0x8f, 0x89, 0xab, 0x83, 0x9e, 0xff, 0x5e, 0x36, 0xe6, 0x31, 0x25, 0x1c, 0x9b, + 0xff, 0x40, 0x2d, 0xa7, 0x3c, 0x05, 0x3f, 0x6b, 0xb0, 0xd7, 0xe3, 0xc1, 0xdb, 0xd8, 0x77, 0x04, + 0x96, 0x58, 0xcf, 0x89, 0xe3, 0x90, 0x04, 0x68, 0x1f, 0x2a, 0x1c, 0x13, 0x1f, 0x33, 0xb5, 0x3b, + 0x15, 0xa1, 0x5d, 0x58, 0xf1, 0x31, 0xa1, 0x91, 0xda, 0x62, 0x12, 0x20, 0x1d, 0x56, 0x3d, 0x4a, + 0x04, 0x73, 0x3c, 0x51, 0x2d, 0x49, 0x20, 0x8d, 0x25, 0xd3, 0x28, 0x72, 0xe9, 0xa0, 0x5a, 0x56, + 0x4c, 0x32, 0x1a, 0x0f, 0xd4, 0xc7, 0x5e, 0x18, 0x39, 0x83, 0xea, 0x4a, 0x53, 0x6b, 0x6d, 0xda, + 0x93, 0xd0, 0x6c, 0xc0, 0xe1, 0x42, 0x51, 0xa9, 0xec, 0xe7, 0xb0, 0x39, 0xde, 0xd3, 0x90, 0x91, + 0x2e, 0x0b, 0xfd, 0x00, 0x2f, 0x55, 0xbb, 0x0f, 0x15, 0x4c, 0x1c, 0x77, 0x80, 0xa5, 0xdc, 0x55, + 0x5b, 0x45, 0xe6, 0x81, 0xdc, 0xf6, 0x94, 0x20, 0x65, 0xfe, 0x00, 0xdb, 0x69, 0xeb, 0x57, 0x0e, + 0x73, 0x22, 0x8e, 0xea, 0xb0, 0xe6, 0x0c, 0x45, 0x9f, 0xb2, 0x50, 0x8c, 0x14, 0xfd, 0x34, 0x81, + 0x1e, 0x41, 0x25, 0x96, 0xef, 0xc9, 0x0e, 0xeb, 0x9d, 0xad, 0xb6, 0x32, 0x73, 0x52, 0xdd, 0x2d, + 0x8f, 0xa7, 0x6a, 0xab, 0x77, 0xcc, 0x1a, 0x1c, 0xcc, 0xd1, 0xa7, 0x9d, 0x2f, 0x60, 0x77, 0x0a, + 0x61, 0x16, 0x85, 0x9c, 0x87, 0x74, 0x89, 0xc9, 0x32, 0x67, 0xa1, 0x38, 0x7b, 0x16, 0x9a, 0xb0, + 0x1e, 0x4f, 0x8b, 0xe5, 0x2c, 0xca, 0x76, 0x36, 0x65, 0x1a, 0x50, 0x5f, 0xd4, 0x27, 0xd5, 0xf1, + 0x4c, 0x3a, 0xfd, 0x8d, 0xa0, 0x0c, 0x77, 0x07, 0xd4, 0xbb, 0x7c, 0x19, 0x72, 0xb1, 0x50, 0x04, + 0x82, 0xb2, 0x3b, 0xa0, 0xae, 0x54, 0xb0, 0x61, 0xcb, 0xb5, 0x32, 0xdb, 0x6c, 0xf1, 0x84, 0xb9, + 0xf3, 0xad, 0x0c, 0xa5, 0x1e, 0x0f, 0xd0, 0x6b, 0xd8, 0x9e, 0x3f, 0xdc, 0xfa, 0xe4, 0xab, 0xe5, + 0x8d, 0xac, 0x9b, 0xcb, 0xb1, 0x09, 0x35, 0x3a, 0x85, 0xad, 0xb9, 0xb3, 0x59, 0xcb, 0x54, 0xcd, + 0x42, 0xfa, 0xbf, 0x4b, 0xa1, 0x94, 0xef, 0x1c, 0xd0, 0x82, 0x33, 0x71, 0x98, 0x29, 0xcc, 0xc3, + 0xfa, 0xff, 0x0f, 0xc2, 0x29, 0x77, 0x17, 0x20, 0xe3, 0xdc, 0xbd, 0xac, 0x98, 0x34, 0xad, 0x1f, + 0x2e, 0x4c, 0xa7, 0x1c, 0x2f, 0x60, 0x63, 0xc6, 0xa3, 0x07, 0xb9, 0xd6, 0x09, 0xa0, 0x37, 0x96, + 0x00, 0x29, 0xd3, 0x7b, 0xd8, 0xc9, 0x7b, 0xae, 0x9e, 0xaf, 0x9a, 0xa2, 0xfa, 0x7f, 0x0f, 0xa1, + 0xd9, 0x91, 0xcc, 0x99, 0x28, 0x3b, 0x92, 0x59, 0x68, 0x66, 0x24, 0x8b, 0xdd, 0xd3, 0x3d, 0xbd, + 0xb9, 0x33, 0xb4, 0xdb, 0x3b, 0x43, 0xfb, 0x75, 0x67, 0x68, 0x1f, 0xef, 0x8d, 0xc2, 0xed, 0xbd, + 0x51, 0xf8, 0x7e, 0x6f, 0x14, 0xce, 0x9f, 0x66, 0x7f, 0x98, 0x6c, 0x14, 0x0b, 0x7a, 0x44, 0x59, + 0x70, 0xe4, 0xf5, 0x9d, 0x90, 0xa8, 0xab, 0xc5, 0xba, 0xea, 0x58, 0xd7, 0x93, 0xb5, 0xfc, 0x85, + 0xba, 0x15, 0x79, 0xdb, 0x3c, 0xf9, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xd4, 0x19, 0xa9, 0x36, 0xd3, + 0x06, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -705,6 +800,7 @@ type MsgClient interface { UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) // UpdatePermissions defines a method to update cronos admins permissions UpdatePermissions(ctx context.Context, in *MsgUpdatePermissions, opts ...grpc.CallOption) (*MsgUpdatePermissionsResponse, error) + StoreBlockList(ctx context.Context, in *MsgStoreBlockList, opts ...grpc.CallOption) (*MsgStoreBlockListResponse, error) } type msgClient struct { @@ -769,6 +865,15 @@ func (c *msgClient) UpdatePermissions(ctx context.Context, in *MsgUpdatePermissi return out, nil } +func (c *msgClient) StoreBlockList(ctx context.Context, in *MsgStoreBlockList, opts ...grpc.CallOption) (*MsgStoreBlockListResponse, error) { + out := new(MsgStoreBlockListResponse) + err := c.cc.Invoke(ctx, "/cronos.Msg/StoreBlockList", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { // ConvertVouchers defines a method for converting ibc voucher to cronos evm @@ -785,6 +890,7 @@ type MsgServer interface { UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) // UpdatePermissions defines a method to update cronos admins permissions UpdatePermissions(context.Context, *MsgUpdatePermissions) (*MsgUpdatePermissionsResponse, error) + StoreBlockList(context.Context, *MsgStoreBlockList) (*MsgStoreBlockListResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -809,6 +915,9 @@ func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateP func (*UnimplementedMsgServer) UpdatePermissions(ctx context.Context, req *MsgUpdatePermissions) (*MsgUpdatePermissionsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdatePermissions not implemented") } +func (*UnimplementedMsgServer) StoreBlockList(ctx context.Context, req *MsgStoreBlockList) (*MsgStoreBlockListResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method StoreBlockList not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -922,6 +1031,24 @@ func _Msg_UpdatePermissions_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _Msg_StoreBlockList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgStoreBlockList) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).StoreBlockList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cronos.Msg/StoreBlockList", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).StoreBlockList(ctx, req.(*MsgStoreBlockList)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "cronos.Msg", HandlerType: (*MsgServer)(nil), @@ -950,6 +1077,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "UpdatePermissions", Handler: _Msg_UpdatePermissions_Handler, }, + { + MethodName: "StoreBlockList", + Handler: _Msg_StoreBlockList_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "cronos/tx.proto", @@ -1366,6 +1497,66 @@ func (m *MsgUpdatePermissionsResponse) MarshalToSizedBuffer(dAtA []byte) (int, e return len(dAtA) - i, nil } +func (m *MsgStoreBlockList) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgStoreBlockList) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgStoreBlockList) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Blob) > 0 { + i -= len(m.Blob) + copy(dAtA[i:], m.Blob) + i = encodeVarintTx(dAtA, i, uint64(len(m.Blob))) + i-- + dAtA[i] = 0x12 + } + if len(m.From) > 0 { + i -= len(m.From) + copy(dAtA[i:], m.From) + i = encodeVarintTx(dAtA, i, uint64(len(m.From))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgStoreBlockListResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgStoreBlockListResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgStoreBlockListResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -1552,6 +1743,32 @@ func (m *MsgUpdatePermissionsResponse) Size() (n int) { return n } +func (m *MsgStoreBlockList) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.From) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Blob) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgStoreBlockListResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -2669,6 +2886,172 @@ func (m *MsgUpdatePermissionsResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgStoreBlockList) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgStoreBlockList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgStoreBlockList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field From", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.From = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Blob", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Blob = append(m.Blob[:0], dAtA[iNdEx:postIndex]...) + if m.Blob == nil { + m.Blob = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgStoreBlockListResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgStoreBlockListResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgStoreBlockListResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/e2ee/README.md b/x/e2ee/README.md new file mode 100644 index 0000000000..4c5f7dd7dd --- /dev/null +++ b/x/e2ee/README.md @@ -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. diff --git a/x/e2ee/client/cli/cmd.go b/x/e2ee/client/cli/cmd.go new file mode 100644 index 0000000000..e7358085a4 --- /dev/null +++ b/x/e2ee/client/cli/cmd.go @@ -0,0 +1,18 @@ +package cli + +import "github.com/spf13/cobra" + +func E2EECommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "e2ee", + Short: "End-to-end encryption commands", + } + + cmd.AddCommand( + KeygenCommand(), + EncryptCommand(), + DecryptCommand(), + ) + + return cmd +} diff --git a/x/e2ee/client/cli/decrypt.go b/x/e2ee/client/cli/decrypt.go new file mode 100644 index 0000000000..89f26f3298 --- /dev/null +++ b/x/e2ee/client/cli/decrypt.go @@ -0,0 +1,108 @@ +package cli + +import ( + "fmt" + "io" + "os" + + "filippo.io/age" + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + + "github.com/crypto-org-chain/cronos/v2/x/e2ee/keyring" + "github.com/crypto-org-chain/cronos/v2/x/e2ee/types" +) + +const FlagIdentity = "identity" + +func DecryptCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "decrypt [input-file]", + Short: "Decrypt input file to local identity", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + kr, err := keyring.New("cronosd", clientCtx.Keyring.Backend(), clientCtx.HomeDir, os.Stdin) + if err != nil { + return err + } + + outputFile, err := cmd.Flags().GetString(flags.FlagOutput) + if err != nil { + return err + } + + identityNames, err := cmd.Flags().GetStringArray(FlagIdentity) + if err != nil { + return err + } + + if len(identityNames) == 0 { + return fmt.Errorf("no identity provided") + } + + identities := make([]age.Identity, len(identityNames)) + for i, name := range identityNames { + secret, err := kr.Get(name) + if err != nil { + return err + } + + identity, err := age.ParseX25519Identity(string(secret)) + if err != nil { + return err + } + + identities[i] = identity + } + + var input io.Reader + inputFile := args[0] + if inputFile == "-" { + input = os.Stdin + } else { + f, err := os.Open(inputFile) + if err != nil { + return err + } + defer f.Close() + input = f + } + + var output io.Writer + if outputFile == "-" { + output = os.Stdout + } else { + f, err := os.Create(outputFile) + if err != nil { + return err + } + defer f.Close() + output = f + } + return decrypt(identities, input, output) + }, + } + + cmd.Flags().StringArrayP(FlagIdentity, "i", []string{types.DefaultKeyringName}, "identity (can be repeated)") + cmd.Flags().StringP(flags.FlagOutput, "o", "-", "output file (default stdout)") + + return cmd +} + +func decrypt(identities []age.Identity, in io.Reader, out io.Writer) error { + r, err := age.Decrypt(in, identities...) + if err != nil { + return err + } + if _, err := io.Copy(out, r); err != nil { + return err + } + return nil +} diff --git a/x/e2ee/client/cli/encrypt.go b/x/e2ee/client/cli/encrypt.go new file mode 100644 index 0000000000..7800d30011 --- /dev/null +++ b/x/e2ee/client/cli/encrypt.go @@ -0,0 +1,106 @@ +package cli + +import ( + "context" + "errors" + "io" + "os" + + "filippo.io/age" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/spf13/cobra" + + "github.com/crypto-org-chain/cronos/v2/x/e2ee/types" +) + +const ( + FlagRecipient = "recipient" +) + +func EncryptCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "encrypt [input-file]", + Short: "Encrypt input file to one or multiple recipients", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + outputFile, err := cmd.Flags().GetString(flags.FlagOutput) + if err != nil { + return err + } + + recs, err := cmd.Flags().GetStringArray(FlagRecipient) + if err != nil { + return err + } + + // query encryption key from chain state + client := types.NewQueryClient(clientCtx) + rsp, err := client.Keys(context.Background(), &types.KeysRequest{ + Addresses: recs, + }) + if err != nil { + return err + } + + recipients := make([]age.Recipient, len(recs)) + for i, key := range rsp.Keys { + recipient, err := age.ParseX25519Recipient(key) + if err != nil { + return err + } + recipients[i] = recipient + } + + inputFile := args[0] + var input io.Reader + if inputFile == "-" { + input = os.Stdin + } else { + f, err := os.Open(inputFile) + if err != nil { + return err + } + defer f.Close() + input = f + } + + var output io.Writer + if outputFile == "-" { + output = os.Stdout + } else { + fp, err := os.Create(outputFile) + if err != nil { + return err + } + defer fp.Close() + output = fp + } + return encrypt(recipients, input, output) + }, + } + f := cmd.Flags() + f.StringArrayP(FlagRecipient, "r", []string{}, "recipients") + f.StringP(flags.FlagOutput, "o", "-", "output file (default stdout)") + return cmd +} + +func encrypt(recipients []age.Recipient, in io.Reader, out io.Writer) (err error) { + var w io.WriteCloser + w, err = age.Encrypt(out, recipients...) + if err != nil { + return err + } + + defer func() { + err = errors.Join(err, w.Close()) + }() + + _, err = io.Copy(w, in) + return +} diff --git a/x/e2ee/client/cli/generate.go b/x/e2ee/client/cli/generate.go new file mode 100644 index 0000000000..2d694d7088 --- /dev/null +++ b/x/e2ee/client/cli/generate.go @@ -0,0 +1,56 @@ +package cli + +import ( + "fmt" + "os" + + "filippo.io/age" + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + + "github.com/crypto-org-chain/cronos/v2/x/e2ee/keyring" + "github.com/crypto-org-chain/cronos/v2/x/e2ee/types" +) + +const FlagKeyringName = "keyring-name" + +func KeygenCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "keygen", + Short: "Generates a new native X25519 key pair", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + krName, err := cmd.Flags().GetString(FlagKeyringName) + if err != nil { + return err + } + + kr, err := keyring.New("cronosd", clientCtx.Keyring.Backend(), clientCtx.HomeDir, os.Stdin) + if err != nil { + return err + } + + k, err := age.GenerateX25519Identity() + if err != nil { + return err + } + + if err := kr.Set(krName, []byte(k.String())); err != nil { + return err + } + + fmt.Println(k.Recipient()) + return nil + }, + } + + cmd.Flags().String(FlagKeyringName, types.DefaultKeyringName, "The keyring name to use") + + return cmd +} diff --git a/x/e2ee/client/cli/query.go b/x/e2ee/client/cli/query.go new file mode 100644 index 0000000000..a2ae880808 --- /dev/null +++ b/x/e2ee/client/cli/query.go @@ -0,0 +1,78 @@ +package cli + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/crypto-org-chain/cronos/v2/x/e2ee/types" + "github.com/spf13/cobra" +) + +// GetQueryCmd returns the cli query commands for this module +func GetQueryCmd(queryRoute string) *cobra.Command { + cmd := &cobra.Command{ + Use: types.ModuleName, + Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName), + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + cmd.AddCommand(CmdEncryptionKey()) + cmd.AddCommand(CmdEncryptionKeys()) + return cmd +} + +func CmdEncryptionKey() *cobra.Command { + cmd := &cobra.Command{ + Use: "key [address]", + Short: "Query an encryption key by address", + + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + params := &types.KeyRequest{ + Address: args[0], + } + res, err := queryClient.Key(cmd.Context(), params) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +func CmdEncryptionKeys() *cobra.Command { + cmd := &cobra.Command{ + Use: "keys [addresses] ...", + Short: "Query a batch of encryption key by addresses", + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + params := &types.KeysRequest{ + Addresses: args, + } + res, err := queryClient.Keys(cmd.Context(), params) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/e2ee/client/cli/tx.go b/x/e2ee/client/cli/tx.go new file mode 100644 index 0000000000..7a9516d48d --- /dev/null +++ b/x/e2ee/client/cli/tx.go @@ -0,0 +1,50 @@ +package cli + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/crypto-org-chain/cronos/v2/x/e2ee/types" + "github.com/spf13/cobra" +) + +// GetTxCmd returns the transaction commands for this module +func GetTxCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: types.ModuleName, + Short: fmt.Sprintf("%s transactions subcommands", types.ModuleName), + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + cmd.AddCommand(CmdRegisterAccount()) + return cmd +} + +func CmdRegisterAccount() *cobra.Command { + cmd := &cobra.Command{ + Use: "register-encryption-key [key]", + Short: "Register encryption key stores an public key for asymmetric encryption with the user address.", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + msg := types.MsgRegisterEncryptionKey{ + Address: clientCtx.GetFromAddress().String(), + Key: args[0], + } + if err := msg.ValidateBasic(); err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/e2ee/keeper/keeper.go b/x/e2ee/keeper/keeper.go new file mode 100644 index 0000000000..131534e6fe --- /dev/null +++ b/x/e2ee/keeper/keeper.go @@ -0,0 +1,96 @@ +package keeper + +import ( + "context" + + "github.com/cosmos/cosmos-sdk/store/prefix" + storetypes "github.com/cosmos/cosmos-sdk/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 +} + +var ( + _ types.MsgServer = Keeper{} + _ types.QueryServer = Keeper{} +) + +func NewKeeper(storeKey storetypes.StoreKey) Keeper { + return Keeper{ + storeKey: storeKey, + } +} + +func (k Keeper) RegisterEncryptionKey( + ctx context.Context, + req *types.MsgRegisterEncryptionKey, +) (*types.MsgRegisterEncryptionKeyResponse, error) { + addr, err := sdk.AccAddressFromBech32(req.Address) + if err != nil { + return nil, err + } + sdkCtx := sdk.UnwrapSDKContext(ctx) + sdkCtx.KVStore(k.storeKey).Set(types.KeyPrefix(addr), []byte(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 := sdk.AccAddress(iter.Key()).String() + key := iter.Value() + keys = append(keys, types.EncryptionKeyEntry{ + Address: address, + Key: string(key), + }) + } + return &types.GenesisState{Keys: keys}, nil +} + +func (k Keeper) Key(ctx context.Context, req *types.KeyRequest) (*types.KeyResponse, error) { + addr, err := sdk.AccAddressFromBech32(req.Address) + if err != nil { + return nil, err + } + sdkCtx := sdk.UnwrapSDKContext(ctx) + value := sdkCtx.KVStore(k.storeKey).Get(types.KeyPrefix(addr)) + return &types.KeyResponse{Key: string(value)}, nil +} + +func (k Keeper) Keys(ctx context.Context, requests *types.KeysRequest) (*types.KeysResponse, error) { + store := sdk.UnwrapSDKContext(ctx).KVStore(k.storeKey) + var rsp types.KeysResponse + for _, address := range requests.Addresses { + addr, err := sdk.AccAddressFromBech32(address) + if err != nil { + return nil, err + } + value := store.Get(types.KeyPrefix(addr)) + rsp.Keys = append(rsp.Keys, string(value)) + } + + return &rsp, nil +} diff --git a/x/e2ee/keyring/keyring.go b/x/e2ee/keyring/keyring.go new file mode 100644 index 0000000000..88332b5bf9 --- /dev/null +++ b/x/e2ee/keyring/keyring.go @@ -0,0 +1,202 @@ +package keyring + +import ( + "bufio" + "fmt" + "io" + "os" + "path/filepath" + + "github.com/99designs/keyring" + "golang.org/x/crypto/bcrypt" + + errorsmod "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/client/input" + sdkkeyring "github.com/cosmos/cosmos-sdk/crypto/keyring" +) + +const ( + keyringFileDirName = "e2ee-keyring-file" + keyringTestDirName = "e2ee-keyring-test" + passKeyringPrefix = "e2ee-keyring-%s" //nolint: gosec + maxPassphraseEntryAttempts = 3 +) + +type Keyring interface { + Get(string) ([]byte, error) + Set(string, []byte) error +} + +func New( + appName, backend, rootDir string, userInput io.Reader, +) (Keyring, error) { + var ( + db keyring.Keyring + err error + ) + serviceName := appName + "-e2ee" + switch backend { + case sdkkeyring.BackendMemory: + return newKeystore(keyring.NewArrayKeyring(nil), sdkkeyring.BackendMemory), nil + case sdkkeyring.BackendTest: + db, err = keyring.Open(keyring.Config{ + AllowedBackends: []keyring.BackendType{keyring.FileBackend}, + ServiceName: serviceName, + FileDir: filepath.Join(rootDir, keyringTestDirName), + FilePasswordFunc: func(_ string) (string, error) { + return "test", nil + }, + }) + case sdkkeyring.BackendFile: + fileDir := filepath.Join(rootDir, keyringFileDirName) + db, err = keyring.Open(keyring.Config{ + AllowedBackends: []keyring.BackendType{keyring.FileBackend}, + ServiceName: serviceName, + FileDir: fileDir, + FilePasswordFunc: newRealPrompt(fileDir, userInput), + }) + case sdkkeyring.BackendOS: + db, err = keyring.Open(keyring.Config{ + ServiceName: serviceName, + FileDir: rootDir, + KeychainTrustApplication: true, + FilePasswordFunc: newRealPrompt(rootDir, userInput), + }) + case sdkkeyring.BackendKWallet: + db, err = keyring.Open(keyring.Config{ + AllowedBackends: []keyring.BackendType{keyring.KWalletBackend}, + ServiceName: "kdewallet", + KWalletAppID: serviceName, + KWalletFolder: "", + }) + case sdkkeyring.BackendPass: + prefix := fmt.Sprintf(passKeyringPrefix, serviceName) + db, err = keyring.Open(keyring.Config{ + AllowedBackends: []keyring.BackendType{keyring.PassBackend}, + ServiceName: serviceName, + PassPrefix: prefix, + }) + default: + return nil, fmt.Errorf("unknown keyring backend %v", backend) + } + + if err != nil { + return nil, err + } + + return newKeystore(db, backend), nil +} + +var _ Keyring = keystore{} + +type keystore struct { + db keyring.Keyring + backend string +} + +func newKeystore(kr keyring.Keyring, backend string) keystore { + return keystore{ + db: kr, + backend: backend, + } +} + +func (ks keystore) Get(name string) ([]byte, error) { + item, err := ks.db.Get(name) + if err != nil { + return nil, err + } + + return item.Data, nil +} + +func (ks keystore) Set(name string, secret []byte) error { + return ks.db.Set(keyring.Item{ + Key: name, + Data: secret, + Label: name, + }) +} + +func newRealPrompt(dir string, buf io.Reader) func(string) (string, error) { + return func(prompt string) (string, error) { + keyhashStored := false + keyhashFilePath := filepath.Join(dir, "keyhash") + + var keyhash []byte + + _, err := os.Stat(keyhashFilePath) + + switch { + case err == nil: + keyhash, err = os.ReadFile(keyhashFilePath) + if err != nil { + return "", errorsmod.Wrap(err, fmt.Sprintf("failed to read %s", keyhashFilePath)) + } + + keyhashStored = true + + case os.IsNotExist(err): + keyhashStored = false + + default: + return "", errorsmod.Wrap(err, fmt.Sprintf("failed to open %s", keyhashFilePath)) + } + + failureCounter := 0 + + for { + failureCounter++ + if failureCounter > maxPassphraseEntryAttempts { + return "", fmt.Errorf("too many failed passphrase attempts") + } + + buf := bufio.NewReader(buf) + pass, err := input.GetPassword(fmt.Sprintf("Enter keyring passphrase (attempt %d/%d):", failureCounter, maxPassphraseEntryAttempts), buf) + if err != nil { + // NOTE: LGTM.io reports a false positive alert that states we are printing the password, + // but we only log the error. + // + // lgtm [go/clear-text-logging] + fmt.Fprintln(os.Stderr, err) + continue + } + + if keyhashStored { + if err := bcrypt.CompareHashAndPassword(keyhash, []byte(pass)); err != nil { + fmt.Fprintln(os.Stderr, "incorrect passphrase") + continue + } + + return pass, nil + } + + reEnteredPass, err := input.GetPassword("Re-enter keyring passphrase:", buf) + if err != nil { + // NOTE: LGTM.io reports a false positive alert that states we are printing the password, + // but we only log the error. + // + // lgtm [go/clear-text-logging] + fmt.Fprintln(os.Stderr, err) + continue + } + + if pass != reEnteredPass { + fmt.Fprintln(os.Stderr, "passphrase do not match") + continue + } + + passwordHash, err := bcrypt.GenerateFromPassword([]byte(pass), 2) + if err != nil { + fmt.Fprintln(os.Stderr, err) + continue + } + + if err := os.WriteFile(keyhashFilePath, passwordHash, 0o600); err != nil { + return "", err + } + + return pass, nil + } + } +} diff --git a/x/e2ee/keyring/keyring_test.go b/x/e2ee/keyring/keyring_test.go new file mode 100644 index 0000000000..ef5690f619 --- /dev/null +++ b/x/e2ee/keyring/keyring_test.go @@ -0,0 +1,47 @@ +package keyring + +import ( + "bytes" + "io" + "testing" + + "filippo.io/age" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/crypto/keyring" +) + +func TestKeyring(t *testing.T) { + kr, err := New("cronosd", keyring.BackendTest, t.TempDir(), nil) + require.NoError(t, err) + + identity, err := age.GenerateX25519Identity() + require.NoError(t, err) + + var ciphertext []byte + { + dst := bytes.NewBuffer(nil) + writer, err := age.Encrypt(dst, identity.Recipient()) + require.NoError(t, err) + writer.Write([]byte("test")) + writer.Close() + ciphertext = dst.Bytes() + } + + require.NoError(t, kr.Set("test", []byte(identity.String()))) + + secret, err := kr.Get("test") + require.NoError(t, err) + + identity, err = age.ParseX25519Identity(string(secret)) + require.NoError(t, err) + + { + reader, err := age.Decrypt(bytes.NewReader(ciphertext), identity) + require.NoError(t, err) + bz, err := io.ReadAll(reader) + require.NoError(t, err) + + require.Equal(t, []byte("test"), bz) + } +} diff --git a/x/e2ee/module.go b/x/e2ee/module.go new file mode 100644 index 0000000000..e868d532c4 --- /dev/null +++ b/x/e2ee/module.go @@ -0,0 +1,148 @@ +package e2ee + +import ( + "context" + "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/client/cli" + "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{} + // 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) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +// RegisterInterfaces registers the module's interface types +func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) { + types.RegisterInterfaces(reg) +} + +// 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) { + if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil { + panic(err) + } +} + +// GetTxCmd returns the capability module's root tx command. +func (a AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd() +} + +// GetQueryCmd returns the capability module's root query command. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd(types.StoreKey) +} + +// ---------------------------------------------------------------------------- +// 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() {} diff --git a/x/e2ee/types/codec.go b/x/e2ee/types/codec.go new file mode 100644 index 0000000000..b24da784c4 --- /dev/null +++ b/x/e2ee/types/codec.go @@ -0,0 +1,20 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" +) + +// RegisterLegacyAminoCodec registers the necessary x/e2ee interfaces and concrete types +// on the provided LegacyAmino codec. These types are used for Amino JSON serialization. +func RegisterLegacyAminoCodec(_ *codec.LegacyAmino) {} + +func RegisterInterfaces(registry types.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgRegisterEncryptionKey{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} diff --git a/x/e2ee/types/genesis.go b/x/e2ee/types/genesis.go new file mode 100644 index 0000000000..d2a392ceab --- /dev/null +++ b/x/e2ee/types/genesis.go @@ -0,0 +1,17 @@ +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 { + for _, key := range gs.Keys { + if err := key.Validate(); err != nil { + return err + } + } + return nil +} diff --git a/x/e2ee/types/genesis.pb.go b/x/e2ee/types/genesis.pb.go new file mode 100644 index 0000000000..69f52bc690 --- /dev/null +++ b/x/e2ee/types/genesis.pb.go @@ -0,0 +1,555 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: e2ee/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// EncryptionKeyEntry is a type that contains the owner and the public key. +type EncryptionKeyEntry struct { + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` +} + +func (m *EncryptionKeyEntry) Reset() { *m = EncryptionKeyEntry{} } +func (m *EncryptionKeyEntry) String() string { return proto.CompactTextString(m) } +func (*EncryptionKeyEntry) ProtoMessage() {} +func (*EncryptionKeyEntry) Descriptor() ([]byte, []int) { + return fileDescriptor_e81aee24edfec633, []int{0} +} +func (m *EncryptionKeyEntry) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EncryptionKeyEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EncryptionKeyEntry.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *EncryptionKeyEntry) XXX_Merge(src proto.Message) { + xxx_messageInfo_EncryptionKeyEntry.Merge(m, src) +} +func (m *EncryptionKeyEntry) XXX_Size() int { + return m.Size() +} +func (m *EncryptionKeyEntry) XXX_DiscardUnknown() { + xxx_messageInfo_EncryptionKeyEntry.DiscardUnknown(m) +} + +var xxx_messageInfo_EncryptionKeyEntry proto.InternalMessageInfo + +func (m *EncryptionKeyEntry) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *EncryptionKeyEntry) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +// GenesisState defines the e2ee module's genesis state. +type GenesisState struct { + // params defines all the paramaters of the module. + Keys []EncryptionKeyEntry `protobuf:"bytes,1,rep,name=keys,proto3" json:"keys"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_e81aee24edfec633, []int{1} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetKeys() []EncryptionKeyEntry { + if m != nil { + return m.Keys + } + return nil +} + +func init() { + proto.RegisterType((*EncryptionKeyEntry)(nil), "e2ee.EncryptionKeyEntry") + proto.RegisterType((*GenesisState)(nil), "e2ee.GenesisState") +} + +func init() { proto.RegisterFile("e2ee/genesis.proto", fileDescriptor_e81aee24edfec633) } + +var fileDescriptor_e81aee24edfec633 = []byte{ + // 236 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4a, 0x35, 0x4a, 0x4d, + 0xd5, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, + 0x01, 0x89, 0x49, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x05, 0xf4, 0x41, 0x2c, 0x88, 0x9c, 0x92, + 0x03, 0x97, 0x90, 0x6b, 0x5e, 0x72, 0x51, 0x65, 0x41, 0x49, 0x66, 0x7e, 0x9e, 0x77, 0x6a, 0xa5, + 0x6b, 0x5e, 0x49, 0x51, 0xa5, 0x90, 0x04, 0x17, 0x7b, 0x62, 0x4a, 0x4a, 0x51, 0x6a, 0x71, 0xb1, + 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x67, 0x10, 0x8c, 0x2b, 0x24, 0xc0, 0xc5, 0x9c, 0x9d, 0x5a, 0x29, + 0xc1, 0x04, 0x16, 0x05, 0x31, 0x95, 0x9c, 0xb8, 0x78, 0xdc, 0x21, 0xd6, 0x05, 0x97, 0x24, 0x96, + 0xa4, 0x0a, 0x19, 0x71, 0xb1, 0x64, 0xa7, 0x56, 0x82, 0x34, 0x32, 0x6b, 0x70, 0x1b, 0x49, 0xe8, + 0x81, 0x2c, 0xd7, 0xc3, 0xb4, 0xc3, 0x89, 0xe5, 0xc4, 0x3d, 0x79, 0x86, 0x20, 0xb0, 0x5a, 0x27, + 0x9f, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, + 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0x32, 0x4a, 0xcf, 0x2c, 0xc9, + 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x07, 0x1b, 0x91, 0xaf, 0x9b, 0x5f, 0x94, 0xae, 0x9b, + 0x9c, 0x91, 0x98, 0x99, 0xa7, 0x9f, 0x5c, 0x94, 0x9f, 0x97, 0x5f, 0xac, 0x5f, 0x66, 0xa4, 0x5f, + 0xa1, 0x0f, 0xf6, 0x77, 0x49, 0x65, 0x41, 0x6a, 0x71, 0x12, 0x1b, 0xd8, 0x6b, 0xc6, 0x80, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xf9, 0x3d, 0x79, 0x56, 0x0c, 0x01, 0x00, 0x00, +} + +func (m *EncryptionKeyEntry) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EncryptionKeyEntry) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EncryptionKeyEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0x12 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *GenesisState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Keys) > 0 { + for iNdEx := len(m.Keys) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Keys[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *EncryptionKeyEntry) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + l = len(m.Key) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + return n +} + +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Keys) > 0 { + for _, e := range m.Keys { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *EncryptionKeyEntry) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EncryptionKeyEntry: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EncryptionKeyEntry: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GenesisState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Keys", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Keys = append(m.Keys, EncryptionKeyEntry{}) + if err := m.Keys[len(m.Keys)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/e2ee/types/keys.go b/x/e2ee/types/keys.go new file mode 100644 index 0000000000..5941cbf264 --- /dev/null +++ b/x/e2ee/types/keys.go @@ -0,0 +1,46 @@ +package types + +import ( + "errors" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // ModuleName defines the module name + ModuleName = "e2ee" + + // StoreKey defines the primary module store key + StoreKey = ModuleName + + // RouterKey is the message route for e2ee + RouterKey = ModuleName +) + +const ( + DefaultKeyringName = "e2ee-identity" +) + +const ( + prefixEncryptionKey = iota + 1 +) + +var KeyPrefixEncryptionKey = []byte{prefixEncryptionKey} + +func KeyPrefix(addr sdk.AccAddress) []byte { + key := make([]byte, 1+len(addr)) + key[0] = prefixEncryptionKey + copy(key[1:], addr) + return key +} + +// Validate checks for address and key correctness. +func (e EncryptionKeyEntry) Validate() error { + if _, err := sdk.AccAddressFromBech32(e.Address); err != nil { + return err + } + if len(e.Key) == 0 { + return errors.New("key can't be nil") + } + return nil +} diff --git a/x/e2ee/types/msg.go b/x/e2ee/types/msg.go new file mode 100644 index 0000000000..df5ab23732 --- /dev/null +++ b/x/e2ee/types/msg.go @@ -0,0 +1,31 @@ +package types + +import ( + fmt "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var _ sdk.Msg = (*MsgRegisterEncryptionKey)(nil) + +func (m *MsgRegisterEncryptionKey) ValidateBasic() error { + if m.Address == "" { + return fmt.Errorf("address cannot be empty") + } + if len(m.Key) == 0 { + return fmt.Errorf("key cannot be nil") + } + // validate bech32 format of Address + if _, err := sdk.AccAddressFromBech32(m.Address); err != nil { + return fmt.Errorf("invalid address: %s", err) + } + return nil +} + +func (m *MsgRegisterEncryptionKey) GetSigners() []sdk.AccAddress { + addr, err := sdk.AccAddressFromBech32(m.Address) + if err != nil { + panic(err) + } + return []sdk.AccAddress{addr} +} diff --git a/x/e2ee/types/query.pb.go b/x/e2ee/types/query.pb.go new file mode 100644 index 0000000000..7a934ff2b5 --- /dev/null +++ b/x/e2ee/types/query.pb.go @@ -0,0 +1,973 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: e2ee/query.proto + +package types + +import ( + context "context" + fmt "fmt" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// KeyRequest is the request type for the Query/Key RPC method. +type KeyRequest struct { + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` +} + +func (m *KeyRequest) Reset() { *m = KeyRequest{} } +func (m *KeyRequest) String() string { return proto.CompactTextString(m) } +func (*KeyRequest) ProtoMessage() {} +func (*KeyRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_1e8b28e605d00558, []int{0} +} +func (m *KeyRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *KeyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_KeyRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *KeyRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_KeyRequest.Merge(m, src) +} +func (m *KeyRequest) XXX_Size() int { + return m.Size() +} +func (m *KeyRequest) XXX_DiscardUnknown() { + xxx_messageInfo_KeyRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_KeyRequest proto.InternalMessageInfo + +func (m *KeyRequest) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +// KeyResponse is the response type for the Query/Key RPC method. +type KeyResponse struct { + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` +} + +func (m *KeyResponse) Reset() { *m = KeyResponse{} } +func (m *KeyResponse) String() string { return proto.CompactTextString(m) } +func (*KeyResponse) ProtoMessage() {} +func (*KeyResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1e8b28e605d00558, []int{1} +} +func (m *KeyResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *KeyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_KeyResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *KeyResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_KeyResponse.Merge(m, src) +} +func (m *KeyResponse) XXX_Size() int { + return m.Size() +} +func (m *KeyResponse) XXX_DiscardUnknown() { + xxx_messageInfo_KeyResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_KeyResponse proto.InternalMessageInfo + +func (m *KeyResponse) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +// KeysRequest is the request type for the Query/Key RPC method. +type KeysRequest struct { + Addresses []string `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty"` +} + +func (m *KeysRequest) Reset() { *m = KeysRequest{} } +func (m *KeysRequest) String() string { return proto.CompactTextString(m) } +func (*KeysRequest) ProtoMessage() {} +func (*KeysRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_1e8b28e605d00558, []int{2} +} +func (m *KeysRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *KeysRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_KeysRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *KeysRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_KeysRequest.Merge(m, src) +} +func (m *KeysRequest) XXX_Size() int { + return m.Size() +} +func (m *KeysRequest) XXX_DiscardUnknown() { + xxx_messageInfo_KeysRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_KeysRequest proto.InternalMessageInfo + +func (m *KeysRequest) GetAddresses() []string { + if m != nil { + return m.Addresses + } + return nil +} + +// KeysResponse is the response type for the Query/Key RPC method. +type KeysResponse struct { + Keys []string `protobuf:"bytes,1,rep,name=keys,proto3" json:"keys,omitempty"` +} + +func (m *KeysResponse) Reset() { *m = KeysResponse{} } +func (m *KeysResponse) String() string { return proto.CompactTextString(m) } +func (*KeysResponse) ProtoMessage() {} +func (*KeysResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1e8b28e605d00558, []int{3} +} +func (m *KeysResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *KeysResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_KeysResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *KeysResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_KeysResponse.Merge(m, src) +} +func (m *KeysResponse) XXX_Size() int { + return m.Size() +} +func (m *KeysResponse) XXX_DiscardUnknown() { + xxx_messageInfo_KeysResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_KeysResponse proto.InternalMessageInfo + +func (m *KeysResponse) GetKeys() []string { + if m != nil { + return m.Keys + } + return nil +} + +func init() { + proto.RegisterType((*KeyRequest)(nil), "e2ee.KeyRequest") + proto.RegisterType((*KeyResponse)(nil), "e2ee.KeyResponse") + proto.RegisterType((*KeysRequest)(nil), "e2ee.KeysRequest") + proto.RegisterType((*KeysResponse)(nil), "e2ee.KeysResponse") +} + +func init() { proto.RegisterFile("e2ee/query.proto", fileDescriptor_1e8b28e605d00558) } + +var fileDescriptor_1e8b28e605d00558 = []byte{ + // 324 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x91, 0xbf, 0x4a, 0x03, 0x41, + 0x10, 0x87, 0xb3, 0x26, 0x2a, 0x19, 0x15, 0xe2, 0x16, 0x72, 0x84, 0xb0, 0xca, 0x16, 0x12, 0x94, + 0xdc, 0xe2, 0xd9, 0x59, 0xda, 0x08, 0xc6, 0xc6, 0x94, 0x76, 0x97, 0xcb, 0x70, 0x39, 0xa2, 0x37, + 0x97, 0xdb, 0x4d, 0x70, 0x11, 0x1b, 0x9f, 0x40, 0xb0, 0xf5, 0x81, 0x2c, 0x03, 0x36, 0x96, 0x92, + 0xf8, 0x20, 0x72, 0xff, 0x48, 0xba, 0xb9, 0x1f, 0xdf, 0x7c, 0x33, 0x73, 0x0b, 0x2d, 0xf4, 0x10, + 0xd5, 0x74, 0x86, 0xa9, 0x75, 0x93, 0x94, 0x0c, 0xf1, 0x46, 0x96, 0xb4, 0x3b, 0x21, 0x51, 0xf8, + 0x88, 0xca, 0x4f, 0x22, 0xe5, 0xc7, 0x31, 0x19, 0xdf, 0x44, 0x14, 0xeb, 0x82, 0x91, 0xa7, 0x00, + 0x7d, 0xb4, 0x03, 0x9c, 0xce, 0x50, 0x1b, 0xee, 0xc0, 0xae, 0x3f, 0x1a, 0xa5, 0xa8, 0xb5, 0xc3, + 0x4e, 0x58, 0xb7, 0x39, 0xa8, 0x3e, 0xe5, 0x31, 0xec, 0xe5, 0x9c, 0x4e, 0x28, 0xd6, 0xc8, 0x5b, + 0x50, 0x9f, 0xa0, 0x2d, 0xa1, 0xac, 0x94, 0xe7, 0x39, 0xa0, 0x2b, 0x53, 0x07, 0x9a, 0x65, 0x2b, + 0x66, 0xae, 0x7a, 0xb7, 0x39, 0x58, 0x07, 0x52, 0xc2, 0x7e, 0x01, 0x97, 0x3a, 0x0e, 0x8d, 0x09, + 0xda, 0x0a, 0xcc, 0x6b, 0xef, 0x93, 0xc1, 0xf6, 0x7d, 0x76, 0x0d, 0xbf, 0x85, 0x7a, 0x1f, 0x2d, + 0x6f, 0xb9, 0xd9, 0x3d, 0xee, 0x7a, 0xdd, 0xf6, 0xe1, 0x46, 0x52, 0x98, 0xa4, 0x78, 0xfb, 0xfe, + 0xfb, 0xd8, 0x72, 0xf8, 0x91, 0xca, 0x7f, 0xc7, 0xfc, 0x42, 0x4d, 0xd0, 0xaa, 0x97, 0x72, 0xf4, + 0x2b, 0xbf, 0x81, 0x46, 0x36, 0x99, 0xaf, 0x5b, 0xab, 0x95, 0xdb, 0x7c, 0x33, 0x2a, 0x75, 0x4e, + 0xae, 0xe3, 0x57, 0xec, 0x4c, 0x1e, 0x6c, 0x1a, 0xf5, 0xf5, 0xdd, 0xd7, 0x52, 0xb0, 0xc5, 0x52, + 0xb0, 0xdf, 0xa5, 0x60, 0xef, 0x2b, 0x51, 0x5b, 0xac, 0x44, 0xed, 0x67, 0x25, 0x6a, 0x0f, 0x5e, + 0x18, 0x99, 0xf1, 0x6c, 0xe8, 0x06, 0xf4, 0xa4, 0x82, 0xd4, 0x26, 0x86, 0x7a, 0x94, 0x86, 0xbd, + 0x60, 0xec, 0x47, 0xb1, 0x0a, 0x52, 0x8a, 0x49, 0xab, 0xb9, 0xa7, 0x9e, 0x0b, 0x9f, 0xb1, 0x09, + 0xea, 0xe1, 0x4e, 0xfe, 0x1a, 0x97, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xdd, 0xbf, 0x49, 0x6b, + 0xc5, 0x01, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // Key queries the encryption key of a given address + Key(ctx context.Context, in *KeyRequest, opts ...grpc.CallOption) (*KeyResponse, error) + // Keys queries the encryption keys for a batch of addresses + Keys(ctx context.Context, in *KeysRequest, opts ...grpc.CallOption) (*KeysResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) Key(ctx context.Context, in *KeyRequest, opts ...grpc.CallOption) (*KeyResponse, error) { + out := new(KeyResponse) + err := c.cc.Invoke(ctx, "/e2ee.Query/Key", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Keys(ctx context.Context, in *KeysRequest, opts ...grpc.CallOption) (*KeysResponse, error) { + out := new(KeysResponse) + err := c.cc.Invoke(ctx, "/e2ee.Query/Keys", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // Key queries the encryption key of a given address + Key(context.Context, *KeyRequest) (*KeyResponse, error) + // Keys queries the encryption keys for a batch of addresses + Keys(context.Context, *KeysRequest) (*KeysResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) Key(ctx context.Context, req *KeyRequest) (*KeyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Key not implemented") +} +func (*UnimplementedQueryServer) Keys(ctx context.Context, req *KeysRequest) (*KeysResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Keys not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_Key_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(KeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Key(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/e2ee.Query/Key", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Key(ctx, req.(*KeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Keys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(KeysRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Keys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/e2ee.Query/Keys", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Keys(ctx, req.(*KeysRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "e2ee.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Key", + Handler: _Query_Key_Handler, + }, + { + MethodName: "Keys", + Handler: _Query_Keys_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "e2ee/query.proto", +} + +func (m *KeyRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *KeyRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *KeyRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *KeyResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *KeyResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *KeyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *KeysRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *KeysRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *KeysRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Addresses) > 0 { + for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Addresses[iNdEx]) + copy(dAtA[i:], m.Addresses[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Addresses[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *KeysResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *KeysResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *KeysResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Keys) > 0 { + for iNdEx := len(m.Keys) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Keys[iNdEx]) + copy(dAtA[i:], m.Keys[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Keys[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *KeyRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *KeyResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Key) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *KeysRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Addresses) > 0 { + for _, s := range m.Addresses { + l = len(s) + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *KeysResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Keys) > 0 { + for _, s := range m.Keys { + l = len(s) + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *KeyRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: KeyRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: KeyRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *KeyResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: KeyResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: KeyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *KeysRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: KeysRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: KeysRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *KeysResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: KeysResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: KeysResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Keys", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Keys = append(m.Keys, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/e2ee/types/query.pb.gw.go b/x/e2ee/types/query.pb.gw.go new file mode 100644 index 0000000000..7e0fed42c3 --- /dev/null +++ b/x/e2ee/types/query.pb.gw.go @@ -0,0 +1,270 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: e2ee/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_Key_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq KeyRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") + } + + protoReq.Address, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) + } + + msg, err := client.Key(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Key_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq KeyRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") + } + + protoReq.Address, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) + } + + msg, err := server.Key(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Keys_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq KeysRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Keys(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Keys_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq KeysRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Keys(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Key_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Key_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Key_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_Query_Keys_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Keys_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Keys_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_Key_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Key_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Key_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_Query_Keys_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Keys_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Keys_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_Key_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"e2ee", "v1", "key", "address"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Keys_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"e2ee", "v1", "keys"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_Key_0 = runtime.ForwardResponseMessage + + forward_Query_Keys_0 = runtime.ForwardResponseMessage +) diff --git a/x/e2ee/types/tx.pb.go b/x/e2ee/types/tx.pb.go new file mode 100644 index 0000000000..b35707b83c --- /dev/null +++ b/x/e2ee/types/tx.pb.go @@ -0,0 +1,580 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: e2ee/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/types/msgservice" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgRegisterEncryptionKey defines the Msg/RegisterEncryptionKey request type +type MsgRegisterEncryptionKey struct { + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` +} + +func (m *MsgRegisterEncryptionKey) Reset() { *m = MsgRegisterEncryptionKey{} } +func (m *MsgRegisterEncryptionKey) String() string { return proto.CompactTextString(m) } +func (*MsgRegisterEncryptionKey) ProtoMessage() {} +func (*MsgRegisterEncryptionKey) Descriptor() ([]byte, []int) { + return fileDescriptor_85e46bdbb1c358a8, []int{0} +} +func (m *MsgRegisterEncryptionKey) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRegisterEncryptionKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRegisterEncryptionKey.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgRegisterEncryptionKey) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRegisterEncryptionKey.Merge(m, src) +} +func (m *MsgRegisterEncryptionKey) XXX_Size() int { + return m.Size() +} +func (m *MsgRegisterEncryptionKey) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRegisterEncryptionKey.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRegisterEncryptionKey proto.InternalMessageInfo + +func (m *MsgRegisterEncryptionKey) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *MsgRegisterEncryptionKey) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +// MsgRegisterEncryptionKeyResponse defines the Msg/RegisterEncryptionKey response type +type MsgRegisterEncryptionKeyResponse struct { +} + +func (m *MsgRegisterEncryptionKeyResponse) Reset() { *m = MsgRegisterEncryptionKeyResponse{} } +func (m *MsgRegisterEncryptionKeyResponse) String() string { return proto.CompactTextString(m) } +func (*MsgRegisterEncryptionKeyResponse) ProtoMessage() {} +func (*MsgRegisterEncryptionKeyResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_85e46bdbb1c358a8, []int{1} +} +func (m *MsgRegisterEncryptionKeyResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRegisterEncryptionKeyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRegisterEncryptionKeyResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgRegisterEncryptionKeyResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRegisterEncryptionKeyResponse.Merge(m, src) +} +func (m *MsgRegisterEncryptionKeyResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgRegisterEncryptionKeyResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRegisterEncryptionKeyResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRegisterEncryptionKeyResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgRegisterEncryptionKey)(nil), "e2ee.MsgRegisterEncryptionKey") + proto.RegisterType((*MsgRegisterEncryptionKeyResponse)(nil), "e2ee.MsgRegisterEncryptionKeyResponse") +} + +func init() { proto.RegisterFile("e2ee/tx.proto", fileDescriptor_85e46bdbb1c358a8) } + +var fileDescriptor_85e46bdbb1c358a8 = []byte{ + // 249 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4d, 0x35, 0x4a, 0x4d, + 0xd5, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x01, 0x71, 0xa5, 0xc4, 0x93, + 0xf3, 0x8b, 0x73, 0xf3, 0x8b, 0xf5, 0x73, 0x8b, 0xd3, 0xf5, 0xcb, 0x0c, 0x41, 0x14, 0x44, 0x5a, + 0xc9, 0x8d, 0x4b, 0xc2, 0xb7, 0x38, 0x3d, 0x28, 0x35, 0x3d, 0xb3, 0xb8, 0x24, 0xb5, 0xc8, 0x35, + 0x2f, 0xb9, 0xa8, 0xb2, 0xa0, 0x24, 0x33, 0x3f, 0xcf, 0x3b, 0xb5, 0x52, 0x48, 0x82, 0x8b, 0x3d, + 0x31, 0x25, 0xa5, 0x28, 0xb5, 0xb8, 0x58, 0x82, 0x51, 0x81, 0x51, 0x83, 0x33, 0x08, 0xc6, 0x15, + 0x12, 0xe0, 0x62, 0xce, 0x4e, 0xad, 0x94, 0x60, 0x02, 0x8b, 0x82, 0x98, 0x4a, 0x4a, 0x5c, 0x0a, + 0xb8, 0xcc, 0x09, 0x4a, 0x2d, 0x2e, 0xc8, 0xcf, 0x2b, 0x4e, 0x35, 0xca, 0xe5, 0x62, 0xf6, 0x2d, + 0x4e, 0x17, 0x8a, 0xe7, 0x12, 0xc5, 0x6e, 0x9f, 0x9c, 0x1e, 0xc8, 0xad, 0x7a, 0xb8, 0xcc, 0x91, + 0x52, 0xc3, 0x2f, 0x0f, 0xb3, 0x47, 0x8a, 0xb5, 0xe1, 0xf9, 0x06, 0x2d, 0x46, 0x27, 0x9f, 0x13, + 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, + 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0x32, 0x4a, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, + 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x07, 0x1b, 0x90, 0xaf, 0x9b, 0x5f, 0x94, 0xae, 0x9b, 0x9c, 0x91, + 0x98, 0x99, 0xa7, 0x9f, 0x5c, 0x94, 0x9f, 0x97, 0x5f, 0xac, 0x5f, 0x66, 0xa4, 0x5f, 0xa1, 0x0f, + 0x09, 0xca, 0xca, 0x82, 0xd4, 0xe2, 0x24, 0x36, 0x70, 0x78, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, + 0xff, 0x8d, 0xda, 0x77, 0x6d, 0x5f, 0x01, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // RegisterEncryptionKey registers a new encryption key to a specific account + RegisterEncryptionKey(ctx context.Context, in *MsgRegisterEncryptionKey, opts ...grpc.CallOption) (*MsgRegisterEncryptionKeyResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) RegisterEncryptionKey(ctx context.Context, in *MsgRegisterEncryptionKey, opts ...grpc.CallOption) (*MsgRegisterEncryptionKeyResponse, error) { + out := new(MsgRegisterEncryptionKeyResponse) + err := c.cc.Invoke(ctx, "/e2ee.Msg/RegisterEncryptionKey", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // RegisterEncryptionKey registers a new encryption key to a specific account + RegisterEncryptionKey(context.Context, *MsgRegisterEncryptionKey) (*MsgRegisterEncryptionKeyResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) RegisterEncryptionKey(ctx context.Context, req *MsgRegisterEncryptionKey) (*MsgRegisterEncryptionKeyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RegisterEncryptionKey not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_RegisterEncryptionKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRegisterEncryptionKey) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RegisterEncryptionKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/e2ee.Msg/RegisterEncryptionKey", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RegisterEncryptionKey(ctx, req.(*MsgRegisterEncryptionKey)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "e2ee.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "RegisterEncryptionKey", + Handler: _Msg_RegisterEncryptionKey_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "e2ee/tx.proto", +} + +func (m *MsgRegisterEncryptionKey) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgRegisterEncryptionKey) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRegisterEncryptionKey) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintTx(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0x12 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgRegisterEncryptionKeyResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgRegisterEncryptionKeyResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRegisterEncryptionKeyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgRegisterEncryptionKey) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Key) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgRegisterEncryptionKeyResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgRegisterEncryptionKey) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgRegisterEncryptionKey: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRegisterEncryptionKey: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRegisterEncryptionKeyResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgRegisterEncryptionKeyResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRegisterEncryptionKeyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) From d3264f587d605c112ffdcf36cdc38f90d637f97e Mon Sep 17 00:00:00 2001 From: huangyi Date: Fri, 3 May 2024 11:42:37 +0800 Subject: [PATCH 02/24] cmd to encrypt to validators --- x/e2ee/client/cli/cmd.go | 1 + x/e2ee/client/cli/encrypt_to_validators.go | 103 +++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 x/e2ee/client/cli/encrypt_to_validators.go diff --git a/x/e2ee/client/cli/cmd.go b/x/e2ee/client/cli/cmd.go index e7358085a4..73f8d69bb2 100644 --- a/x/e2ee/client/cli/cmd.go +++ b/x/e2ee/client/cli/cmd.go @@ -12,6 +12,7 @@ func E2EECommand() *cobra.Command { KeygenCommand(), EncryptCommand(), DecryptCommand(), + EncryptToValidatorsCommand(), ) return cmd diff --git a/x/e2ee/client/cli/encrypt_to_validators.go b/x/e2ee/client/cli/encrypt_to_validators.go new file mode 100644 index 0000000000..6935923294 --- /dev/null +++ b/x/e2ee/client/cli/encrypt_to_validators.go @@ -0,0 +1,103 @@ +package cli + +import ( + "context" + "io" + "os" + + "filippo.io/age" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/spf13/cobra" + + "github.com/crypto-org-chain/cronos/v2/x/e2ee/types" +) + +func EncryptToValidatorsCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "encrypt-to-validators [input-file]", + Short: "Encrypt input file to one or multiple recipients", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + outputFile, err := cmd.Flags().GetString(flags.FlagOutput) + if err != nil { + return err + } + + ctx := context.Background() + + // get validator list + stakingClient := stakingtypes.NewQueryClient(clientCtx) + valsRsp, err := stakingClient.Validators(ctx, &stakingtypes.QueryValidatorsRequest{ + Status: stakingtypes.BondStatusBonded, + }) + if err != nil { + return err + } + + recs := make([]string, len(valsRsp.Validators)) + for i, val := range valsRsp.Validators { + bz, err := sdk.ValAddressFromBech32(val.OperatorAddress) + if err != nil { + return err + } + // convert to account address + recs[i] = sdk.AccAddress(bz).String() + } + + // query encryption key from chain state + client := types.NewQueryClient(clientCtx) + rsp, err := client.Keys(context.Background(), &types.KeysRequest{ + Addresses: recs, + }) + if err != nil { + return err + } + + recipients := make([]age.Recipient, len(recs)) + for i, key := range rsp.Keys { + recipient, err := age.ParseX25519Recipient(key) + if err != nil { + return err + } + recipients[i] = recipient + } + + inputFile := args[0] + var input io.Reader + if inputFile == "-" { + input = os.Stdin + } else { + f, err := os.Open(inputFile) + if err != nil { + return err + } + defer f.Close() + input = f + } + + var output io.Writer + if outputFile == "-" { + output = os.Stdout + } else { + fp, err := os.Create(outputFile) + if err != nil { + return err + } + defer fp.Close() + output = fp + } + return encrypt(recipients, input, output) + }, + } + f := cmd.Flags() + f.StringP(flags.FlagOutput, "o", "-", "output file (default stdout)") + return cmd +} From 101490de13877d6f82554330c5bb57354b6305ea Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 3 May 2024 11:46:21 +0800 Subject: [PATCH 03/24] fix test --- integration_tests/test_e2ee.py | 33 ++++++++++++++++----- integration_tests/test_gov_update_params.py | 30 +++++++++++++------ integration_tests/utils.py | 25 ---------------- 3 files changed, 47 insertions(+), 41 deletions(-) diff --git a/integration_tests/test_e2ee.py b/integration_tests/test_e2ee.py index ebe6a3dcae..ca560e56ac 100644 --- a/integration_tests/test_e2ee.py +++ b/integration_tests/test_e2ee.py @@ -1,12 +1,31 @@ -from .utils import prepare_cipherfile - - def test_encrypt_decrypt(cronos): - cli = cronos.cosmos_cli() + cli0 = cronos.cosmos_cli() cli1 = cronos.cosmos_cli(1) + + # gen two keys for two accounts name0 = "key0" name1 = "key1" + pubkey0 = cli0.keygen(keyring_name=name0) + pubkey1 = cli1.keygen(keyring_name=name1) + sender = "validator" + cli0.register_e2ee_key(pubkey0, _from=sender) + cli1.register_e2ee_key(pubkey1, _from=sender) + # query in batch + assert cli0.query_e2ee_keys(cli0.address(sender), cli1.address(sender)) == [ + pubkey0, + pubkey1, + ] + # prepare data file to encrypt content = "Hello World!" - cipherfile = prepare_cipherfile(cli, cli1, name0, name1, content) - assert cli.decrypt(cipherfile, identity=name0) == content - assert cli1.decrypt(cipherfile, identity=name1) == content + plainfile = cli0.data_dir / "plaintext" + plainfile.write_text(content) + cipherfile = cli0.data_dir / "ciphertext" + cli0.encrypt( + plainfile, + cli0.address(sender), + cli1.address(sender), + output=cipherfile, + ) + + assert cli0.decrypt(cipherfile, identity="key0") == content + assert cli1.decrypt(cipherfile, identity="key1") == content diff --git a/integration_tests/test_gov_update_params.py b/integration_tests/test_gov_update_params.py index 69f3f41d41..dcc56d4121 100644 --- a/integration_tests/test_gov_update_params.py +++ b/integration_tests/test_gov_update_params.py @@ -9,7 +9,6 @@ approve_proposal, deploy_contract, eth_to_bech32, - prepare_cipherfile, wait_for_new_blocks, wait_for_port, ) @@ -96,18 +95,31 @@ def test_gov_update_params(cronos, tmp_path): print("params", rsp) assert rsp == params - # gen two keys for two accounts + # gen identity key for one account name = "e2ee-identity" - cli1 = cronos.cosmos_cli(1) addr = cli.address("user") content = json.dumps({"addresses": [addr]}) - cipherfile = prepare_cipherfile(cli, cli1, name, name, content) - cronos.supervisorctl("stop", "all") - cronos.supervisorctl("start", "cronos_777-1-node0", "cronos_777-1-node1") + pubkey0 = cli.keygen(keyring_name=name) + sender = "validator" + cli.register_e2ee_key(pubkey0, _from=sender) + assert cli.query_e2ee_key(cli.address(sender)) == pubkey0 + # prepare data file to encrypt + plainfile = cli.data_dir / "plaintext" + plainfile.write_text(content) + cipherfile = cli.data_dir / "ciphertext" + cli.encrypt( + plainfile, + cli.address(sender), + output=cipherfile, + ) + cronos.supervisorctl("stop", "cronos_777-1-node0") + cronos.supervisorctl("start", "cronos_777-1-node0") wait_for_port(ports.evmrpc_port(cronos.base_port(0))) rsp = cli.store_blocklist(cipherfile, from_="validator") assert rsp["code"] == 0, rsp["raw_log"] wait_for_new_blocks(cli, 2) - rsp = cli.transfer(addr, cli.address("validator"), "1basetcro") - assert rsp["code"] != 0 - assert "signer is blocked" in rsp["raw_log"] + with pytest.raises(AssertionError): + rsp = cli.transfer(addr, cli.address("validator"), "1basetcro") + cli1 = cronos.cosmos_cli(1) + rsp = cli1.transfer(cli1.address("validator"), cli1.address("validator"), "1basetcro") + assert rsp["code"] == 0, rsp["raw_log"] \ No newline at end of file diff --git a/integration_tests/utils.py b/integration_tests/utils.py index fd9cfb933b..323207d83e 100644 --- a/integration_tests/utils.py +++ b/integration_tests/utils.py @@ -732,28 +732,3 @@ def get_send_enable(port): url = f"http://127.0.0.1:{port}/cosmos/bank/v1beta1/params" raw = requests.get(url).json() return raw["params"]["send_enabled"] - - -def prepare_cipherfile(cli0, cli1, name0, name1, content): - # gen two keys for two accounts - pubkey0 = cli0.keygen(keyring_name=name0) - pubkey1 = cli1.keygen(keyring_name=name1) - sender = "validator" - cli0.register_e2ee_key(pubkey0, _from=sender) - cli1.register_e2ee_key(pubkey1, _from=sender) - # query in batch - assert cli0.query_e2ee_keys(cli0.address(sender), cli1.address(sender)) == [ - pubkey0, - pubkey1, - ] - # prepare data file to encrypt - plainfile = cli0.data_dir / "plaintext" - plainfile.write_text(content) - cipherfile = cli0.data_dir / "ciphertext" - cli0.encrypt( - plainfile, - cli0.address(sender), - cli1.address(sender), - output=cipherfile, - ) - return cipherfile From 92d6366f132440ca80b087626790073c162bd2e2 Mon Sep 17 00:00:00 2001 From: huangyi Date: Fri, 3 May 2024 14:13:50 +0800 Subject: [PATCH 04/24] temp --- app/app.go | 2 +- app/proposal.go | 6 +++++ integration_tests/cosmoscli.py | 13 ++++++++++ integration_tests/test_e2ee.py | 27 ++++++++++++++++++++- integration_tests/test_gov_update_params.py | 16 ------------ 5 files changed, 46 insertions(+), 18 deletions(-) diff --git a/app/app.go b/app/app.go index 8cddb2032a..e3ffe67c33 100644 --- a/app/app.go +++ b/app/app.go @@ -1063,7 +1063,7 @@ func (app *App) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.Respo } func (app *App) RefreshBlockList(ctx sdk.Context) error { - if app.blockProposalHandler.Identity == nil { + if app.blockProposalHandler == nil || app.blockProposalHandler.Identity == nil { return nil } diff --git a/app/proposal.go b/app/proposal.go index fe23975ba8..851ecb9a20 100644 --- a/app/proposal.go +++ b/app/proposal.go @@ -33,6 +33,7 @@ func NewProposalHandler(txDecoder sdk.TxDecoder, identity age.Identity) *Proposa } func (h *ProposalHandler) SetBlockList(blob []byte) error { + fmt.Println("SetBlockList") if h.Identity == nil { return nil } @@ -42,6 +43,11 @@ func (h *ProposalHandler) SetBlockList(blob []byte) error { } h.LastBlockList = blob + if len(blob) == 0 { + h.Blocklist = make(map[string]struct{}) + return nil + } + reader, err := age.Decrypt(bytes.NewBuffer(blob), h.Identity) if err != nil { return err diff --git a/integration_tests/cosmoscli.py b/integration_tests/cosmoscli.py index 978a718e35..11742dfdd3 100644 --- a/integration_tests/cosmoscli.py +++ b/integration_tests/cosmoscli.py @@ -1919,3 +1919,16 @@ def decrypt(self, input, identity="e2ee-identity", **kwargs): .strip() .decode() ) + + def encrypt_to_validators(self, input, **kwargs): + return ( + self.raw( + "e2ee", + "encrypt-to-validators", + input, + home=self.data_dir, + **kwargs, + ) + .strip() + .decode() + ) diff --git a/integration_tests/test_e2ee.py b/integration_tests/test_e2ee.py index ebe6a3dcae..752abc4a66 100644 --- a/integration_tests/test_e2ee.py +++ b/integration_tests/test_e2ee.py @@ -1,4 +1,6 @@ -from .utils import prepare_cipherfile +import json + +from .utils import prepare_cipherfile, wait_for_new_blocks def test_encrypt_decrypt(cronos): @@ -10,3 +12,26 @@ def test_encrypt_decrypt(cronos): cipherfile = prepare_cipherfile(cli, cli1, name0, name1, content) assert cli.decrypt(cipherfile, identity=name0) == content assert cli1.decrypt(cipherfile, identity=name1) == content + + +def test_block_list(cronos): + cli0 = cronos.cosmos_cli() + cli1 = cronos.cosmos_cli(1) + + # prepare encryption keys for validators + cli0.register_e2ee_key(cli0.keygen(), _from="validator") + cli1.register_e2ee_key(cli1.keygen(), _from="validator") + + user = cli0.address("user") + + blocklist = json.dumps({"addresses": [user]}) + plainfile = cli0.data_dir / "plaintext" + plainfile.write_text(blocklist) + cipherfile = cli0.data_dir / "ciphertext" + cli0.encrypt_to_validators(plainfile, output=cipherfile) + rsp = cli0.store_blocklist(cipherfile, _from="validator") + assert rsp["code"] == 0, rsp["raw_log"] + + wait_for_new_blocks(cli0, 2) + rsp = cli0.transfer(user, cli0.address("validator"), "1basetcro") + assert rsp["code"] != 0 diff --git a/integration_tests/test_gov_update_params.py b/integration_tests/test_gov_update_params.py index 69f3f41d41..8234292d1b 100644 --- a/integration_tests/test_gov_update_params.py +++ b/integration_tests/test_gov_update_params.py @@ -95,19 +95,3 @@ def test_gov_update_params(cronos, tmp_path): rsp = cli.query_params() print("params", rsp) assert rsp == params - - # gen two keys for two accounts - name = "e2ee-identity" - cli1 = cronos.cosmos_cli(1) - addr = cli.address("user") - content = json.dumps({"addresses": [addr]}) - cipherfile = prepare_cipherfile(cli, cli1, name, name, content) - cronos.supervisorctl("stop", "all") - cronos.supervisorctl("start", "cronos_777-1-node0", "cronos_777-1-node1") - wait_for_port(ports.evmrpc_port(cronos.base_port(0))) - rsp = cli.store_blocklist(cipherfile, from_="validator") - assert rsp["code"] == 0, rsp["raw_log"] - wait_for_new_blocks(cli, 2) - rsp = cli.transfer(addr, cli.address("validator"), "1basetcro") - assert rsp["code"] != 0 - assert "signer is blocked" in rsp["raw_log"] From 8ad4b75806c0eb4f63cc1519993bcaba4fd18f8a Mon Sep 17 00:00:00 2001 From: huangyi Date: Fri, 3 May 2024 15:36:48 +0800 Subject: [PATCH 05/24] fix test --- app/proposal.go | 1 - integration_tests/cosmoscli.py | 4 +- integration_tests/test_e2ee.py | 89 ++++++++++++++++++++++++---------- 3 files changed, 65 insertions(+), 29 deletions(-) diff --git a/app/proposal.go b/app/proposal.go index 851ecb9a20..40646cd374 100644 --- a/app/proposal.go +++ b/app/proposal.go @@ -33,7 +33,6 @@ func NewProposalHandler(txDecoder sdk.TxDecoder, identity age.Identity) *Proposa } func (h *ProposalHandler) SetBlockList(blob []byte) error { - fmt.Println("SetBlockList") if h.Identity == nil { return nil } diff --git a/integration_tests/cosmoscli.py b/integration_tests/cosmoscli.py index 11742dfdd3..af10bbab84 100644 --- a/integration_tests/cosmoscli.py +++ b/integration_tests/cosmoscli.py @@ -1857,7 +1857,7 @@ def query_e2ee_key(self, address): home=self.data_dir, output="json", ) - )["key"] + ).get("key") def query_e2ee_keys(self, *addresses): return json.loads( @@ -1869,7 +1869,7 @@ def query_e2ee_keys(self, *addresses): home=self.data_dir, output="json", ) - )["keys"] + ).get("keys") def register_e2ee_key(self, key, **kwargs): kwargs.setdefault("gas_prices", DEFAULT_GAS_PRICE) diff --git a/integration_tests/test_e2ee.py b/integration_tests/test_e2ee.py index 9a8ae989f6..304ee3ee2f 100644 --- a/integration_tests/test_e2ee.py +++ b/integration_tests/test_e2ee.py @@ -1,40 +1,77 @@ +import json + +import pytest + +from .network import Cronos +from .utils import wait_for_new_blocks + + +def gen_validator_identity(cronos: Cronos): + for i in range(len(cronos.config["validators"])): + cli = cronos.cosmos_cli(i) + if cli.query_e2ee_key(cli.address("validator")): + return + pubkey = cli.keygen() + cli.register_e2ee_key(pubkey, _from="validator") + assert cli.query_e2ee_key(cli.address("validator")) == pubkey + + cronos.supervisorctl("restart", f"cronos_777-1-node{i}") + + wait_for_new_blocks(cronos.cosmos_cli(), 1) + + def test_encrypt_decrypt(cronos): + gen_validator_identity(cronos) + cli0 = cronos.cosmos_cli() cli1 = cronos.cosmos_cli(1) - # gen two keys for two accounts - name0 = "key0" - name1 = "key1" - pubkey0 = cli0.keygen(keyring_name=name0) - pubkey1 = cli1.keygen(keyring_name=name1) - sender = "validator" - cli0.register_e2ee_key(pubkey0, _from=sender) - cli1.register_e2ee_key(pubkey1, _from=sender) # query in batch - assert cli0.query_e2ee_keys(cli0.address(sender), cli1.address(sender)) == [ - pubkey0, - pubkey1, - ] + assert ( + len( + cli0.query_e2ee_keys( + cli0.address("validator"), + cli1.address("validator"), + ) + ) + == 2 + ) + # prepare data file to encrypt content = "Hello World!" -def test_block_list(cronos): - cli0 = cronos.cosmos_cli() - cli1 = cronos.cosmos_cli(1) + plainfile = cli0.data_dir / "plaintext" + plainfile.write_text(content) + cipherfile = cli0.data_dir / "ciphertext" + cli0.encrypt( + plainfile, + cli0.address("validator"), + cli1.address("validator"), + output=cipherfile, + ) + + assert cli0.decrypt(cipherfile) == content + assert cli1.decrypt(cipherfile) == content - # prepare encryption keys for validators - cli0.register_e2ee_key(cli0.keygen(), _from="validator") - cli1.register_e2ee_key(cli1.keygen(), _from="validator") - user = cli0.address("user") +def test_block_list(cronos): + gen_validator_identity(cronos) + cli = cronos.cosmos_cli() + + user = cli.address("user") blocklist = json.dumps({"addresses": [user]}) - plainfile = cli0.data_dir / "plaintext" + plainfile = cli.data_dir / "plaintext" plainfile.write_text(blocklist) - cipherfile = cli0.data_dir / "ciphertext" - cli0.encrypt_to_validators(plainfile, output=cipherfile) - rsp = cli0.store_blocklist(cipherfile, _from="validator") + cipherfile = cli.data_dir / "ciphertext" + cli.encrypt_to_validators(plainfile, output=cipherfile) + rsp = cli.store_blocklist(cipherfile, _from="validator") assert rsp["code"] == 0, rsp["raw_log"] - wait_for_new_blocks(cli0, 2) - rsp = cli0.transfer(user, cli0.address("validator"), "1basetcro") - assert rsp["code"] != 0 + # normal tx works + cli.transfer(cli.address("validator"), user, "1basetcro") + + # blocked tx don't work + with pytest.raises(AssertionError) as exc: + cli.transfer(user, cli.address("validator"), "1basetcro") + + assert "timed out waiting for event" in str(exc.value) From ebbe1486d2b86b09dcdeb96db1838e56bcd00152 Mon Sep 17 00:00:00 2001 From: huangyi Date: Fri, 3 May 2024 15:43:27 +0800 Subject: [PATCH 06/24] improve test --- integration_tests/test_e2ee.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/integration_tests/test_e2ee.py b/integration_tests/test_e2ee.py index 304ee3ee2f..a0ef790e2a 100644 --- a/integration_tests/test_e2ee.py +++ b/integration_tests/test_e2ee.py @@ -75,3 +75,10 @@ def test_block_list(cronos): cli.transfer(user, cli.address("validator"), "1basetcro") assert "timed out waiting for event" in str(exc.value) + + # empty string can clear all blocklist + cipherfile.write_text("") + rsp = cli.store_blocklist(cipherfile, _from="validator") + assert rsp["code"] == 0, rsp["raw_log"] + + cli.transfer(user, cli.address("validator"), "1basetcro") From bec195ec3752870759e5243d6b67c9c287e2ac97 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 3 May 2024 11:39:25 +0800 Subject: [PATCH 07/24] Problem: no validate for malformed e2ee key in register (#1421) * Problem: no validate for malformed e2ee key in register * update doc * Apply suggestions from code review * cleanup --------- Co-authored-by: yihuang --- CHANGELOG.md | 1 + integration_tests/configs/default.jsonnet | 2 +- integration_tests/test_e2ee.py | 8 ++++++++ x/e2ee/keeper/keeper.go | 23 +++++++++++++++-------- x/e2ee/types/keys.go | 7 +------ x/e2ee/types/msg.go | 14 +++++++------- 6 files changed, 33 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85fab28148..b6cf0f03cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * [#1413](https://github.com/crypto-org-chain/cronos/pull/1413) Add custom keyring implementation for e2ee module. * (e2ee)[#1415](https://github.com/crypto-org-chain/cronos/pull/1415) Add batch keys query for e2ee module. +* (e2ee)[#1421](https://github.com/crypto-org-chain/cronos/pull/1421) Validate e2ee key when register. *April 22, 2024* diff --git a/integration_tests/configs/default.jsonnet b/integration_tests/configs/default.jsonnet index 41b0364d56..43daba916f 100644 --- a/integration_tests/configs/default.jsonnet +++ b/integration_tests/configs/default.jsonnet @@ -88,7 +88,7 @@ e2ee: { keys: [{ address: 'crc16z0herz998946wr659lr84c8c556da55dc34hh', - key: std.base64('key'), + key: 'age1k3mpspxytgvx6e0jja0xgrtzz7vw2p00c2a3xmq5ygfzhwh4wg0s35z4c8', }], }, gov: { diff --git a/integration_tests/test_e2ee.py b/integration_tests/test_e2ee.py index a0ef790e2a..cdc610d77c 100644 --- a/integration_tests/test_e2ee.py +++ b/integration_tests/test_e2ee.py @@ -6,6 +6,14 @@ from .utils import wait_for_new_blocks +def test_register(cronos: Cronos): + cli = cronos.cosmos_cli() + pubkey0 = cli.keygen(keyring_name="key0") + rsp = cli.register_e2ee_key(pubkey0 + "malformed", _from="validator") + assert not rsp["code"] + assert not cli.query_e2ee_key(cli.address("validator")) + + def gen_validator_identity(cronos: Cronos): for i in range(len(cronos.config["validators"])): cli = cronos.cosmos_cli(i) diff --git a/x/e2ee/keeper/keeper.go b/x/e2ee/keeper/keeper.go index 131534e6fe..00a421e487 100644 --- a/x/e2ee/keeper/keeper.go +++ b/x/e2ee/keeper/keeper.go @@ -25,16 +25,26 @@ func NewKeeper(storeKey storetypes.StoreKey) Keeper { } } +func (k Keeper) registerEncryptionKey( + ctx context.Context, + address string, + key []byte, +) error { + bz, err := sdk.AccAddressFromBech32(address) + if err != nil { + return err + } + sdk.UnwrapSDKContext(ctx).KVStore(k.storeKey).Set(types.KeyPrefix(bz), key) + return nil +} + func (k Keeper) RegisterEncryptionKey( ctx context.Context, req *types.MsgRegisterEncryptionKey, ) (*types.MsgRegisterEncryptionKeyResponse, error) { - addr, err := sdk.AccAddressFromBech32(req.Address) - if err != nil { + if err := k.registerEncryptionKey(ctx, req.Address, []byte(req.Key)); err != nil { return nil, err } - sdkCtx := sdk.UnwrapSDKContext(ctx) - sdkCtx.KVStore(k.storeKey).Set(types.KeyPrefix(addr), []byte(req.Key)) return &types.MsgRegisterEncryptionKeyResponse{}, nil } @@ -43,10 +53,7 @@ func (k Keeper) InitGenesis( state *types.GenesisState, ) error { for _, key := range state.Keys { - if _, err := k.RegisterEncryptionKey(ctx, &types.MsgRegisterEncryptionKey{ - Address: key.Address, - Key: key.Key, - }); err != nil { + if err := k.registerEncryptionKey(ctx, key.Address, []byte(key.Key)); err != nil { return err } } diff --git a/x/e2ee/types/keys.go b/x/e2ee/types/keys.go index 5941cbf264..0dacda824f 100644 --- a/x/e2ee/types/keys.go +++ b/x/e2ee/types/keys.go @@ -1,8 +1,6 @@ package types import ( - "errors" - sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -39,8 +37,5 @@ func (e EncryptionKeyEntry) Validate() error { if _, err := sdk.AccAddressFromBech32(e.Address); err != nil { return err } - if len(e.Key) == 0 { - return errors.New("key can't be nil") - } - return nil + return ValidateRecipientKey(e.Key) } diff --git a/x/e2ee/types/msg.go b/x/e2ee/types/msg.go index df5ab23732..85b2ec0cfc 100644 --- a/x/e2ee/types/msg.go +++ b/x/e2ee/types/msg.go @@ -3,23 +3,23 @@ package types import ( fmt "fmt" + "filippo.io/age" sdk "github.com/cosmos/cosmos-sdk/types" ) var _ sdk.Msg = (*MsgRegisterEncryptionKey)(nil) func (m *MsgRegisterEncryptionKey) ValidateBasic() error { - if m.Address == "" { - return fmt.Errorf("address cannot be empty") - } - if len(m.Key) == 0 { - return fmt.Errorf("key cannot be nil") - } // validate bech32 format of Address if _, err := sdk.AccAddressFromBech32(m.Address); err != nil { return fmt.Errorf("invalid address: %s", err) } - return nil + return ValidateRecipientKey(m.Key) +} + +func ValidateRecipientKey(key string) error { + _, err := age.ParseX25519Recipient(key) + return err } func (m *MsgRegisterEncryptionKey) GetSigners() []sdk.AccAddress { From b3d343be448916f6e258d84cdd19d219f1dc5244 Mon Sep 17 00:00:00 2001 From: huangyi Date: Fri, 3 May 2024 16:10:18 +0800 Subject: [PATCH 08/24] cleanup test --- integration_tests/configs/default.jsonnet | 3 --- integration_tests/test_e2ee.py | 5 +++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/integration_tests/configs/default.jsonnet b/integration_tests/configs/default.jsonnet index 43daba916f..123b5275d0 100644 --- a/integration_tests/configs/default.jsonnet +++ b/integration_tests/configs/default.jsonnet @@ -61,9 +61,6 @@ name: 'signer2', coins: '30000000000000000000000basetcro', mnemonic: '${SIGNER2_MNEMONIC}', - }, { - name: 'user', - coins: '10000000000000000000000basetcro', }], genesis: { consensus_params: { diff --git a/integration_tests/test_e2ee.py b/integration_tests/test_e2ee.py index cdc610d77c..8261b7c158 100644 --- a/integration_tests/test_e2ee.py +++ b/integration_tests/test_e2ee.py @@ -65,7 +65,7 @@ def test_block_list(cronos): gen_validator_identity(cronos) cli = cronos.cosmos_cli() - user = cli.address("user") + user = cli.address("signer2") blocklist = json.dumps({"addresses": [user]}) plainfile = cli.data_dir / "plaintext" @@ -89,4 +89,5 @@ def test_block_list(cronos): rsp = cli.store_blocklist(cipherfile, _from="validator") assert rsp["code"] == 0, rsp["raw_log"] - cli.transfer(user, cli.address("validator"), "1basetcro") + rsp = cli.transfer(user, cli.address("validator"), "1basetcro") + assert rsp["code"] == 0, rsp["raw_log"] From 720e407f1155aaa208ed371ea3acb2b4f4b8a73e Mon Sep 17 00:00:00 2001 From: huangyi Date: Fri, 3 May 2024 16:11:09 +0800 Subject: [PATCH 09/24] revert --- integration_tests/test_gov_update_params.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/integration_tests/test_gov_update_params.py b/integration_tests/test_gov_update_params.py index 03539531b1..cc9d6651cc 100644 --- a/integration_tests/test_gov_update_params.py +++ b/integration_tests/test_gov_update_params.py @@ -2,16 +2,8 @@ import json import pytest -from pystarport import ports -from .utils import ( - CONTRACTS, - approve_proposal, - deploy_contract, - eth_to_bech32, - wait_for_new_blocks, - wait_for_port, -) +from .utils import CONTRACTS, approve_proposal, deploy_contract, eth_to_bech32 pytestmark = pytest.mark.gov From 36dd2d65fd5182efd8f9e739a872d2ea8cd573a3 Mon Sep 17 00:00:00 2001 From: huangyi Date: Fri, 3 May 2024 16:15:31 +0800 Subject: [PATCH 10/24] fix test --- integration_tests/cosmoscli.py | 1 - 1 file changed, 1 deletion(-) diff --git a/integration_tests/cosmoscli.py b/integration_tests/cosmoscli.py index af10bbab84..834423d766 100644 --- a/integration_tests/cosmoscli.py +++ b/integration_tests/cosmoscli.py @@ -1839,7 +1839,6 @@ def event_query_tx_for(self, hash): "event-query-tx-for", hash, home=self.data_dir, - stderr=subprocess.DEVNULL, ) ) From c176be9ec89619d15e01e0360acbd1d93206df89 Mon Sep 17 00:00:00 2001 From: huangyi Date: Fri, 3 May 2024 16:20:29 +0800 Subject: [PATCH 11/24] fix test --- integration_tests/test_e2ee.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration_tests/test_e2ee.py b/integration_tests/test_e2ee.py index 8261b7c158..dcfed32fad 100644 --- a/integration_tests/test_e2ee.py +++ b/integration_tests/test_e2ee.py @@ -84,8 +84,8 @@ def test_block_list(cronos): assert "timed out waiting for event" in str(exc.value) - # empty string can clear all blocklist - cipherfile.write_text("") + # clear blocklist + cipherfile.write_text("{}") rsp = cli.store_blocklist(cipherfile, _from="validator") assert rsp["code"] == 0, rsp["raw_log"] From b3538c405915025dcbd14cc3181f58a04fdc7693 Mon Sep 17 00:00:00 2001 From: huangyi Date: Fri, 3 May 2024 16:22:54 +0800 Subject: [PATCH 12/24] remove mempool blocked-addresses --- app/app.go | 36 +------------------ app/block_address.go | 31 ---------------- .../configs/long_timeout_commit.jsonnet | 3 -- integration_tests/test_mempool.py | 7 ---- 4 files changed, 1 insertion(+), 76 deletions(-) delete mode 100644 app/block_address.go diff --git a/app/app.go b/app/app.go index e3ffe67c33..7552389175 100644 --- a/app/app.go +++ b/app/app.go @@ -1,8 +1,6 @@ package app import ( - "crypto/sha256" - "encoding/hex" stderrors "errors" "fmt" "io" @@ -11,7 +9,6 @@ import ( "net/http" "os" "path/filepath" - "sort" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1" @@ -178,8 +175,6 @@ const ( // // NOTE: In the SDK, the default value is 255. AddrLen = 20 - - FlagBlockedAddresses = "blocked-addresses" ) var Forks = []Fork{} @@ -923,7 +918,6 @@ func New( app.SetEndBlocker(app.EndBlocker) if err := app.setAnteHandler(encodingConfig.TxConfig, cast.ToUint64(appOpts.Get(srvflags.EVMMaxTxGasWanted)), - cast.ToStringSlice(appOpts.Get(FlagBlockedAddresses)), ); err != nil { panic(err) } @@ -971,34 +965,7 @@ func New( } // use Ethermint's custom AnteHandler -func (app *App) setAnteHandler(txConfig client.TxConfig, maxGasWanted uint64, blacklist []string) error { - if len(blacklist) > 0 { - sort.Strings(blacklist) - // hash blacklist concatenated - h := sha256.New() - for _, addr := range blacklist { - _, err := h.Write([]byte(addr)) - if err != nil { - panic(err) - } - } - app.Logger().Error("Setting ante handler with blacklist", "size", len(blacklist), "hash", hex.EncodeToString(h.Sum(nil))) - for _, addr := range blacklist { - app.Logger().Error("Blacklisted address", "address", addr) - } - } else { - app.Logger().Error("Setting ante handler without blacklist") - } - blockedMap := make(map[string]struct{}, len(blacklist)) - for _, str := range blacklist { - addr, err := sdk.AccAddressFromBech32(str) - if err != nil { - return fmt.Errorf("invalid bech32 address: %s, err: %w", str, err) - } - - blockedMap[string(addr)] = struct{}{} - } - blockAddressDecorator := NewBlockAddressesDecorator(blockedMap) +func (app *App) setAnteHandler(txConfig client.TxConfig, maxGasWanted uint64) error { options := evmante.HandlerOptions{ AccountKeeper: app.AccountKeeper, BankKeeper: app.BankKeeper, @@ -1015,7 +982,6 @@ func (app *App) setAnteHandler(txConfig client.TxConfig, maxGasWanted uint64, bl sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{}), sdk.MsgTypeURL(&vestingtypes.MsgCreateVestingAccount{}), }, - ExtraDecorators: []sdk.AnteDecorator{blockAddressDecorator}, } anteHandler, err := evmante.NewAnteHandler(options) diff --git a/app/block_address.go b/app/block_address.go deleted file mode 100644 index 11cb1cfa68..0000000000 --- a/app/block_address.go +++ /dev/null @@ -1,31 +0,0 @@ -package app - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// BlockAddressesDecorator block addresses from sending transactions -type BlockAddressesDecorator struct { - blockedMap map[string]struct{} -} - -func NewBlockAddressesDecorator(blacklist map[string]struct{}) BlockAddressesDecorator { - return BlockAddressesDecorator{ - blockedMap: blacklist, - } -} - -func (bad BlockAddressesDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { - if ctx.IsCheckTx() { - for _, msg := range tx.GetMsgs() { - for _, signer := range msg.GetSigners() { - if _, ok := bad.blockedMap[string(signer)]; ok { - return ctx, fmt.Errorf("signer is blocked: %s", signer.String()) - } - } - } - } - return next(ctx, tx, simulate) -} diff --git a/integration_tests/configs/long_timeout_commit.jsonnet b/integration_tests/configs/long_timeout_commit.jsonnet index 2dfe559653..2036a74ee6 100644 --- a/integration_tests/configs/long_timeout_commit.jsonnet +++ b/integration_tests/configs/long_timeout_commit.jsonnet @@ -7,8 +7,5 @@ default { timeout_commit: '15s', }, }, - 'app-config'+: { - 'blocked-addresses': ['crc16z0herz998946wr659lr84c8c556da55dc34hh'], - }, }, } diff --git a/integration_tests/test_mempool.py b/integration_tests/test_mempool.py index b565edf1a0..80d54ba8f5 100644 --- a/integration_tests/test_mempool.py +++ b/integration_tests/test_mempool.py @@ -76,10 +76,3 @@ def test_mempool(cronos_mempool): break wait_for_new_blocks(cli, 1, sleep=0.1) assert len(sended_hash_set) == 0 - - -def test_blocked_address(cronos_mempool): - cli = cronos_mempool.cosmos_cli(0) - rsp = cli.transfer("signer1", cli.address("validator"), "1basecro") - assert rsp["code"] != 0 - assert "signer is blocked" in rsp["raw_log"] From c6642ef7d8400f900d39c5e6873d06c4265b598e Mon Sep 17 00:00:00 2001 From: huangyi Date: Fri, 3 May 2024 16:25:28 +0800 Subject: [PATCH 13/24] fix test --- integration_tests/test_e2ee.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration_tests/test_e2ee.py b/integration_tests/test_e2ee.py index dcfed32fad..ee46fd1406 100644 --- a/integration_tests/test_e2ee.py +++ b/integration_tests/test_e2ee.py @@ -9,8 +9,9 @@ def test_register(cronos: Cronos): cli = cronos.cosmos_cli() pubkey0 = cli.keygen(keyring_name="key0") - rsp = cli.register_e2ee_key(pubkey0 + "malformed", _from="validator") - assert not rsp["code"] + with pytest.raises(AssertionError) as exc: + cli.register_e2ee_key(pubkey0 + "malformed", _from="validator") + assert "malformed recipient" in str(exc.value) assert not cli.query_e2ee_key(cli.address("validator")) @@ -81,7 +82,6 @@ def test_block_list(cronos): # blocked tx don't work with pytest.raises(AssertionError) as exc: cli.transfer(user, cli.address("validator"), "1basetcro") - assert "timed out waiting for event" in str(exc.value) # clear blocklist From 015023d4e4861495c66e7af44ba1f49d91a5e149 Mon Sep 17 00:00:00 2001 From: huangyi Date: Fri, 3 May 2024 17:13:18 +0800 Subject: [PATCH 14/24] fix test --- integration_tests/cosmoscli.py | 12 ++++++++++++ integration_tests/test_e2ee.py | 18 ++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/integration_tests/cosmoscli.py b/integration_tests/cosmoscli.py index aa711080da..e034223f2c 100644 --- a/integration_tests/cosmoscli.py +++ b/integration_tests/cosmoscli.py @@ -237,6 +237,18 @@ def tx_search_rpc(self, criteria: str, order=None): assert "error" not in rsp, rsp["error"] return rsp["result"]["txs"] + def query_account(self, addr, **kwargs): + return json.loads( + self.raw( + "query", + "auth", + "account", + addr, + home=self.data_dir, + **kwargs, + ) + ) + def distribution_commission(self, addr): coin = json.loads( self.raw( diff --git a/integration_tests/test_e2ee.py b/integration_tests/test_e2ee.py index ee46fd1406..a10109c94e 100644 --- a/integration_tests/test_e2ee.py +++ b/integration_tests/test_e2ee.py @@ -79,15 +79,25 @@ def test_block_list(cronos): # normal tx works cli.transfer(cli.address("validator"), user, "1basetcro") - # blocked tx don't work + # blocked tx can be included into mempool + rsp = cli.transfer( + user, cli.address("validator"), "1basetcro", event_query_tx=False + ) + assert rsp["code"] == 0, rsp["raw_log"] + + # but won't be included into block + txhash = rsp["txhash"] with pytest.raises(AssertionError) as exc: - cli.transfer(user, cli.address("validator"), "1basetcro") + cli.event_query_tx_for(txhash) assert "timed out waiting for event" in str(exc.value) + nonce = cli.query_account(user)["base_account"]["sequence"] + # clear blocklist cipherfile.write_text("{}") rsp = cli.store_blocklist(cipherfile, _from="validator") assert rsp["code"] == 0, rsp["raw_log"] - rsp = cli.transfer(user, cli.address("validator"), "1basetcro") - assert rsp["code"] == 0, rsp["raw_log"] + # the blocked tx should be unblocked now + wait_for_new_blocks(cli, 1) + assert nonce + 1 == cli.query_account(user)["base_account"]["sequence"] From 2fee8fab56029565564414247972edd1a8897f5f Mon Sep 17 00:00:00 2001 From: huangyi Date: Fri, 3 May 2024 17:16:30 +0800 Subject: [PATCH 15/24] fix test --- integration_tests/test_e2ee.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration_tests/test_e2ee.py b/integration_tests/test_e2ee.py index a10109c94e..e1018e0f12 100644 --- a/integration_tests/test_e2ee.py +++ b/integration_tests/test_e2ee.py @@ -91,7 +91,7 @@ def test_block_list(cronos): cli.event_query_tx_for(txhash) assert "timed out waiting for event" in str(exc.value) - nonce = cli.query_account(user)["base_account"]["sequence"] + nonce = int(cli.query_account(user)["base_account"]["sequence"]) # clear blocklist cipherfile.write_text("{}") @@ -100,4 +100,4 @@ def test_block_list(cronos): # the blocked tx should be unblocked now wait_for_new_blocks(cli, 1) - assert nonce + 1 == cli.query_account(user)["base_account"]["sequence"] + assert nonce + 1 == int(cli.query_account(user)["base_account"]["sequence"]) From 2d45561ab484da4e5000d5a07cd8d952249f0fcc Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 3 May 2024 17:17:58 +0800 Subject: [PATCH 16/24] fix patch --- integration_tests/configs/broken-cronosd.patch | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/integration_tests/configs/broken-cronosd.patch b/integration_tests/configs/broken-cronosd.patch index 5794e32017..f01f0d29b7 100644 --- a/integration_tests/configs/broken-cronosd.patch +++ b/integration_tests/configs/broken-cronosd.patch @@ -1,15 +1,15 @@ diff --git a/app/app.go b/app/app.go -index 21eab4d..156fad7 100644 +index 75523891..dbe74030 100644 --- a/app/app.go +++ b/app/app.go -@@ -773,6 +773,10 @@ func (app *App) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.R +@@ -1019,6 +1019,10 @@ func (app *App) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.R // EndBlocker application updates every end block func (app *App) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { -+ if ctx.BlockHeight() % 10 == 0 { ++ if ctx.BlockHeight()%10 == 0 { + store := ctx.KVStore(app.keys["cronos"]) + store.Set([]byte("hello"), []byte("world")) + } - return app.mm.EndBlock(ctx, req) - } + rsp := app.mm.EndBlock(ctx, req) + if err := app.RefreshBlockList(ctx); err != nil { From e693ab42028edfb891308de953a917bc121fe6b1 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 3 May 2024 17:19:29 +0800 Subject: [PATCH 17/24] avoid prompt --- integration_tests/cosmoscli.py | 4 ++-- integration_tests/test_rollback.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/integration_tests/cosmoscli.py b/integration_tests/cosmoscli.py index e034223f2c..1e98428ac9 100644 --- a/integration_tests/cosmoscli.py +++ b/integration_tests/cosmoscli.py @@ -1753,8 +1753,8 @@ def store_blocklist(self, data, **kwargs): rsp = self.event_query_tx_for(rsp["txhash"]) return rsp - def rollback(self): - self.raw("rollback", home=self.data_dir) + def rollback(self, **kwargs): + self.raw("rollback", home=self.data_dir, **kwargs) def changeset_dump(self, changeset_dir, **kwargs): default_kwargs = { diff --git a/integration_tests/test_rollback.py b/integration_tests/test_rollback.py index 1ae2ea9ebb..bc38dba8f8 100644 --- a/integration_tests/test_rollback.py +++ b/integration_tests/test_rollback.py @@ -84,7 +84,7 @@ def test_rollback(custom_cronos): supervisorctl(custom_cronos.base_dir / "../tasks.ini", "stop", "cronos_777-1-node2") print("do rollback on node2") - cli2.rollback() + cli2.rollback(keyring_backend="test") print("switch to normal binary") update_node2_cmd(custom_cronos.base_dir, "cronosd", 2) From 1b2abf411a6bdb98a29ff44b7b8dacad4f660505 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 3 May 2024 17:20:17 +0800 Subject: [PATCH 18/24] encrypt clear list --- integration_tests/test_e2ee.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/integration_tests/test_e2ee.py b/integration_tests/test_e2ee.py index e1018e0f12..fbb5d10ce0 100644 --- a/integration_tests/test_e2ee.py +++ b/integration_tests/test_e2ee.py @@ -62,13 +62,8 @@ def test_encrypt_decrypt(cronos): assert cli1.decrypt(cipherfile) == content -def test_block_list(cronos): - gen_validator_identity(cronos) - cli = cronos.cosmos_cli() - - user = cli.address("signer2") - - blocklist = json.dumps({"addresses": [user]}) +def encrypt_to_validators(cli, content): + blocklist = json.dumps(content) plainfile = cli.data_dir / "plaintext" plainfile.write_text(blocklist) cipherfile = cli.data_dir / "ciphertext" @@ -76,6 +71,13 @@ def test_block_list(cronos): rsp = cli.store_blocklist(cipherfile, _from="validator") assert rsp["code"] == 0, rsp["raw_log"] + +def test_block_list(cronos): + gen_validator_identity(cronos) + cli = cronos.cosmos_cli() + user = cli.address("signer2") + encrypt_to_validators(cli, {"addresses": [user]}) + # normal tx works cli.transfer(cli.address("validator"), user, "1basetcro") @@ -94,8 +96,7 @@ def test_block_list(cronos): nonce = int(cli.query_account(user)["base_account"]["sequence"]) # clear blocklist - cipherfile.write_text("{}") - rsp = cli.store_blocklist(cipherfile, _from="validator") + encrypt_to_validators(cli, {}) assert rsp["code"] == 0, rsp["raw_log"] # the blocked tx should be unblocked now From ab2f559b431f00b6a9d5ffe4647dca48db619f08 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 3 May 2024 22:59:14 +0800 Subject: [PATCH 19/24] cleanup --- integration_tests/cosmoscli.py | 18 +++++++++++++----- integration_tests/test_basic.py | 10 +++++----- integration_tests/test_e2ee.py | 4 ++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/integration_tests/cosmoscli.py b/integration_tests/cosmoscli.py index 1e98428ac9..595806f953 100644 --- a/integration_tests/cosmoscli.py +++ b/integration_tests/cosmoscli.py @@ -1790,9 +1790,14 @@ def changeset_ingest_versiondb_sst(self, versiondb_dir, sst_dir, **kwargs): **kwargs, ).decode() - def restore_versiondb(self, height, format=3): + def restore_versiondb(self, height, format=3, **kwargs): return self.raw( - "changeset", "restore-versiondb", height, format, home=self.data_dir + "changeset", + "restore-versiondb", + height, + format, + home=self.data_dir, + **kwargs, ) def dump_snapshot(self, height, tarball, format=3): @@ -1826,24 +1831,26 @@ def list_snapshot(self): items.append(SnapshotItem(int(parts[1]), int(parts[3]), int(parts[5]))) return items - def export_snapshot(self, height): + def export_snapshot(self, height, **kwargs): return self.raw( "snapshots", "export", height=height, home=self.data_dir, + **kwargs, ).decode() - def restore_snapshot(self, height, format=3): + def restore_snapshot(self, height, format=3, **kwargs): return self.raw( "snapshots", "restore", height, format, home=self.data_dir, + **kwargs, ).decode() - def bootstrap_state(self, height=None): + def bootstrap_state(self, height=None, **kwargs): """ bootstrap cometbft state for local state sync """ @@ -1852,6 +1859,7 @@ def bootstrap_state(self, height=None): "bootstrap-state", height=height, home=self.data_dir, + **kwargs, ) def event_query_tx_for(self, hash): diff --git a/integration_tests/test_basic.py b/integration_tests/test_basic.py index d25ac588f8..d558016bfa 100644 --- a/integration_tests/test_basic.py +++ b/integration_tests/test_basic.py @@ -353,7 +353,7 @@ def test_local_statesync(cronos, tmp_path_factory): height -= height % 5 if height not in set(item.height for item in cli0.list_snapshot()): - cli0.export_snapshot(height) + cli0.export_snapshot(height, keyring_backend="test") cli0.dump_snapshot(height, tarball) cronos.supervisorctl("start", "cronos_777-1-node0") @@ -414,12 +414,12 @@ def test_local_statesync(cronos, tmp_path_factory): # restore the states cli.load_snapshot(tarball) print(cli.list_snapshot()) - cli.restore_snapshot(height) - cli.bootstrap_state() - cli.restore_versiondb(height) + cli.restore_snapshot(height, keyring_backend="test") + cli.bootstrap_state(keyring_backend="test") + cli.restore_versiondb(height, keyring_backend="test") with subprocess.Popen( - [cronos.chain_binary, "start", "--home", home], + [cronos.chain_binary, "start", "--home", home, "--keyring-backend", "test"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ): diff --git a/integration_tests/test_e2ee.py b/integration_tests/test_e2ee.py index fbb5d10ce0..54c7de7d60 100644 --- a/integration_tests/test_e2ee.py +++ b/integration_tests/test_e2ee.py @@ -76,6 +76,7 @@ def test_block_list(cronos): gen_validator_identity(cronos) cli = cronos.cosmos_cli() user = cli.address("signer2") + # set blocklist encrypt_to_validators(cli, {"addresses": [user]}) # normal tx works @@ -91,13 +92,12 @@ def test_block_list(cronos): txhash = rsp["txhash"] with pytest.raises(AssertionError) as exc: cli.event_query_tx_for(txhash) - assert "timed out waiting for event" in str(exc.value) + assert "timed out waiting" in str(exc.value) nonce = int(cli.query_account(user)["base_account"]["sequence"]) # clear blocklist encrypt_to_validators(cli, {}) - assert rsp["code"] == 0, rsp["raw_log"] # the blocked tx should be unblocked now wait_for_new_blocks(cli, 1) From 85bbc04d020ff2662047e602755232d9763e974f Mon Sep 17 00:00:00 2001 From: mmsqe Date: Sat, 4 May 2024 09:22:38 +0800 Subject: [PATCH 20/24] add validate --- integration_tests/cosmoscli.py | 1 - integration_tests/test_e2ee.py | 9 +++++++++ x/cronos/types/messages.go | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/integration_tests/cosmoscli.py b/integration_tests/cosmoscli.py index 595806f953..b7fc5f37ca 100644 --- a/integration_tests/cosmoscli.py +++ b/integration_tests/cosmoscli.py @@ -1745,7 +1745,6 @@ def store_blocklist(self, data, **kwargs): data, "-y", home=self.data_dir, - stderr=subprocess.DEVNULL, **kwargs, ) ) diff --git a/integration_tests/test_e2ee.py b/integration_tests/test_e2ee.py index 54c7de7d60..6abc44e61e 100644 --- a/integration_tests/test_e2ee.py +++ b/integration_tests/test_e2ee.py @@ -102,3 +102,12 @@ def test_block_list(cronos): # the blocked tx should be unblocked now wait_for_new_blocks(cli, 1) assert nonce + 1 == int(cli.query_account(user)["base_account"]["sequence"]) + + +def test_invalid_block_list(cronos): + cli = cronos.cosmos_cli() + cipherfile = cli.data_dir / "ciphertext" + cipherfile.write_text("{}") + with pytest.raises(AssertionError) as exc: + cli.store_blocklist(cipherfile, _from="validator") + assert "failed to read header" in str(exc.value) diff --git a/x/cronos/types/messages.go b/x/cronos/types/messages.go index 4981703385..9e506099dc 100644 --- a/x/cronos/types/messages.go +++ b/x/cronos/types/messages.go @@ -1,7 +1,12 @@ package types import ( + "bytes" + + stderrors "errors" + "cosmossdk.io/errors" + "filippo.io/age" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/ethereum/go-ethereum/common" @@ -327,11 +332,24 @@ func NewMsgStoreBlockList(from string, blob []byte) *MsgStoreBlockList { } } +var errDummyIdentity = stderrors.New("dummy") + +type dummyIdentity struct{} + +func (i *dummyIdentity) Unwrap(stanzas []*age.Stanza) ([]byte, error) { + return nil, errDummyIdentity +} + func (msg *MsgStoreBlockList) ValidateBasic() error { _, err := sdk.AccAddressFromBech32(msg.From) if err != nil { return errors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid sender address (%s)", err) } + + _, err = age.Decrypt(bytes.NewBuffer(msg.Blob), new(dummyIdentity)) + if err != nil && err != errDummyIdentity { + return err + } return nil } From db9d98782d84b581f5024272f1d15d043490bc5b Mon Sep 17 00:00:00 2001 From: mmsqe Date: Sat, 4 May 2024 09:31:03 +0800 Subject: [PATCH 21/24] avoid concurrent mutate --- app/proposal.go | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/app/proposal.go b/app/proposal.go index 40646cd374..ed1fa11b2c 100644 --- a/app/proposal.go +++ b/app/proposal.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io" + "sync" "filippo.io/age" @@ -20,30 +21,33 @@ type BlockList struct { type ProposalHandler struct { TxDecoder sdk.TxDecoder Identity age.Identity - Blocklist map[string]struct{} - LastBlockList []byte + blocklist map[string]struct{} + lastBlockList []byte + blockLock sync.RWMutex } func NewProposalHandler(txDecoder sdk.TxDecoder, identity age.Identity) *ProposalHandler { return &ProposalHandler{ TxDecoder: txDecoder, Identity: identity, - Blocklist: make(map[string]struct{}), + blocklist: make(map[string]struct{}), } } func (h *ProposalHandler) SetBlockList(blob []byte) error { + h.blockLock.Lock() + defer h.blockLock.Unlock() + if h.Identity == nil { return nil } - - if bytes.Equal(h.LastBlockList, blob) { + if bytes.Equal(h.lastBlockList, blob) { return nil } - h.LastBlockList = blob + h.lastBlockList = blob if len(blob) == 0 { - h.Blocklist = make(map[string]struct{}) + h.blocklist = make(map[string]struct{}) return nil } @@ -72,7 +76,7 @@ func (h *ProposalHandler) SetBlockList(blob []byte) error { m[addr.String()] = struct{}{} } - h.Blocklist = m + h.blocklist = m return nil } @@ -87,8 +91,10 @@ func (h *ProposalHandler) ValidateTransaction(txBz []byte) error { return fmt.Errorf("tx of type %T does not implement SigVerifiableTx", tx) } + h.blockLock.RLock() + defer h.blockLock.RUnlock() for _, signer := range sigTx.GetSigners() { - if _, ok := h.Blocklist[signer.String()]; ok { + if _, ok := h.blocklist[signer.String()]; ok { return fmt.Errorf("signer is blocked: %s", signer.String()) } } From 09d17359ad8866111692ad2b0a1b47edcb90da47 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Sat, 4 May 2024 10:50:44 +0800 Subject: [PATCH 22/24] Update app/proposal.go Signed-off-by: mmsqe --- app/proposal.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/proposal.go b/app/proposal.go index ed1fa11b2c..5d89fc60a8 100644 --- a/app/proposal.go +++ b/app/proposal.go @@ -44,7 +44,8 @@ func (h *ProposalHandler) SetBlockList(blob []byte) error { if bytes.Equal(h.lastBlockList, blob) { return nil } - h.lastBlockList = blob + h.lastBlockList = make([]byte, len(blob)) + copy(h.lastBlockList, blob) if len(blob) == 0 { h.blocklist = make(map[string]struct{}) From e0ad4065548ba932a1847b889fffaa4054fdd766 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Sat, 4 May 2024 21:07:51 +0800 Subject: [PATCH 23/24] cleanup --- app/proposal.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/proposal.go b/app/proposal.go index 5d89fc60a8..c86f03dcc1 100644 --- a/app/proposal.go +++ b/app/proposal.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "io" - "sync" "filippo.io/age" @@ -23,7 +22,6 @@ type ProposalHandler struct { Identity age.Identity blocklist map[string]struct{} lastBlockList []byte - blockLock sync.RWMutex } func NewProposalHandler(txDecoder sdk.TxDecoder, identity age.Identity) *ProposalHandler { @@ -35,12 +33,10 @@ func NewProposalHandler(txDecoder sdk.TxDecoder, identity age.Identity) *Proposa } func (h *ProposalHandler) SetBlockList(blob []byte) error { - h.blockLock.Lock() - defer h.blockLock.Unlock() - if h.Identity == nil { return nil } + if bytes.Equal(h.lastBlockList, blob) { return nil } @@ -92,8 +88,6 @@ func (h *ProposalHandler) ValidateTransaction(txBz []byte) error { return fmt.Errorf("tx of type %T does not implement SigVerifiableTx", tx) } - h.blockLock.RLock() - defer h.blockLock.RUnlock() for _, signer := range sigTx.GetSigners() { if _, ok := h.blocklist[signer.String()]; ok { return fmt.Errorf("signer is blocked: %s", signer.String()) From 30d327cc38e1061502526852c5a6a4cde861529a Mon Sep 17 00:00:00 2001 From: huangyi Date: Mon, 6 May 2024 00:16:46 +0800 Subject: [PATCH 24/24] proto-gen --- x/cronos/types/tx.pb.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x/cronos/types/tx.pb.go b/x/cronos/types/tx.pb.go index bd1874ea78..e5617a8b93 100644 --- a/x/cronos/types/tx.pb.go +++ b/x/cronos/types/tx.pb.go @@ -800,6 +800,7 @@ type MsgClient interface { UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) // UpdatePermissions defines a method to update cronos admins permissions UpdatePermissions(ctx context.Context, in *MsgUpdatePermissions, opts ...grpc.CallOption) (*MsgUpdatePermissionsResponse, error) + // StoreBlockList StoreBlockList(ctx context.Context, in *MsgStoreBlockList, opts ...grpc.CallOption) (*MsgStoreBlockListResponse, error) } @@ -890,6 +891,7 @@ type MsgServer interface { UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) // UpdatePermissions defines a method to update cronos admins permissions UpdatePermissions(context.Context, *MsgUpdatePermissions) (*MsgUpdatePermissionsResponse, error) + // StoreBlockList StoreBlockList(context.Context, *MsgStoreBlockList) (*MsgStoreBlockListResponse, error) }