From 1eb7706c28edb0a2640216cdb5ceb00e9595def3 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 19 Jun 2019 14:24:11 +0200 Subject: [PATCH] Separate account getters from client/context (#4579) Account getters are removed from client context. x/auth has the queriers necessary for retrieving account information. These functions should be removed since they are currently redundant and don't provide any extra value. Closes: #4543 --- .pending/breaking/sdk/4543-Account-getters | 2 + Makefile | 9 ++- client/context/query.go | 76 ---------------------- go.mod | 3 +- go.sum | 8 +++ tests/mocks/account_retriever.go | 39 +++++++++++ x/auth/alias.go | 1 + x/auth/client/cli/query.go | 5 +- x/auth/client/cli/tx_multisign.go | 8 +-- x/auth/client/cli/tx_sign.go | 2 +- x/auth/client/utils/tx.go | 35 ++++------ x/auth/types/account_retriever.go | 65 ++++++++++++++++++ x/auth/types/account_retriever_test.go | 40 ++++++++++++ 13 files changed, 184 insertions(+), 109 deletions(-) create mode 100644 .pending/breaking/sdk/4543-Account-getters create mode 100644 tests/mocks/account_retriever.go create mode 100644 x/auth/types/account_retriever.go create mode 100644 x/auth/types/account_retriever_test.go diff --git a/.pending/breaking/sdk/4543-Account-getters b/.pending/breaking/sdk/4543-Account-getters new file mode 100644 index 000000000000..b3f614ef5a51 --- /dev/null +++ b/.pending/breaking/sdk/4543-Account-getters @@ -0,0 +1,2 @@ +#4543 Account getters are no longer part of client.CLIContext() and have now moved +to reside in the auth-specific AccountRetriever. diff --git a/Makefile b/Makefile index d750aaa5a995..f4bef96dad85 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,7 @@ COMMIT := $(shell git log -1 --format='%H') LEDGER_ENABLED ?= true BINDIR ?= $(GOPATH)/bin SIMAPP = github.com/cosmos/cosmos-sdk/simapp +MOCKS_DIR = $(CURDIR)/tests/mocks export GO111MODULE = on @@ -33,6 +34,12 @@ dist: @bash publish/dist.sh @bash publish/publish.sh +mocks: $(MOCKS_DIR) + mockgen -source=x/auth/types/account_retriever.go -package mocks -destination tests/mocks/account_retriever.go + +$(MOCKS_DIR): + mkdir -p $(MOCKS_DIR) + ######################################## ### Tools & dependencies @@ -186,7 +193,7 @@ snapcraft-local.yaml: snapcraft-local.yaml.in # To avoid unintended conflicts with file names, always add to .PHONY # unless there is a reason not to. # https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html -.PHONY: build dist clean test test_unit test_cover lint \ +.PHONY: build dist clean test test_unit test_cover lint mocks \ benchmark devdoc_init devdoc devdoc_save devdoc_update runsim \ format test_sim_app_nondeterminism test_sim_modules test_sim_app_fast \ test_sim_app_custom_genesis_fast test_sim_app_custom_genesis_multi_seed \ diff --git a/client/context/query.go b/client/context/query.go index de1779da0286..87f96aece166 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -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 @@ -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 @@ -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. diff --git a/go.mod b/go.mod index 7a9886c738ef..7324ba3df867 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/fortytw2/leaktest v1.3.0 // indirect github.com/go-logfmt/logfmt v0.4.0 // indirect github.com/gogo/protobuf v1.1.1 + github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129 github.com/golang/protobuf v1.3.0 github.com/golang/snappy v0.0.1 // indirect github.com/gorilla/mux v1.7.0 @@ -41,7 +42,7 @@ require ( github.com/tendermint/go-amino v0.15.0 github.com/tendermint/iavl v0.12.2 github.com/tendermint/tendermint v0.31.5 - golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 + golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 google.golang.org/grpc v1.19.0 // indirect gopkg.in/yaml.v2 v2.2.2 ) diff --git a/go.sum b/go.sum index 1d0f153daa76..5ae57a4c34ad 100644 --- a/go.sum +++ b/go.sum @@ -49,7 +49,10 @@ github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129 h1:tT8iWCYw4uOem71yYA3htfH+LNopJvcqZQshm56G5L4= +github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk= @@ -158,6 +161,8 @@ golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc h1:a3CU5tJYVj92DY2LaA1kUkrsqD5/3mLDhx2NcNqyW+0= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -165,6 +170,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FY golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -175,6 +182,7 @@ golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b h1:qMK98NmNCRVDIYFycQ5yVRkvgDUFfdP8Ip4KqmDEB7g= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= diff --git a/tests/mocks/account_retriever.go b/tests/mocks/account_retriever.go new file mode 100644 index 000000000000..34f10bc2c5c2 --- /dev/null +++ b/tests/mocks/account_retriever.go @@ -0,0 +1,39 @@ +package mocks + +import ( + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +type MockNodeQuerier struct { + ctrl *gomock.Controller + recorder *MockNodeQuerierMockRecorder +} + +type MockNodeQuerierMockRecorder struct { + mock *MockNodeQuerier +} + +func NewMockNodeQuerier(ctrl *gomock.Controller) *MockNodeQuerier { + mock := &MockNodeQuerier{ctrl: ctrl} + mock.recorder = &MockNodeQuerierMockRecorder{mock} + return mock +} + +func (m *MockNodeQuerier) EXPECT() *MockNodeQuerierMockRecorder { + return m.recorder +} + +func (m *MockNodeQuerier) QueryWithData(path string, data []byte) ([]byte, int64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryWithData", path, data) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(int64) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +func (mr *MockNodeQuerierMockRecorder) QueryWithData(path, data interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryWithData", reflect.TypeOf((*MockNodeQuerier)(nil).QueryWithData), path, data) +} diff --git a/x/auth/alias.go b/x/auth/alias.go index afd3b94b0252..f4638631e7cd 100644 --- a/x/auth/alias.go +++ b/x/auth/alias.go @@ -51,6 +51,7 @@ var ( NewTxBuilder = types.NewTxBuilder NewTxBuilderFromCLI = types.NewTxBuilderFromCLI MakeSignature = types.MakeSignature + NewAccountRetriever = types.NewAccountRetriever // variable aliases ModuleCdc = types.ModuleCdc diff --git a/x/auth/client/cli/query.go b/x/auth/client/cli/query.go index f5da295f1d0f..ff5af41ac6e6 100644 --- a/x/auth/client/cli/query.go +++ b/x/auth/client/cli/query.go @@ -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.NewAccountRetriever(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 } diff --git a/x/auth/client/cli/tx_multisign.go b/x/auth/client/cli/tx_multisign.go index 34c5630da187..c1343c77963c 100644 --- a/x/auth/client/cli/tx_multisign.go +++ b/x/auth/client/cli/tx_multisign.go @@ -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.NewAccountRetriever(cliCtx).GetAccountNumberSequence(multisigInfo.GetAddress()) if err != nil { return err } diff --git a/x/auth/client/cli/tx_sign.go b/x/auth/client/cli/tx_sign.go index f18cc4de7c3f..b7046b9bf285 100644 --- a/x/auth/client/cli/tx_sign.go +++ b/x/auth/client/cli/tx_sign.go @@ -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.NewAccountRetriever(cliCtx).GetAccount(sigAddr) if err != nil { fmt.Printf("failed to get account: %s\n", sigAddr) return false diff --git a/x/auth/client/utils/tx.go b/x/auth/client/utils/tx.go index 7dcb43ec13ce..3353f25980dd 100644 --- a/x/auth/client/utils/tx.go +++ b/x/auth/client/utils/tx.go @@ -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.NewAccountRetriever(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. @@ -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.NewAccountRetriever(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.NewAccountRetriever(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 diff --git a/x/auth/types/account_retriever.go b/x/auth/types/account_retriever.go new file mode 100644 index 000000000000..22ac0957f5f3 --- /dev/null +++ b/x/auth/types/account_retriever.go @@ -0,0 +1,65 @@ +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) +} + +// AccountRetriever defines the properties of a type that can be used to +// retrieve accounts. +type AccountRetriever struct { + querier NodeQuerier +} + +// NewAccountRetriever initialises a new AccountRetriever instance. +func NewAccountRetriever(querier NodeQuerier) AccountRetriever { + return AccountRetriever{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 (ar AccountRetriever) GetAccount(addr sdk.AccAddress) (Account, error) { + bs, err := ModuleCdc.MarshalJSON(NewQueryAccountParams(addr)) + if err != nil { + return nil, err + } + + res, _, err := ar.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 +} + +// EnsureExists returns an error if no account exists for the given address else nil. +func (ar AccountRetriever) EnsureExists(addr sdk.AccAddress) error { + if _, err := ar.GetAccount(addr); err != nil { + return err + } + return nil +} + +// GetAccountNumberSequence returns sequence and account number for the given address. +// It returns an error if the account couldn't be retrieved from the state. +func (ar AccountRetriever) GetAccountNumberSequence(addr sdk.AccAddress) (uint64, uint64, error) { + acc, err := ar.GetAccount(addr) + if err != nil { + return 0, 0, err + } + return acc.GetAccountNumber(), acc.GetSequence(), nil +} diff --git a/x/auth/types/account_retriever_test.go b/x/auth/types/account_retriever_test.go new file mode 100644 index 000000000000..64e232bc5351 --- /dev/null +++ b/x/auth/types/account_retriever_test.go @@ -0,0 +1,40 @@ +package types + +import ( + "errors" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/tests/mocks" +) + +var dummyError = errors.New("dummy") + +func TestAccountRetriever(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + mockNodeQuerier := mocks.NewMockNodeQuerier(mockCtrl) + accRetr := NewAccountRetriever(mockNodeQuerier) + addr := []byte("test") + bs, err := ModuleCdc.MarshalJSON(NewQueryAccountParams(addr)) + require.NoError(t, err) + + mockNodeQuerier.EXPECT().QueryWithData(gomock.Eq("custom/acc/account"), + gomock.Eq(bs)).Return(nil, int64(0), dummyError).Times(1) + _, err = accRetr.GetAccount(addr) + require.Error(t, err) + + mockNodeQuerier.EXPECT().QueryWithData(gomock.Eq("custom/acc/account"), + gomock.Eq(bs)).Return(nil, int64(0), dummyError).Times(1) + n, s, err := accRetr.GetAccountNumberSequence(addr) + require.Error(t, err) + require.Equal(t, uint64(0), n) + require.Equal(t, uint64(0), s) + + mockNodeQuerier.EXPECT().QueryWithData(gomock.Eq("custom/acc/account"), + gomock.Eq(bs)).Return(nil, int64(0), dummyError).Times(1) + require.Error(t, accRetr.EnsureExists(addr)) +}