Skip to content

Commit

Permalink
Separate account getters from client/context
Browse files Browse the repository at this point in the history
Closes: #4543
  • Loading branch information
alessio committed Jun 18, 2019
1 parent 55928ad commit 4fa7fcf
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 107 deletions.
76 changes: 0 additions & 76 deletions client/context/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (

"github.com/cosmos/cosmos-sdk/store/rootmulti"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
)

// GetNode returns an RPC client. If the context's client is not defined, an
Expand Down Expand Up @@ -63,26 +62,6 @@ func (ctx CLIContext) QuerySubspace(subspace []byte, storeName string) (res []sd
return
}

// GetAccount queries for an account given an address and a block height. An
// error is returned if the query or decoding fails.
func (ctx CLIContext) GetAccount(address []byte) (authtypes.Account, error) {
if ctx.AccDecoder == nil {
return nil, errors.New("account decoder required but not provided")
}

res, err := ctx.queryAccount(address)
if err != nil {
return nil, err
}

var account authtypes.Account
if err := ctx.Codec.UnmarshalJSON(res, &account); err != nil {
return nil, err
}

return account, nil
}

// GetFromAddress returns the from address from the context's name.
func (ctx CLIContext) GetFromAddress() sdk.AccAddress {
return ctx.FromAddress
Expand All @@ -93,61 +72,6 @@ func (ctx CLIContext) GetFromName() string {
return ctx.FromName
}

// GetAccountNumber returns the next account number for the given account
// address.
func (ctx CLIContext) GetAccountNumber(address []byte) (uint64, error) {
account, err := ctx.GetAccount(address)
if err != nil {
return 0, err
}

return account.GetAccountNumber(), nil
}

// GetAccountSequence returns the sequence number for the given account
// address.
func (ctx CLIContext) GetAccountSequence(address []byte) (uint64, error) {
account, err := ctx.GetAccount(address)
if err != nil {
return 0, err
}

return account.GetSequence(), nil
}

// EnsureAccountExists ensures that an account exists for a given context. An
// error is returned if it does not.
func (ctx CLIContext) EnsureAccountExists() error {
addr := ctx.GetFromAddress()
return ctx.EnsureAccountExistsFromAddr(addr)
}

// EnsureAccountExistsFromAddr ensures that an account exists for a given
// address. Instead of using the context's from name, a direct address is
// given. An error is returned if it does not.
func (ctx CLIContext) EnsureAccountExistsFromAddr(addr sdk.AccAddress) error {
_, err := ctx.queryAccount(addr)
return err
}

// queryAccount queries an account using custom query endpoint of auth module
// returns an error if result is `null` otherwise account data
func (ctx CLIContext) queryAccount(addr sdk.AccAddress) ([]byte, error) {
bz, err := ctx.Codec.MarshalJSON(authtypes.NewQueryAccountParams(addr))
if err != nil {
return nil, err
}

route := fmt.Sprintf("custom/%s/%s", ctx.AccountStore, authtypes.QueryAccount)

res, _, err := ctx.query(route, bz)
if err != nil {
return nil, err
}

return res, nil
}

// query performs a query to a Tendermint node with the provided store name
// and path. It returns the result and height of the query upon success
// or an error if the query fails.
Expand Down
1 change: 1 addition & 0 deletions x/auth/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ var (
NewTxBuilder = types.NewTxBuilder
NewTxBuilderFromCLI = types.NewTxBuilderFromCLI
MakeSignature = types.MakeSignature
NewAccountGetter = types.NewAccountGetter

// variable aliases
ModuleCdc = types.ModuleCdc
Expand Down
5 changes: 3 additions & 2 deletions x/auth/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,18 @@ func GetAccountCmd(cdc *codec.Codec) *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().
WithCodec(cdc).WithAccountDecoder(cdc)
accGetter := types.NewAccountGetter(cliCtx)

key, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}

if err = cliCtx.EnsureAccountExistsFromAddr(key); err != nil {
if err := accGetter.EnsureExists(key); err != nil {
return err
}

acc, err := cliCtx.GetAccount(key)
acc, err := accGetter.GetAccount(key)
if err != nil {
return err
}
Expand Down
8 changes: 1 addition & 7 deletions x/auth/client/cli/tx_multisign.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,7 @@ func makeMultiSignCmd(cdc *codec.Codec) func(cmd *cobra.Command, args []string)
txBldr := types.NewTxBuilderFromCLI()

if !viper.GetBool(flagOffline) {
addr := multisigInfo.GetAddress()
accnum, err := cliCtx.GetAccountNumber(addr)
if err != nil {
return err
}

seq, err := cliCtx.GetAccountSequence(addr)
accnum, seq, err := types.NewAccountGetter(cliCtx).GetAccountNumberSequence(multisigInfo.GetAddress())
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion x/auth/client/cli/tx_sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ func printAndValidateSigs(
// Validate the actual signature over the transaction bytes since we can
// reach out to a full node to query accounts.
if !offline && success {
acc, err := cliCtx.GetAccount(sigAddr)
acc, err := types.NewAccountGetter(cliCtx).GetAccount(sigAddr)
if err != nil {
fmt.Printf("failed to get account: %s\n", sigAddr)
return false
Expand Down
35 changes: 14 additions & 21 deletions x/auth/client/utils/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,17 +251,12 @@ func populateAccountFromState(
txBldr authtypes.TxBuilder, cliCtx context.CLIContext, addr sdk.AccAddress,
) (authtypes.TxBuilder, error) {

accNum, err := cliCtx.GetAccountNumber(addr)
num, seq, err := authtypes.NewAccountGetter(cliCtx).GetAccountNumberSequence(addr)
if err != nil {
return txBldr, err
}

accSeq, err := cliCtx.GetAccountSequence(addr)
if err != nil {
return txBldr, err
}

return txBldr.WithAccountNumber(accNum).WithSequence(accSeq), nil
return txBldr.WithAccountNumber(num).WithSequence(seq), nil
}

// GetTxEncoder return tx encoder from global sdk configuration if ones is defined.
Expand Down Expand Up @@ -302,30 +297,28 @@ func parseQueryResponse(cdc *codec.Codec, rawRes []byte) (uint64, error) {

// PrepareTxBuilder populates a TxBuilder in preparation for the build of a Tx.
func PrepareTxBuilder(txBldr authtypes.TxBuilder, cliCtx context.CLIContext) (authtypes.TxBuilder, error) {
if err := cliCtx.EnsureAccountExists(); err != nil {
from := cliCtx.GetFromAddress()

accGetter := authtypes.NewAccountGetter(cliCtx)
if err := accGetter.EnsureExists(from); err != nil {
return txBldr, err
}

from := cliCtx.GetFromAddress()

txbldrAccNum, txbldrAccSeq := txBldr.AccountNumber(), txBldr.Sequence()
// TODO: (ref #1903) Allow for user supplied account number without
// automatically doing a manual lookup.
if txBldr.AccountNumber() == 0 {
accNum, err := cliCtx.GetAccountNumber(from)
if txbldrAccNum == 0 || txbldrAccSeq == 0 {
num, seq, err := authtypes.NewAccountGetter(cliCtx).GetAccountNumberSequence(from)
if err != nil {
return txBldr, err
}
txBldr = txBldr.WithAccountNumber(accNum)
}

// TODO: (ref #1903) Allow for user supplied account sequence without
// automatically doing a manual lookup.
if txBldr.Sequence() == 0 {
accSeq, err := cliCtx.GetAccountSequence(from)
if err != nil {
return txBldr, err
if txbldrAccNum == 0 {
txBldr = txBldr.WithAccountNumber(num)
}
if txbldrAccSeq == 0 {
txBldr = txBldr.WithSequence(seq)
}
txBldr = txBldr.WithSequence(accSeq)
}

return txBldr, nil
Expand Down
59 changes: 59 additions & 0 deletions x/auth/types/account_getter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package types

import (
"fmt"

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

// 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)
}

type AccountGetter struct {
querier NodeQuerier
}

func NewAccountGetter(querier NodeQuerier) AccountGetter {
return AccountGetter{querier: querier}
}

// GetAccount queries for an account given an address and a block height. An
// error is returned if the query or decoding fails.
func (ag AccountGetter) GetAccount(addr sdk.AccAddress) (Account, error) {
bs, err := ModuleCdc.MarshalJSON(NewQueryAccountParams(addr))
if err != nil {
return nil, err
}

res, _, err := ag.querier.QueryWithData(fmt.Sprintf("custom/%s/%s", QuerierRoute, QueryAccount), bs)
if err != nil {
return nil, err
}

var account Account
if err := ModuleCdc.UnmarshalJSON(res, &account); err != nil {
return nil, err
}

return account, nil
}

func (ag AccountGetter) EnsureExists(addr sdk.AccAddress) error {
if _, err := ag.GetAccount(addr); err != nil {
return err
}
return nil
}

func (ag AccountGetter) GetAccountNumberSequence(addr sdk.AccAddress) (uint64, uint64, error) {
acc, err := ag.GetAccount(addr)
if err != nil {
return 0, 0, err
}
return acc.GetAccountNumber(), acc.GetSequence(), nil
}

0 comments on commit 4fa7fcf

Please sign in to comment.