Migrate {x/auth, x/gov, x/staking} missing CLI queries to proto (#6994)

* Fix error code

* Fix decoder

* Fix typo

* Fix decode

* refactor

* Migrate SearchTxsResult to proto

* fix MarkEventsToIndex

* lint++

* Fix output

* Add QueryTxCmd cli test

* Add fmt

* Put txBuilder in types/tx

* Add GetAnyTx in TxBuilder

* Add new IsAnyTx

* Rename to IntoAny

* Fix bug

* fmt

Co-authored-by: Marie <marie.gauthier63@gmail.com>

* Fix ibc CLI to use proto

* Fix any MarshalJSON

* Fix test

* Make tx.Tx implement sdk.Tx

* Register sdk.Tx

* Fix lint

* Allow DefaultJSONTxEncoder to take tx.Tx

* refactor

* Rename variable

* remove fmt

Co-authored-by: Anil Kumar Kammari <anil@vitwit.com>
Co-authored-by: Alexander Bezobchuk <alexanderbez@users.noreply.github.com>
Co-authored-by: Aleksandr Bezobchuk <aleks.bezobchuk@gmail.com>
Co-authored-by: Amaury Martiny <amaury.martiny@protonmail.com>
Co-authored-by: Marie <marie.gauthier63@gmail.com>
This commit is contained in:
SaReN
2020-09-10 18:26:47 +00:00
committed by GitHub
co-authored by Marie Anil Kumar Kammari Alexander Bezobchuk Aleksandr Bezobchuk Amaury Martiny
parent d84296a5fc
commit b2348180b8
26 changed files with 758 additions and 258 deletions
+41 -2
View File
@@ -8,8 +8,6 @@ import (
"strings"
"testing"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
tmcrypto "github.com/tendermint/tendermint/crypto"
@@ -18,6 +16,7 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
codec2 "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
@@ -165,6 +164,46 @@ func (s *IntegrationTestSuite) TestCLISignBatch() {
s.Require().Error(err)
}
func (s *IntegrationTestSuite) TestCLITxQueryCmd() {
val := s.network.Validators[0]
var txHash string
s.Run("bank send tx", func() {
clientCtx := val.ClientCtx
bz, err := bankcli.MsgSendExec(clientCtx, val.Address, val.Address, sdk.NewCoins(
sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(10)),
sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)),
), []string{
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
}...)
var txRes sdk.TxResponse
s.Require().NoError(err)
s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(bz.Bytes(), &txRes), bz.String())
txHash = txRes.TxHash
s.Require().Equal(uint32(0), txRes.Code)
})
s.network.WaitForNextBlock()
s.Run("test QueryTxCmd", func() {
cmd := authcli.QueryTxCmd()
args := []string{
txHash,
}
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, args)
s.Require().NoError(err)
var tx sdk.TxResponse
s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &tx))
})
}
func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
val1 := s.network.Validators[0]
+1 -7
View File
@@ -167,13 +167,7 @@ $ %s query txs --%s 'message.sender=cosmos1...&message.action=withdraw_delegator
return err
}
output, err := clientCtx.LegacyAmino.MarshalJSON(txs)
if err != nil {
return err
}
fmt.Println(string(output))
return nil
return clientCtx.PrintOutput(txs)
},
}
+20 -15
View File
@@ -3,15 +3,15 @@ package client
import (
"encoding/hex"
"errors"
"fmt"
"strings"
"time"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
// QueryTxsByEvents performs a search for transactions for a given set of events
@@ -53,14 +53,14 @@ func QueryTxsByEvents(clientCtx client.Context, events []string, page, limit int
return nil, err
}
txs, err := formatTxResults(clientCtx.LegacyAmino, resTxs.Txs, resBlocks)
txs, err := formatTxResults(clientCtx.TxConfig, resTxs.Txs, resBlocks)
if err != nil {
return nil, err
}
result := sdk.NewSearchTxsResult(resTxs.TotalCount, len(txs), page, limit, txs)
result := sdk.NewSearchTxsResult(uint64(resTxs.TotalCount), uint64(len(txs)), uint64(page), uint64(limit), txs)
return &result, nil
return result, nil
}
// QueryTx queries for a single transaction by a hash string in hex format. An
@@ -88,7 +88,7 @@ func QueryTx(clientCtx client.Context, hashHexStr string) (*sdk.TxResponse, erro
return nil, err
}
out, err := formatTxResult(clientCtx.LegacyAmino, resTx, resBlocks[resTx.Height])
out, err := formatTxResult(clientCtx.TxConfig, resTx, resBlocks[resTx.Height])
if err != nil {
return out, err
}
@@ -97,11 +97,11 @@ func QueryTx(clientCtx client.Context, hashHexStr string) (*sdk.TxResponse, erro
}
// formatTxResults parses the indexed txs into a slice of TxResponse objects.
func formatTxResults(cdc *codec.LegacyAmino, resTxs []*ctypes.ResultTx, resBlocks map[int64]*ctypes.ResultBlock) ([]*sdk.TxResponse, error) {
func formatTxResults(txConfig client.TxConfig, resTxs []*ctypes.ResultTx, resBlocks map[int64]*ctypes.ResultBlock) ([]*sdk.TxResponse, error) {
var err error
out := make([]*sdk.TxResponse, len(resTxs))
for i := range resTxs {
out[i], err = formatTxResult(cdc, resTxs[i], resBlocks[resTxs[i].Height])
out[i], err = formatTxResult(txConfig, resTxs[i], resBlocks[resTxs[i].Height])
if err != nil {
return nil, err
}
@@ -132,22 +132,27 @@ func getBlocksForTxResults(clientCtx client.Context, resTxs []*ctypes.ResultTx)
return resBlocks, nil
}
func formatTxResult(cdc *codec.LegacyAmino, resTx *ctypes.ResultTx, resBlock *ctypes.ResultBlock) (*sdk.TxResponse, error) {
tx, err := parseTx(cdc, resTx.Tx)
func formatTxResult(txConfig client.TxConfig, resTx *ctypes.ResultTx, resBlock *ctypes.ResultBlock) (*sdk.TxResponse, error) {
anyTx, err := parseTx(txConfig, resTx.Tx)
if err != nil {
return nil, err
}
return sdk.NewResponseResultTx(resTx, tx, resBlock.Block.Time.Format(time.RFC3339)), nil
return sdk.NewResponseResultTx(resTx, anyTx.AsAny(), resBlock.Block.Time.Format(time.RFC3339)), nil
}
func parseTx(cdc *codec.LegacyAmino, txBytes []byte) (sdk.Tx, error) {
var tx types.StdTx
func parseTx(txConfig client.TxConfig, txBytes []byte) (codectypes.IntoAny, error) {
var tx sdk.Tx
err := cdc.UnmarshalBinaryBare(txBytes, &tx)
tx, err := txConfig.TxDecoder()(txBytes)
if err != nil {
return nil, err
}
return tx, nil
anyTx, ok := tx.(codectypes.IntoAny)
if !ok {
return nil, fmt.Errorf("tx cannot be packed into Any")
}
return anyTx, nil
}
+8 -80
View File
@@ -1,8 +1,6 @@
package tx
import (
"fmt"
"github.com/gogo/protobuf/proto"
"github.com/tendermint/tendermint/crypto"
@@ -10,7 +8,6 @@ import (
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
@@ -44,6 +41,7 @@ var (
_ client.TxBuilder = &wrapper{}
_ ante.HasExtensionOptionsTx = &wrapper{}
_ ExtensionOptionsTxBuilder = &wrapper{}
_ codectypes.IntoAny = &wrapper{}
)
// ExtensionOptionsTxBuilder defines a TxBuilder that can also set extensions.
@@ -67,71 +65,11 @@ func newBuilder(pubkeyCodec types.PublicKeyCodec) *wrapper {
}
func (w *wrapper) GetMsgs() []sdk.Msg {
if w.tx == nil || w.tx.Body == nil {
return nil
}
anys := w.tx.Body.Messages
res := make([]sdk.Msg, len(anys))
for i, any := range anys {
msg := any.GetCachedValue().(sdk.Msg)
res[i] = msg
}
return res
return w.tx.GetMsgs()
}
// MaxGasWanted defines the max gas allowed.
const MaxGasWanted = uint64((1 << 63) - 1)
func (w *wrapper) ValidateBasic() error {
theTx := w.tx
if theTx == nil {
return fmt.Errorf("bad Tx")
}
body := w.tx.Body
if body == nil {
return fmt.Errorf("missing TxBody")
}
authInfo := w.tx.AuthInfo
if authInfo == nil {
return fmt.Errorf("missing AuthInfo")
}
fee := authInfo.Fee
if fee == nil {
return fmt.Errorf("missing fee")
}
if fee.GasLimit > MaxGasWanted {
return sdkerrors.Wrapf(
sdkerrors.ErrInvalidRequest,
"invalid gas supplied; %d > %d", fee.GasLimit, MaxGasWanted,
)
}
if fee.Amount.IsAnyNegative() {
return sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFee,
"invalid fee provided: %s", fee.Amount,
)
}
sigs := theTx.Signatures
if len(sigs) == 0 {
return sdkerrors.ErrNoSignatures
}
if len(sigs) != len(w.GetSigners()) {
return sdkerrors.Wrapf(
sdkerrors.ErrUnauthorized,
"wrong number of signers; expected %d, got %d", w.GetSigners(), len(sigs),
)
}
return nil
return w.tx.ValidateBasic()
}
func (w *wrapper) getBodyBytes() []byte {
@@ -167,19 +105,7 @@ func (w *wrapper) getAuthInfoBytes() []byte {
}
func (w *wrapper) GetSigners() []sdk.AccAddress {
var signers []sdk.AccAddress
seen := map[string]bool{}
for _, msg := range w.GetMsgs() {
for _, addr := range msg.GetSigners() {
if !seen[addr.String()] {
signers = append(signers, addr)
seen[addr.String()] = true
}
}
}
return signers
return w.tx.GetSigners()
}
func (w *wrapper) GetPubKeys() []crypto.PubKey {
@@ -358,8 +284,10 @@ func (w *wrapper) GetTx() authsigning.Tx {
}
// GetProtoTx returns the tx as a proto.Message.
func (w *wrapper) GetProtoTx() *tx.Tx {
return w.tx
func (w *wrapper) AsAny() *codectypes.Any {
// We're sure here that w.tx is a proto.Message, so this will call
// codectypes.NewAnyWithValue under the hood.
return codectypes.UnsafePackAny(w.tx)
}
// WrapTx creates a TxBuilder wrapper around a tx.Tx proto message.
+2 -2
View File
@@ -201,10 +201,10 @@ func TestBuilderValidateBasic(t *testing.T) {
require.NoError(t, err)
// gas limit too high
txBuilder.SetGasLimit(MaxGasWanted + 1)
txBuilder.SetGasLimit(txtypes.MaxGasWanted + 1)
err = txBuilder.ValidateBasic()
require.Error(t, err)
txBuilder.SetGasLimit(MaxGasWanted - 1)
txBuilder.SetGasLimit(txtypes.MaxGasWanted - 1)
err = txBuilder.ValidateBasic()
require.NoError(t, err)
+15 -9
View File
@@ -6,13 +6,13 @@ import (
"github.com/gogo/protobuf/proto"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/types"
sdk "github.com/cosmos/cosmos-sdk/types"
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
)
// DefaultTxEncoder returns a default protobuf TxEncoder using the provided Marshaler
func DefaultTxEncoder() types.TxEncoder {
return func(tx types.Tx) ([]byte, error) {
func DefaultTxEncoder() sdk.TxEncoder {
return func(tx sdk.Tx) ([]byte, error) {
txWrapper, ok := tx.(*wrapper)
if !ok {
return nil, fmt.Errorf("expected %T, got %T", &wrapper{}, tx)
@@ -28,14 +28,20 @@ func DefaultTxEncoder() types.TxEncoder {
}
}
// DefaultTxEncoder returns a default protobuf JSON TxEncoder using the provided Marshaler
func DefaultJSONTxEncoder() types.TxEncoder {
return func(tx types.Tx) ([]byte, error) {
// DefaultJSONTxEncoder returns a default protobuf JSON TxEncoder using the provided Marshaler.
func DefaultJSONTxEncoder() sdk.TxEncoder {
return func(tx sdk.Tx) ([]byte, error) {
txWrapper, ok := tx.(*wrapper)
if !ok {
return nil, fmt.Errorf("expected %T, got %T", &wrapper{}, tx)
if ok {
return codec.ProtoMarshalJSON(txWrapper.tx)
}
return codec.ProtoMarshalJSON(txWrapper.tx)
protoTx, ok := tx.(*txtypes.Tx)
if ok {
return codec.ProtoMarshalJSON(protoTx)
}
return nil, fmt.Errorf("expected %T, got %T", &wrapper{}, tx)
}
}
-7
View File
@@ -6,7 +6,6 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
)
@@ -26,12 +25,6 @@ func (s *StdTxBuilder) GetTx() authsigning.Tx {
return s.StdTx
}
// GetProtoTx implements TxBuilder.GetProtoTx
func (s *StdTxBuilder) GetProtoTx() *txtypes.Tx {
// Stdtx isn't a proto.Message
return nil
}
// SetMsgs implements TxBuilder.SetMsgs
func (s *StdTxBuilder) SetMsgs(msgs ...sdk.Msg) error {
s.Msgs = msgs
+9 -1
View File
@@ -133,7 +133,10 @@ func CountSubKeys(pub crypto.PubKey) int {
// DEPRECATED
// ---------------------------------------------------------------------------
var _ sdk.Tx = (*StdTx)(nil)
var (
_ sdk.Tx = (*StdTx)(nil)
_ codectypes.IntoAny = (*StdTx)(nil)
)
// StdTx is the legacy transaction format for wrapping a Msg with Fee and Signatures.
// It only works with Amino, please prefer the new protobuf Tx in types/tx.
@@ -189,6 +192,11 @@ func (tx StdTx) ValidateBasic() error {
return nil
}
// AsAny implements IntoAny.AsAny.
func (tx *StdTx) AsAny() *codectypes.Any {
return codectypes.UnsafePackAny(tx)
}
// GetSigners returns the addresses that must sign the transaction.
// Addresses are returned in a deterministic order.
// They are accumulated from the GetSigners method for each Msg
+34 -28
View File
@@ -1,6 +1,8 @@
package utils
package utils_test
import (
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/x/gov/client/utils"
"testing"
"github.com/stretchr/testify/require"
@@ -59,7 +61,7 @@ func TestGetPaginatedVotes(t *testing.T) {
type testCase struct {
description string
page, limit int
txs []authtypes.StdTx
msgs [][]sdk.Msg
votes []types.Vote
}
acc1 := make(sdk.AccAddress, 20)
@@ -79,22 +81,21 @@ func TestGetPaginatedVotes(t *testing.T) {
description: "1MsgPerTxAll",
page: 1,
limit: 2,
txs: []authtypes.StdTx{
{Msgs: acc1Msgs[:1]},
{Msgs: acc2Msgs[:1]},
msgs: [][]sdk.Msg{
acc1Msgs[:1],
acc2Msgs[:1],
},
votes: []types.Vote{
types.NewVote(0, acc1, types.OptionYes),
types.NewVote(0, acc2, types.OptionYes)},
},
{
description: "2MsgPerTx1Chunk",
page: 1,
limit: 2,
txs: []authtypes.StdTx{
{Msgs: acc1Msgs},
{Msgs: acc2Msgs},
msgs: [][]sdk.Msg{
acc1Msgs,
acc2Msgs,
},
votes: []types.Vote{
types.NewVote(0, acc1, types.OptionYes),
@@ -104,9 +105,9 @@ func TestGetPaginatedVotes(t *testing.T) {
description: "2MsgPerTx2Chunk",
page: 2,
limit: 2,
txs: []authtypes.StdTx{
{Msgs: acc1Msgs},
{Msgs: acc2Msgs},
msgs: [][]sdk.Msg{
acc1Msgs,
acc2Msgs,
},
votes: []types.Vote{
types.NewVote(0, acc2, types.OptionYes),
@@ -116,49 +117,54 @@ func TestGetPaginatedVotes(t *testing.T) {
description: "IncompleteSearchTx",
page: 1,
limit: 2,
txs: []authtypes.StdTx{
{Msgs: acc1Msgs[:1]},
msgs: [][]sdk.Msg{
acc1Msgs[:1],
},
votes: []types.Vote{types.NewVote(0, acc1, types.OptionYes)},
},
{
description: "InvalidPage",
page: -1,
txs: []authtypes.StdTx{
{Msgs: acc1Msgs[:1]},
msgs: [][]sdk.Msg{
acc1Msgs[:1],
},
},
{
description: "OutOfBounds",
page: 2,
limit: 10,
txs: []authtypes.StdTx{
{Msgs: acc1Msgs[:1]},
msgs: [][]sdk.Msg{
acc1Msgs[:1],
},
},
} {
tc := tc
t.Run(tc.description, func(t *testing.T) {
var (
marshalled = make([]tmtypes.Tx, len(tc.txs))
marshalled = make([]tmtypes.Tx, len(tc.msgs))
cdc = newTestCodec()
)
for i := range tc.txs {
tx, err := cdc.MarshalBinaryBare(&tc.txs[i])
encodingConfig := simapp.MakeEncodingConfig()
cli := TxSearchMock{txs: marshalled}
clientCtx := client.Context{}.
WithLegacyAmino(cdc).
WithClient(cli).
WithTxConfig(encodingConfig.TxConfig)
for i := range tc.msgs {
txBuilder := clientCtx.TxConfig.NewTxBuilder()
err := txBuilder.SetMsgs(tc.msgs[i]...)
require.NoError(t, err)
tx, err := clientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
require.NoError(t, err)
marshalled[i] = tx
}
cli := TxSearchMock{txs: marshalled}
clientCtx := client.Context{}.
WithLegacyAmino(cdc).
WithClient(cli)
params := types.NewQueryProposalVotesParams(0, tc.page, tc.limit)
votesData, err := QueryVotesByTxQuery(clientCtx, params)
votesData, err := utils.QueryVotesByTxQuery(clientCtx, params)
require.NoError(t, err)
votes := []types.Vote{}
require.NoError(t, clientCtx.LegacyAmino.UnmarshalJSON(votesData, &votes))
+1 -1
View File
@@ -211,7 +211,7 @@ func GetCmdQueryHeader() *cobra.Command {
}
clientCtx = clientCtx.WithHeight(height)
return clientCtx.PrintOutputLegacy(header)
return clientCtx.PrintOutput(&header)
},
}
+1 -1
View File
@@ -161,7 +161,7 @@ func GetCmdQueryChannelClientState() *cobra.Command {
return err
}
return clientCtx.PrintOutputLegacy(res.IdentifiedClientState)
return clientCtx.PrintOutput(res.IdentifiedClientState)
},
}