diff --git a/CHANGELOG.md b/CHANGELOG.md index f69fe047b6..3e1327fc95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ older clients. ### API Breaking Changes +* (baseapp) [\#5865](https://github.com/cosmos/cosmos-sdk/pull/5865) The `SimulationResponse` returned from tx simulation is now JSON encoded instead of Amino binary. * [\#5719](https://github.com/cosmos/cosmos-sdk/pull/5719) Bump Go requirement to 1.14+ * (x/params) [\#5619](https://github.com/cosmos/cosmos-sdk/pull/5619) The `x/params` keeper now accepts a `codec.Marshaller` instead of a reference to an amino codec. Amino is still used for JSON serialization. diff --git a/baseapp/abci.go b/baseapp/abci.go index e984fe0edf..30273a12c8 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -189,7 +189,7 @@ func (app *BaseApp) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx { GasUsed: int64(gInfo.GasUsed), // TODO: Should type accept unsigned ints? Log: result.Log, Data: result.Data, - Events: result.Events.ToABCIEvents(), + Events: result.Events, } } @@ -214,7 +214,7 @@ func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx GasUsed: int64(gInfo.GasUsed), // TODO: Should type accept unsigned ints? Log: result.Log, Data: result.Data, - Events: result.Events.ToABCIEvents(), + Events: result.Events, } } @@ -331,15 +331,20 @@ func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) abci.Res return sdkerrors.QueryResult(sdkerrors.Wrap(err, "failed to simulate tx")) } - simRes := sdk.SimulationResponse{ + simRes := &sdk.SimulationResponse{ GasInfo: gInfo, Result: res, } + bz, err := codec.ProtoMarshalJSON(simRes) + if err != nil { + return sdkerrors.QueryResult(sdkerrors.Wrap(err, "failed to JSON encode simulation response")) + } + return abci.ResponseQuery{ Codespace: sdkerrors.RootCodespace, Height: req.Height, - Value: codec.Cdc.MustMarshalBinaryBare(simRes), + Value: bz, } case "version": diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 0373a199cf..f52aa0dd11 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -606,7 +606,7 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (*s msgEvents := sdk.Events{ sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, msg.Type())), } - msgEvents = msgEvents.AppendEvents(msgResult.Events) + msgEvents = msgEvents.AppendEvents(msgResult.GetEvents()) // append message events, data and logs // @@ -620,6 +620,6 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (*s return &sdk.Result{ Data: data, Log: strings.TrimSpace(msgLogs.String()), - Events: events, + Events: events.ToABCIEvents(), }, nil } diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index 2da5b95f6f..9de25e7010 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -5,9 +5,11 @@ import ( "encoding/binary" "fmt" "os" + "strings" "sync" "testing" + "github.com/gogo/protobuf/jsonpb" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -936,12 +938,13 @@ func TestSimulateTx(t *testing.T) { require.True(t, queryResult.IsOK(), queryResult.Log) var simRes sdk.SimulationResponse - err = codec.Cdc.UnmarshalBinaryBare(queryResult.Value, &simRes) - require.NoError(t, err) + require.NoError(t, jsonpb.Unmarshal(strings.NewReader(string(queryResult.Value)), &simRes)) + require.Equal(t, gInfo, simRes.GasInfo) require.Equal(t, result.Log, simRes.Result.Log) require.Equal(t, result.Events, simRes.Result.Events) require.True(t, bytes.Equal(result.Data, simRes.Result.Data)) + app.EndBlock(abci.RequestEndBlock{}) app.Commit() } diff --git a/client/context/context.go b/client/context/context.go index 30e2c141ab..5e536251b0 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -7,14 +7,12 @@ import ( "github.com/pkg/errors" "github.com/spf13/viper" - yaml "gopkg.in/yaml.v2" - "github.com/tendermint/tendermint/libs/cli" tmlite "github.com/tendermint/tendermint/lite" rpcclient "github.com/tendermint/tendermint/rpc/client" + yaml "gopkg.in/yaml.v2" "github.com/cosmos/cosmos-sdk/client/flags" - clientx "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" @@ -26,7 +24,6 @@ type CLIContext struct { FromAddress sdk.AccAddress Client rpcclient.Client ChainID string - TxGenerator clientx.Generator Marshaler codec.Marshaler Keybase keyring.Keybase Input io.Reader @@ -138,12 +135,6 @@ func (ctx CLIContext) WithInput(r io.Reader) CLIContext { return ctx } -// WithTxGenerator returns a copy of the CLIContext with an updated TxGenerator. -func (ctx CLIContext) WithTxGenerator(txg clientx.Generator) CLIContext { - ctx.TxGenerator = txg - return ctx -} - // WithMarshaler returns a copy of the CLIContext with an updated Marshaler. func (ctx CLIContext) WithMarshaler(m codec.Marshaler) CLIContext { ctx.Marshaler = m @@ -249,9 +240,44 @@ func (ctx CLIContext) WithBroadcastMode(mode string) CLIContext { return ctx } +// Println outputs toPrint to the ctx.Output based on ctx.OutputFormat which is +// either text or json. If text, toPrint will be YAML encoded. Otherwise, toPrint +// will be JSON encoded using ctx.Marshaler. An error is returned upon failure. +func (ctx CLIContext) Println(toPrint interface{}) error { + var ( + out []byte + err error + ) + + switch ctx.OutputFormat { + case "text": + out, err = yaml.Marshal(&toPrint) + + case "json": + out, err = ctx.Marshaler.MarshalJSON(toPrint) + + // To JSON indent, we re-encode the already encoded JSON given there is no + // error. The re-encoded JSON uses the standard library as the initial encoded + // JSON should have the correct output produced by ctx.Marshaler. + if ctx.Indent && err == nil { + out, err = codec.MarshalIndentFromJSON(out) + } + } + + if err != nil { + return err + } + + _, err = fmt.Fprintf(ctx.Output, "%s\n", out) + return err +} + // PrintOutput prints output while respecting output and indent flags // NOTE: pass in marshalled structs that have been unmarshaled -// because this function will panic on marshaling errors +// because this function will panic on marshaling errors. +// +// TODO: Remove once client-side Protobuf migration has been completed. +// ref: https://github.com/cosmos/cosmos-sdk/issues/5864 func (ctx CLIContext) PrintOutput(toPrint interface{}) error { var ( out []byte diff --git a/client/tx/factory.go b/client/tx/factory.go new file mode 100644 index 0000000000..4b05b2419a --- /dev/null +++ b/client/tx/factory.go @@ -0,0 +1,163 @@ +package tx + +import ( + "io" + + "github.com/spf13/viper" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// AccountRetriever defines the interfaces required for use by the Factory to +// ensure an account exists and to be able to query for account fields necessary +// for signing. +type AccountRetriever interface { + EnsureExists(addr sdk.AccAddress) error + GetAccountNumberSequence(addr sdk.AccAddress) (uint64, uint64, error) +} + +// Factory defines a client transaction factory that facilitates generating and +// signing an application-specific transaction. +type Factory struct { + keybase keyring.Keybase + txGenerator Generator + accountRetriever AccountRetriever + accountNumber uint64 + sequence uint64 + gas uint64 + gasAdjustment float64 + simulateAndExecute bool + chainID string + memo string + fees sdk.Coins + gasPrices sdk.DecCoins +} + +func NewFactoryFromCLI(input io.Reader) Factory { + kb, err := keyring.NewKeyring( + sdk.KeyringServiceName(), + viper.GetString(flags.FlagKeyringBackend), + viper.GetString(flags.FlagHome), + input, + ) + if err != nil { + panic(err) + } + + f := Factory{ + keybase: kb, + accountNumber: viper.GetUint64(flags.FlagAccountNumber), + sequence: viper.GetUint64(flags.FlagSequence), + gas: flags.GasFlagVar.Gas, + gasAdjustment: viper.GetFloat64(flags.FlagGasAdjustment), + simulateAndExecute: flags.GasFlagVar.Simulate, + chainID: viper.GetString(flags.FlagChainID), + memo: viper.GetString(flags.FlagMemo), + } + + f = f.WithFees(viper.GetString(flags.FlagFees)) + f = f.WithGasPrices(viper.GetString(flags.FlagGasPrices)) + + return f +} + +// nolint +func (f Factory) AccountNumber() uint64 { return f.accountNumber } +func (f Factory) Sequence() uint64 { return f.sequence } +func (f Factory) Gas() uint64 { return f.gas } +func (f Factory) GasAdjustment() float64 { return f.gasAdjustment } +func (f Factory) Keybase() keyring.Keybase { return f.keybase } +func (f Factory) ChainID() string { return f.chainID } +func (f Factory) Memo() string { return f.memo } +func (f Factory) Fees() sdk.Coins { return f.fees } +func (f Factory) GasPrices() sdk.DecCoins { return f.gasPrices } +func (f Factory) AccountRetriever() AccountRetriever { return f.accountRetriever } + +// SimulateAndExecute returns the option to simulate and then execute the transaction +// using the gas from the simulation results +func (f Factory) SimulateAndExecute() bool { return f.simulateAndExecute } + +// WithTxGenerator returns a copy of the Factory with an updated Generator. +func (f Factory) WithTxGenerator(g Generator) Factory { + f.txGenerator = g + return f +} + +// WithAccountRetriever returns a copy of the Factory with an updated AccountRetriever. +func (f Factory) WithAccountRetriever(ar AccountRetriever) Factory { + f.accountRetriever = ar + return f +} + +// WithChainID returns a copy of the Factory with an updated chainID. +func (f Factory) WithChainID(chainID string) Factory { + f.chainID = chainID + return f +} + +// WithGas returns a copy of the Factory with an updated gas value. +func (f Factory) WithGas(gas uint64) Factory { + f.gas = gas + return f +} + +// WithFees returns a copy of the Factory with an updated fee. +func (f Factory) WithFees(fees string) Factory { + parsedFees, err := sdk.ParseCoins(fees) + if err != nil { + panic(err) + } + + f.fees = parsedFees + return f +} + +// WithGasPrices returns a copy of the Factory with updated gas prices. +func (f Factory) WithGasPrices(gasPrices string) Factory { + parsedGasPrices, err := sdk.ParseDecCoins(gasPrices) + if err != nil { + panic(err) + } + + f.gasPrices = parsedGasPrices + return f +} + +// WithKeybase returns a copy of the Factory with updated Keybase. +func (f Factory) WithKeybase(keybase keyring.Keybase) Factory { + f.keybase = keybase + return f +} + +// WithSequence returns a copy of the Factory with an updated sequence number. +func (f Factory) WithSequence(sequence uint64) Factory { + f.sequence = sequence + return f +} + +// WithMemo returns a copy of the Factory with an updated memo. +func (f Factory) WithMemo(memo string) Factory { + f.memo = memo + return f +} + +// WithAccountNumber returns a copy of the Factory with an updated account number. +func (f Factory) WithAccountNumber(accnum uint64) Factory { + f.accountNumber = accnum + return f +} + +// WithGasAdjustment returns a copy of the Factory with an updated gas adjustment. +func (f Factory) WithGasAdjustment(gasAdj float64) Factory { + f.gasAdjustment = gasAdj + return f +} + +// WithSimulateAndExecute returns a copy of the Factory with an updated gas +// simulation value. +func (f Factory) WithSimulateAndExecute(sim bool) Factory { + f.simulateAndExecute = sim + return f +} diff --git a/client/tx/tx.go b/client/tx/tx.go index be25ec7541..6d1c1cd081 100644 --- a/client/tx/tx.go +++ b/client/tx/tx.go @@ -1,8 +1,24 @@ package tx import ( + "bufio" + "errors" + "fmt" + "net/http" + "os" + "strings" + + "github.com/gogo/protobuf/jsonpb" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/input" + clientkeys "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/rest" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/auth/types" ) type ( @@ -36,3 +52,301 @@ type ( CanonicalSignBytes(cid string, num, seq uint64) ([]byte, error) } ) + +// GenerateOrBroadcastTx will either generate and print and unsigned transaction +// or sign it and broadcast it returning an error upon failure. +func GenerateOrBroadcastTx(ctx context.CLIContext, txf Factory, msgs ...sdk.Msg) error { + if ctx.GenerateOnly { + return GenerateTx(ctx, txf, msgs...) + } + + return BroadcastTx(ctx, txf, msgs...) +} + +// GenerateTx will generate an unsigned transaction and print it to the writer +// specified by ctx.Output. If simulation was requested, the gas will be +// simulated and also printed to the same writer before the transaction is +// printed. +func GenerateTx(ctx context.CLIContext, txf Factory, msgs ...sdk.Msg) error { + if txf.SimulateAndExecute() { + if ctx.Offline { + return errors.New("cannot estimate gas in offline mode") + } + + _, adjusted, err := CalculateGas(ctx.QueryWithData, txf, msgs...) + if err != nil { + return err + } + + txf = txf.WithGas(adjusted) + _, _ = fmt.Fprintf(os.Stderr, "%s\n", GasEstimateResponse{GasEstimate: txf.Gas()}) + } + + tx, err := BuildUnsignedTx(txf, msgs...) + if err != nil { + return err + } + + return ctx.Println(tx) +} + +// BroadcastTx attempts to generate, sign and broadcast a transaction with the +// given set of messages. It will also simulate gas requirements if necessary. +// It will return an error upon failure. +func BroadcastTx(ctx context.CLIContext, txf Factory, msgs ...sdk.Msg) error { + txf, err := PrepareFactory(ctx, txf) + if err != nil { + return err + } + + if txf.SimulateAndExecute() || ctx.Simulate { + _, adjusted, err := CalculateGas(ctx.QueryWithData, txf, msgs...) + if err != nil { + return err + } + + txf = txf.WithGas(adjusted) + _, _ = fmt.Fprintf(os.Stderr, "%s\n", GasEstimateResponse{GasEstimate: txf.Gas()}) + } + + if ctx.Simulate { + return nil + } + + tx, err := BuildUnsignedTx(txf, msgs...) + if err != nil { + return err + } + + if !ctx.SkipConfirm { + out, err := ctx.Marshaler.MarshalJSON(tx) + if err != nil { + return err + } + + _, _ = fmt.Fprintf(os.Stderr, "%s\n\n", out) + + buf := bufio.NewReader(os.Stdin) + ok, err := input.GetConfirmation("confirm transaction before signing and broadcasting", buf) + if err != nil || !ok { + _, _ = fmt.Fprintf(os.Stderr, "%s\n", "cancelled transaction") + return err + } + } + + txBytes, err := Sign(txf, ctx.GetFromName(), clientkeys.DefaultKeyPass, tx) + if err != nil { + return err + } + + // broadcast to a Tendermint node + res, err := ctx.BroadcastTx(txBytes) + if err != nil { + return err + } + + return ctx.Println(res) +} + +// WriteGeneratedTxResponse writes a generated unsigned transaction to the +// provided http.ResponseWriter. It will simulate gas costs if requested by the +// BaseReq. Upon any error, the error will be written to the http.ResponseWriter. +func WriteGeneratedTxResponse( + ctx context.CLIContext, w http.ResponseWriter, txg Generator, br rest.BaseReq, msgs ...sdk.Msg, +) { + + gasAdj, ok := rest.ParseFloat64OrReturnBadRequest(w, br.GasAdjustment, flags.DefaultGasAdjustment) + if !ok { + return + } + + simAndExec, gas, err := flags.ParseGas(br.Gas) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + txf := Factory{fees: br.Fees, gasPrices: br.GasPrices}. + WithAccountNumber(br.AccountNumber). + WithSequence(br.Sequence). + WithGas(gas). + WithGasAdjustment(gasAdj). + WithMemo(br.Memo). + WithChainID(br.ChainID). + WithSimulateAndExecute(br.Simulate) + + if br.Simulate || simAndExec { + if gasAdj < 0 { + rest.WriteErrorResponse(w, http.StatusBadRequest, types.ErrorInvalidGasAdjustment.Error()) + return + } + + _, adjusted, err := CalculateGas(ctx.QueryWithData, txf, msgs...) + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + + txf = txf.WithGas(adjusted) + + if br.Simulate { + rest.WriteSimulationResponse(w, ctx.Marshaler, txf.Gas()) + return + } + } + + tx, err := BuildUnsignedTx(txf, msgs...) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + output, err := ctx.Marshaler.MarshalJSON(tx) + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(output) +} + +// BuildUnsignedTx builds a transaction to be signed given a set of messages. The +// transaction is initially created via the provided factory's generator. Once +// created, the fee, memo, and messages are set. +func BuildUnsignedTx(txf Factory, msgs ...sdk.Msg) (ClientTx, error) { + if txf.chainID == "" { + return nil, fmt.Errorf("chain ID required but not specified") + } + + fees := txf.fees + if !txf.gasPrices.IsZero() { + if !fees.IsZero() { + return nil, errors.New("cannot provide both fees and gas prices") + } + + glDec := sdk.NewDec(int64(txf.gas)) + + // Derive the fees based on the provided gas prices, where + // fee = ceil(gasPrice * gasLimit). + fees = make(sdk.Coins, len(txf.gasPrices)) + for i, gp := range txf.gasPrices { + fee := gp.Amount.Mul(glDec) + fees[i] = sdk.NewCoin(gp.Denom, fee.Ceil().RoundInt()) + } + } + + tx := txf.txGenerator.NewTx() + tx.SetFee(auth.NewStdFee(txf.gas, fees)) + tx.SetMsgs(msgs...) + tx.SetMemo(txf.memo) + tx.SetSignatures() + + return tx, nil +} + +// BuildSimTx creates an unsigned tx with an empty single signature and returns +// the encoded transaction or an error if the unsigned transaction cannot be +// built. +func BuildSimTx(txf Factory, msgs ...sdk.Msg) ([]byte, error) { + tx, err := BuildUnsignedTx(txf, msgs...) + if err != nil { + return nil, err + } + + // Create an empty signature literal as the ante handler will populate with a + // sentinel pubkey. + tx.SetSignatures(auth.NewStdSignature(nil, nil)) + + return tx.Marshal() +} + +// CalculateGas simulates the execution of a transaction and returns the +// simulation response obtained by the query and the adjusted gas amount. +func CalculateGas( + queryFunc func(string, []byte) ([]byte, int64, error), txf Factory, msgs ...sdk.Msg, +) (sdk.SimulationResponse, uint64, error) { + + txBytes, err := BuildSimTx(txf, msgs...) + if err != nil { + return sdk.SimulationResponse{}, 0, err + } + + bz, _, err := queryFunc("/app/simulate", txBytes) + if err != nil { + return sdk.SimulationResponse{}, 0, err + } + + var simRes sdk.SimulationResponse + if err := jsonpb.Unmarshal(strings.NewReader(string(bz)), &simRes); err != nil { + return sdk.SimulationResponse{}, 0, err + } + + return simRes, uint64(txf.GasAdjustment() * float64(simRes.GasUsed)), nil +} + +// PrepareFactory ensures the account defined by ctx.GetFromAddress() exists and +// if the account number and/or the account sequence number are zero (not set), +// they will be queried for and set on the provided Factory. A new Factory with +// the updated fields will be returned. +func PrepareFactory(ctx context.CLIContext, txf Factory) (Factory, error) { + from := ctx.GetFromAddress() + + if err := txf.accountRetriever.EnsureExists(from); err != nil { + return txf, err + } + + initNum, initSeq := txf.accountNumber, txf.sequence + if initNum == 0 || initSeq == 0 { + num, seq, err := txf.accountRetriever.GetAccountNumberSequence(from) + if err != nil { + return txf, err + } + + if initNum == 0 { + txf = txf.WithAccountNumber(num) + } + if initSeq == 0 { + txf = txf.WithSequence(seq) + } + } + + return txf, nil +} + +// Sign signs a given tx with the provided name and passphrase. If the Factory's +// Keybase is not set, a new one will be created based on the client's backend. +// The bytes signed over are canconical. The resulting signature will be set on +// the transaction. Finally, the marshaled transaction is returned. An error is +// returned upon failure. +// +// Note, It is assumed the Factory has the necessary fields set that are required +// by the CanonicalSignBytes call. +func Sign(txf Factory, name, passphrase string, tx ClientTx) ([]byte, error) { + if txf.keybase == nil { + return nil, errors.New("keybase must be set prior to signing a transaction") + } + + signBytes, err := tx.CanonicalSignBytes(txf.chainID, txf.accountNumber, txf.sequence) + if err != nil { + return nil, err + } + + sigBytes, pubkey, err := txf.keybase.Sign(name, passphrase, signBytes) + if err != nil { + return nil, err + } + + tx.SetSignatures(auth.NewStdSignature(pubkey, sigBytes)) + return tx.Marshal() +} + +// GasEstimateResponse defines a response definition for tx gas estimation. +type GasEstimateResponse struct { + GasEstimate uint64 `json:"gas_estimate" yaml:"gas_estimate"` +} + +func (gr GasEstimateResponse) String() string { + return fmt.Sprintf("gas estimate: %d", gr.GasEstimate) +} diff --git a/client/tx/tx_test.go b/client/tx/tx_test.go new file mode 100644 index 0000000000..13e94f819b --- /dev/null +++ b/client/tx/tx_test.go @@ -0,0 +1,107 @@ +package tx_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/std" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/bank" +) + +func TestCalculateGas(t *testing.T) { + makeQueryFunc := func(gasUsed uint64, wantErr bool) func(string, []byte) ([]byte, int64, error) { + return func(string, []byte) ([]byte, int64, error) { + if wantErr { + return nil, 0, errors.New("query failed") + } + simRes := &sdk.SimulationResponse{ + GasInfo: sdk.GasInfo{GasUsed: gasUsed, GasWanted: gasUsed}, + Result: &sdk.Result{Data: []byte("tx data"), Log: "log"}, + } + + bz, err := codec.ProtoMarshalJSON(simRes) + if err != nil { + return nil, 0, err + } + + return bz, 0, nil + } + } + + type args struct { + queryFuncGasUsed uint64 + queryFuncWantErr bool + adjustment float64 + } + + testCases := []struct { + name string + args args + wantEstimate uint64 + wantAdjusted uint64 + expPass bool + }{ + {"error", args{0, true, 1.2}, 0, 0, false}, + {"adjusted gas", args{10, false, 1.2}, 10, 12, true}, + } + + for _, tc := range testCases { + stc := tc + txf := tx.Factory{}.WithChainID("test-chain").WithTxGenerator(std.TxGenerator{}) + + t.Run(stc.name, func(t *testing.T) { + queryFunc := makeQueryFunc(stc.args.queryFuncGasUsed, stc.args.queryFuncWantErr) + simRes, gotAdjusted, err := tx.CalculateGas(queryFunc, txf.WithGasAdjustment(stc.args.adjustment)) + if stc.expPass { + require.NoError(t, err) + require.Equal(t, simRes.GasInfo.GasUsed, stc.wantEstimate) + require.Equal(t, gotAdjusted, stc.wantAdjusted) + require.NotNil(t, simRes.Result) + } else { + require.Error(t, err) + require.Nil(t, simRes.Result) + } + }) + } +} + +func TestBuildSimTx(t *testing.T) { + txf := tx.Factory{}. + WithTxGenerator(std.TxGenerator{}). + WithAccountNumber(50). + WithSequence(23). + WithFees("50stake"). + WithMemo("memo"). + WithChainID("test-chain") + + msg := bank.NewMsgSend(sdk.AccAddress("from"), sdk.AccAddress("to"), nil) + bz, err := tx.BuildSimTx(txf, msg) + require.NoError(t, err) + require.NotNil(t, bz) + + tx := &std.Transaction{} + require.NoError(t, tx.Unmarshal(bz)) + require.Equal(t, []sdk.Signature{sdk.Signature(auth.StdSignature{})}, tx.GetSignatures()) +} + +func TestBuildUnsignedTx(t *testing.T) { + txf := tx.Factory{}. + WithTxGenerator(std.TxGenerator{}). + WithAccountNumber(50). + WithSequence(23). + WithFees("50stake"). + WithMemo("memo"). + WithChainID("test-chain") + + msg := bank.NewMsgSend(sdk.AccAddress("from"), sdk.AccAddress("to"), nil) + tx, err := tx.BuildUnsignedTx(txf, msg) + require.NoError(t, err) + require.NotNil(t, tx) + require.Equal(t, []sdk.Signature{}, tx.GetSignatures()) +} diff --git a/codec/json.go b/codec/json.go new file mode 100644 index 0000000000..0bb44df31f --- /dev/null +++ b/codec/json.go @@ -0,0 +1,48 @@ +package codec + +import ( + "bytes" + "encoding/json" + + "github.com/gogo/protobuf/jsonpb" + "github.com/gogo/protobuf/proto" +) + +// MarshalIndentFromJSON returns indented JSON-encoded bytes from already encoded +// JSON bytes. The output encoding will adhere to the original input's encoding +// (e.g. Proto3). +func MarshalIndentFromJSON(bz []byte) ([]byte, error) { + var generic interface{} + + if err := json.Unmarshal(bz, &generic); err != nil { + return nil, err + } + + return json.MarshalIndent(generic, "", " ") +} + +// ProtoMarshalJSON provides an auxiliary function to return Proto3 JSON encoded +// bytes of a message. +func ProtoMarshalJSON(msg proto.Message) ([]byte, error) { + jm := &jsonpb.Marshaler{EmitDefaults: false, OrigName: false} + buf := new(bytes.Buffer) + + if err := jm.Marshal(buf, msg); err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +// ProtoMarshalJSONIndent provides an auxiliary function to return Proto3 indented +// JSON encoded bytes of a message. +func ProtoMarshalJSONIndent(msg proto.Message) ([]byte, error) { + jm := &jsonpb.Marshaler{EmitDefaults: false, OrigName: false, Indent: " "} + buf := new(bytes.Buffer) + + if err := jm.Marshal(buf, msg); err != nil { + return nil, err + } + + return buf.Bytes(), nil +} diff --git a/codec/proto_codec.go b/codec/proto_codec.go index f8a4169d4d..ff123cee23 100644 --- a/codec/proto_codec.go +++ b/codec/proto_codec.go @@ -95,14 +95,7 @@ func (pc *ProtoCodec) MarshalJSON(o interface{}) ([]byte, error) { // nolint: st return nil, fmt.Errorf("cannot protobuf JSON encode unsupported type: %T", o) } - buf := new(bytes.Buffer) - - marshaler := &jsonpb.Marshaler{} - if err := marshaler.Marshal(buf, m); err != nil { - return nil, err - } - - return buf.Bytes(), nil + return ProtoMarshalJSON(m) } func (pc *ProtoCodec) MustMarshalJSON(o interface{}) []byte { diff --git a/codec/std/tx.go b/codec/std/tx.go index eca3553f30..8305c75177 100644 --- a/codec/std/tx.go +++ b/codec/std/tx.go @@ -122,9 +122,11 @@ func (tx Transaction) GetSignatures() []sdk.Signature { // SetSignatures sets the transaction's signatures. It will overwrite any // existing signatures set. func (tx *Transaction) SetSignatures(sdkSigs ...sdk.Signature) { - sigs := make([]auth.StdSignature, len(tx.Signatures)) + sigs := make([]auth.StdSignature, len(sdkSigs)) for i, sig := range sdkSigs { - sigs[i] = auth.NewStdSignature(sig.GetPubKey(), sig.GetSignature()) + if sig != nil { + sigs[i] = auth.NewStdSignature(sig.GetPubKey(), sig.GetSignature()) + } } tx.Signatures = sigs diff --git a/docs/architecture/adr-020-protobuf-transaction-encoding.md b/docs/architecture/adr-020-protobuf-transaction-encoding.md index 6689f29e23..4d32267a7a 100644 --- a/docs/architecture/adr-020-protobuf-transaction-encoding.md +++ b/docs/architecture/adr-020-protobuf-transaction-encoding.md @@ -103,6 +103,11 @@ to handle all the types, but also knows how to generate transactions, signatures and messages. ```go +type AccountRetriever interface { + EnsureExists(addr sdk.AccAddress) error + GetAccountNumberSequence(addr sdk.AccAddress) (uint64, uint64, error) +} + type Generator interface { NewTx() ClientTx } @@ -123,11 +128,13 @@ type ClientTx interface { } ``` -We then update `CLIContext` to have two new fields: `Generator` and `Marshler`. +We then update `CLIContext` to have a new field: `Marshaler`. -Then, each module will at the minimum accept a `Marshaler` instead of a concrete -Amino codec. If the module needs to work with any interface types, it will use -the `Codec` interface defined by the module which also extends `Marshaler`. +Then, each module's client handler will at the minimum accept a `Marshaler` instead +of a concrete Amino codec and a `Generator` along with an `AccountRetriever` so +that account fields can be retrieved for signing. If the module needs to work with +any interface types, it will use the `Codec` interface defined by the module which +also extends `Marshaler`. ## Future Improvements diff --git a/types/codec.go b/types/codec.go index 21cd269043..9cd1097c20 100644 --- a/types/codec.go +++ b/types/codec.go @@ -1,10 +1,7 @@ package types import ( - "bytes" - jsonc "github.com/gibson042/canonicaljson-go" - "github.com/gogo/protobuf/jsonpb" "github.com/cosmos/cosmos-sdk/codec" ) @@ -19,19 +16,17 @@ func RegisterCodec(cdc *codec.Codec) { // can be signed over. The JSON encoding ensures all field names adhere to their // Proto definition, default values are omitted, and follows the JSON Canonical // Form. -func CanonicalSignBytes(m codec.ProtoMarshaler) ([]byte, error) { - jm := &jsonpb.Marshaler{EmitDefaults: false, OrigName: false} - buf := new(bytes.Buffer) - - // first, encode via canonical Protocol Buffer JSON - if err := jm.Marshal(buf, m); err != nil { +func CanonicalSignBytes(msg codec.ProtoMarshaler) ([]byte, error) { + // first, encode via canonical Proto3 JSON + bz, err := codec.ProtoMarshalJSON(msg) + if err != nil { return nil, err } genericJSON := make(map[string]interface{}) // decode canonical proto encoding into a generic map - if err := jsonc.Unmarshal(buf.Bytes(), &genericJSON); err != nil { + if err := jsonc.Unmarshal(bz, &genericJSON); err != nil { return nil, err } diff --git a/types/rest/rest.go b/types/rest/rest.go index 2589175862..74bf5946d4 100644 --- a/types/rest/rest.go +++ b/types/rest/rest.go @@ -119,16 +119,16 @@ func (br BaseReq) ValidateBasic(w http.ResponseWriter) bool { return true } -// ReadRESTReq reads and unmarshals a Request's body to the the BaseReq stuct. +// ReadRESTReq reads and unmarshals a Request's body to the the BaseReq struct. // Writes an error response to ResponseWriter and returns true if errors occurred. -func ReadRESTReq(w http.ResponseWriter, r *http.Request, cdc *codec.Codec, req interface{}) bool { +func ReadRESTReq(w http.ResponseWriter, r *http.Request, m codec.JSONMarshaler, req interface{}) bool { body, err := ioutil.ReadAll(r.Body) if err != nil { WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return false } - err = cdc.UnmarshalJSON(body, req) + err = m.UnmarshalJSON(body, req) if err != nil { WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to decode JSON payload: %s", err)) return false @@ -158,9 +158,10 @@ func WriteErrorResponse(w http.ResponseWriter, status int, err string) { // WriteSimulationResponse prepares and writes an HTTP // response for transactions simulations. -func WriteSimulationResponse(w http.ResponseWriter, cdc *codec.Codec, gas uint64) { +func WriteSimulationResponse(w http.ResponseWriter, m codec.JSONMarshaler, gas uint64) { gasEst := GasEstimateResponse{GasEstimate: gas} - resp, err := cdc.MarshalJSON(gasEst) + + resp, err := m.MarshalJSON(gasEst) if err != nil { WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return @@ -229,21 +230,31 @@ func ParseQueryHeightOrReturnBadRequest(w http.ResponseWriter, cliCtx context.CL // PostProcessResponseBare post processes a body similar to PostProcessResponse // except it does not wrap the body and inject the height. -func PostProcessResponseBare(w http.ResponseWriter, cliCtx context.CLIContext, body interface{}) { +func PostProcessResponseBare(w http.ResponseWriter, ctx context.CLIContext, body interface{}) { var ( resp []byte err error ) + // TODO: Remove once client-side Protobuf migration has been completed. + // ref: https://github.com/cosmos/cosmos-sdk/issues/5864 + var marshaler codec.JSONMarshaler + + if ctx.Marshaler != nil { + marshaler = ctx.Marshaler + } else { + marshaler = ctx.Codec + } + switch b := body.(type) { case []byte: resp = b default: - if cliCtx.Indent { - resp, err = cliCtx.Codec.MarshalJSONIndent(body, "", " ") - } else { - resp, err = cliCtx.Codec.MarshalJSON(body) + resp, err = marshaler.MarshalJSON(body) + + if ctx.Indent && err == nil { + resp, err = codec.MarshalIndentFromJSON(resp) } if err != nil { @@ -259,24 +270,36 @@ func PostProcessResponseBare(w http.ResponseWriter, cliCtx context.CLIContext, b // PostProcessResponse performs post processing for a REST response. The result // returned to clients will contain two fields, the height at which the resource // was queried at and the original result. -func PostProcessResponse(w http.ResponseWriter, cliCtx context.CLIContext, resp interface{}) { - var result []byte +func PostProcessResponse(w http.ResponseWriter, ctx context.CLIContext, resp interface{}) { + var ( + result []byte + err error + ) - if cliCtx.Height < 0 { + if ctx.Height < 0 { WriteErrorResponse(w, http.StatusInternalServerError, fmt.Errorf("negative height in response").Error()) return } + // TODO: Remove once client-side Protobuf migration has been completed. + // ref: https://github.com/cosmos/cosmos-sdk/issues/5864 + var marshaler codec.JSONMarshaler + + if ctx.Marshaler != nil { + marshaler = ctx.Marshaler + } else { + marshaler = ctx.Codec + } + switch res := resp.(type) { case []byte: result = res default: - var err error - if cliCtx.Indent { - result, err = cliCtx.Codec.MarshalJSONIndent(resp, "", " ") - } else { - result, err = cliCtx.Codec.MarshalJSON(resp) + result, err = marshaler.MarshalJSON(resp) + + if ctx.Indent && err == nil { + result, err = codec.MarshalIndentFromJSON(result) } if err != nil { @@ -285,17 +308,11 @@ func PostProcessResponse(w http.ResponseWriter, cliCtx context.CLIContext, resp } } - wrappedResp := NewResponseWithHeight(cliCtx.Height, result) + wrappedResp := NewResponseWithHeight(ctx.Height, result) - var ( - output []byte - err error - ) - - if cliCtx.Indent { - output, err = cliCtx.Codec.MarshalJSONIndent(wrappedResp, "", " ") - } else { - output, err = cliCtx.Codec.MarshalJSON(wrappedResp) + output, err := marshaler.MarshalJSON(wrappedResp) + if ctx.Indent && err == nil { + output, err = codec.MarshalIndentFromJSON(output) } if err != nil { @@ -312,10 +329,12 @@ func PostProcessResponse(w http.ResponseWriter, cliCtx context.CLIContext, resp // default limit can be provided. func ParseHTTPArgsWithLimit(r *http.Request, defaultLimit int) (tags []string, page, limit int, err error) { tags = make([]string, 0, len(r.Form)) + for key, values := range r.Form { if key == "page" || key == "limit" { continue } + var value string value, err = url.QueryUnescape(values[0]) if err != nil { @@ -326,13 +345,17 @@ func ParseHTTPArgsWithLimit(r *http.Request, defaultLimit int) (tags []string, p switch key { case types.TxHeightKey: tag = fmt.Sprintf("%s=%s", key, value) + case TxMinHeightKey: tag = fmt.Sprintf("%s>=%s", types.TxHeightKey, value) + case TxMaxHeightKey: tag = fmt.Sprintf("%s<=%s", types.TxHeightKey, value) + default: tag = fmt.Sprintf("%s='%s'", key, value) } + tags = append(tags, tag) } diff --git a/types/rest/rest_test.go b/types/rest/rest_test.go index db842696ee..0f259b7fc1 100644 --- a/types/rest/rest_test.go +++ b/types/rest/rest_test.go @@ -204,13 +204,12 @@ func TestProcessPostResponse(t *testing.T) { // setup expected results jsonNoIndent, err := ctx.Codec.MarshalJSON(acc) require.Nil(t, err) - jsonWithIndent, err := ctx.Codec.MarshalJSONIndent(acc, "", " ") - require.Nil(t, err) + respNoIndent := NewResponseWithHeight(height, jsonNoIndent) - respWithIndent := NewResponseWithHeight(height, jsonWithIndent) expectedNoIndent, err := ctx.Codec.MarshalJSON(respNoIndent) require.Nil(t, err) - expectedWithIndent, err := ctx.Codec.MarshalJSONIndent(respWithIndent, "", " ") + + expectedWithIndent, err := codec.MarshalIndentFromJSON(expectedNoIndent) require.Nil(t, err) // check that negative height writes an error @@ -222,6 +221,7 @@ func TestProcessPostResponse(t *testing.T) { // check that height returns expected response ctx = ctx.WithHeight(height) runPostProcessResponse(t, ctx, acc, expectedNoIndent, false) + // check height with indent runPostProcessResponse(t, ctx, acc, expectedWithIndent, true) } @@ -313,11 +313,15 @@ func TestPostProcessResponseBare(t *testing.T) { ctx := context.CLIContext{} w := httptest.NewRecorder() bs := []byte("text string") + PostProcessResponseBare(w, ctx, bs) + res := w.Result() require.Equal(t, http.StatusOK, res.StatusCode) + got, err := ioutil.ReadAll(res.Body) require.NoError(t, err) + t.Cleanup(func() { res.Body.Close() }) require.Equal(t, "text string", string(got)) @@ -328,15 +332,19 @@ func TestPostProcessResponseBare(t *testing.T) { X int `json:"x"` S string `json:"s"` }{X: 10, S: "test"} + PostProcessResponseBare(w, ctx, data) + res = w.Result() require.Equal(t, http.StatusOK, res.StatusCode) + got, err = ioutil.ReadAll(res.Body) require.NoError(t, err) + t.Cleanup(func() { res.Body.Close() }) require.Equal(t, `{ - "x": "10", - "s": "test" + "s": "test", + "x": "10" }`, string(got)) // write struct, don't indent response @@ -346,11 +354,15 @@ func TestPostProcessResponseBare(t *testing.T) { X int `json:"x"` S string `json:"s"` }{X: 10, S: "test"} + PostProcessResponseBare(w, ctx, data) + res = w.Result() require.Equal(t, http.StatusOK, res.StatusCode) + got, err = ioutil.ReadAll(res.Body) require.NoError(t, err) + t.Cleanup(func() { res.Body.Close() }) require.Equal(t, `{"x":"10","s":"test"}`, string(got)) @@ -358,11 +370,15 @@ func TestPostProcessResponseBare(t *testing.T) { ctx = context.CLIContext{Indent: false}.WithCodec(codec.New()) w = httptest.NewRecorder() data2 := badJSONMarshaller{} + PostProcessResponseBare(w, ctx, data2) + res = w.Result() require.Equal(t, http.StatusInternalServerError, res.StatusCode) + got, err = ioutil.ReadAll(res.Body) require.NoError(t, err) + t.Cleanup(func() { res.Body.Close() }) require.Equal(t, []string{"application/json"}, res.Header["Content-Type"]) require.Equal(t, `{"error":"couldn't marshal"}`, string(got)) @@ -384,31 +400,37 @@ func runPostProcessResponse(t *testing.T, ctx context.CLIContext, obj interface{ // test using regular struct w := httptest.NewRecorder() + PostProcessResponse(w, ctx, obj) require.Equal(t, http.StatusOK, w.Code, w.Body) + resp := w.Result() t.Cleanup(func() { resp.Body.Close() }) + body, err := ioutil.ReadAll(resp.Body) require.Nil(t, err) require.Equal(t, expectedBody, body) - var marshalled []byte + marshalled, err := ctx.Codec.MarshalJSON(obj) + require.NoError(t, err) + if indent { - marshalled, err = ctx.Codec.MarshalJSONIndent(obj, "", " ") - } else { - marshalled, err = ctx.Codec.MarshalJSON(obj) + marshalled, err = codec.MarshalIndentFromJSON(marshalled) + require.NoError(t, err) } - require.Nil(t, err) // test using marshalled struct w = httptest.NewRecorder() PostProcessResponse(w, ctx, marshalled) + require.Equal(t, http.StatusOK, w.Code, w.Body) resp = w.Result() + t.Cleanup(func() { resp.Body.Close() }) body, err = ioutil.ReadAll(resp.Body) + require.Nil(t, err) - require.Equal(t, expectedBody, body) + require.Equal(t, string(expectedBody), string(body)) } func mustNewRequest(t *testing.T, method, url string, body io.Reader) *http.Request { diff --git a/types/result.go b/types/result.go index 54cc0e0533..c488a02770 100644 --- a/types/result.go +++ b/types/result.go @@ -7,39 +7,30 @@ import ( "math" "strings" + yaml "gopkg.in/yaml.v2" + "github.com/cosmos/cosmos-sdk/codec" ctypes "github.com/tendermint/tendermint/rpc/core/types" ) -// GasInfo defines tx execution gas context. -type GasInfo struct { - // GasWanted is the maximum units of work we allow this tx to perform. - GasWanted uint64 - - // GasUsed is the amount of gas actually consumed. - GasUsed uint64 +func (gi GasInfo) String() string { + bz, _ := yaml.Marshal(gi) + return string(bz) } -// Result is the union of ResponseFormat and ResponseCheckTx. -type Result struct { - // Data is any data returned from message or handler execution. It MUST be length - // prefixed in order to separate data from multiple message executions. - Data []byte - - // Log contains the log information from message or handler execution. - Log string - - // Events contains a slice of Event objects that were emitted during message or - // handler execution. - Events Events +func (r Result) String() string { + bz, _ := yaml.Marshal(r) + return string(bz) } -// SimulationResponse defines the response generated when a transaction is successfully -// simulated by the Baseapp. -type SimulationResponse struct { - GasInfo - Result *Result +func (r Result) GetEvents() Events { + events := make(Events, len(r.Events)) + for i, e := range r.Events { + events[i] = Event(e) + } + + return events } // ABCIMessageLogs represents a slice of ABCIMessageLog. diff --git a/types/types.pb.go b/types/types.pb.go index 845bf267ba..6b4d9813ab 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -7,6 +7,7 @@ import ( fmt "fmt" _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" + types "github.com/tendermint/tendermint/abci/types" io "io" math "math" math_bits "math/bits" @@ -239,38 +240,199 @@ func (m *ValAddresses) GetAddresses() []ValAddress { return nil } +// GasInfo defines tx execution gas context. +type GasInfo struct { + // GasWanted is the maximum units of work we allow this tx to perform. + GasWanted uint64 `protobuf:"varint,1,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty" yaml:"gas_wanted"` + // GasUsed is the amount of gas actually consumed. + GasUsed uint64 `protobuf:"varint,2,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty" yaml:"gas_used"` +} + +func (m *GasInfo) Reset() { *m = GasInfo{} } +func (*GasInfo) ProtoMessage() {} +func (*GasInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_2c0f90c600ad7e2e, []int{5} +} +func (m *GasInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GasInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GasInfo.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 *GasInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_GasInfo.Merge(m, src) +} +func (m *GasInfo) XXX_Size() int { + return m.Size() +} +func (m *GasInfo) XXX_DiscardUnknown() { + xxx_messageInfo_GasInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_GasInfo proto.InternalMessageInfo + +func (m *GasInfo) GetGasWanted() uint64 { + if m != nil { + return m.GasWanted + } + return 0 +} + +func (m *GasInfo) GetGasUsed() uint64 { + if m != nil { + return m.GasUsed + } + return 0 +} + +// Result is the union of ResponseFormat and ResponseCheckTx. +type Result struct { + // Data is any data returned from message or handler execution. It MUST be length + // prefixed in order to separate data from multiple message executions. + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` + // Log contains the log information from message or handler execution. + Log string `protobuf:"bytes,2,opt,name=log,proto3" json:"log,omitempty"` + // Events contains a slice of Event objects that were emitted during message or + // handler execution. + Events []types.Event `protobuf:"bytes,3,rep,name=events,proto3" json:"events"` +} + +func (m *Result) Reset() { *m = Result{} } +func (*Result) ProtoMessage() {} +func (*Result) Descriptor() ([]byte, []int) { + return fileDescriptor_2c0f90c600ad7e2e, []int{6} +} +func (m *Result) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Result) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Result.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 *Result) XXX_Merge(src proto.Message) { + xxx_messageInfo_Result.Merge(m, src) +} +func (m *Result) XXX_Size() int { + return m.Size() +} +func (m *Result) XXX_DiscardUnknown() { + xxx_messageInfo_Result.DiscardUnknown(m) +} + +var xxx_messageInfo_Result proto.InternalMessageInfo + +// SimulationResponse defines the response generated when a transaction is +// successfully simulated. +type SimulationResponse struct { + GasInfo `protobuf:"bytes,1,opt,name=gas_info,json=gasInfo,proto3,embedded=gas_info" json:"gas_info"` + Result *Result `protobuf:"bytes,2,opt,name=result,proto3" json:"result,omitempty"` +} + +func (m *SimulationResponse) Reset() { *m = SimulationResponse{} } +func (*SimulationResponse) ProtoMessage() {} +func (*SimulationResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2c0f90c600ad7e2e, []int{7} +} +func (m *SimulationResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SimulationResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SimulationResponse.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 *SimulationResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_SimulationResponse.Merge(m, src) +} +func (m *SimulationResponse) XXX_Size() int { + return m.Size() +} +func (m *SimulationResponse) XXX_DiscardUnknown() { + xxx_messageInfo_SimulationResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_SimulationResponse proto.InternalMessageInfo + +func (m *SimulationResponse) GetResult() *Result { + if m != nil { + return m.Result + } + return nil +} + func init() { proto.RegisterType((*Coin)(nil), "cosmos_sdk.v1.Coin") proto.RegisterType((*DecCoin)(nil), "cosmos_sdk.v1.DecCoin") proto.RegisterType((*IntProto)(nil), "cosmos_sdk.v1.IntProto") proto.RegisterType((*DecProto)(nil), "cosmos_sdk.v1.DecProto") proto.RegisterType((*ValAddresses)(nil), "cosmos_sdk.v1.ValAddresses") + proto.RegisterType((*GasInfo)(nil), "cosmos_sdk.v1.GasInfo") + proto.RegisterType((*Result)(nil), "cosmos_sdk.v1.Result") + proto.RegisterType((*SimulationResponse)(nil), "cosmos_sdk.v1.SimulationResponse") } func init() { proto.RegisterFile("types/types.proto", fileDescriptor_2c0f90c600ad7e2e) } var fileDescriptor_2c0f90c600ad7e2e = []byte{ - // 305 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2c, 0xa9, 0x2c, 0x48, - 0x2d, 0xd6, 0x07, 0x93, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0xbc, 0xc9, 0xf9, 0xc5, 0xb9, - 0xf9, 0xc5, 0xf1, 0xc5, 0x29, 0xd9, 0x7a, 0x65, 0x86, 0x52, 0x6a, 0x25, 0x19, 0x99, 0x45, 0x29, - 0xf1, 0x05, 0x89, 0x45, 0x25, 0x95, 0xfa, 0x60, 0x15, 0xfa, 0xe9, 0xf9, 0xe9, 0xf9, 0x08, 0x16, - 0x44, 0x9b, 0x92, 0x3b, 0x17, 0x8b, 0x73, 0x7e, 0x66, 0x9e, 0x90, 0x08, 0x17, 0x6b, 0x4a, 0x6a, - 0x5e, 0x7e, 0xae, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x67, 0x10, 0x84, 0x23, 0xa4, 0xcc, 0xc5, 0x96, - 0x98, 0x9b, 0x5f, 0x9a, 0x57, 0x22, 0xc1, 0x04, 0x12, 0x76, 0xe2, 0x3e, 0x71, 0x4f, 0x9e, 0xe1, - 0xd6, 0x3d, 0x79, 0x66, 0xcf, 0xbc, 0x92, 0x20, 0xa8, 0x94, 0x15, 0xcb, 0x8b, 0x05, 0xf2, 0x8c, - 0x4a, 0x5e, 0x5c, 0xec, 0x2e, 0xa9, 0xc9, 0xe4, 0x98, 0xe5, 0x92, 0x9a, 0x8c, 0x66, 0x96, 0x26, - 0x17, 0x87, 0x67, 0x5e, 0x49, 0x00, 0xd8, 0x5f, 0xb2, 0x5c, 0xcc, 0x99, 0x79, 0x25, 0x10, 0xa3, - 0x50, 0xed, 0x07, 0x89, 0x83, 0x94, 0xba, 0xa4, 0x26, 0xc3, 0x95, 0xa6, 0xa4, 0x26, 0xa3, 0x2b, - 0x05, 0x19, 0x0f, 0x12, 0x57, 0x72, 0xe2, 0xe2, 0x09, 0x4b, 0xcc, 0x71, 0x4c, 0x49, 0x29, 0x4a, - 0x2d, 0x2e, 0x4e, 0x2d, 0x16, 0xd2, 0xe1, 0xe2, 0x4c, 0x84, 0x71, 0x24, 0x18, 0x15, 0x98, 0x35, - 0x78, 0x9c, 0xf8, 0x7e, 0xdd, 0x93, 0xe7, 0x42, 0x28, 0x0a, 0x42, 0x28, 0xb0, 0x62, 0x69, 0xb8, - 0xa3, 0xc0, 0xe8, 0xe4, 0x72, 0xe3, 0xa1, 0x1c, 0x43, 0xc3, 0x23, 0x39, 0x86, 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, 0x52, 0x4a, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, - 0xce, 0xcf, 0xd5, 0x87, 0x44, 0x09, 0x94, 0xd2, 0x2d, 0x4e, 0xc9, 0x86, 0xc4, 0x58, 0x12, 0x1b, - 0x38, 0xec, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa7, 0x40, 0xd2, 0x04, 0xc7, 0x01, 0x00, - 0x00, + // 534 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x52, 0x4f, 0x6f, 0xd3, 0x4e, + 0x10, 0xb5, 0x7f, 0xf6, 0x2f, 0x7f, 0x36, 0xe1, 0x4f, 0x17, 0x8a, 0xa2, 0x0a, 0xec, 0xc8, 0x48, + 0x28, 0x48, 0xd4, 0x16, 0x29, 0xa7, 0x70, 0xc2, 0x04, 0x55, 0xe1, 0x84, 0x16, 0x01, 0x12, 0x97, + 0x68, 0xe3, 0xdd, 0xba, 0x56, 0xe3, 0xdd, 0xc8, 0xbb, 0x29, 0xca, 0x2d, 0x47, 0x8e, 0x7c, 0x84, + 0x7e, 0x9c, 0x1e, 0x73, 0xac, 0x10, 0xb2, 0x20, 0xb9, 0x70, 0xee, 0x91, 0x13, 0xda, 0xb5, 0xc1, + 0x6a, 0x7a, 0xe3, 0x92, 0xcc, 0xce, 0xbc, 0x79, 0x33, 0xf3, 0xfc, 0xc0, 0x8e, 0x5c, 0xcc, 0xa8, + 0x08, 0xf4, 0xaf, 0x3f, 0xcb, 0xb8, 0xe4, 0xf0, 0x46, 0xc4, 0x45, 0xca, 0xc5, 0x58, 0x90, 0x13, + 0xff, 0xf4, 0xe9, 0xde, 0x23, 0x79, 0x9c, 0x64, 0x64, 0x3c, 0xc3, 0x99, 0x5c, 0x04, 0x1a, 0x11, + 0xc4, 0x3c, 0xe6, 0x55, 0x54, 0xb4, 0xed, 0x1d, 0x5c, 0xc7, 0x49, 0xca, 0x08, 0xcd, 0xd2, 0x84, + 0xc9, 0x00, 0x4f, 0xa2, 0x24, 0xb8, 0x36, 0xcb, 0x3b, 0x04, 0xf6, 0x4b, 0x9e, 0x30, 0x78, 0x17, + 0xfc, 0x4f, 0x28, 0xe3, 0x69, 0xc7, 0xec, 0x9a, 0xbd, 0x26, 0x2a, 0x1e, 0xf0, 0x21, 0xa8, 0xe1, + 0x94, 0xcf, 0x99, 0xec, 0xfc, 0xa7, 0xd2, 0x61, 0xeb, 0x3c, 0x77, 0x8d, 0xaf, 0xb9, 0x6b, 0x8d, + 0x98, 0x44, 0x65, 0x69, 0x60, 0xff, 0x3c, 0x73, 0x4d, 0xef, 0x35, 0xa8, 0x0f, 0x69, 0xf4, 0x2f, + 0x5c, 0x43, 0x1a, 0x6d, 0x71, 0x3d, 0x06, 0x8d, 0x11, 0x93, 0x6f, 0xb4, 0x18, 0x0f, 0x80, 0x95, + 0x30, 0x59, 0x50, 0x5d, 0x9d, 0xaf, 0xf2, 0x0a, 0x3a, 0xa4, 0xd1, 0x5f, 0x28, 0xa1, 0xd1, 0x36, + 0x54, 0xd1, 0xab, 0xbc, 0x17, 0x82, 0xf6, 0x7b, 0x3c, 0x7d, 0x41, 0x48, 0x46, 0x85, 0xa0, 0x02, + 0x3e, 0x01, 0x4d, 0xfc, 0xe7, 0xd1, 0x31, 0xbb, 0x56, 0xaf, 0x1d, 0xde, 0xfc, 0x95, 0xbb, 0xa0, + 0x02, 0xa1, 0x0a, 0x30, 0xb0, 0x97, 0xdf, 0xba, 0xa6, 0xc7, 0x41, 0xfd, 0x10, 0x8b, 0x11, 0x3b, + 0xe2, 0xf0, 0x19, 0x00, 0x31, 0x16, 0xe3, 0x4f, 0x98, 0x49, 0x4a, 0xf4, 0x50, 0x3b, 0xdc, 0xbd, + 0xcc, 0xdd, 0x9d, 0x05, 0x4e, 0xa7, 0x03, 0xaf, 0xaa, 0x79, 0xa8, 0x19, 0x63, 0xf1, 0x41, 0xc7, + 0xd0, 0x07, 0x0d, 0x55, 0x99, 0x0b, 0x4a, 0xb4, 0x0e, 0x76, 0x78, 0xe7, 0x32, 0x77, 0x6f, 0x55, + 0x3d, 0xaa, 0xe2, 0xa1, 0x7a, 0x8c, 0xc5, 0x3b, 0x15, 0xcd, 0x40, 0x0d, 0x51, 0x31, 0x9f, 0x4a, + 0x08, 0x81, 0x4d, 0xb0, 0xc4, 0x7a, 0x52, 0x1b, 0xe9, 0x18, 0xde, 0x06, 0xd6, 0x94, 0xc7, 0x85, + 0xa0, 0x48, 0x85, 0x70, 0x00, 0x6a, 0xf4, 0x94, 0x32, 0x29, 0x3a, 0x56, 0xd7, 0xea, 0xb5, 0xfa, + 0xf7, 0xfd, 0xca, 0x03, 0xbe, 0xf2, 0x80, 0x5f, 0x7c, 0xfd, 0x57, 0x0a, 0x14, 0xda, 0x4a, 0x24, + 0x54, 0x76, 0x0c, 0xec, 0xcf, 0x67, 0xae, 0xe1, 0x2d, 0x4d, 0x00, 0xdf, 0x26, 0xe9, 0x7c, 0x8a, + 0x65, 0xc2, 0x19, 0xa2, 0x62, 0xc6, 0x99, 0xa0, 0xf0, 0x79, 0xb1, 0x78, 0xc2, 0x8e, 0xb8, 0x5e, + 0xa1, 0xd5, 0xbf, 0xe7, 0x5f, 0xf1, 0xa9, 0x5f, 0x0a, 0x13, 0x36, 0x14, 0xe9, 0x2a, 0x77, 0x4d, + 0x7d, 0x85, 0xd6, 0x6a, 0x1f, 0xd4, 0x32, 0x7d, 0x85, 0x5e, 0xb5, 0xd5, 0xdf, 0xdd, 0x6a, 0x2d, + 0x4e, 0x44, 0x25, 0x28, 0x1c, 0x5e, 0xfc, 0x70, 0x8c, 0xe5, 0xda, 0x31, 0xce, 0xd7, 0x8e, 0xb9, + 0x5a, 0x3b, 0xe6, 0xf7, 0xb5, 0x63, 0x7e, 0xd9, 0x38, 0xc6, 0x6a, 0xe3, 0x18, 0x17, 0x1b, 0xc7, + 0xf8, 0xe8, 0xc5, 0x89, 0x3c, 0x9e, 0x4f, 0xfc, 0x88, 0xa7, 0x41, 0x41, 0x55, 0xfe, 0xed, 0x0b, + 0x72, 0x52, 0x18, 0x7c, 0x52, 0xd3, 0x0e, 0x3f, 0xf8, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x0e, 0xe8, + 0xc3, 0x0c, 0x62, 0x03, 0x00, 0x00, } func (this *Coin) Equal(that interface{}) bool { @@ -505,6 +667,135 @@ func (m *ValAddresses) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *GasInfo) 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 *GasInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GasInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.GasUsed != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GasUsed)) + i-- + dAtA[i] = 0x10 + } + if m.GasWanted != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GasWanted)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Result) 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 *Result) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Result) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Events) > 0 { + for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Events[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.Log) > 0 { + i -= len(m.Log) + copy(dAtA[i:], m.Log) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Log))) + i-- + dAtA[i] = 0x12 + } + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *SimulationResponse) 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 *SimulationResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SimulationResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Result != nil { + { + size, err := m.Result.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + { + size, err := m.GasInfo.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { offset -= sovTypes(v) base := offset @@ -583,6 +874,59 @@ func (m *ValAddresses) Size() (n int) { return n } +func (m *GasInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GasWanted != 0 { + n += 1 + sovTypes(uint64(m.GasWanted)) + } + if m.GasUsed != 0 { + n += 1 + sovTypes(uint64(m.GasUsed)) + } + return n +} + +func (m *Result) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Log) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Events) > 0 { + for _, e := range m.Events { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *SimulationResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.GasInfo.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.Result != nil { + l = m.Result.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + func sovTypes(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1104,6 +1448,372 @@ func (m *ValAddresses) Unmarshal(dAtA []byte) error { } return nil } +func (m *GasInfo) 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 ErrIntOverflowTypes + } + 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: GasInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GasInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasWanted", wireType) + } + m.GasWanted = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasWanted |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasUsed", wireType) + } + m.GasUsed = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasUsed |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Result) 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 ErrIntOverflowTypes + } + 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: Result: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Result: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + 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 ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Log = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Events = append(m.Events, types.Event{}) + if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SimulationResponse) 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 ErrIntOverflowTypes + } + 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: SimulationResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SimulationResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GasInfo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.GasInfo.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Result == nil { + m.Result = &Result{} + } + if err := m.Result.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTypes(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/types/types.proto b/types/types.proto index 7fff608b9c..c26219caa7 100644 --- a/types/types.proto +++ b/types/types.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package cosmos_sdk.v1; import "third_party/proto/gogoproto/gogo.proto"; +import "third_party/proto/tendermint/abci/types/types.proto"; option go_package = "github.com/cosmos/cosmos-sdk/types"; option (gogoproto.goproto_stringer_all) = false; @@ -45,3 +46,35 @@ message ValAddresses { repeated bytes addresses = 1 [(gogoproto.casttype) = "ValAddress"]; } + +// GasInfo defines tx execution gas context. +message GasInfo { + // GasWanted is the maximum units of work we allow this tx to perform. + uint64 gas_wanted = 1 [(gogoproto.moretags) = "yaml:\"gas_wanted\""]; + + // GasUsed is the amount of gas actually consumed. + uint64 gas_used = 2 [(gogoproto.moretags) = "yaml:\"gas_used\""]; +} + +// Result is the union of ResponseFormat and ResponseCheckTx. +message Result { + option (gogoproto.goproto_getters) = false; + + // Data is any data returned from message or handler execution. It MUST be length + // prefixed in order to separate data from multiple message executions. + bytes data = 1; + + // Log contains the log information from message or handler execution. + string log = 2; + + // Events contains a slice of Event objects that were emitted during message or + // handler execution. + repeated tendermint.abci.types.Event events = 3 [(gogoproto.nullable) = false]; +} + +// SimulationResponse defines the response generated when a transaction is +// successfully simulated. +message SimulationResponse { + GasInfo gas_info = 1 [(gogoproto.embed) = true, (gogoproto.nullable) = false]; + Result result = 2; +} diff --git a/x/auth/types/stdtx.go b/x/auth/types/stdtx.go index 12e4aecd0b..04e9ec1fdd 100644 --- a/x/auth/types/stdtx.go +++ b/x/auth/types/stdtx.go @@ -59,7 +59,12 @@ func (fee StdFee) GasPrices() sdk.DecCoins { } func NewStdSignature(pk crypto.PubKey, sig []byte) StdSignature { - return StdSignature{PubKey: pk.Bytes(), Signature: sig} + var pkBz []byte + if pk != nil { + pkBz = pk.Bytes() + } + + return StdSignature{PubKey: pkBz, Signature: sig} } // GetSignature returns the raw signature bytes. diff --git a/x/bank/client/cli/query.go b/x/bank/client/cli/query.go index e7327a091e..ba81f44dfa 100644 --- a/x/bank/client/cli/query.go +++ b/x/bank/client/cli/query.go @@ -18,7 +18,95 @@ const ( flagDenom = "denom" ) +// NewQueryCmd returns a root CLI command handler for all x/bank query commands. +func NewQueryCmd(m codec.Marshaler) *cobra.Command { + cmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for the bank module", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmd.AddCommand(NewBalancesCmd(m)) + + return cmd +} + +// NewBalancesCmd returns a CLI command handler for querying account balance(s). +func NewBalancesCmd(m codec.Marshaler) *cobra.Command { + cmd := &cobra.Command{ + Use: "balances [address]", + Short: "Query for account balance(s) by address", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx := context.NewCLIContext().WithMarshaler(m) + + addr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + var ( + params interface{} + result interface{} + route string + ) + + denom := viper.GetString(flagDenom) + if denom == "" { + params = types.NewQueryAllBalancesParams(addr) + route = fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryAllBalances) + } else { + params = types.NewQueryBalanceParams(addr, denom) + route = fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryBalance) + } + + bz, err := m.MarshalJSON(params) + if err != nil { + return fmt.Errorf("failed to marshal params: %w", err) + } + + res, _, err := cliCtx.QueryWithData(route, bz) + if err != nil { + return err + } + + if denom == "" { + var balances sdk.Coins + if err := m.UnmarshalJSON(res, &balances); err != nil { + return err + } + + result = balances + } else { + var balance sdk.Coin + if err := m.UnmarshalJSON(res, &balance); err != nil { + return err + } + + result = balance + } + + return cliCtx.Println(result) + }, + } + + cmd.Flags().String(flagDenom, "", "The specific balance denomination to query for") + + return flags.GetCommands(cmd)[0] +} + +// --------------------------------------------------------------------------- +// Deprecated +// +// TODO: Remove once client-side Protobuf migration has been completed. +// --------------------------------------------------------------------------- + // GetQueryCmd returns the parent querying command for the bank module. +// +// TODO: Remove once client-side Protobuf migration has been completed. +// ref: https://github.com/cosmos/cosmos-sdk/issues/5864 func GetQueryCmd(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: types.ModuleName, @@ -35,6 +123,9 @@ func GetQueryCmd(cdc *codec.Codec) *cobra.Command { // GetAccountCmd returns a CLI command handler that facilitates querying for a // single or all account balances by address. +// +// TODO: Remove once client-side Protobuf migration has been completed. +// ref: https://github.com/cosmos/cosmos-sdk/issues/5864 func GetBalancesCmd(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "balances [address]", diff --git a/x/bank/client/cli/tx.go b/x/bank/client/cli/tx.go index 0764045968..92341a371a 100644 --- a/x/bank/client/cli/tx.go +++ b/x/bank/client/cli/tx.go @@ -8,6 +8,8 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + clientx "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" @@ -15,7 +17,63 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank/types" ) +// NewTxCmd returns a root CLI command handler for all x/bank transaction commands. +func NewTxCmd(m codec.Marshaler, txg tx.Generator, ar tx.AccountRetriever) *cobra.Command { + txCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Bank transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + txCmd.AddCommand(NewSendTxCmd(m, txg, ar)) + + return txCmd +} + +// NewSendTxCmd returns a CLI command handler for creating a MsgSend transaction. +func NewSendTxCmd(m codec.Marshaler, txg tx.Generator, ar tx.AccountRetriever) *cobra.Command { + cmd := &cobra.Command{ + Use: "send [from_key_or_address] [to_address] [amount]", + Short: "Create and/or sign and broadcast a MsgSend transaction", + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + inBuf := bufio.NewReader(cmd.InOrStdin()) + txf := tx.NewFactoryFromCLI(inBuf). + WithTxGenerator(txg). + WithAccountRetriever(ar) + + cliCtx := context.NewCLIContextWithInputAndFrom(inBuf, args[0]).WithMarshaler(m) + + toAddr, err := sdk.AccAddressFromBech32(args[1]) + if err != nil { + return err + } + + coins, err := sdk.ParseCoins(args[2]) + if err != nil { + return err + } + + msg := types.NewMsgSend(cliCtx.GetFromAddress(), toAddr, coins) + return clientx.GenerateOrBroadcastTx(cliCtx, txf, msg) + }, + } + + return flags.PostCommands(cmd)[0] +} + +// --------------------------------------------------------------------------- +// Deprecated +// +// TODO: Remove once client-side Protobuf migration has been completed. +// --------------------------------------------------------------------------- + // GetTxCmd returns the transaction commands for this module +// +// TODO: Remove once client-side Protobuf migration has been completed. +// ref: https://github.com/cosmos/cosmos-sdk/issues/5864 func GetTxCmd(cdc *codec.Codec) *cobra.Command { txCmd := &cobra.Command{ Use: types.ModuleName, @@ -31,6 +89,9 @@ func GetTxCmd(cdc *codec.Codec) *cobra.Command { } // SendTxCmd will create a send tx and sign it with the given key. +// +// TODO: Remove once client-side Protobuf migration has been completed. +// ref: https://github.com/cosmos/cosmos-sdk/issues/5864 func SendTxCmd(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "send [from_key_or_address] [to_address] [amount]", diff --git a/x/bank/client/rest/query.go b/x/bank/client/rest/query.go index 99b3680bbb..baf1cbe429 100644 --- a/x/bank/client/rest/query.go +++ b/x/bank/client/rest/query.go @@ -7,6 +7,7 @@ import ( "github.com/gorilla/mux" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/rest" "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -14,7 +15,7 @@ import ( // QueryBalancesRequestHandlerFn returns a REST handler that queries for all // account balances or a specific balance by denomination. -func QueryBalancesRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { +func QueryBalancesRequestHandlerFn(ctx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") vars := mux.Vars(r) @@ -26,7 +27,7 @@ func QueryBalancesRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return } - cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + ctx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, ctx, r) if !ok { return } @@ -36,6 +37,16 @@ func QueryBalancesRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { route string ) + // TODO: Remove once client-side Protobuf migration has been completed. + // ref: https://github.com/cosmos/cosmos-sdk/issues/5864 + var marshaler codec.JSONMarshaler + + if ctx.Marshaler != nil { + marshaler = ctx.Marshaler + } else { + marshaler = ctx.Codec + } + denom := r.FormValue("denom") if denom == "" { params = types.NewQueryAllBalancesParams(addr) @@ -45,19 +56,19 @@ func QueryBalancesRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { route = fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryBalance) } - bz, err := cliCtx.Codec.MarshalJSON(params) + bz, err := marshaler.MarshalJSON(params) if err != nil { rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } - res, height, err := cliCtx.QueryWithData(route, bz) + res, height, err := ctx.QueryWithData(route, bz) if err != nil { rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } - cliCtx = cliCtx.WithHeight(height) - rest.PostProcessResponse(w, cliCtx, res) + ctx = ctx.WithHeight(height) + rest.PostProcessResponse(w, ctx, res) } } diff --git a/x/bank/client/rest/rest.go b/x/bank/client/rest/rest.go index 578e41c067..48e2776c87 100644 --- a/x/bank/client/rest/rest.go +++ b/x/bank/client/rest/rest.go @@ -4,8 +4,23 @@ import ( "github.com/gorilla/mux" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/codec" ) +// RegisterHandlers registers all x/bank transaction and query HTTP REST handlers +// on the provided mux router. +func RegisterHandlers(ctx context.CLIContext, m codec.Marshaler, txg tx.Generator, r *mux.Router) { + r.HandleFunc("/bank/accounts/{address}/transfers", NewSendRequestHandlerFn(ctx, m, txg)).Methods("POST") + r.HandleFunc("/bank/balances/{address}", QueryBalancesRequestHandlerFn(ctx)).Methods("GET") +} + +// --------------------------------------------------------------------------- +// Deprecated +// +// TODO: Remove once client-side Protobuf migration has been completed. +// --------------------------------------------------------------------------- + // RegisterRoutes - Central function to define routes that get registered by the main application func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) { r.HandleFunc("/bank/accounts/{address}/transfers", SendRequestHandlerFn(cliCtx)).Methods("POST") diff --git a/x/bank/client/rest/tx.go b/x/bank/client/rest/tx.go index 30178166bb..b9712c160a 100644 --- a/x/bank/client/rest/tx.go +++ b/x/bank/client/rest/tx.go @@ -6,6 +6,8 @@ import ( "github.com/gorilla/mux" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/rest" authclient "github.com/cosmos/cosmos-sdk/x/auth/client" @@ -18,7 +20,52 @@ type SendReq struct { Amount sdk.Coins `json:"amount" yaml:"amount"` } +// NewSendRequestHandlerFn returns an HTTP REST handler for creating a MsgSend +// transaction. +func NewSendRequestHandlerFn(ctx context.CLIContext, m codec.Marshaler, txg tx.Generator) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + ctx = ctx.WithMarshaler(m) + + vars := mux.Vars(r) + bech32Addr := vars["address"] + + toAddr, err := sdk.AccAddressFromBech32(bech32Addr) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + var req SendReq + if !rest.ReadRESTReq(w, r, ctx.Marshaler, &req) { + return + } + + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { + return + } + + fromAddr, err := sdk.AccAddressFromBech32(req.BaseReq.From) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + msg := types.NewMsgSend(fromAddr, toAddr, req.Amount) + tx.WriteGeneratedTxResponse(ctx, w, txg, req.BaseReq, msg) + } +} + +// --------------------------------------------------------------------------- +// Deprecated +// +// TODO: Remove once client-side Protobuf migration has been completed. +// --------------------------------------------------------------------------- + // SendRequestHandlerFn - http request handler to send coins to a address. +// +// TODO: Remove once client-side Protobuf migration has been completed. +// ref: https://github.com/cosmos/cosmos-sdk/issues/5864 func SendRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/x/bank/handler.go b/x/bank/handler.go index 30341ab47b..5ec0033bce 100644 --- a/x/bank/handler.go +++ b/x/bank/handler.go @@ -47,7 +47,7 @@ func handleMsgSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgSend) (*sdk.Re ), ) - return &sdk.Result{Events: ctx.EventManager().Events()}, nil + return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil } // Handle MsgMultiSend. @@ -75,5 +75,5 @@ func handleMsgMultiSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgMultiSend ), ) - return &sdk.Result{Events: ctx.EventManager().Events()}, nil + return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil } diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index 472fe39972..c41e41be09 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -240,7 +240,7 @@ func (suite *IntegrationTestSuite) TestMsgSendEvents() { suite.Require().Error(app.BankKeeper.SendCoins(ctx, addr, addr2, newCoins)) - events := ctx.EventManager().Events() + events := ctx.EventManager().ABCIEvents() suite.Require().Equal(2, len(events)) event1 := sdk.Event{ @@ -264,18 +264,18 @@ func (suite *IntegrationTestSuite) TestMsgSendEvents() { tmkv.Pair{Key: []byte(types.AttributeKeySender), Value: []byte(addr.String())}, ) - suite.Require().Equal(event1, events[0]) - suite.Require().Equal(event2, events[1]) + suite.Require().Equal(abci.Event(event1), events[0]) + suite.Require().Equal(abci.Event(event2), events[1]) app.BankKeeper.SetBalances(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50))) newCoins = sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50)) suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr, addr2, newCoins)) - events = ctx.EventManager().Events() + events = ctx.EventManager().ABCIEvents() suite.Require().Equal(4, len(events)) - suite.Require().Equal(event1, events[2]) - suite.Require().Equal(event2, events[3]) + suite.Require().Equal(abci.Event(event1), events[2]) + suite.Require().Equal(abci.Event(event2), events[3]) } func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { @@ -306,7 +306,7 @@ func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { suite.Require().Error(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)) - events := ctx.EventManager().Events() + events := ctx.EventManager().ABCIEvents() suite.Require().Equal(0, len(events)) // Set addr's coins but not addr2's coins @@ -314,7 +314,7 @@ func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { suite.Require().Error(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)) - events = ctx.EventManager().Events() + events = ctx.EventManager().ABCIEvents() suite.Require().Equal(1, len(events)) event1 := sdk.Event{ @@ -325,7 +325,7 @@ func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { event1.Attributes, tmkv.Pair{Key: []byte(types.AttributeKeySender), Value: []byte(addr.String())}, ) - suite.Require().Equal(event1, events[0]) + suite.Require().Equal(abci.Event(event1), events[0]) // Set addr's coins and addr2's coins app.BankKeeper.SetBalances(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50))) @@ -336,7 +336,7 @@ func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { suite.Require().NoError(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)) - events = ctx.EventManager().Events() + events = ctx.EventManager().ABCIEvents() suite.Require().Equal(5, len(events)) event2 := sdk.Event{ @@ -371,10 +371,10 @@ func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { tmkv.Pair{Key: []byte(sdk.AttributeKeyAmount), Value: []byte(newCoins2.String())}, ) - suite.Require().Equal(event1, events[1]) - suite.Require().Equal(event2, events[2]) - suite.Require().Equal(event3, events[3]) - suite.Require().Equal(event4, events[4]) + suite.Require().Equal(abci.Event(event1), events[1]) + suite.Require().Equal(abci.Event(event2), events[2]) + suite.Require().Equal(abci.Event(event3), events[3]) + suite.Require().Equal(abci.Event(event4), events[4]) } func (suite *IntegrationTestSuite) TestSpendableCoins() { diff --git a/x/crisis/handler.go b/x/crisis/handler.go index cd94db85a5..3abf3fa831 100644 --- a/x/crisis/handler.go +++ b/x/crisis/handler.go @@ -83,5 +83,5 @@ func handleMsgVerifyInvariant(ctx sdk.Context, msg types.MsgVerifyInvariant, k k ), }) - return &sdk.Result{Events: ctx.EventManager().Events()}, nil + return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil } diff --git a/x/distribution/handler.go b/x/distribution/handler.go index 642b9e0d89..5216cdad29 100644 --- a/x/distribution/handler.go +++ b/x/distribution/handler.go @@ -47,7 +47,7 @@ func handleMsgModifyWithdrawAddress(ctx sdk.Context, msg types.MsgSetWithdrawAdd ), ) - return &sdk.Result{Events: ctx.EventManager().Events()}, nil + return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil } func handleMsgWithdrawDelegatorReward(ctx sdk.Context, msg types.MsgWithdrawDelegatorReward, k keeper.Keeper) (*sdk.Result, error) { @@ -64,7 +64,7 @@ func handleMsgWithdrawDelegatorReward(ctx sdk.Context, msg types.MsgWithdrawDele ), ) - return &sdk.Result{Events: ctx.EventManager().Events()}, nil + return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil } func handleMsgWithdrawValidatorCommission(ctx sdk.Context, msg types.MsgWithdrawValidatorCommission, k keeper.Keeper) (*sdk.Result, error) { @@ -81,7 +81,7 @@ func handleMsgWithdrawValidatorCommission(ctx sdk.Context, msg types.MsgWithdraw ), ) - return &sdk.Result{Events: ctx.EventManager().Events()}, nil + return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil } func handleMsgFundCommunityPool(ctx sdk.Context, msg types.MsgFundCommunityPool, k keeper.Keeper) (*sdk.Result, error) { @@ -97,7 +97,7 @@ func handleMsgFundCommunityPool(ctx sdk.Context, msg types.MsgFundCommunityPool, ), ) - return &sdk.Result{Events: ctx.EventManager().Events()}, nil + return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil } func NewCommunityPoolSpendProposalHandler(k Keeper) govtypes.Handler { diff --git a/x/evidence/handler.go b/x/evidence/handler.go index e7b83eb190..1d3c82f937 100644 --- a/x/evidence/handler.go +++ b/x/evidence/handler.go @@ -41,6 +41,6 @@ func handleMsgSubmitEvidence(ctx sdk.Context, k Keeper, msg exported.MsgSubmitEv return &sdk.Result{ Data: evidence.Hash(), - Events: ctx.EventManager().Events(), + Events: ctx.EventManager().ABCIEvents(), }, nil } diff --git a/x/gov/handler.go b/x/gov/handler.go index b50644a519..02edefcdbd 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -59,7 +59,7 @@ func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitPropos return &sdk.Result{ Data: GetProposalIDBytes(proposal.ProposalID), - Events: ctx.EventManager().Events(), + Events: ctx.EventManager().ABCIEvents(), }, nil } @@ -86,7 +86,7 @@ func handleMsgDeposit(ctx sdk.Context, keeper Keeper, msg MsgDeposit) (*sdk.Resu ) } - return &sdk.Result{Events: ctx.EventManager().Events()}, nil + return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil } func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) (*sdk.Result, error) { @@ -103,5 +103,5 @@ func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) (*sdk.Result, er ), ) - return &sdk.Result{Events: ctx.EventManager().Events()}, nil + return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil } diff --git a/x/slashing/handler.go b/x/slashing/handler.go index 629a92dde2..91d3c49d1e 100644 --- a/x/slashing/handler.go +++ b/x/slashing/handler.go @@ -37,5 +37,5 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) (*sdk.Result, err ), ) - return &sdk.Result{Events: ctx.EventManager().Events()}, nil + return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil } diff --git a/x/staking/handler.go b/x/staking/handler.go index e6ed8e3b57..d140dc92bf 100644 --- a/x/staking/handler.go +++ b/x/staking/handler.go @@ -116,7 +116,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k ), }) - return &sdk.Result{Events: ctx.EventManager().Events()}, nil + return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil } func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keeper.Keeper) (*sdk.Result, error) { @@ -172,7 +172,7 @@ func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keepe ), }) - return &sdk.Result{Events: ctx.EventManager().Events()}, nil + return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil } func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) (*sdk.Result, error) { @@ -204,7 +204,7 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) ), }) - return &sdk.Result{Events: ctx.EventManager().Events()}, nil + return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil } func handleMsgUndelegate(ctx sdk.Context, msg types.MsgUndelegate, k keeper.Keeper) (*sdk.Result, error) { @@ -244,7 +244,7 @@ func handleMsgUndelegate(ctx sdk.Context, msg types.MsgUndelegate, k keeper.Keep ), }) - return &sdk.Result{Data: completionTimeBz, Events: ctx.EventManager().Events()}, nil + return &sdk.Result{Data: completionTimeBz, Events: ctx.EventManager().ABCIEvents()}, nil } func handleMsgBeginRedelegate(ctx sdk.Context, msg types.MsgBeginRedelegate, k keeper.Keeper) (*sdk.Result, error) { @@ -287,5 +287,5 @@ func handleMsgBeginRedelegate(ctx sdk.Context, msg types.MsgBeginRedelegate, k k ), }) - return &sdk.Result{Data: completionTimeBz, Events: ctx.EventManager().Events()}, nil + return &sdk.Result{Data: completionTimeBz, Events: ctx.EventManager().ABCIEvents()}, nil }