From b42410ea8029e18d7c1cf92e10f07eb01390db2d Mon Sep 17 00:00:00 2001 From: Tony Stark Date: Fri, 1 Mar 2019 01:10:32 +0530 Subject: [PATCH 1/6] Added custom querier --- x/auth/keeper.go | 21 +++++++++++------- x/auth/querier.go | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 x/auth/querier.go diff --git a/x/auth/keeper.go b/x/auth/keeper.go index 3727981cf..9476029a1 100644 --- a/x/auth/keeper.go +++ b/x/auth/keeper.go @@ -10,17 +10,22 @@ import ( "github.com/cosmos/cosmos-sdk/x/params" ) -var ( - // AddressStoreKeyPrefix prefix for account-by-address store - AddressStoreKeyPrefix = []byte{0x01} - - globalAccountNumberKey = []byte("globalAccountNumber") - +const ( // StoreKey is string representation of the store key for auth StoreKey = "acc" // FeeStoreKey is a string representation of the store key for fees 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) @@ -193,7 +198,7 @@ func (ak AccountKeeper) GetNextAccountNumber(ctx sdk.Context) uint64 { return accNumber } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // Params // SetParams sets the auth module's parameters. @@ -207,7 +212,7 @@ func (ak AccountKeeper) GetParams(ctx sdk.Context) (params Params) { return } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // Misc. func (ak AccountKeeper) decodeAccount(bz []byte) (acc Account) { diff --git a/x/auth/querier.go b/x/auth/querier.go new file mode 100644 index 000000000..5b40bcbf3 --- /dev/null +++ b/x/auth/querier.go @@ -0,0 +1,54 @@ +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) + + 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 +} From cf18b5a11a85aec4aa2603efaf930a60093f8ade Mon Sep 17 00:00:00 2001 From: Tony Stark Date: Fri, 1 Mar 2019 01:10:55 +0530 Subject: [PATCH 2/6] Modified CLI context --- client/context/query.go | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/client/context/query.go b/client/context/query.go index a2fc7ff78..3bf67c76b 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -66,15 +66,13 @@ func (ctx CLIContext) GetAccount(address []byte) (auth.Account, error) { 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 { return nil, err - } else if len(res) == 0 { - return nil, ErrInvalidAccount(address) } - account, err := ctx.AccDecoder(res) - if err != nil { + var account auth.Account + if err := ctx.Codec.UnmarshalJSON(res, &account); err != nil { return nil, err } @@ -117,32 +115,35 @@ func (ctx CLIContext) GetAccountSequence(address []byte) (uint64, error) { // error is returned if it does not. func (ctx CLIContext) EnsureAccountExists() error { addr := ctx.GetFromAddress() - accountBytes, err := ctx.QueryStore(auth.AddressStoreKey(addr), ctx.AccountStore) - if err != nil { - return err - } - - if len(accountBytes) == 0 { - return ErrInvalidAccount(addr) - } - - return nil + 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 { - accountBytes, err := ctx.QueryStore(auth.AddressStoreKey(addr), ctx.AccountStore) + _, 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(auth.NewQueryAccountParams(addr)) if err != nil { - return err + return nil, err } - if len(accountBytes) == 0 { - return ErrInvalidAccount(addr) + route := fmt.Sprintf("custom/%s/%s", ctx.AccountStore, auth.QueryAccount) + + res, err := ctx.QueryWithData(route, bz) + if err != nil { + return nil, err + } else if len(res) == 4 && string(res) == "null" { + return nil, ErrInvalidAccount(addr) } - return nil + return res, nil } // query performs a query from a Tendermint node with the provided store name From 2899ff9ce43d9739f3c8f0259a742100cc50e44e Mon Sep 17 00:00:00 2001 From: Tony Stark Date: Fri, 1 Mar 2019 01:11:14 +0530 Subject: [PATCH 3/6] Added tests for querier --- x/auth/querier_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 x/auth/querier_test.go diff --git a/x/auth/querier_test.go b/x/auth/querier_test.go new file mode 100644 index 000000000..3eb632e1b --- /dev/null +++ b/x/auth/querier_test.go @@ -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.Nil(t, err) + require.Equal(t, res, []byte("null")) + + _, _, addr := keyPubAddr() + req.Data = input.cdc.MustMarshalJSON(NewQueryAccountParams(addr)) + res, err = queryAccount(input.ctx, req, input.ak) + require.Nil(t, err) + require.Equal(t, res, []byte("null")) + + input.ak.SetAccount(input.ctx, input.ak.NewAccountWithAddress(input.ctx, addr)) + res, err = queryAccount(input.ctx, req, input.ak) + require.Nil(t, err) + require.NotEqual(t, res, []byte("null")) + + var account Account + err2 := input.cdc.UnmarshalJSON(res, &account) + require.Nil(t, err2) +} From 9f383c0031279b938aee23e939d634e93d6d5aeb Mon Sep 17 00:00:00 2001 From: Tony Stark Date: Fri, 1 Mar 2019 01:12:12 +0530 Subject: [PATCH 4/6] Added custom querier in Gaia App --- cmd/gaia/app/app.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 096d68ba5..d5b031272 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -157,6 +157,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b AddRoute(gov.RouterKey, gov.NewHandler(app.govKeeper)) app.QueryRouter(). + AddRoute(auth.QuerierRoute, auth.NewQuerier(app.accountKeeper)). AddRoute(distr.QuerierRoute, distr.NewQuerier(app.distrKeeper)). AddRoute(gov.QuerierRoute, gov.NewQuerier(app.govKeeper)). AddRoute(slashing.QuerierRoute, slashing.NewQuerier(app.slashingKeeper, app.cdc)). @@ -324,7 +325,7 @@ func (app *GaiaApp) LoadHeight(height int64) error { return app.LoadVersion(height, app.keyMain) } -//______________________________________________________________________________________________ +// ______________________________________________________________________________________________ var _ sdk.StakingHooks = StakingHooks{} From 7c3251fa26c0f723ced882bcf63fcac75d0d1573 Mon Sep 17 00:00:00 2001 From: Tony Stark Date: Fri, 1 Mar 2019 08:49:18 +0530 Subject: [PATCH 5/6] Added a condition in querier --- client/context/query.go | 2 -- x/auth/querier.go | 3 +++ x/auth/querier_test.go | 10 +++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/client/context/query.go b/client/context/query.go index 3bf67c76b..7f625e801 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -139,8 +139,6 @@ func (ctx CLIContext) queryAccount(addr sdk.AccAddress) ([]byte, error) { res, err := ctx.QueryWithData(route, bz) if err != nil { return nil, err - } else if len(res) == 4 && string(res) == "null" { - return nil, ErrInvalidAccount(addr) } return res, nil diff --git a/x/auth/querier.go b/x/auth/querier.go index 5b40bcbf3..2a5dbf422 100644 --- a/x/auth/querier.go +++ b/x/auth/querier.go @@ -44,6 +44,9 @@ func queryAccount(ctx sdk.Context, req abci.RequestQuery, keeper AccountKeeper) } 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 { diff --git a/x/auth/querier_test.go b/x/auth/querier_test.go index 3eb632e1b..6d9ec0e96 100644 --- a/x/auth/querier_test.go +++ b/x/auth/querier_test.go @@ -21,19 +21,19 @@ func Test_queryAccount(t *testing.T) { req.Data = input.cdc.MustMarshalJSON(NewQueryAccountParams([]byte(""))) res, err = queryAccount(input.ctx, req, input.ak) - require.Nil(t, err) - require.Equal(t, res, []byte("null")) + 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.Nil(t, err) - require.Equal(t, res, []byte("null")) + 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.NotEqual(t, res, []byte("null")) + require.NotNil(t, res) var account Account err2 := input.cdc.UnmarshalJSON(res, &account) From f7df00fab684fdf72c1c26126e718d64c12b5e70 Mon Sep 17 00:00:00 2001 From: Tony Stark Date: Sat, 2 Mar 2019 00:13:36 +0530 Subject: [PATCH 6/6] Added pending log entry --- PENDING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PENDING.md b/PENDING.md index 0447beee0..71542e0d6 100644 --- a/PENDING.md +++ b/PENDING.md @@ -54,9 +54,9 @@ decoded automatically. * [\#3653] Prompt user confirmation prior to signing and broadcasting a transaction. * [\#3670] CLI support for showing bech32 addresses in Ledger devices -* [\#3711] Update `tx sign` to use `--from` instead of the deprecated `--name` -CLI flag. +* [\#3711] Update `tx sign` to use `--from` instead of the deprecated `--name` 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. +* [\#3761](https://github.com/cosmos/cosmos-sdk/issues/3761) Querying account related information using custom querier in auth module ### Gaia