Merge PR #3767: Added querier for auth module
This commit is contained in:
commit
7ac01bd76a
|
@ -55,9 +55,9 @@ decoded automatically.
|
||||||
|
|
||||||
* [\#3653] Prompt user confirmation prior to signing and broadcasting a transaction.
|
* [\#3653] Prompt user confirmation prior to signing and broadcasting a transaction.
|
||||||
* [\#3670] CLI support for showing bech32 addresses in Ledger devices
|
* [\#3670] CLI support for showing bech32 addresses in Ledger devices
|
||||||
* [\#3711] Update `tx sign` to use `--from` instead of the deprecated `--name`
|
* [\#3711] Update `tx sign` to use `--from` instead of the deprecated `--name` CLI flag.
|
||||||
CLI flag.
|
|
||||||
* [\#3730](https://github.com/cosmos/cosmos-sdk/issues/3730) Improve workflow for `gaiad gentx` with offline public keys, by outputting stdtx file that needs to be signed.
|
* [\#3730](https://github.com/cosmos/cosmos-sdk/issues/3730) Improve workflow for `gaiad gentx` with offline public keys, by outputting stdtx file that needs to be signed.
|
||||||
|
* [\#3761](https://github.com/cosmos/cosmos-sdk/issues/3761) Querying account related information using custom querier in auth module
|
||||||
|
|
||||||
### Gaia
|
### Gaia
|
||||||
|
|
||||||
|
|
|
@ -66,15 +66,13 @@ func (ctx CLIContext) GetAccount(address []byte) (auth.Account, error) {
|
||||||
return nil, errors.New("account decoder required but not provided")
|
return nil, errors.New("account decoder required but not provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := ctx.QueryStore(auth.AddressStoreKey(address), ctx.AccountStore)
|
res, err := ctx.queryAccount(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if len(res) == 0 {
|
|
||||||
return nil, ErrInvalidAccount(address)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
account, err := ctx.AccDecoder(res)
|
var account auth.Account
|
||||||
if err != nil {
|
if err := ctx.Codec.UnmarshalJSON(res, &account); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,32 +115,33 @@ func (ctx CLIContext) GetAccountSequence(address []byte) (uint64, error) {
|
||||||
// error is returned if it does not.
|
// error is returned if it does not.
|
||||||
func (ctx CLIContext) EnsureAccountExists() error {
|
func (ctx CLIContext) EnsureAccountExists() error {
|
||||||
addr := ctx.GetFromAddress()
|
addr := ctx.GetFromAddress()
|
||||||
accountBytes, err := ctx.QueryStore(auth.AddressStoreKey(addr), ctx.AccountStore)
|
return ctx.EnsureAccountExistsFromAddr(addr)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(accountBytes) == 0 {
|
|
||||||
return ErrInvalidAccount(addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnsureAccountExistsFromAddr ensures that an account exists for a given
|
// EnsureAccountExistsFromAddr ensures that an account exists for a given
|
||||||
// address. Instead of using the context's from name, a direct address is
|
// address. Instead of using the context's from name, a direct address is
|
||||||
// given. An error is returned if it does not.
|
// given. An error is returned if it does not.
|
||||||
func (ctx CLIContext) EnsureAccountExistsFromAddr(addr sdk.AccAddress) error {
|
func (ctx CLIContext) EnsureAccountExistsFromAddr(addr sdk.AccAddress) error {
|
||||||
accountBytes, err := ctx.QueryStore(auth.AddressStoreKey(addr), ctx.AccountStore)
|
_, err := ctx.queryAccount(addr)
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(accountBytes) == 0 {
|
// queryAccount queries an account using custom query endpoint of auth module
|
||||||
return ErrInvalidAccount(addr)
|
// returns an error if result is `null` otherwise account data
|
||||||
|
func (ctx CLIContext) queryAccount(addr sdk.AccAddress) ([]byte, error) {
|
||||||
|
bz, err := ctx.Codec.MarshalJSON(auth.NewQueryAccountParams(addr))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
route := fmt.Sprintf("custom/%s/%s", ctx.AccountStore, auth.QueryAccount)
|
||||||
|
|
||||||
|
res, err := ctx.QueryWithData(route, bz)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// query performs a query from a Tendermint node with the provided store name
|
// query performs a query from a Tendermint node with the provided store name
|
||||||
|
|
|
@ -157,6 +157,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b
|
||||||
AddRoute(gov.RouterKey, gov.NewHandler(app.govKeeper))
|
AddRoute(gov.RouterKey, gov.NewHandler(app.govKeeper))
|
||||||
|
|
||||||
app.QueryRouter().
|
app.QueryRouter().
|
||||||
|
AddRoute(auth.QuerierRoute, auth.NewQuerier(app.accountKeeper)).
|
||||||
AddRoute(distr.QuerierRoute, distr.NewQuerier(app.distrKeeper)).
|
AddRoute(distr.QuerierRoute, distr.NewQuerier(app.distrKeeper)).
|
||||||
AddRoute(gov.QuerierRoute, gov.NewQuerier(app.govKeeper)).
|
AddRoute(gov.QuerierRoute, gov.NewQuerier(app.govKeeper)).
|
||||||
AddRoute(slashing.QuerierRoute, slashing.NewQuerier(app.slashingKeeper, app.cdc)).
|
AddRoute(slashing.QuerierRoute, slashing.NewQuerier(app.slashingKeeper, app.cdc)).
|
||||||
|
|
|
@ -10,17 +10,22 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/params"
|
"github.com/cosmos/cosmos-sdk/x/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
const (
|
||||||
// AddressStoreKeyPrefix prefix for account-by-address store
|
|
||||||
AddressStoreKeyPrefix = []byte{0x01}
|
|
||||||
|
|
||||||
globalAccountNumberKey = []byte("globalAccountNumber")
|
|
||||||
|
|
||||||
// StoreKey is string representation of the store key for auth
|
// StoreKey is string representation of the store key for auth
|
||||||
StoreKey = "acc"
|
StoreKey = "acc"
|
||||||
|
|
||||||
// FeeStoreKey is a string representation of the store key for fees
|
// FeeStoreKey is a string representation of the store key for fees
|
||||||
FeeStoreKey = "fee"
|
FeeStoreKey = "fee"
|
||||||
|
|
||||||
|
// QuerierRoute is the querier route for acc
|
||||||
|
QuerierRoute = StoreKey
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// AddressStoreKeyPrefix prefix for account-by-address store
|
||||||
|
AddressStoreKeyPrefix = []byte{0x01}
|
||||||
|
|
||||||
|
globalAccountNumberKey = []byte("globalAccountNumber")
|
||||||
)
|
)
|
||||||
|
|
||||||
// AccountKeeper encodes/decodes accounts using the go-amino (binary)
|
// AccountKeeper encodes/decodes accounts using the go-amino (binary)
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// query endpoints supported by the auth Querier
|
||||||
|
const (
|
||||||
|
QueryAccount = "account"
|
||||||
|
)
|
||||||
|
|
||||||
|
// creates a querier for auth REST endpoints
|
||||||
|
func NewQuerier(keeper AccountKeeper) sdk.Querier {
|
||||||
|
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) {
|
||||||
|
switch path[0] {
|
||||||
|
case QueryAccount:
|
||||||
|
return queryAccount(ctx, req, keeper)
|
||||||
|
default:
|
||||||
|
return nil, sdk.ErrUnknownRequest("unknown auth query endpoint")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// defines the params for query: "custom/acc/account"
|
||||||
|
type QueryAccountParams struct {
|
||||||
|
Address sdk.AccAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewQueryAccountParams(addr sdk.AccAddress) QueryAccountParams {
|
||||||
|
return QueryAccountParams{
|
||||||
|
Address: addr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func queryAccount(ctx sdk.Context, req abci.RequestQuery, keeper AccountKeeper) ([]byte, sdk.Error) {
|
||||||
|
var params QueryAccountParams
|
||||||
|
if err := keeper.cdc.UnmarshalJSON(req.Data, ¶ms); err != nil {
|
||||||
|
return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
account := keeper.GetAccount(ctx, params.Address)
|
||||||
|
if account == nil {
|
||||||
|
return nil, sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", params.Address))
|
||||||
|
}
|
||||||
|
|
||||||
|
bz, err := codec.MarshalJSONIndent(keeper.cdc, account)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return bz, nil
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_queryAccount(t *testing.T) {
|
||||||
|
input := setupTestInput()
|
||||||
|
req := abci.RequestQuery{
|
||||||
|
Path: fmt.Sprintf("custom/%s/%s", QuerierRoute, QueryAccount),
|
||||||
|
Data: []byte{},
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := queryAccount(input.ctx, req, input.ak)
|
||||||
|
require.NotNil(t, err)
|
||||||
|
require.Nil(t, res)
|
||||||
|
|
||||||
|
req.Data = input.cdc.MustMarshalJSON(NewQueryAccountParams([]byte("")))
|
||||||
|
res, err = queryAccount(input.ctx, req, input.ak)
|
||||||
|
require.NotNil(t, err)
|
||||||
|
require.Nil(t, res)
|
||||||
|
|
||||||
|
_, _, addr := keyPubAddr()
|
||||||
|
req.Data = input.cdc.MustMarshalJSON(NewQueryAccountParams(addr))
|
||||||
|
res, err = queryAccount(input.ctx, req, input.ak)
|
||||||
|
require.NotNil(t, err)
|
||||||
|
require.Nil(t, res)
|
||||||
|
|
||||||
|
input.ak.SetAccount(input.ctx, input.ak.NewAccountWithAddress(input.ctx, addr))
|
||||||
|
res, err = queryAccount(input.ctx, req, input.ak)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.NotNil(t, res)
|
||||||
|
|
||||||
|
var account Account
|
||||||
|
err2 := input.cdc.UnmarshalJSON(res, &account)
|
||||||
|
require.Nil(t, err2)
|
||||||
|
}
|
Loading…
Reference in New Issue