From 703c643fc08487b954ccd750d63d2cd405be61a4 Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Thu, 30 Aug 2018 12:50:41 +0800 Subject: [PATCH 1/5] IRISHUB-238: Add multiply store proof build and verification --- client/context/client_manager.go | 46 ++++++++++ client/context/client_manager_test.go | 16 ++++ client/context/context.go | 15 ++++ client/context/query.go | 79 ++++++++++++++++++ client/lcd/root.go | 14 ++++ store/multistoreproof.go | 116 ++++++++++++++++++++++++++ store/multistoreproof_test.go | 96 +++++++++++++++++++++ store/rootmultistore.go | 19 +++++ 8 files changed, 401 insertions(+) create mode 100644 client/context/client_manager.go create mode 100644 client/context/client_manager_test.go create mode 100644 store/multistoreproof.go create mode 100644 store/multistoreproof_test.go diff --git a/client/context/client_manager.go b/client/context/client_manager.go new file mode 100644 index 0000000000..8fffb9d651 --- /dev/null +++ b/client/context/client_manager.go @@ -0,0 +1,46 @@ +package context + +import ( + "github.com/pkg/errors" + rpcclient "github.com/tendermint/tendermint/rpc/client" + "strings" + "sync" +) + +// ClientManager is a manager of a set of rpc clients to full nodes. +// This manager can do load balancing upon these rpc clients. +type ClientManager struct { + clients []rpcclient.Client + currentIndex int + mutex sync.Mutex +} + +// NewClientManager create a new ClientManager +func NewClientManager(nodeURIs string) (*ClientManager, error) { + if nodeURIs != "" { + nodeURLArray := strings.Split(nodeURIs, ",") + var clients []rpcclient.Client + for _, url := range nodeURLArray { + client := rpcclient.NewHTTP(url, "/websocket") + clients = append(clients, client) + } + mgr := &ClientManager{ + currentIndex: 0, + clients: clients, + } + return mgr, nil + } + return nil, errors.New("missing node URIs") +} + +func (mgr *ClientManager) getClient() rpcclient.Client { + mgr.mutex.Lock() + defer mgr.mutex.Unlock() + + client := mgr.clients[mgr.currentIndex] + mgr.currentIndex++ + if mgr.currentIndex >= len(mgr.clients) { + mgr.currentIndex = 0 + } + return client +} diff --git a/client/context/client_manager_test.go b/client/context/client_manager_test.go new file mode 100644 index 0000000000..c060e11cea --- /dev/null +++ b/client/context/client_manager_test.go @@ -0,0 +1,16 @@ +package context + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestClientManager(t *testing.T) { + nodeURIs := "10.10.10.10:26657,20.20.20.20:26657,30.30.30.30:26657" + clientMgr, err := NewClientManager(nodeURIs) + assert.Empty(t, err) + endpoint := clientMgr.getClient() + assert.NotEqual(t, endpoint, clientMgr.getClient()) + clientMgr.getClient() + assert.Equal(t, endpoint, clientMgr.getClient()) +} \ No newline at end of file diff --git a/client/context/context.go b/client/context/context.go index 743c923552..b57e336657 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -10,6 +10,7 @@ import ( "github.com/spf13/viper" rpcclient "github.com/tendermint/tendermint/rpc/client" + tendermintLite "github.com/tendermint/tendermint/lite" ) const ctxAccStoreName = "acc" @@ -32,6 +33,8 @@ type CLIContext struct { Async bool JSON bool PrintResponse bool + Certifier tendermintLite.Certifier + ClientManager *ClientManager } // NewCLIContext returns a new initialized CLIContext with parameters from the @@ -117,3 +120,15 @@ func (ctx CLIContext) WithUseLedger(useLedger bool) CLIContext { ctx.UseLedger = useLedger return ctx } + +// WithCertifier - return a copy of the context with an updated Certifier +func (ctx CLIContext) WithCertifier(certifier tendermintLite.Certifier) CLIContext { + ctx.Certifier = certifier + return ctx +} + +// WithClientManager - return a copy of the context with an updated ClientManager +func (ctx CLIContext) WithClientManager(clientManager *ClientManager) CLIContext { + ctx.ClientManager = clientManager + return ctx +} diff --git a/client/context/query.go b/client/context/query.go index e526c0abbc..72defb0d4a 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -13,6 +13,11 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" rpcclient "github.com/tendermint/tendermint/rpc/client" ctypes "github.com/tendermint/tendermint/rpc/core/types" + "github.com/cosmos/cosmos-sdk/store" + "github.com/cosmos/cosmos-sdk/wire" + "strings" + tendermintLiteProxy "github.com/tendermint/tendermint/lite/proxy" + abci "github.com/tendermint/tendermint/abci/types" ) // GetNode returns an RPC client. If the context's client is not defined, an @@ -304,12 +309,86 @@ func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, err erro return res, errors.Errorf("query failed: (%d) %s", resp.Code, resp.Log) } + // Data from trusted node or subspace query doesn't need verification + if ctx.TrustNode || !isQueryStoreWithProof(path) { + return resp.Value, nil + } + + err = ctx.verifyProof(path, resp) + if err != nil { + return nil, err + } + return resp.Value, nil } +// verifyProof perform response proof verification +func (ctx CLIContext) verifyProof(path string, resp abci.ResponseQuery) error { + + // TODO: Later we consider to return error for missing valid certifier to verify data from untrusted node + if ctx.Certifier == nil { + if ctx.Logger != nil { + io.WriteString(ctx.Logger, fmt.Sprintf("Missing valid certifier to verify data from untrusted node\n")) + } + return nil + } + + node, err := ctx.GetNode() + if err != nil { + return err + } + + // TODO: need improvement + // If the the node http client connect to a full node which can't produce or receive new blocks, + // then here the code will wait for a while and return error if time is out. + // AppHash for height H is in header H+1 + commit, err := tendermintLiteProxy.GetCertifiedCommit(resp.Height+1, node, ctx.Certifier) + if err != nil { + return err + } + + var multiStoreProof store.MultiStoreProof + cdc := wire.NewCodec() + err = cdc.UnmarshalBinary(resp.Proof, &multiStoreProof) + if err != nil { + return errors.Wrap(err, "failed to unmarshalBinary rangeProof") + } + + // Validate the substore commit hash against trusted appHash + substoreCommitHash, err := store.VerifyMultiStoreCommitInfo(multiStoreProof.StoreName, + multiStoreProof.CommitIDList, commit.Header.AppHash) + if err != nil { + return errors.Wrap(err, "failed in verifying the proof against appHash") + } + err = store.VerifyRangeProof(resp.Key, resp.Value, substoreCommitHash, &multiStoreProof.RangeProof) + if err != nil { + return errors.Wrap(err, "failed in the range proof verification") + } + return nil +} + // queryStore performs a query from a Tendermint node with the provided a store // name and path. func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, error) { path := fmt.Sprintf("/store/%s/%s", storeName, endPath) return ctx.query(path, key) } + +// isQueryStoreWithProof expects a format like /// +// queryType can be app or store +// if subpath equals to "/store" or "/key", then return true +func isQueryStoreWithProof(path string) (bool) { + if !strings.HasPrefix(path, "/") { + return false + } + paths := strings.SplitN(path[1:], "/", 3) + if len(paths) != 3 { + return false + } + // Currently, only when query subpath is "/store" or "/key", will proof be included in response. + // If there are some changes about proof building in iavlstore.go, we must change code here to keep consistency with iavlstore.go + if paths[2] == "store" || paths[2] == "key" { + return true + } + return false +} diff --git a/client/lcd/root.go b/client/lcd/root.go index bfa62f1cf0..71c9a51144 100644 --- a/client/lcd/root.go +++ b/client/lcd/root.go @@ -22,6 +22,9 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/libs/log" tmserver "github.com/tendermint/tendermint/rpc/lib/server" + tendermintLiteProxy "github.com/tendermint/tendermint/lite/proxy" + "github.com/tendermint/tendermint/libs/cli" + tendermintLite "github.com/tendermint/tendermint/lite" ) // ServeCommand will generate a long-running rest server @@ -80,6 +83,17 @@ func createHandler(cdc *wire.Codec) http.Handler { cliCtx := context.NewCLIContext().WithCodec(cdc).WithLogger(os.Stdout) + chainID := viper.GetString(client.FlagChainID) + home := viper.GetString(cli.HomeFlag) + nodeURI := viper.GetString(client.FlagNode) + var certifier tendermintLite.Certifier + if chainID != "" && home != "" && nodeURI != ""{ + certifier, err = tendermintLiteProxy.GetCertifier(chainID, home, nodeURI) + if err != nil { + panic(err) + } + cliCtx = cliCtx.WithCertifier(certifier) + } // TODO: make more functional? aka r = keys.RegisterRoutes(r) r.HandleFunc("/version", CLIVersionRequestHandler).Methods("GET") r.HandleFunc("/node_version", NodeVersionRequestHandler(cliCtx)).Methods("GET") diff --git a/store/multistoreproof.go b/store/multistoreproof.go new file mode 100644 index 0000000000..e98a198e93 --- /dev/null +++ b/store/multistoreproof.go @@ -0,0 +1,116 @@ +package store + +import ( + "bytes" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pkg/errors" + "github.com/tendermint/iavl" + cmn "github.com/tendermint/tendermint/libs/common" +) + +// commitID of substores, such as acc store, gov store +type SubstoreCommitID struct { + Name string `json:"name"` + Version int64 `json:"version"` + CommitHash cmn.HexBytes `json:"commit_hash"` +} + +// proof of store which have multi substores +type MultiStoreProof struct { + CommitIDList []SubstoreCommitID `json:"commit_id_list"` + StoreName string `json:"store_name"` + RangeProof iavl.RangeProof `json:"range_proof"` +} + +// build MultiStoreProof based on iavl proof and storeInfos +func BuildMultiStoreProof(iavlProof []byte, storeName string, storeInfos []storeInfo) ([]byte, error) { + var rangeProof iavl.RangeProof + err := cdc.UnmarshalBinary(iavlProof, &rangeProof) + if err != nil { + return nil, err + } + + var multiStoreProof MultiStoreProof + for _, storeInfo := range storeInfos { + + commitID := SubstoreCommitID{ + Name: storeInfo.Name, + Version: storeInfo.Core.CommitID.Version, + CommitHash: storeInfo.Core.CommitID.Hash, + } + multiStoreProof.CommitIDList = append(multiStoreProof.CommitIDList, commitID) + } + multiStoreProof.StoreName = storeName + multiStoreProof.RangeProof = rangeProof + + proof, err := cdc.MarshalBinary(multiStoreProof) + if err != nil { + return nil, err + } + + return proof, nil +} + +// verify multiStoreCommitInfo against appHash +func VerifyMultiStoreCommitInfo(storeName string, multiStoreCommitInfo []SubstoreCommitID, appHash []byte) ([]byte, error) { + var substoreCommitHash []byte + var storeInfos []storeInfo + var height int64 + for _, multiStoreCommitID := range multiStoreCommitInfo { + + if multiStoreCommitID.Name == storeName { + substoreCommitHash = multiStoreCommitID.CommitHash + height = multiStoreCommitID.Version + } + storeInfo := storeInfo{ + Name: multiStoreCommitID.Name, + Core: storeCore{ + CommitID: sdk.CommitID{ + Version: multiStoreCommitID.Version, + Hash: multiStoreCommitID.CommitHash, + }, + }, + } + + storeInfos = append(storeInfos, storeInfo) + } + if len(substoreCommitHash) == 0 { + return nil, cmn.NewError("failed to get substore root commit hash by store name") + } + + ci := commitInfo{ + Version: height, + StoreInfos: storeInfos, + } + + if !bytes.Equal(appHash, ci.Hash()) { + return nil, cmn.NewError("the merkle root of multiStoreCommitInfo doesn't equal to appHash") + } + return substoreCommitHash, nil +} + +// verify iavl proof +func VerifyRangeProof(key, value []byte, substoreCommitHash []byte, rangeProof *iavl.RangeProof) error { + + // Validate the proof to ensure data integrity. + err := rangeProof.Verify(substoreCommitHash) + if err != nil { + return errors.Wrap(err, "proof root hash doesn't equal to substore commit root hash") + } + + if len(value) != 0 { + // Validate existence proof + err = rangeProof.VerifyItem(key, value) + if err != nil { + return errors.Wrap(err, "failed in existence verification") + } + } else { + // Validate absence proof + err = rangeProof.VerifyAbsence(key) + if err != nil { + return errors.Wrap(err, "failed in absence verification") + } + } + + return nil +} \ No newline at end of file diff --git a/store/multistoreproof_test.go b/store/multistoreproof_test.go new file mode 100644 index 0000000000..b1667c7265 --- /dev/null +++ b/store/multistoreproof_test.go @@ -0,0 +1,96 @@ +package store + +import ( + "encoding/hex" + "github.com/stretchr/testify/assert" + "github.com/tendermint/iavl" + cmn "github.com/tendermint/tendermint/libs/common" + "testing" +) + +func TestVerifyMultiStoreCommitInfo(t *testing.T) { + appHash, _ := hex.DecodeString("ebf3c1fb724d3458023c8fefef7b33add2fc1e84") + + substoreRootHash, _ := hex.DecodeString("ea5d468431015c2cd6295e9a0bb1fc0e49033828") + storeName := "acc" + + var multiStoreCommitInfo []SubstoreCommitID + + gocRootHash, _ := hex.DecodeString("62c171bb022e47d1f745608ff749e676dbd25f78") + multiStoreCommitInfo = append(multiStoreCommitInfo, SubstoreCommitID{ + Name: "gov", + Version: 689, + CommitHash: gocRootHash, + }) + + multiStoreCommitInfo = append(multiStoreCommitInfo, SubstoreCommitID{ + Name: "main", + Version: 689, + CommitHash: nil, + }) + + accRootHash, _ := hex.DecodeString("ea5d468431015c2cd6295e9a0bb1fc0e49033828") + multiStoreCommitInfo = append(multiStoreCommitInfo, SubstoreCommitID{ + Name: "acc", + Version: 689, + CommitHash: accRootHash, + }) + + multiStoreCommitInfo = append(multiStoreCommitInfo, SubstoreCommitID{ + Name: "ibc", + Version: 689, + CommitHash: nil, + }) + + stakeRootHash, _ := hex.DecodeString("987d1d27b8771d93aa3691262f661d2c85af7ca4") + multiStoreCommitInfo = append(multiStoreCommitInfo, SubstoreCommitID{ + Name: "stake", + Version: 689, + CommitHash: stakeRootHash, + }) + + slashingRootHash, _ := hex.DecodeString("388ee6e5b11f367069beb1eefd553491afe9d73e") + multiStoreCommitInfo = append(multiStoreCommitInfo, SubstoreCommitID{ + Name: "slashing", + Version: 689, + CommitHash: slashingRootHash, + }) + + commitHash, err := VerifyMultiStoreCommitInfo(storeName, multiStoreCommitInfo, appHash) + assert.Nil(t, err) + assert.Equal(t, commitHash, substoreRootHash) + + appHash, _ = hex.DecodeString("29de216bf5e2531c688de36caaf024cd3bb09ee3") + + _, err = VerifyMultiStoreCommitInfo(storeName, multiStoreCommitInfo, appHash) + assert.Error(t, err, "appHash doesn't match to the merkle root of multiStoreCommitInfo") +} + +func TestVerifyRangeProof(t *testing.T) { + tree := iavl.NewTree(nil, 0) + + rand := cmn.NewRand() + rand.Seed(0) // for determinism + for _, ikey := range []byte{0x11, 0x32, 0x50, 0x72, 0x99} { + key := []byte{ikey} + tree.Set(key, []byte(rand.Str(8))) + } + + root := tree.Hash() + + key := []byte{0x32} + val, proof, err := tree.GetWithProof(key) + assert.Nil(t, err) + assert.NotEmpty(t, val) + assert.NotEmpty(t, proof) + err = VerifyRangeProof(key, val, root, proof) + assert.Nil(t, err) + + key = []byte{0x40} + val, proof, err = tree.GetWithProof(key) + assert.Nil(t, err) + assert.Empty(t, val) + assert.NotEmpty(t, proof) + err = VerifyRangeProof(key, val, root, proof) + assert.Nil(t, err) +} \ No newline at end of file diff --git a/store/rootmultistore.go b/store/rootmultistore.go index 04f8e44e69..2a9a9373a4 100644 --- a/store/rootmultistore.go +++ b/store/rootmultistore.go @@ -291,6 +291,25 @@ func (rs *rootMultiStore) Query(req abci.RequestQuery) abci.ResponseQuery { // trim the path and make the query req.Path = subpath res := queryable.Query(req) + + + // Currently, only when query subpath is "/store" or "/key", will proof be included in response. + // If there are some changes about proof building in iavlstore.go, we must change code here to keep consistency with iavlstore.go + if !req.Prove || subpath != "/store" && subpath != "/key" { + return res + } + + //Load commit info from db + commitInfo, errMsg := getCommitInfo(rs.db,res.Height) + if errMsg != nil { + return sdk.ErrInternal(errMsg.Error()).QueryResult() + } + + res.Proof, errMsg = BuildMultiStoreProof(res.Proof, storeName, commitInfo.StoreInfos) + if errMsg != nil { + return sdk.ErrInternal(errMsg.Error()).QueryResult() + } + return res } From 5473771105b5db36c093a6a6de649240cd40e3bb Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Thu, 30 Aug 2018 15:08:10 +0800 Subject: [PATCH 2/5] IRISHUB-238 :add trust option for rest-server command --- client/lcd/root.go | 1 + 1 file changed, 1 insertion(+) diff --git a/client/lcd/root.go b/client/lcd/root.go index 71c9a51144..75cf3632ea 100644 --- a/client/lcd/root.go +++ b/client/lcd/root.go @@ -69,6 +69,7 @@ func ServeCommand(cdc *wire.Codec) *cobra.Command { cmd.Flags().String(client.FlagChainID, "", "The chain ID to connect to") cmd.Flags().String(client.FlagNode, "tcp://localhost:26657", "Address of the node to connect to") cmd.Flags().Int(flagMaxOpenConnections, 1000, "The number of maximum open connections") + cmd.Flags().Bool(client.FlagTrustNode, false, "Whether trust connected full node") return cmd } From b878edc388788542b55398c1923b742e63c4ecc2 Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Thu, 30 Aug 2018 15:52:17 +0800 Subject: [PATCH 3/5] IRISHUB-238: fix failures in test_lint and test_cover --- client/context/client_manager_test.go | 2 +- client/context/context.go | 2 +- client/context/query.go | 20 ++++++++++---------- client/lcd/test_helpers.go | 2 ++ store/multistoreproof.go | 2 +- store/multistoreproof_test.go | 2 +- store/rootmultistore.go | 3 +-- 7 files changed, 17 insertions(+), 16 deletions(-) diff --git a/client/context/client_manager_test.go b/client/context/client_manager_test.go index c060e11cea..1960f74ced 100644 --- a/client/context/client_manager_test.go +++ b/client/context/client_manager_test.go @@ -13,4 +13,4 @@ func TestClientManager(t *testing.T) { assert.NotEqual(t, endpoint, clientMgr.getClient()) clientMgr.getClient() assert.Equal(t, endpoint, clientMgr.getClient()) -} \ No newline at end of file +} diff --git a/client/context/context.go b/client/context/context.go index b57e336657..28506756cf 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -9,8 +9,8 @@ import ( "github.com/spf13/viper" - rpcclient "github.com/tendermint/tendermint/rpc/client" tendermintLite "github.com/tendermint/tendermint/lite" + rpcclient "github.com/tendermint/tendermint/rpc/client" ) const ctxAccStoreName = "acc" diff --git a/client/context/query.go b/client/context/query.go index 72defb0d4a..aac0c90306 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -10,14 +10,14 @@ import ( "github.com/pkg/errors" - cmn "github.com/tendermint/tendermint/libs/common" - rpcclient "github.com/tendermint/tendermint/rpc/client" - ctypes "github.com/tendermint/tendermint/rpc/core/types" "github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/wire" - "strings" - tendermintLiteProxy "github.com/tendermint/tendermint/lite/proxy" abci "github.com/tendermint/tendermint/abci/types" + cmn "github.com/tendermint/tendermint/libs/common" + tendermintLiteProxy "github.com/tendermint/tendermint/lite/proxy" + rpcclient "github.com/tendermint/tendermint/rpc/client" + ctypes "github.com/tendermint/tendermint/rpc/core/types" + "strings" ) // GetNode returns an RPC client. If the context's client is not defined, an @@ -351,18 +351,18 @@ func (ctx CLIContext) verifyProof(path string, resp abci.ResponseQuery) error { cdc := wire.NewCodec() err = cdc.UnmarshalBinary(resp.Proof, &multiStoreProof) if err != nil { - return errors.Wrap(err, "failed to unmarshalBinary rangeProof") + return errors.Wrap(err, "failed to unmarshalBinary rangeProof") } // Validate the substore commit hash against trusted appHash - substoreCommitHash, err := store.VerifyMultiStoreCommitInfo(multiStoreProof.StoreName, + substoreCommitHash, err := store.VerifyMultiStoreCommitInfo(multiStoreProof.StoreName, multiStoreProof.CommitIDList, commit.Header.AppHash) if err != nil { - return errors.Wrap(err, "failed in verifying the proof against appHash") + return errors.Wrap(err, "failed in verifying the proof against appHash") } err = store.VerifyRangeProof(resp.Key, resp.Value, substoreCommitHash, &multiStoreProof.RangeProof) if err != nil { - return errors.Wrap(err, "failed in the range proof verification") + return errors.Wrap(err, "failed in the range proof verification") } return nil } @@ -377,7 +377,7 @@ func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([ // isQueryStoreWithProof expects a format like /// // queryType can be app or store // if subpath equals to "/store" or "/key", then return true -func isQueryStoreWithProof(path string) (bool) { +func isQueryStoreWithProof(path string) bool { if !strings.HasPrefix(path, "/") { return false } diff --git a/client/lcd/test_helpers.go b/client/lcd/test_helpers.go index 818eae1e86..8a344976a1 100644 --- a/client/lcd/test_helpers.go +++ b/client/lcd/test_helpers.go @@ -37,6 +37,7 @@ import ( "github.com/tendermint/tendermint/proxy" tmrpc "github.com/tendermint/tendermint/rpc/lib/server" tmtypes "github.com/tendermint/tendermint/types" + "time" ) // makePathname creates a unique pathname for each test. It will panic if it @@ -190,6 +191,7 @@ func InitializeTestLCD(t *testing.T, nValidators int, initAddrs []sdk.AccAddress node, err := startTM(config, logger, genDoc, privVal, app) require.NoError(t, err) + time.Sleep(3 * time.Second) lcd, err := startLCD(logger, listenAddr, cdc) require.NoError(t, err) diff --git a/store/multistoreproof.go b/store/multistoreproof.go index e98a198e93..5ca214bc7d 100644 --- a/store/multistoreproof.go +++ b/store/multistoreproof.go @@ -113,4 +113,4 @@ func VerifyRangeProof(key, value []byte, substoreCommitHash []byte, rangeProof * } return nil -} \ No newline at end of file +} diff --git a/store/multistoreproof_test.go b/store/multistoreproof_test.go index b1667c7265..1538915677 100644 --- a/store/multistoreproof_test.go +++ b/store/multistoreproof_test.go @@ -93,4 +93,4 @@ func TestVerifyRangeProof(t *testing.T) { assert.NotEmpty(t, proof) err = VerifyRangeProof(key, val, root, proof) assert.Nil(t, err) -} \ No newline at end of file +} diff --git a/store/rootmultistore.go b/store/rootmultistore.go index 2a9a9373a4..c5ce52b0ba 100644 --- a/store/rootmultistore.go +++ b/store/rootmultistore.go @@ -292,7 +292,6 @@ func (rs *rootMultiStore) Query(req abci.RequestQuery) abci.ResponseQuery { req.Path = subpath res := queryable.Query(req) - // Currently, only when query subpath is "/store" or "/key", will proof be included in response. // If there are some changes about proof building in iavlstore.go, we must change code here to keep consistency with iavlstore.go if !req.Prove || subpath != "/store" && subpath != "/key" { @@ -300,7 +299,7 @@ func (rs *rootMultiStore) Query(req abci.RequestQuery) abci.ResponseQuery { } //Load commit info from db - commitInfo, errMsg := getCommitInfo(rs.db,res.Height) + commitInfo, errMsg := getCommitInfo(rs.db, res.Height) if errMsg != nil { return sdk.ErrInternal(errMsg.Error()).QueryResult() } From 3f83aca5992ea483ad42dc4431dfdbf6af4540c7 Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Thu, 30 Aug 2018 16:24:56 +0800 Subject: [PATCH 4/5] IRISHUB-238: fix test_lint failures in client/lcd/root.go and server/ --- client/lcd/root.go | 8 ++++---- server/export_test.go | 16 ++++++++-------- server/mock/app.go | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/client/lcd/root.go b/client/lcd/root.go index 75cf3632ea..f05fb88081 100644 --- a/client/lcd/root.go +++ b/client/lcd/root.go @@ -19,12 +19,12 @@ import ( "github.com/gorilla/mux" "github.com/spf13/cobra" "github.com/spf13/viper" + "github.com/tendermint/tendermint/libs/cli" cmn "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/libs/log" - tmserver "github.com/tendermint/tendermint/rpc/lib/server" - tendermintLiteProxy "github.com/tendermint/tendermint/lite/proxy" - "github.com/tendermint/tendermint/libs/cli" tendermintLite "github.com/tendermint/tendermint/lite" + tendermintLiteProxy "github.com/tendermint/tendermint/lite/proxy" + tmserver "github.com/tendermint/tendermint/rpc/lib/server" ) // ServeCommand will generate a long-running rest server @@ -88,7 +88,7 @@ func createHandler(cdc *wire.Codec) http.Handler { home := viper.GetString(cli.HomeFlag) nodeURI := viper.GetString(client.FlagNode) var certifier tendermintLite.Certifier - if chainID != "" && home != "" && nodeURI != ""{ + if chainID != "" && home != "" && nodeURI != "" { certifier, err = tendermintLiteProxy.GetCertifier(chainID, home, nodeURI) if err != nil { panic(err) diff --git a/server/export_test.go b/server/export_test.go index 358f72cf60..488c55bbf6 100644 --- a/server/export_test.go +++ b/server/export_test.go @@ -1,16 +1,16 @@ package server import ( - "testing" - "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/wire" - "github.com/tendermint/tendermint/libs/log" - tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" - "os" "bytes" + "github.com/cosmos/cosmos-sdk/server/mock" + "github.com/cosmos/cosmos-sdk/wire" + "github.com/stretchr/testify/require" + tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" + "github.com/tendermint/tendermint/libs/log" "io" - "github.com/cosmos/cosmos-sdk/server/mock" - ) + "os" + "testing" +) func TestEmptyState(t *testing.T) { defer setupViper(t)() diff --git a/server/mock/app.go b/server/mock/app.go index eb2dfc3cc3..3c6ad3ec27 100644 --- a/server/mock/app.go +++ b/server/mock/app.go @@ -129,7 +129,7 @@ func AppGenStateEmpty(_ *wire.Codec, _ []json.RawMessage) (appState json.RawMess // Return a validator, not much else func AppGenTx(_ *wire.Codec, pk crypto.PubKey, genTxConfig gc.GenTx) ( - appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) { + appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) { validator = tmtypes.GenesisValidator{ PubKey: pk, From 5e85a5cdcdba8d9d7287e3950ae439d6b9ffd515 Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Thu, 30 Aug 2018 17:14:10 +0800 Subject: [PATCH 5/5] IRISHUB-238: delete client manager --- client/context/client_manager.go | 46 --------------------------- client/context/client_manager_test.go | 16 ---------- client/context/context.go | 7 ---- 3 files changed, 69 deletions(-) delete mode 100644 client/context/client_manager.go delete mode 100644 client/context/client_manager_test.go diff --git a/client/context/client_manager.go b/client/context/client_manager.go deleted file mode 100644 index 8fffb9d651..0000000000 --- a/client/context/client_manager.go +++ /dev/null @@ -1,46 +0,0 @@ -package context - -import ( - "github.com/pkg/errors" - rpcclient "github.com/tendermint/tendermint/rpc/client" - "strings" - "sync" -) - -// ClientManager is a manager of a set of rpc clients to full nodes. -// This manager can do load balancing upon these rpc clients. -type ClientManager struct { - clients []rpcclient.Client - currentIndex int - mutex sync.Mutex -} - -// NewClientManager create a new ClientManager -func NewClientManager(nodeURIs string) (*ClientManager, error) { - if nodeURIs != "" { - nodeURLArray := strings.Split(nodeURIs, ",") - var clients []rpcclient.Client - for _, url := range nodeURLArray { - client := rpcclient.NewHTTP(url, "/websocket") - clients = append(clients, client) - } - mgr := &ClientManager{ - currentIndex: 0, - clients: clients, - } - return mgr, nil - } - return nil, errors.New("missing node URIs") -} - -func (mgr *ClientManager) getClient() rpcclient.Client { - mgr.mutex.Lock() - defer mgr.mutex.Unlock() - - client := mgr.clients[mgr.currentIndex] - mgr.currentIndex++ - if mgr.currentIndex >= len(mgr.clients) { - mgr.currentIndex = 0 - } - return client -} diff --git a/client/context/client_manager_test.go b/client/context/client_manager_test.go deleted file mode 100644 index 1960f74ced..0000000000 --- a/client/context/client_manager_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package context - -import ( - "github.com/stretchr/testify/assert" - "testing" -) - -func TestClientManager(t *testing.T) { - nodeURIs := "10.10.10.10:26657,20.20.20.20:26657,30.30.30.30:26657" - clientMgr, err := NewClientManager(nodeURIs) - assert.Empty(t, err) - endpoint := clientMgr.getClient() - assert.NotEqual(t, endpoint, clientMgr.getClient()) - clientMgr.getClient() - assert.Equal(t, endpoint, clientMgr.getClient()) -} diff --git a/client/context/context.go b/client/context/context.go index 28506756cf..ffdd0f7bc0 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -34,7 +34,6 @@ type CLIContext struct { JSON bool PrintResponse bool Certifier tendermintLite.Certifier - ClientManager *ClientManager } // NewCLIContext returns a new initialized CLIContext with parameters from the @@ -126,9 +125,3 @@ func (ctx CLIContext) WithCertifier(certifier tendermintLite.Certifier) CLIConte ctx.Certifier = certifier return ctx } - -// WithClientManager - return a copy of the context with an updated ClientManager -func (ctx CLIContext) WithClientManager(clientManager *ClientManager) CLIContext { - ctx.ClientManager = clientManager - return ctx -}