Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Problem: e2ee module not up to date #1610

Merged
merged 17 commits into from
Sep 27, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* [#1592](https://github.com/crypto-org-chain/cronos/pull/1592) Change the default parallelism of the block-stm to minimum between GOMAXPROCS and NumCPU
* [#1600](https://github.com/crypto-org-chain/cronos/pull/1600) Update ethermint to avoid unnecessary block result in header related api call.
* [#1606](https://github.com/crypto-org-chain/cronos/pull/1606) Fix pebbledb support.
* [#1610](https://github.com/crypto-org-chain/cronos/pull/1610) Sync e2ee module with v1.3.x branch.

### Bug Fixes

Expand Down
45 changes: 41 additions & 4 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
stdruntime "runtime"
"sort"

"filippo.io/age"

abci "github.com/cometbft/cometbft/abci/types"
tmos "github.com/cometbft/cometbft/libs/os"
dbm "github.com/cosmos/cosmos-db"
Expand Down Expand Up @@ -159,6 +161,7 @@ import (
cronosprecompiles "github.com/crypto-org-chain/cronos/v2/x/cronos/keeper/precompiles"
"github.com/crypto-org-chain/cronos/v2/x/cronos/middleware"
cronostypes "github.com/crypto-org-chain/cronos/v2/x/cronos/types"
e2eekeyring "github.com/crypto-org-chain/cronos/v2/x/e2ee/keyring"

e2ee "github.com/crypto-org-chain/cronos/v2/x/e2ee"
e2eekeeper "github.com/crypto-org-chain/cronos/v2/x/e2ee/keeper"
Expand Down Expand Up @@ -360,23 +363,57 @@ func New(
cdc := encodingConfig.Amino
txConfig := encodingConfig.TxConfig
interfaceRegistry := encodingConfig.InterfaceRegistry

txDecoder := txConfig.TxDecoder()
eip712.SetEncodingConfig(encodingConfig)

homePath := cast.ToString(appOpts.Get(flags.FlagHome))
var identity age.Identity
{
if cast.ToString(appOpts.Get("mode")) == "validator" {
krBackend := cast.ToString(appOpts.Get(flags.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)
}
yihuang marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
yihuang marked this conversation as resolved.
Show resolved Hide resolved

var mpool mempool.Mempool
if maxTxs := cast.ToInt(appOpts.Get(server.FlagMempoolMaxTxs)); maxTxs >= 0 {
// NOTE we use custom transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx
// Setup Mempool and Proposal Handlers
mempool := mempool.NewPriorityMempool(mempool.PriorityNonceMempoolConfig[int64]{
mpool = mempool.NewPriorityMempool(mempool.PriorityNonceMempoolConfig[int64]{
TxPriority: mempool.NewDefaultTxPriority(),
SignerExtractor: evmapp.NewEthSignerExtractionAdapter(mempool.NewDefaultSignerExtractionAdapter()),
MaxTx: maxTxs,
})
baseAppOptions = append(baseAppOptions, baseapp.SetMempool(mempool))
} else {
mpool = mempool.NoOpMempool{}
}
blockProposalHandler := NewProposalHandler(txDecoder, identity)
baseAppOptions = append(baseAppOptions, func(app *baseapp.BaseApp) {
app.SetMempool(mpool)

// Re-use the default prepare proposal handler, extend the transaction validation logic
defaultProposalHandler := baseapp.NewDefaultProposalHandler(mpool, app)
defaultProposalHandler.SetTxSelector(NewExtTxSelector(
baseapp.NewDefaultTxSelector(),
txDecoder,
blockProposalHandler.ValidateTransaction,
))
})
yihuang marked this conversation as resolved.
Show resolved Hide resolved

blockSTMEnabled := cast.ToString(appOpts.Get(srvflags.EVMBlockExecutor)) == "block-stm"

homePath := cast.ToString(appOpts.Get(flags.FlagHome))
var cacheSize int
if !blockSTMEnabled {
// only enable memiavl cache if block-stm is not enabled, because it's not concurrency-safe.
Expand Down
171 changes: 171 additions & 0 deletions app/proposal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package app

import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"

"filippo.io/age"

"cosmossdk.io/core/address"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/signing"
)

type BlockList struct {
Addresses []string `mapstructure:"addresses"`
}

var _ baseapp.TxSelector = &ExtTxSelector{}

// ExtTxSelector extends a baseapp.TxSelector with extra tx validation method
type ExtTxSelector struct {
baseapp.TxSelector
TxDecoder sdk.TxDecoder
ValidateTx func(sdk.Tx) error
}

func NewExtTxSelector(parent baseapp.TxSelector, txDecoder sdk.TxDecoder, validateTx func(sdk.Tx) error) *ExtTxSelector {
return &ExtTxSelector{
TxSelector: parent,
TxDecoder: txDecoder,
ValidateTx: validateTx,
}
}

func (ts *ExtTxSelector) SelectTxForProposal(ctx context.Context, maxTxBytes, maxBlockGas uint64, memTx sdk.Tx, txBz []byte, gasWanted uint64) bool {
var err error
if memTx == nil {
memTx, err = ts.TxDecoder(txBz)
if err != nil {
return false

Check warning on line 45 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L40-L45

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

if err := ts.ValidateTx(memTx); err != nil {
return false

Check warning on line 50 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L49-L50

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

// don't pass `memTx` to parent selector so it don't check tx gas wanted against block gas limit,
// it conflicts with the max-tx-gas-wanted logic.
return ts.TxSelector.SelectTxForProposal(ctx, maxTxBytes, maxBlockGas, nil, txBz, gasWanted)

Check warning on line 55 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L55

Added line #L55 was not covered by tests
}

type ProposalHandler struct {
TxDecoder sdk.TxDecoder
// Identity is nil if it's not a validator node
Identity age.Identity
blocklist map[string]struct{}
lastBlockList []byte
addressCodec address.Codec
}

func NewProposalHandler(txDecoder sdk.TxDecoder, identity age.Identity) *ProposalHandler {
return &ProposalHandler{
TxDecoder: txDecoder,
Identity: identity,
blocklist: make(map[string]struct{}),
yihuang marked this conversation as resolved.
Show resolved Hide resolved
}
}

// SetBlockList don't fail if the identity is not set or the block list is empty.
func (h *ProposalHandler) SetBlockList(blob []byte) error {
if h.Identity == nil {
return nil

Check warning on line 78 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L76-L78

Added lines #L76 - L78 were not covered by tests
}

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

Check warning on line 82 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L81-L82

Added lines #L81 - L82 were not covered by tests
}
h.lastBlockList = make([]byte, len(blob))
copy(h.lastBlockList, blob)

Check warning on line 85 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L84-L85

Added lines #L84 - L85 were not covered by tests

if len(blob) == 0 {
h.blocklist = make(map[string]struct{})
return nil

Check warning on line 89 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L87-L89

Added lines #L87 - L89 were not covered by tests
}

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

Check warning on line 94 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L92-L94

Added lines #L92 - L94 were not covered by tests
}

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

Check warning on line 99 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L97-L99

Added lines #L97 - L99 were not covered by tests
}

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

Check warning on line 104 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L102-L104

Added lines #L102 - L104 were not covered by tests
}

// convert to map
m := make(map[string]struct{}, len(blocklist.Addresses))
for _, s := range blocklist.Addresses {
addr, err := h.addressCodec.StringToBytes(s)
if err != nil {
return fmt.Errorf("invalid bech32 address: %s, err: %w", s, err)

Check warning on line 112 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L108-L112

Added lines #L108 - L112 were not covered by tests
}
encoded, err := h.addressCodec.BytesToString(addr)
if err != nil {
return fmt.Errorf("invalid bech32 address: %s, err: %w", s, err)

Check warning on line 116 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L114-L116

Added lines #L114 - L116 were not covered by tests
}
m[encoded] = struct{}{}

Check warning on line 118 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L118

Added line #L118 was not covered by tests
}

h.blocklist = m
return nil

Check warning on line 122 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L121-L122

Added lines #L121 - L122 were not covered by tests
}

func (h *ProposalHandler) ValidateTransaction(tx sdk.Tx) error {
sigTx, ok := tx.(signing.SigVerifiableTx)
if !ok {
return fmt.Errorf("tx of type %T does not implement SigVerifiableTx", tx)

Check warning on line 128 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L125-L128

Added lines #L125 - L128 were not covered by tests
}

signers, err := sigTx.GetSigners()
if err != nil {
return err

Check warning on line 133 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L131-L133

Added lines #L131 - L133 were not covered by tests
}
for _, signer := range signers {
encoded, err := h.addressCodec.BytesToString(signer)
if err != nil {
return fmt.Errorf("invalid bech32 address: %s, err: %w", signer, err)

Check warning on line 138 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L135-L138

Added lines #L135 - L138 were not covered by tests
yihuang marked this conversation as resolved.
Show resolved Hide resolved
}
if _, ok := h.blocklist[encoded]; ok {
return fmt.Errorf("signer is blocked: %s", encoded)

Check warning on line 141 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L140-L141

Added lines #L140 - L141 were not covered by tests
}
}
return nil

Check warning on line 144 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L144

Added line #L144 was not covered by tests
}

func (h *ProposalHandler) ProcessProposalHandler() sdk.ProcessProposalHandler {
return func(ctx sdk.Context, req *abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) {
for _, txBz := range req.Txs {
memTx, err := h.TxDecoder(txBz)
if err != nil {
return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil

Check warning on line 152 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L147-L152

Added lines #L147 - L152 were not covered by tests
}

if err := h.ValidateTransaction(memTx); err != nil {
return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil

Check warning on line 156 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L155-L156

Added lines #L155 - L156 were not covered by tests
}
}

return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil

Check warning on line 160 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L160

Added line #L160 was not covered by tests
}
}

// noneIdentity is a dummy identity which postpone the failure to the decryption time
type noneIdentity struct{}

var _ age.Identity = noneIdentity{}

func (noneIdentity) Unwrap([]*age.Stanza) ([]byte, error) {
return nil, age.ErrIncorrectIdentity

Check warning on line 170 in app/proposal.go

View check run for this annotation

Codecov / codecov/patch

app/proposal.go#L169-L170

Added lines #L169 - L170 were not covered by tests
}
Loading
Loading