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

Tx CLI proto module interface #5989

Merged
merged 58 commits into from
May 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
7d8b68c
WIP
aaronc Apr 9, 2020
c37ce56
WIP
aaronc Apr 9, 2020
66d5f7a
Merge branch 'master' of github.com:cosmos/cosmos-sdk into aaronc/586…
aaronc Apr 13, 2020
11947b1
WIP on removing x/auth dependency from client/tx
aaronc Apr 13, 2020
387a963
Merge branch 'master' of github.com:cosmos/cosmos-sdk into aaronc/586…
aaronc Apr 28, 2020
6a0fa18
Revert unneeded changes
aaronc Apr 28, 2020
026a8ea
Simplify cli tx UX
aaronc Apr 28, 2020
d0cd45a
Wire up bank tx REST routes
aaronc Apr 28, 2020
97d3537
Fix assignment issue
aaronc Apr 28, 2020
db78c99
Merge branch 'master' of github.com:cosmos/cosmos-sdk into aaronc/586…
aaronc May 15, 2020
77a96a0
Wire up bank NewSendTxCmd
aaronc May 15, 2020
31ba870
fix lint
aaronc May 18, 2020
89bc11d
revert file
aaronc May 18, 2020
a2c9f54
revert file
aaronc May 18, 2020
fcc4e07
Merge branch 'master' of github.com:cosmos/cosmos-sdk into aaronc/586…
aaronc May 18, 2020
b7600bd
fix simcli
aaronc May 18, 2020
2f99c3f
Refactor AccountRetriever
aaronc May 19, 2020
cab64cd
Fix build
aaronc May 19, 2020
6af906d
Fix build
aaronc May 19, 2020
457a612
Fix build
aaronc May 19, 2020
d702137
Fix integration tests
aaronc May 19, 2020
3ab0141
Merge branch 'master' of github.com:cosmos/cosmos-sdk into aaronc/586…
aaronc May 19, 2020
7203652
Fix tests
aaronc May 19, 2020
fc0b01a
Docs, linting
aaronc May 19, 2020
aacd246
Linting
aaronc May 19, 2020
8ef7861
WIP on all modules
aaronc May 19, 2020
848c5e4
Merge branch 'master' of github.com:cosmos/cosmos-sdk into aaronc/586…
aaronc May 19, 2020
b6918f6
Implement other module new tx cmd's
aaronc May 19, 2020
ed494ce
Fix cmd's
aaronc May 19, 2020
c51730b
Refactor existing GetTxCmd
aaronc May 19, 2020
992cef3
Merge branch 'master' of github.com:cosmos/cosmos-sdk into aaronc/586…
aaronc May 19, 2020
0c624ce
Fix cmd
aaronc May 20, 2020
414ef2c
Removing deprecated code
aaronc May 20, 2020
50c1044
Update ADR 020 & CHANGELOG
aaronc May 20, 2020
b47fdc1
Lint
aaronc May 20, 2020
aa16184
Lint
aaronc May 20, 2020
3d24b15
Lint
aaronc May 20, 2020
865bcd0
Lint
aaronc May 20, 2020
b3f030d
Lint
aaronc May 20, 2020
f952ed3
Lint
aaronc May 20, 2020
7dc136b
Lint
aaronc May 20, 2020
c19ba5b
Fix client/tx tests
aaronc May 20, 2020
e6d1ff3
Fix mocks
aaronc May 20, 2020
0d74f75
Merge branch 'master' of github.com:cosmos/cosmos-sdk into aaronc/586…
aaronc May 20, 2020
06ceb42
Fix tests
aaronc May 20, 2020
0632d70
Lint fixes
aaronc May 20, 2020
0eb278c
REST tx migration
aaronc May 20, 2020
4d9c978
Wire up REST
aaronc May 20, 2020
4ac82f0
Linting
aaronc May 20, 2020
753b792
Update CHANGELOG, docs
aaronc May 20, 2020
4ffd783
Fix tests
aaronc May 20, 2020
952a3da
Merge branch 'master' of github.com:cosmos/cosmos-sdk into aaronc/586…
aaronc May 20, 2020
b5460b5
lint
aaronc May 20, 2020
01f7f55
Address review feedback
aaronc May 21, 2020
d4c047f
Merge branch 'master' of github.com:cosmos/cosmos-sdk into aaronc/586…
aaronc May 21, 2020
30b0c06
Update CHANGELOG.md
aaronc May 21, 2020
22f3b92
Update CHANGELOG.md
aaronc May 21, 2020
dd99d83
group vars
aaronc May 21, 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ ALL legacy code should use `*codec.Codec` instead of `*amino.Codec` directly
* (x/gov) [\#6147](https://github.com/cosmos/cosmos-sdk/pull/6147) The `Content` field on `Proposal` and `MsgSubmitProposal`
is now `Any` in concordance with [ADR 019](docs/architecture/adr-019-protobuf-state-encoding.md) and `GetContent` should now
be used to retrieve the actual proposal `Content`. Also the `NewMsgSubmitProposal` constructor now may return an `error`
* (modules) [\#5989](https://github.com/cosmos/cosmos-sdk/pull/5989) `AppModuleBasic.GetTxCmd` now takes a single `CLIContext` parameter.
* (x/auth) [\#5989](https://github.com/cosmos/cosmos-sdk/pull/5989) All `AccountRetriever` methods now take `NodeQuerier` as a parameter instead of as a struct member.

### Features

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ build-sim: go.sum
build-sim

mocks: $(MOCKS_DIR)
mockgen -source=x/auth/types/account_retriever.go -package mocks -destination tests/mocks/account_retriever.go
mockgen -source=client/context/account_retriever.go -package mocks -destination tests/mocks/account_retriever.go
mockgen -package mocks -destination tests/mocks/tendermint_tm_db_DB.go github.com/tendermint/tm-db DB
mockgen -source=types/module/module.go -package mocks -destination tests/mocks/types_module_module.go
mockgen -source=types/invariant.go -package mocks -destination tests/mocks/types_invariant.go
Expand Down
21 changes: 21 additions & 0 deletions client/context/account_retriever.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package context

import "github.com/cosmos/cosmos-sdk/types"

// AccountRetriever defines the interfaces required by transactions to
// ensure an account exists and to be able to query for account fields necessary
// for signing.
type AccountRetriever interface {
EnsureExists(nodeQuerier NodeQuerier, addr types.AccAddress) error
GetAccountNumberSequence(nodeQuerier NodeQuerier, addr types.AccAddress) (accNum uint64, accSeq uint64, err error)
}

// NodeQuerier is an interface that is satisfied by types that provide the QueryWithData method
type NodeQuerier interface {
// QueryWithData performs a query to a Tendermint node with the provided path
// and a data payload. It returns the result and height of the query upon success
// or an error if the query fails.
QueryWithData(path string, data []byte) ([]byte, int64, error)
}

var _ NodeQuerier = CLIContext{}
212 changes: 129 additions & 83 deletions client/context/context.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package context

import (
"bufio"
"fmt"
"io"
"os"

"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"
rpchttp "github.com/tendermint/tendermint/rpc/client/http"
yaml "gopkg.in/yaml.v2"

"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/codec"
Expand All @@ -22,28 +24,30 @@ import (
// CLIContext implements a typical CLI context created in SDK modules for
// transaction handling and queries.
type CLIContext struct {
FromAddress sdk.AccAddress
Client rpcclient.Client
ChainID string
Marshaler codec.Marshaler
Input io.Reader
Keyring keyring.Keyring
Output io.Writer
OutputFormat string
Height int64
HomeDir string
NodeURI string
From string
BroadcastMode string
Verifier tmlite.Verifier
FromName string
TrustNode bool
UseLedger bool
Simulate bool
GenerateOnly bool
Offline bool
Indent bool
SkipConfirm bool
FromAddress sdk.AccAddress
Client rpcclient.Client
ChainID string
JSONMarshaler codec.JSONMarshaler
Input io.Reader
Keyring keyring.Keyring
Output io.Writer
OutputFormat string
Height int64
HomeDir string
NodeURI string
From string
BroadcastMode string
Verifier tmlite.Verifier
FromName string
TrustNode bool
UseLedger bool
Simulate bool
GenerateOnly bool
Offline bool
Indent bool
SkipConfirm bool
TxGenerator TxGenerator
AccountRetriever AccountRetriever

// TODO: Deprecated (remove).
Codec *codec.Codec
Expand All @@ -56,26 +60,40 @@ type CLIContext struct {
// a CLIContext in tests or any non CLI-based environment, the verifier will not be created
// and will be set as nil because FlagTrustNode must be set.
func NewCLIContextWithInputAndFrom(input io.Reader, from string) CLIContext {
var nodeURI string
var rpc rpcclient.Client
ctx := CLIContext{}
return ctx.InitWithInputAndFrom(input, from)
}

homedir := viper.GetString(flags.FlagHome)
genOnly := viper.GetBool(flags.FlagGenerateOnly)
backend := viper.GetString(flags.FlagKeyringBackend)
if len(backend) == 0 {
backend = keyring.BackendMemory
}
// NewCLIContextWithFrom returns a new initialized CLIContext with parameters from the
// command line using Viper. It takes a key name or address and populates the FromName and
// FromAddress field accordingly. It will also create Tendermint verifier using
// the chain ID, home directory and RPC URI provided by the command line. If using
// a CLIContext in tests or any non CLI-based environment, the verifier will not
// be created and will be set as nil because FlagTrustNode must be set.
func NewCLIContextWithFrom(from string) CLIContext {
return NewCLIContextWithInputAndFrom(os.Stdin, from)
}

keyring, err := newKeyringFromFlags(backend, homedir, input, genOnly)
if err != nil {
panic(fmt.Errorf("couldn't acquire keyring: %v", err))
}
// NewCLIContext returns a new initialized CLIContext with parameters from the
// command line using Viper.
func NewCLIContext() CLIContext { return NewCLIContextWithFrom(viper.GetString(flags.FlagFrom)) }

fromAddress, fromName, err := GetFromFields(keyring, from, genOnly)
if err != nil {
fmt.Printf("failed to get from fields: %v\n", err)
os.Exit(1)
}
// NewCLIContextWithInput returns a new initialized CLIContext with a io.Reader and parameters
// from the command line using Viper.
func NewCLIContextWithInput(input io.Reader) CLIContext {
return NewCLIContextWithInputAndFrom(input, viper.GetString(flags.FlagFrom))
}

// InitWithInputAndFrom returns a new CLIContext re-initialized from an existing
// CLIContext with a new io.Reader and from parameter
func (ctx CLIContext) InitWithInputAndFrom(input io.Reader, from string) CLIContext {
input = bufio.NewReader(input)

var (
nodeURI string
rpc rpcclient.Client
err error
)

offline := viper.GetBool(flags.FlagOffline)
if !offline {
Expand All @@ -90,29 +108,48 @@ func NewCLIContextWithInputAndFrom(input io.Reader, from string) CLIContext {
}

trustNode := viper.GetBool(flags.FlagTrustNode)
ctx := CLIContext{
Client: rpc,
ChainID: viper.GetString(flags.FlagChainID),
Input: input,
Output: os.Stdout,
NodeURI: nodeURI,
From: viper.GetString(flags.FlagFrom),
Keyring: keyring,
OutputFormat: viper.GetString(cli.OutputFlag),
Height: viper.GetInt64(flags.FlagHeight),
HomeDir: homedir,
TrustNode: trustNode,
UseLedger: viper.GetBool(flags.FlagUseLedger),
BroadcastMode: viper.GetString(flags.FlagBroadcastMode),
Simulate: viper.GetBool(flags.FlagDryRun),
GenerateOnly: genOnly,
Offline: offline,
FromAddress: fromAddress,
FromName: fromName,
Indent: viper.GetBool(flags.FlagIndentResponse),
SkipConfirm: viper.GetBool(flags.FlagSkipConfirmation),

ctx.Client = rpc
ctx.ChainID = viper.GetString(flags.FlagChainID)
ctx.Input = input
ctx.Output = os.Stdout
ctx.NodeURI = nodeURI
ctx.From = viper.GetString(flags.FlagFrom)
ctx.OutputFormat = viper.GetString(cli.OutputFlag)
ctx.Height = viper.GetInt64(flags.FlagHeight)
ctx.TrustNode = trustNode
ctx.UseLedger = viper.GetBool(flags.FlagUseLedger)
ctx.BroadcastMode = viper.GetString(flags.FlagBroadcastMode)
ctx.Simulate = viper.GetBool(flags.FlagDryRun)
ctx.Offline = offline
ctx.Indent = viper.GetBool(flags.FlagIndentResponse)
ctx.SkipConfirm = viper.GetBool(flags.FlagSkipConfirmation)

homedir := viper.GetString(flags.FlagHome)
genOnly := viper.GetBool(flags.FlagGenerateOnly)
backend := viper.GetString(flags.FlagKeyringBackend)
if len(backend) == 0 {
backend = keyring.BackendMemory
}

kr, err := newKeyringFromFlags(backend, homedir, input, genOnly)
if err != nil {
panic(fmt.Errorf("couldn't acquire keyring: %v", err))
}

fromAddress, fromName, err := GetFromFields(kr, from, genOnly)
if err != nil {
fmt.Printf("failed to get from fields: %v\n", err)
os.Exit(1)
}

ctx.HomeDir = homedir

ctx.Keyring = kr
ctx.FromAddress = fromAddress
ctx.FromName = fromName
ctx.GenerateOnly = genOnly

if offline {
return ctx
}
Expand All @@ -124,27 +161,24 @@ func NewCLIContextWithInputAndFrom(input io.Reader, from string) CLIContext {
os.Exit(1)
}

return ctx.WithVerifier(verifier)
ctx.Verifier = verifier
return ctx
}

// NewCLIContextWithFrom returns a new initialized CLIContext with parameters from the
// command line using Viper. It takes a key name or address and populates the FromName and
// FromAddress field accordingly. It will also create Tendermint verifier using
// the chain ID, home directory and RPC URI provided by the command line. If using
// a CLIContext in tests or any non CLI-based environment, the verifier will not
// be created and will be set as nil because FlagTrustNode must be set.
func NewCLIContextWithFrom(from string) CLIContext {
return NewCLIContextWithInputAndFrom(os.Stdin, from)
// InitWithFrom returns a new CLIContext re-initialized from an existing
// CLIContext with a new from parameter
func (ctx CLIContext) InitWithFrom(from string) CLIContext {
return ctx.InitWithInputAndFrom(os.Stdin, from)
}

// NewCLIContext returns a new initialized CLIContext with parameters from the
// command line using Viper.
func NewCLIContext() CLIContext { return NewCLIContextWithFrom(viper.GetString(flags.FlagFrom)) }
// Init returns a new CLIContext re-initialized from an existing
// CLIContext with parameters from the command line using Viper.
func (ctx CLIContext) Init() CLIContext { return ctx.InitWithFrom(viper.GetString(flags.FlagFrom)) }

// NewCLIContextWithInput returns a new initialized CLIContext with a io.Reader and parameters
// from the command line using Viper.
func NewCLIContextWithInput(input io.Reader) CLIContext {
return NewCLIContextWithInputAndFrom(input, viper.GetString(flags.FlagFrom))
// InitWithInput returns a new CLIContext re-initialized from an existing
// CLIContext with a new io.Reader and from parameter
func (ctx CLIContext) InitWithInput(input io.Reader) CLIContext {
return ctx.InitWithInputAndFrom(input, viper.GetString(flags.FlagFrom))
}

// WithKeyring returns a copy of the context with an updated keyring.
Expand All @@ -159,9 +193,9 @@ func (ctx CLIContext) WithInput(r io.Reader) CLIContext {
return ctx
}

// WithMarshaler returns a copy of the CLIContext with an updated Marshaler.
func (ctx CLIContext) WithMarshaler(m codec.Marshaler) CLIContext {
ctx.Marshaler = m
// WithJSONMarshaler returns a copy of the CLIContext with an updated JSONMarshaler.
func (ctx CLIContext) WithJSONMarshaler(m codec.JSONMarshaler) CLIContext {
ctx.JSONMarshaler = m
return ctx
}

Expand Down Expand Up @@ -265,9 +299,21 @@ func (ctx CLIContext) WithBroadcastMode(mode string) CLIContext {
return ctx
}

// WithTxGenerator returns the context with an updated TxGenerator
func (ctx CLIContext) WithTxGenerator(generator TxGenerator) CLIContext {
ctx.TxGenerator = generator
return ctx
}

// WithAccountRetriever returns the context with an updated AccountRetriever
func (ctx CLIContext) WithAccountRetriever(retriever AccountRetriever) CLIContext {
ctx.AccountRetriever = retriever
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.
// will be JSON encoded using ctx.JSONMarshaler. An error is returned upon failure.
func (ctx CLIContext) Println(toPrint interface{}) error {
var (
out []byte
Expand All @@ -279,11 +325,11 @@ func (ctx CLIContext) Println(toPrint interface{}) error {
out, err = yaml.Marshal(&toPrint)

case "json":
out, err = ctx.Marshaler.MarshalJSON(toPrint)
out, err = ctx.JSONMarshaler.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.
// JSON should have the correct output produced by ctx.JSONMarshaler.
if ctx.Indent && err == nil {
out, err = codec.MarshalIndentFromJSON(out)
}
Expand Down
51 changes: 51 additions & 0 deletions client/context/tx_generator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package context

import (
"github.com/tendermint/tendermint/crypto"

"github.com/cosmos/cosmos-sdk/types"
)

type (
// TxGenerator defines an interface a client can utilize to generate an
// application-defined concrete transaction type. The type returned must
// implement TxBuilder.
TxGenerator interface {
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
NewTx() TxBuilder
NewFee() ClientFee
NewSignature() ClientSignature
MarshalTx(tx types.Tx) ([]byte, error)
}

ClientFee interface {
types.Fee
SetGas(uint64)
SetAmount(types.Coins)
}

ClientSignature interface {
types.Signature
SetPubKey(crypto.PubKey) error
SetSignature([]byte)
}

// TxBuilder defines an interface which an application-defined concrete transaction
// type must implement. Namely, it must be able to set messages, generate
// signatures, and provide canonical bytes to sign over. The transaction must
// also know how to encode itself.
TxBuilder interface {
GetTx() types.Tx

SetMsgs(...types.Msg) error
GetSignatures() []types.Signature
SetSignatures(...ClientSignature) error
GetFee() types.Fee
SetFee(ClientFee) error
GetMemo() string
SetMemo(string)

// CanonicalSignBytes returns the canonical sign bytes to sign over, given a
// chain ID, along with an account and sequence number.
CanonicalSignBytes(cid string, num, seq uint64) ([]byte, error)
alessio marked this conversation as resolved.
Show resolved Hide resolved
}
)
Loading