Skip to content

Commit

Permalink
Problem: e2ee module is not backported
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: yihuang <[email protected]>

* Update x/e2ee/types/codec.go

Co-authored-by: mmsqe <[email protected]>
Signed-off-by: yihuang <[email protected]>

---------

Signed-off-by: yihuang <[email protected]>
Co-authored-by: mmsqe <[email protected]>

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 <[email protected]>

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 <[email protected]>

fix lint

---------

Signed-off-by: yihuang <[email protected]>
Co-authored-by: yihuang <[email protected]>
Co-authored-by: yihuang <[email protected]>

Problem: no efficient batch query for encryption keys (#1415)

Update CHANGELOG.md

Signed-off-by: yihuang <[email protected]>

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 c2700f5.

reject on err

fix prepare proposal

fix proto lint
  • Loading branch information
yihuang committed May 3, 2024
1 parent 4584c0a commit 3258b5b
Show file tree
Hide file tree
Showing 57 changed files with 5,053 additions and 127 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/proto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)

# ------
Expand All @@ -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
Expand Down
90 changes: 78 additions & 12 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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"
)
Expand Down Expand Up @@ -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{},
Expand All @@ -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,
}
Expand Down Expand Up @@ -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
Expand All @@ -371,6 +385,8 @@ type App struct {
configurator module.Configurator

qms storetypes.MultiStore

blockProposalHandler *ProposalHandler
}

// New returns a reference to an initialized chain.
Expand All @@ -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...)

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

Expand Down Expand Up @@ -737,6 +781,7 @@ func New(
vestingtypes.ModuleName,
cronostypes.ModuleName,
consensusparamtypes.ModuleName,
e2eetypes.ModuleName,
}
endBlockersOrder := []string{
crisistypes.ModuleName, govtypes.ModuleName, stakingtypes.ModuleName,
Expand All @@ -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.
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

path flow from Begin/EndBlock to a panic call
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
Expand Down
117 changes: 117 additions & 0 deletions app/proposal.go
Original file line number Diff line number Diff line change
@@ -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

Check warning on line 37 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L35-L37

Added lines #L35 - L37 were not covered by tests
}

if bytes.Equal(h.LastBlockList, blob) {
return nil

Check warning on line 41 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L40-L41

Added lines #L40 - L41 were not covered by tests
}
h.LastBlockList = blob

Check warning on line 43 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L43

Added line #L43 was not covered by tests

reader, err := age.Decrypt(bytes.NewBuffer(blob), h.Identity)
if err != nil {
return err

Check warning on line 47 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L45-L47

Added lines #L45 - L47 were not covered by tests
}

data, err := io.ReadAll(reader)
if err != nil {
return err

Check warning on line 52 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L50-L52

Added lines #L50 - L52 were not covered by tests
}

var blocklist BlockList
if err := json.Unmarshal(data, &blocklist); err != nil {
return err

Check warning on line 57 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L55-L57

Added lines #L55 - L57 were not covered by tests
}

// 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)

Check warning on line 65 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L61-L65

Added lines #L61 - L65 were not covered by tests
}
m[addr.String()] = struct{}{}

Check warning on line 67 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L67

Added line #L67 was not covered by tests
}

h.Blocklist = m
return nil

Check warning on line 71 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L70-L71

Added lines #L70 - L71 were not covered by tests
}

func (h *ProposalHandler) ValidateTransaction(txBz []byte) error {
tx, err := h.TxDecoder(txBz)
if err != nil {
return err

Check warning on line 77 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L74-L77

Added lines #L74 - L77 were not covered by tests
}

sigTx, ok := tx.(signing.SigVerifiableTx)
if !ok {
return fmt.Errorf("tx of type %T does not implement SigVerifiableTx", tx)

Check warning on line 82 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L80-L82

Added lines #L80 - L82 were not covered by tests
}

for _, signer := range sigTx.GetSigners() {
if _, ok := h.Blocklist[signer.String()]; ok {
return fmt.Errorf("signer is blocked: %s", signer.String())

Check warning on line 87 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L85-L87

Added lines #L85 - L87 were not covered by tests
}
}
return nil

Check warning on line 90 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L90

Added line #L90 was not covered by tests
}

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

Check warning on line 98 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L95-L98

Added lines #L95 - L98 were not covered by tests
}
txs = append(txs, txBz)

Check warning on line 100 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L100

Added line #L100 was not covered by tests
}

return abci.ResponsePrepareProposal{Txs: txs}

Check warning on line 103 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L103

Added line #L103 was not covered by tests
}
}

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}

Check warning on line 111 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L109-L111

Added lines #L109 - L111 were not covered by tests
}
}

return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}

Check warning on line 115 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L115

Added line #L115 was not covered by tests
}
}
Loading

0 comments on commit 3258b5b

Please sign in to comment.