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

fix: Improve gentx validation & error messages #11500

Merged
merged 14 commits into from Mar 31, 2022
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Features

* (x/genutil) [\#11500](https://github.com/cosmos/cosmos-sdk/pull/11500) Fix GenTx validation and adjust error messages
* [\#11430](https://github.com/cosmos/cosmos-sdk/pull/11430) Introduce a new `grpc-only` flag, such that when enabled, will start the node in a query-only mode. Note, gRPC MUST be enabled with this flag.
* (x/upgrade) [\#11116](https://github.com/cosmos/cosmos-sdk/pull/11116) `MsgSoftwareUpgrade` and has been added to support v1beta2 msgs-based gov proposals.
* (x/bank) [\#11417](https://github.com/cosmos/cosmos-sdk/pull/11417) Introduce a new `SpendableBalances` gRPC query that retrieves an account's total (paginated) spendable balances.
Expand Down
4 changes: 2 additions & 2 deletions x/genutil/collect.go
Expand Up @@ -111,8 +111,8 @@ func CollectTxs(cdc codec.JSONCodec, txJSONDecoder sdk.TxDecoder, moniker, genTx
return appGenTxs, persistentPeers, err
}

var genTx sdk.Tx
if genTx, err = txJSONDecoder(jsonRawTx); err != nil {
genTx, err := types.ValidateAndGetGenTx(jsonRawTx, txJSONDecoder)
if err != nil {
return appGenTxs, persistentPeers, err
}

Expand Down
6 changes: 3 additions & 3 deletions x/genutil/gentx.go
Expand Up @@ -100,17 +100,17 @@ func DeliverGenTxs(
for _, genTx := range genTxs {
tx, err := txEncodingConfig.TxJSONDecoder()(genTx)
if err != nil {
panic(err)
return nil, fmt.Errorf("failed to decode GenTx '%s': %s", genTx, err)
}

bz, err := txEncodingConfig.TxEncoder()(tx)
if err != nil {
panic(err)
return nil, fmt.Errorf("failed to encode GenTx '%s': %s", genTx, err)
}

res := deliverTx(abci.RequestDeliverTx{Tx: bz})
if !res.IsOK() {
panic(res.Log)
return nil, fmt.Errorf("failed to execute DelverTx for '%s': %s", genTx, res.Log)
}
}

Expand Down
12 changes: 6 additions & 6 deletions x/genutil/gentx_test.go
Expand Up @@ -269,12 +269,12 @@ func (suite *GenTxTestSuite) TestDeliverGenTxs() {
)
})
} else {
suite.Require().Panics(func() {
genutil.DeliverGenTxs(
suite.ctx, genTxs, suite.app.StakingKeeper, suite.app.BaseApp.DeliverTx,
suite.encodingConfig.TxConfig,
)
})
_, err := genutil.DeliverGenTxs(
suite.ctx, genTxs, suite.app.StakingKeeper, suite.app.BaseApp.DeliverTx,
suite.encodingConfig.TxConfig,
)

suite.Require().Error(err)
}
})
}
Expand Down
41 changes: 26 additions & 15 deletions x/genutil/types/genesis_state.go
Expand Up @@ -2,7 +2,6 @@ package types

import (
"encoding/json"
"errors"
"fmt"

tmos "github.com/tendermint/tendermint/libs/os"
Expand Down Expand Up @@ -96,24 +95,36 @@ func GenesisStateFromGenFile(genFile string) (genesisState map[string]json.RawMe

// ValidateGenesis validates GenTx transactions
func ValidateGenesis(genesisState *GenesisState, txJSONDecoder sdk.TxDecoder) error {
for i, genTx := range genesisState.GenTxs {
var tx sdk.Tx
tx, err := txJSONDecoder(genTx)
for _, genTx := range genesisState.GenTxs {
_, err := ValidateAndGetGenTx(genTx, txJSONDecoder)
if err != nil {
return err
}
}
return nil
}

msgs := tx.GetMsgs()
if len(msgs) != 1 {
return errors.New(
"must provide genesis Tx with exactly 1 CreateValidator message")
}
// ValidateAndGetGenTx validates the genesis transaction and returns GenTx if valid
// it cannot verify the signature as it is stateless validation
func ValidateAndGetGenTx(genTx json.RawMessage, txJSONDecoder sdk.TxDecoder) (sdk.Tx, error) {
anilcse marked this conversation as resolved.
Show resolved Hide resolved
tx, err := txJSONDecoder(genTx)
if err != nil {
return tx, fmt.Errorf("failed to decode gentx: %s, error: %s", genTx, err)
}

// TODO: abstract back to staking
if _, ok := msgs[0].(*stakingtypes.MsgCreateValidator); !ok {
return fmt.Errorf(
"genesis transaction %v does not contain a MsgCreateValidator", i)
}
msgs := tx.GetMsgs()
if len(msgs) != 1 {
return tx, fmt.Errorf("unexpected number of GenTx messages; got: %d, expected: 1", len(msgs))
}
return nil

// TODO: abstract back to staking
if _, ok := msgs[0].(*stakingtypes.MsgCreateValidator); !ok {
return tx, fmt.Errorf("unexpected GenTx message type; expected: MsgCreateValidator, got: %T", msgs[0])
}

if err := msgs[0].ValidateBasic(); err != nil {
return tx, fmt.Errorf("invalid GenTx '%s': %s", msgs[0], err)
}

return tx, nil
}