From 703c643fc08487b954ccd750d63d2cd405be61a4 Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Thu, 30 Aug 2018 12:50:41 +0800 Subject: [PATCH 01/13] 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 02/13] 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 03/13] 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 04/13] 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 05/13] 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 -} From ab76fd964a8af03c41ed7160bc2399b8d811502e Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Fri, 31 Aug 2018 10:03:48 +0800 Subject: [PATCH 06/13] IRISHUB-238: remove todo, refactor comment and refactor multistoreproof --- client/context/context.go | 6 +-- client/context/query.go | 21 +++------- store/multistoreproof.go | 78 ++++++++++++++--------------------- store/multistoreproof_test.go | 78 +++++++++++++++++++++++------------ store/rootmultistore.go | 7 +--- 5 files changed, 92 insertions(+), 98 deletions(-) diff --git a/client/context/context.go b/client/context/context.go index ffdd0f7bc0..d28cc34f87 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/viper" - tendermintLite "github.com/tendermint/tendermint/lite" + tmlite "github.com/tendermint/tendermint/lite" rpcclient "github.com/tendermint/tendermint/rpc/client" ) @@ -33,7 +33,7 @@ type CLIContext struct { Async bool JSON bool PrintResponse bool - Certifier tendermintLite.Certifier + Certifier tmlite.Certifier } // NewCLIContext returns a new initialized CLIContext with parameters from the @@ -121,7 +121,7 @@ func (ctx CLIContext) WithUseLedger(useLedger bool) CLIContext { } // WithCertifier - return a copy of the context with an updated Certifier -func (ctx CLIContext) WithCertifier(certifier tendermintLite.Certifier) CLIContext { +func (ctx CLIContext) WithCertifier(certifier tmlite.Certifier) CLIContext { ctx.Certifier = certifier return ctx } diff --git a/client/context/query.go b/client/context/query.go index aac0c90306..47390d7872 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -14,7 +14,7 @@ import ( "github.com/cosmos/cosmos-sdk/wire" abci "github.com/tendermint/tendermint/abci/types" cmn "github.com/tendermint/tendermint/libs/common" - tendermintLiteProxy "github.com/tendermint/tendermint/lite/proxy" + tmliteProxy "github.com/tendermint/tendermint/lite/proxy" rpcclient "github.com/tendermint/tendermint/rpc/client" ctypes "github.com/tendermint/tendermint/rpc/core/types" "strings" @@ -325,12 +325,8 @@ func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, err erro // 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 + return fmt.Errorf("missing valid certifier to verify data from untrusted node") } node, err := ctx.GetNode() @@ -338,11 +334,8 @@ func (ctx CLIContext) verifyProof(path string, resp abci.ResponseQuery) error { 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) + commit, err := tmliteProxy.GetCertifiedCommit(resp.Height+1, node, ctx.Certifier) if err != nil { return err } @@ -356,7 +349,7 @@ func (ctx CLIContext) verifyProof(path string, resp abci.ResponseQuery) error { // Validate the substore commit hash against trusted appHash substoreCommitHash, err := store.VerifyMultiStoreCommitInfo(multiStoreProof.StoreName, - multiStoreProof.CommitIDList, commit.Header.AppHash) + multiStoreProof.StoreInfos, commit.Header.AppHash) if err != nil { return errors.Wrap(err, "failed in verifying the proof against appHash") } @@ -376,7 +369,6 @@ 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 { if !strings.HasPrefix(path, "/") { return false @@ -385,9 +377,8 @@ func isQueryStoreWithProof(path string) bool { 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" { + + if store.RequireProof(paths[2]) { return true } return false diff --git a/store/multistoreproof.go b/store/multistoreproof.go index 5ca214bc7d..62cc30ddfc 100644 --- a/store/multistoreproof.go +++ b/store/multistoreproof.go @@ -2,48 +2,33 @@ 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 +// MultiStoreProof defines a collection of store proofs in a multi-store type MultiStoreProof struct { - CommitIDList []SubstoreCommitID `json:"commit_id_list"` - StoreName string `json:"store_name"` - RangeProof iavl.RangeProof `json:"range_proof"` + StoreInfos []storeInfo + StoreName string + RangeProof iavl.RangeProof } -// build MultiStoreProof based on iavl proof and storeInfos -func BuildMultiStoreProof(iavlProof []byte, storeName string, storeInfos []storeInfo) ([]byte, error) { +// buildMultiStoreProof 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) + msp := MultiStoreProof{ + StoreInfos: storeInfos, + StoreName: storeName, + RangeProof: rangeProof, } - multiStoreProof.StoreName = storeName - multiStoreProof.RangeProof = rangeProof - proof, err := cdc.MarshalBinary(multiStoreProof) + proof, err := cdc.MarshalBinary(msp) if err != nil { return nil, err } @@ -51,28 +36,15 @@ func BuildMultiStoreProof(iavlProof []byte, storeName string, storeInfos []store return proof, nil } -// verify multiStoreCommitInfo against appHash -func VerifyMultiStoreCommitInfo(storeName string, multiStoreCommitInfo []SubstoreCommitID, appHash []byte) ([]byte, error) { +// VerifyMultiStoreCommitInfo verify multiStoreCommitInfo against appHash +func VerifyMultiStoreCommitInfo(storeName string, storeInfos []storeInfo, 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 + for _, storeInfo := range storeInfos { + if storeInfo.Name == storeName { + substoreCommitHash = storeInfo.Core.CommitID.Hash + height = storeInfo.Core.CommitID.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") @@ -89,7 +61,7 @@ func VerifyMultiStoreCommitInfo(storeName string, multiStoreCommitInfo []Substor return substoreCommitHash, nil } -// verify iavl proof +// VerifyRangeProof verify iavl RangeProof func VerifyRangeProof(key, value []byte, substoreCommitHash []byte, rangeProof *iavl.RangeProof) error { // Validate the proof to ensure data integrity. @@ -99,13 +71,13 @@ func VerifyRangeProof(key, value []byte, substoreCommitHash []byte, rangeProof * } if len(value) != 0 { - // Validate existence proof + // Verify existence proof err = rangeProof.VerifyItem(key, value) if err != nil { return errors.Wrap(err, "failed in existence verification") } } else { - // Validate absence proof + // Verify absence proof err = rangeProof.VerifyAbsence(key) if err != nil { return errors.Wrap(err, "failed in absence verification") @@ -114,3 +86,13 @@ func VerifyRangeProof(key, value []byte, substoreCommitHash []byte, rangeProof * return nil } + +// RequireProof return whether proof is require for the subpath +func RequireProof(subpath string) bool { + // 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:212 + if subpath == "/store" || subpath == "/key" { + return true + } + return false +} diff --git a/store/multistoreproof_test.go b/store/multistoreproof_test.go index 1538915677..b4e8a84b16 100644 --- a/store/multistoreproof_test.go +++ b/store/multistoreproof_test.go @@ -14,55 +14,79 @@ func TestVerifyMultiStoreCommitInfo(t *testing.T) { substoreRootHash, _ := hex.DecodeString("ea5d468431015c2cd6295e9a0bb1fc0e49033828") storeName := "acc" - var multiStoreCommitInfo []SubstoreCommitID + var storeInfos []storeInfo gocRootHash, _ := hex.DecodeString("62c171bb022e47d1f745608ff749e676dbd25f78") - multiStoreCommitInfo = append(multiStoreCommitInfo, SubstoreCommitID{ - Name: "gov", - Version: 689, - CommitHash: gocRootHash, + storeInfos = append(storeInfos, storeInfo{ + Name: "gov", + Core: storeCore{ + CommitID: CommitID{ + Version: 689, + Hash: gocRootHash, + }, + }, }) - multiStoreCommitInfo = append(multiStoreCommitInfo, SubstoreCommitID{ - Name: "main", - Version: 689, - CommitHash: nil, + storeInfos = append(storeInfos, storeInfo{ + Name: "main", + Core: storeCore{ + CommitID: CommitID{ + Version: 689, + Hash: nil, + }, + }, }) accRootHash, _ := hex.DecodeString("ea5d468431015c2cd6295e9a0bb1fc0e49033828") - multiStoreCommitInfo = append(multiStoreCommitInfo, SubstoreCommitID{ - Name: "acc", - Version: 689, - CommitHash: accRootHash, + storeInfos = append(storeInfos, storeInfo{ + Name: "acc", + Core: storeCore{ + CommitID: CommitID{ + Version: 689, + Hash: accRootHash, + }, + }, }) - multiStoreCommitInfo = append(multiStoreCommitInfo, SubstoreCommitID{ - Name: "ibc", - Version: 689, - CommitHash: nil, + storeInfos = append(storeInfos, storeInfo{ + Name: "ibc", + Core: storeCore{ + CommitID: CommitID{ + Version: 689, + Hash: nil, + }, + }, }) stakeRootHash, _ := hex.DecodeString("987d1d27b8771d93aa3691262f661d2c85af7ca4") - multiStoreCommitInfo = append(multiStoreCommitInfo, SubstoreCommitID{ - Name: "stake", - Version: 689, - CommitHash: stakeRootHash, + storeInfos = append(storeInfos, storeInfo{ + Name: "stake", + Core: storeCore{ + CommitID: CommitID{ + Version: 689, + Hash: stakeRootHash, + }, + }, }) slashingRootHash, _ := hex.DecodeString("388ee6e5b11f367069beb1eefd553491afe9d73e") - multiStoreCommitInfo = append(multiStoreCommitInfo, SubstoreCommitID{ - Name: "slashing", - Version: 689, - CommitHash: slashingRootHash, + storeInfos = append(storeInfos, storeInfo{ + Name: "slashing", + Core: storeCore{ + CommitID: CommitID{ + Version: 689, + Hash: slashingRootHash, + }, + }, }) - commitHash, err := VerifyMultiStoreCommitInfo(storeName, multiStoreCommitInfo, appHash) + commitHash, err := VerifyMultiStoreCommitInfo(storeName, storeInfos, appHash) assert.Nil(t, err) assert.Equal(t, commitHash, substoreRootHash) appHash, _ = hex.DecodeString("29de216bf5e2531c688de36caaf024cd3bb09ee3") - _, err = VerifyMultiStoreCommitInfo(storeName, multiStoreCommitInfo, appHash) + _, err = VerifyMultiStoreCommitInfo(storeName, storeInfos, appHash) assert.Error(t, err, "appHash doesn't match to the merkle root of multiStoreCommitInfo") } diff --git a/store/rootmultistore.go b/store/rootmultistore.go index c5ce52b0ba..5f6b082832 100644 --- a/store/rootmultistore.go +++ b/store/rootmultistore.go @@ -292,19 +292,16 @@ 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" { + if !req.Prove || !RequireProof(subpath) { 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) + res.Proof, errMsg = buildMultiStoreProof(res.Proof, storeName, commitInfo.StoreInfos) if errMsg != nil { return sdk.ErrInternal(errMsg.Error()).QueryResult() } From 9de7650b990f2186084448804789447782b3aff7 Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Fri, 31 Aug 2018 10:15:37 +0800 Subject: [PATCH 07/13] IRISHUB-238: fix a bug in judge whether proof is required and refactor comment --- client/context/query.go | 2 +- store/multistoreproof.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/context/query.go b/client/context/query.go index 47390d7872..31861a972e 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -378,7 +378,7 @@ func isQueryStoreWithProof(path string) bool { return false } - if store.RequireProof(paths[2]) { + if store.RequireProof("/" + paths[2]) { return true } return false diff --git a/store/multistoreproof.go b/store/multistoreproof.go index 62cc30ddfc..05eb49730a 100644 --- a/store/multistoreproof.go +++ b/store/multistoreproof.go @@ -64,7 +64,7 @@ func VerifyMultiStoreCommitInfo(storeName string, storeInfos []storeInfo, appHas // VerifyRangeProof verify iavl RangeProof func VerifyRangeProof(key, value []byte, substoreCommitHash []byte, rangeProof *iavl.RangeProof) error { - // Validate the proof to ensure data integrity. + // Verify 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") From 6d2fb8edefe61f31ea47234d2a5b5164fe51ac9f Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Fri, 31 Aug 2018 11:29:55 +0800 Subject: [PATCH 08/13] IRISHUB-238: fix test_cli failure, move certifier creation from lcd/root.go to NewCLIContext --- client/context/context.go | 23 ++++++++++++++++++++++- client/flags.go | 1 + client/lcd/root.go | 22 ++++------------------ 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/client/context/context.go b/client/context/context.go index d28cc34f87..2d9c9b90c9 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -9,8 +9,12 @@ import ( "github.com/spf13/viper" + "github.com/tendermint/tendermint/libs/cli" + tendermintLite "github.com/tendermint/tendermint/lite" tmlite "github.com/tendermint/tendermint/lite" + tendermintLiteProxy "github.com/tendermint/tendermint/lite/proxy" rpcclient "github.com/tendermint/tendermint/rpc/client" + "fmt" ) const ctxAccStoreName = "acc" @@ -46,6 +50,22 @@ func NewCLIContext() CLIContext { rpc = rpcclient.NewHTTP(nodeURI, "/websocket") } + trustNode := viper.GetBool(client.FlagTrustNode) + var certifier tendermintLite.Certifier + if !trustNode { + chainID := viper.GetString(client.FlagChainID) + home := viper.GetString(cli.HomeFlag) + if chainID != "" && home != "" && nodeURI != "" { + var err error + certifier, err = tendermintLiteProxy.GetCertifier(chainID, home, nodeURI) + if err != nil { + panic(err) + } + } else { + panic(fmt.Errorf("can't create certifier for distrust mode, values from these options may be empty: --chain-id, --home or --node")) + } + } + return CLIContext{ Client: rpc, NodeURI: nodeURI, @@ -54,11 +74,12 @@ func NewCLIContext() CLIContext { Height: viper.GetInt64(client.FlagHeight), Gas: viper.GetInt64(client.FlagGas), GasAdjustment: viper.GetFloat64(client.FlagGasAdjustment), - TrustNode: viper.GetBool(client.FlagTrustNode), + TrustNode: trustNode, UseLedger: viper.GetBool(client.FlagUseLedger), Async: viper.GetBool(client.FlagAsync), JSON: viper.GetBool(client.FlagJson), PrintResponse: viper.GetBool(client.FlagPrintResponse), + Certifier: certifier, } } diff --git a/client/flags.go b/client/flags.go index 81e0670678..12bddb7d96 100644 --- a/client/flags.go +++ b/client/flags.go @@ -58,6 +58,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().Bool(FlagAsync, false, "broadcast transactions asynchronously") c.Flags().Bool(FlagJson, false, "return output in json format") c.Flags().Bool(FlagPrintResponse, true, "return tx response (only works with async = false)") + c.Flags().Bool(FlagTrustNode, true, "Don't verify proofs for query responses") } return cmds } diff --git a/client/lcd/root.go b/client/lcd/root.go index f05fb88081..f18ee5dfd4 100644 --- a/client/lcd/root.go +++ b/client/lcd/root.go @@ -4,11 +4,11 @@ import ( "net/http" "os" - client "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" - keys "github.com/cosmos/cosmos-sdk/client/keys" - rpc "github.com/cosmos/cosmos-sdk/client/rpc" - tx "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/client/keys" + "github.com/cosmos/cosmos-sdk/client/rpc" + "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/wire" auth "github.com/cosmos/cosmos-sdk/x/auth/client/rest" bank "github.com/cosmos/cosmos-sdk/x/bank/client/rest" @@ -19,11 +19,8 @@ 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" - tendermintLite "github.com/tendermint/tendermint/lite" - tendermintLiteProxy "github.com/tendermint/tendermint/lite/proxy" tmserver "github.com/tendermint/tendermint/rpc/lib/server" ) @@ -84,17 +81,6 @@ 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") From b977baec73ea1cf51dc8d439e49a186fb6e8625b Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Fri, 31 Aug 2018 13:31:24 +0800 Subject: [PATCH 09/13] IRISHUB-238: move certifier creation to a function --- client/context/context.go | 57 ++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/client/context/context.go b/client/context/context.go index 2d9c9b90c9..da37795f08 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -2,7 +2,8 @@ package context import ( "io" - + "bytes" + "fmt" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/x/auth" @@ -10,11 +11,9 @@ import ( "github.com/spf13/viper" "github.com/tendermint/tendermint/libs/cli" - tendermintLite "github.com/tendermint/tendermint/lite" tmlite "github.com/tendermint/tendermint/lite" - tendermintLiteProxy "github.com/tendermint/tendermint/lite/proxy" + tmliteProxy "github.com/tendermint/tendermint/lite/proxy" rpcclient "github.com/tendermint/tendermint/rpc/client" - "fmt" ) const ctxAccStoreName = "acc" @@ -50,22 +49,6 @@ func NewCLIContext() CLIContext { rpc = rpcclient.NewHTTP(nodeURI, "/websocket") } - trustNode := viper.GetBool(client.FlagTrustNode) - var certifier tendermintLite.Certifier - if !trustNode { - chainID := viper.GetString(client.FlagChainID) - home := viper.GetString(cli.HomeFlag) - if chainID != "" && home != "" && nodeURI != "" { - var err error - certifier, err = tendermintLiteProxy.GetCertifier(chainID, home, nodeURI) - if err != nil { - panic(err) - } - } else { - panic(fmt.Errorf("can't create certifier for distrust mode, values from these options may be empty: --chain-id, --home or --node")) - } - } - return CLIContext{ Client: rpc, NodeURI: nodeURI, @@ -74,15 +57,45 @@ func NewCLIContext() CLIContext { Height: viper.GetInt64(client.FlagHeight), Gas: viper.GetInt64(client.FlagGas), GasAdjustment: viper.GetFloat64(client.FlagGasAdjustment), - TrustNode: trustNode, + TrustNode: viper.GetBool(client.FlagTrustNode), UseLedger: viper.GetBool(client.FlagUseLedger), Async: viper.GetBool(client.FlagAsync), JSON: viper.GetBool(client.FlagJson), PrintResponse: viper.GetBool(client.FlagPrintResponse), - Certifier: certifier, + Certifier: createCertifier(), } } +func createCertifier() tmlite.Certifier { + trustNode := viper.GetBool(client.FlagTrustNode) + if !trustNode { + chainID := viper.GetString(client.FlagChainID) + home := viper.GetString(cli.HomeFlag) + nodeURI := viper.GetString(client.FlagNode) + + var errMsg bytes.Buffer + if chainID == "" { + errMsg.WriteString("chain-id ") + } + if home == "" { + errMsg.WriteString("home ") + } + if nodeURI == "" { + errMsg.WriteString("node ") + } + // errMsg is not empty + if errMsg.Len() != 0 { + panic(fmt.Errorf("can't create certifier for distrust mode, empty values from these options: %s", errMsg.String())) + } + certifier, err := tmliteProxy.GetCertifier(chainID, home, nodeURI) + if err != nil { + panic(err) + } + return certifier + } + return nil +} + // WithCodec returns a copy of the context with an updated codec. func (ctx CLIContext) WithCodec(cdc *wire.Codec) CLIContext { ctx.Codec = cdc From de8ac6e2a982ceccfaa72061048e813304d05702 Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Fri, 31 Aug 2018 14:06:53 +0800 Subject: [PATCH 10/13] IRISHUB-238: missing change a comment --- client/context/query.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/context/query.go b/client/context/query.go index 31861a972e..4c1cad8777 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -347,7 +347,7 @@ func (ctx CLIContext) verifyProof(path string, resp abci.ResponseQuery) error { return errors.Wrap(err, "failed to unmarshalBinary rangeProof") } - // Validate the substore commit hash against trusted appHash + // Verify the substore commit hash against trusted appHash substoreCommitHash, err := store.VerifyMultiStoreCommitInfo(multiStoreProof.StoreName, multiStoreProof.StoreInfos, commit.Header.AppHash) if err != nil { From 959582476bd32b90d4375cd147638f11b86a0b9f Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Fri, 31 Aug 2018 15:21:35 +0800 Subject: [PATCH 11/13] IRISHUB-238: fix test_lint failure --- Gopkg.lock | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index fa6fafb99d..5e40c17e6c 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -34,7 +34,7 @@ [[projects]] branch = "master" - digest = "1:6aabc1566d6351115d561d038da82a4c19b46c3b6e17f4a0a2fa60260663dc79" + digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8" name = "github.com/btcsuite/btcd" packages = ["btcec"] pruneopts = "UT" @@ -71,7 +71,7 @@ version = "v1.4.7" [[projects]] - digest = "1:fa30c0652956e159cdb97dcb2ef8b8db63ed668c02a5c3a40961c8f0641252fe" + digest = "1:fdf5169073fb0ad6dc12a70c249145e30f4058647bea25f0abd48b6d9f228a11" name = "github.com/go-kit/kit" packages = [ "log", @@ -103,7 +103,7 @@ version = "v1.7.0" [[projects]] - digest = "1:212285efb97b9ec2e20550d81f0446cb7897e57cbdfd7301b1363ab113d8be45" + digest = "1:35621fe20f140f05a0c4ef662c26c0ab4ee50bca78aa30fe87d33120bd28165e" name = "github.com/gogo/protobuf" packages = [ "gogoproto", @@ -118,7 +118,7 @@ version = "v1.1.1" [[projects]] - digest = "1:cb22af0ed7c72d495d8be1106233ee553898950f15fd3f5404406d44c2e86888" + digest = "1:17fe264ee908afc795734e8c4e63db2accabaf57326dbf21763a7d6b86096260" name = "github.com/golang/protobuf" packages = [ "proto", @@ -165,13 +165,12 @@ [[projects]] branch = "master" - digest = "1:ac64f01acc5eeea9dde40e326de6b6471e501392ec06524c3b51033aa50789bc" + digest = "1:12247a2e99a060cc692f6680e5272c8adf0b8f572e6bce0d7095e624c958a240" name = "github.com/hashicorp/hcl" packages = [ ".", "hcl/ast", "hcl/parser", - "hcl/printer", "hcl/scanner", "hcl/strconv", "hcl/token", @@ -263,7 +262,7 @@ version = "v1.0.0" [[projects]] - digest = "1:98225904b7abff96c052b669b25788f18225a36673fba022fb93514bb9a2a64e" + digest = "1:c1a04665f9613e082e1209cf288bf64f4068dcd6c87a64bf1c4ff006ad422ba0" name = "github.com/prometheus/client_golang" packages = [ "prometheus", @@ -274,7 +273,7 @@ [[projects]] branch = "master" - digest = "1:0f37e09b3e92aaeda5991581311f8dbf38944b36a3edec61cc2d1991f527554a" + digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4" name = "github.com/prometheus/client_model" packages = ["go"] pruneopts = "UT" @@ -282,7 +281,7 @@ [[projects]] branch = "master" - digest = "1:dad2e5a2153ee7a6c9ab8fc13673a16ee4fb64434a7da980965a3741b0c981a3" + digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5" name = "github.com/prometheus/common" packages = [ "expfmt", @@ -294,7 +293,7 @@ [[projects]] branch = "master" - digest = "1:a37c98f4b7a66bb5c539c0539f0915a74ef1c8e0b3b6f45735289d94cae92bfd" + digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290" name = "github.com/prometheus/procfs" packages = [ ".", @@ -313,7 +312,7 @@ revision = "e2704e165165ec55d062f5919b4b29494e9fa790" [[projects]] - digest = "1:37ace7f35375adec11634126944bdc45a673415e2fcc07382d03b75ec76ea94c" + digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84" name = "github.com/spf13/afero" packages = [ ".", @@ -332,7 +331,7 @@ version = "v1.2.0" [[projects]] - digest = "1:627ab2f549a6a55c44f46fa24a4307f4d0da81bfc7934ed0473bf38b24051d26" + digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e" name = "github.com/spf13/cobra" packages = ["."] pruneopts = "UT" @@ -364,7 +363,7 @@ version = "v1.0.0" [[projects]] - digest = "1:73697231b93fb74a73ebd8384b68b9a60c57ea6b13c56d2425414566a72c8e6d" + digest = "1:7e8d267900c7fa7f35129a2a37596e38ed0f11ca746d6d9ba727980ee138f9f6" name = "github.com/stretchr/testify" packages = [ "assert", @@ -376,7 +375,7 @@ [[projects]] branch = "master" - digest = "1:442d2ffa75ffae302ce8800bf4144696b92bef02917923ea132ce2d39efe7d65" + digest = "1:f2ffd421680b0a3f7887501b3c6974bcf19217ecd301d0e2c9b681940ec363d5" name = "github.com/syndtr/goleveldb" packages = [ "leveldb", @@ -397,7 +396,7 @@ [[projects]] branch = "master" - digest = "1:203b409c21115233a576f99e8f13d8e07ad82b25500491f7e1cca12588fb3232" + digest = "1:087aaa7920e5d0bf79586feb57ce01c35c830396ab4392798112e8aae8c47722" name = "github.com/tendermint/ed25519" packages = [ ".", @@ -424,7 +423,7 @@ version = "v0.9.2" [[projects]] - digest = "1:963f6c04345ce36f900c1d6367200eebc3cc2db6ee632ff865ea8dcf64b748a0" + digest = "1:4f15e95fe3888cc75dd34f407d6394cbc7fd3ff24920851b92b295f6a8b556e6" name = "github.com/tendermint/tendermint" packages = [ "abci/client", @@ -491,7 +490,7 @@ version = "v0.23.1-rc0" [[projects]] - digest = "1:ad879bb8c71020a3f92f0c61f414d93eae1d5dc2f37023b6abaa3cc84b00165e" + digest = "1:bf6d9a827ea3cad964c2f863302e4f6823170d0b5ed16f72cf1184a7c615067e" name = "github.com/tendermint/tmlibs" packages = ["cli"] pruneopts = "UT" @@ -507,7 +506,7 @@ [[projects]] branch = "master" - digest = "1:2a3ce1f08dcae8bac666deb6e4c88b5d7170c510da38fd746231144cac351704" + digest = "1:27507554c6d4f060d8d700c31c624a43d3a92baa634e178ddc044bdf7d13b44a" name = "golang.org/x/crypto" packages = [ "blowfish", @@ -529,7 +528,7 @@ revision = "614d502a4dac94afa3a6ce146bd1736da82514c6" [[projects]] - digest = "1:04dda8391c3e2397daf254ac68003f30141c069b228d06baec8324a5f81dc1e9" + digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" name = "golang.org/x/net" packages = [ "context", @@ -546,7 +545,7 @@ [[projects]] branch = "master" - digest = "1:c8baf78f0ac6eb27c645e264fe5e8a74d5a50db188ab41a7ff3b275c112e0735" + digest = "1:86171d21d59449dcf7cee0b7d2da83dff989dab9b9b69bfe0a3d59c3c1ca6081" name = "golang.org/x/sys" packages = [ "cpu", @@ -556,7 +555,7 @@ revision = "11551d06cbcc94edc80a0facaccbda56473c19c1" [[projects]] - digest = "1:7509ba4347d1f8de6ae9be8818b0cd1abc3deeffe28aeaf4be6d4b6b5178d9ca" + digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" name = "golang.org/x/text" packages = [ "collate", @@ -587,7 +586,7 @@ revision = "c66870c02cf823ceb633bcd05be3c7cda29976f4" [[projects]] - digest = "1:4515e3030c440845b046354fd5d57671238428b820deebce2e9dabb5cd3c51ac" + digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" name = "google.golang.org/grpc" packages = [ ".", @@ -664,6 +663,8 @@ "github.com/tendermint/tendermint/libs/common", "github.com/tendermint/tendermint/libs/db", "github.com/tendermint/tendermint/libs/log", + "github.com/tendermint/tendermint/lite", + "github.com/tendermint/tendermint/lite/proxy", "github.com/tendermint/tendermint/node", "github.com/tendermint/tendermint/p2p", "github.com/tendermint/tendermint/privval", From cb3e729582b6b7410d56f06077a24d9e9c545d2c Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Fri, 31 Aug 2018 15:54:15 +0800 Subject: [PATCH 12/13] IRISHUB-238: fix test_lint failure in context.go --- client/context/context.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/context/context.go b/client/context/context.go index da37795f08..f05cf69f98 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -1,12 +1,12 @@ package context import ( - "io" "bytes" "fmt" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/x/auth" + "io" "github.com/spf13/viper" From 67857d704bda708583bd95b94dce25f28c081121 Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Fri, 31 Aug 2018 23:20:06 +0800 Subject: [PATCH 13/13] IRISHUB-238: change wait 3 second to wait tendermint new block. use MustUnmarshalBinary instead of UnmarshalBinary --- client/context/context.go | 50 +++++++++++++++++++------------------- client/lcd/test_helpers.go | 3 +-- store/multistoreproof.go | 21 ++++++---------- store/rootmultistore.go | 5 +--- tests/util.go | 12 +++++++++ 5 files changed, 46 insertions(+), 45 deletions(-) diff --git a/client/context/context.go b/client/context/context.go index f05cf69f98..4122cbab30 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -68,32 +68,32 @@ func NewCLIContext() CLIContext { func createCertifier() tmlite.Certifier { trustNode := viper.GetBool(client.FlagTrustNode) - if !trustNode { - chainID := viper.GetString(client.FlagChainID) - home := viper.GetString(cli.HomeFlag) - nodeURI := viper.GetString(client.FlagNode) - - var errMsg bytes.Buffer - if chainID == "" { - errMsg.WriteString("chain-id ") - } - if home == "" { - errMsg.WriteString("home ") - } - if nodeURI == "" { - errMsg.WriteString("node ") - } - // errMsg is not empty - if errMsg.Len() != 0 { - panic(fmt.Errorf("can't create certifier for distrust mode, empty values from these options: %s", errMsg.String())) - } - certifier, err := tmliteProxy.GetCertifier(chainID, home, nodeURI) - if err != nil { - panic(err) - } - return certifier + if trustNode { + return nil } - return nil + chainID := viper.GetString(client.FlagChainID) + home := viper.GetString(cli.HomeFlag) + nodeURI := viper.GetString(client.FlagNode) + + var errMsg bytes.Buffer + if chainID == "" { + errMsg.WriteString("chain-id ") + } + if home == "" { + errMsg.WriteString("home ") + } + if nodeURI == "" { + errMsg.WriteString("node ") + } + // errMsg is not empty + if errMsg.Len() != 0 { + panic(fmt.Errorf("can't create certifier for distrust mode, empty values from these options: %s", errMsg.String())) + } + certifier, err := tmliteProxy.GetCertifier(chainID, home, nodeURI) + if err != nil { + panic(err) + } + return certifier } // WithCodec returns a copy of the context with an updated codec. diff --git a/client/lcd/test_helpers.go b/client/lcd/test_helpers.go index 8a344976a1..7d9a46403c 100644 --- a/client/lcd/test_helpers.go +++ b/client/lcd/test_helpers.go @@ -37,7 +37,6 @@ 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 @@ -191,7 +190,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) + tests.WaitForNextHeightTM(tests.ExtractPortFromAddress(config.RPC.ListenAddress)) lcd, err := startLCD(logger, listenAddr, cdc) require.NoError(t, err) diff --git a/store/multistoreproof.go b/store/multistoreproof.go index 05eb49730a..e25f1cc1f2 100644 --- a/store/multistoreproof.go +++ b/store/multistoreproof.go @@ -15,12 +15,9 @@ type MultiStoreProof struct { } // buildMultiStoreProof build MultiStoreProof based on iavl proof and storeInfos -func buildMultiStoreProof(iavlProof []byte, storeName string, storeInfos []storeInfo) ([]byte, error) { +func buildMultiStoreProof(iavlProof []byte, storeName string, storeInfos []storeInfo) []byte { var rangeProof iavl.RangeProof - err := cdc.UnmarshalBinary(iavlProof, &rangeProof) - if err != nil { - return nil, err - } + cdc.MustUnmarshalBinary(iavlProof, &rangeProof) msp := MultiStoreProof{ StoreInfos: storeInfos, @@ -28,12 +25,8 @@ func buildMultiStoreProof(iavlProof []byte, storeName string, storeInfos []store RangeProof: rangeProof, } - proof, err := cdc.MarshalBinary(msp) - if err != nil { - return nil, err - } - - return proof, nil + proof := cdc.MustMarshalBinary(msp) + return proof } // VerifyMultiStoreCommitInfo verify multiStoreCommitInfo against appHash @@ -64,20 +57,20 @@ func VerifyMultiStoreCommitInfo(storeName string, storeInfos []storeInfo, appHas // VerifyRangeProof verify iavl RangeProof func VerifyRangeProof(key, value []byte, substoreCommitHash []byte, rangeProof *iavl.RangeProof) error { - // Verify the proof to ensure data integrity. + // verify 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 { - // Verify existence proof + // verify existence proof err = rangeProof.VerifyItem(key, value) if err != nil { return errors.Wrap(err, "failed in existence verification") } } else { - // Verify absence proof + // verify absence proof err = rangeProof.VerifyAbsence(key) if err != nil { return errors.Wrap(err, "failed in absence verification") diff --git a/store/rootmultistore.go b/store/rootmultistore.go index 5f6b082832..d9cf8a29a2 100644 --- a/store/rootmultistore.go +++ b/store/rootmultistore.go @@ -301,10 +301,7 @@ func (rs *rootMultiStore) Query(req abci.RequestQuery) abci.ResponseQuery { return sdk.ErrInternal(errMsg.Error()).QueryResult() } - res.Proof, errMsg = buildMultiStoreProof(res.Proof, storeName, commitInfo.StoreInfos) - if errMsg != nil { - return sdk.ErrInternal(errMsg.Error()).QueryResult() - } + res.Proof = buildMultiStoreProof(res.Proof, storeName, commitInfo.StoreInfos) return res } diff --git a/tests/util.go b/tests/util.go index 1138bc95e9..48649eaf76 100644 --- a/tests/util.go +++ b/tests/util.go @@ -10,6 +10,7 @@ import ( tmclient "github.com/tendermint/tendermint/rpc/client" ctypes "github.com/tendermint/tendermint/rpc/core/types" rpcclient "github.com/tendermint/tendermint/rpc/lib/client" + "strings" ) // Wait for the next tendermint block from the Tendermint RPC @@ -185,6 +186,17 @@ func WaitForRPC(laddr string) { } } +// ExtractPortFromAddress extract port from listenAddress +// The listenAddress must be some strings like tcp://0.0.0.0:12345 +func ExtractPortFromAddress(listenAddress string) string { + stringList := strings.Split(listenAddress, ":") + length := len(stringList) + if length != 3 { + panic(fmt.Errorf("expected listen address: tcp://0.0.0.0:12345, got %s", listenAddress)) + } + return stringList[2] +} + var cdc = amino.NewCodec() func init() {