Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Proto Client Migration: x/bank #5865

Merged
merged 31 commits into from
Mar 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
b0f784d
Implement factory and remove tx generator from CLIContext
alexanderbez Mar 24, 2020
d4d4da4
Implement client and factory
alexanderbez Mar 24, 2020
8bb0cfd
Use JSON for SimulationResponse
alexanderbez Mar 24, 2020
0f44739
Fix imports
alexanderbez Mar 24, 2020
ef29fef
Fix test and update ADR
alexanderbez Mar 24, 2020
486fa5b
Fix constructors
alexanderbez Mar 24, 2020
33c090e
Use auth instead of func interface
alexanderbez Mar 24, 2020
70d0241
tx tests
alexanderbez Mar 24, 2020
c4a4047
Implement NewSendTxCmd
alexanderbez Mar 25, 2020
f20db1c
Update ADR
alexanderbez Mar 25, 2020
e77d5cb
Update ADR + changelog
alexanderbez Mar 25, 2020
d962526
Implement and use CLIContext.Print
alexanderbez Mar 25, 2020
d21020e
Update x/bank CLI query commands
alexanderbez Mar 25, 2020
7e67d84
Lint
alexanderbez Mar 25, 2020
3ecc461
Implement and use MarshalIndentFromJSON
alexanderbez Mar 25, 2020
17b68fb
Prep PostProcessResponseBare and PostProcessResponse
alexanderbez Mar 25, 2020
0e83e32
Prep QueryBalancesRequestHandlerFn for proto
alexanderbez Mar 25, 2020
3e0cf99
Finish remaining x/bank REST handlers
alexanderbez Mar 25, 2020
37885b8
Merge branch 'master' into bez/tx-client-proto-i
alexanderbez Mar 25, 2020
f4e6bd6
Fix build
alexanderbez Mar 25, 2020
e950dd3
Error when keybase is nil during Sign
alexanderbez Mar 25, 2020
6a33b42
Do not sanitize memo
alexanderbez Mar 25, 2020
75412d0
Rename to Println
alexanderbez Mar 25, 2020
7310a0c
Fix build
alexanderbez Mar 25, 2020
2978de9
Fix MarshalIndentFromJSON
alexanderbez Mar 25, 2020
c77b2b9
Update docs/architecture/adr-020-protobuf-transaction-encoding.md
alexanderbez Mar 26, 2020
e485789
Merge branch 'master' into bez/tx-client-proto-i
alexanderbez Mar 26, 2020
6135912
JSON Proto changes
alexanderbez Mar 26, 2020
da40015
Fix tests
alexanderbez Mar 26, 2020
78fd300
Fix bank tests
alexanderbez Mar 26, 2020
fb599ad
Merge branch 'master' into bez/tx-client-proto-i
alexanderbez Mar 26, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
13 changes: 9 additions & 4 deletions baseapp/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}

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

Expand Down Expand Up @@ -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":
Expand Down
4 changes: 2 additions & 2 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
//
Expand All @@ -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
}
7 changes: 5 additions & 2 deletions baseapp/baseapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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()
}
Expand Down
48 changes: 37 additions & 11 deletions client/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
163 changes: 163 additions & 0 deletions client/tx/factory.go
Original file line number Diff line number Diff line change
@@ -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
}
Loading