Skip to content

Commit

Permalink
context: remove verifier & trust node (cosmos#6805)
Browse files Browse the repository at this point in the history
* remove verifier

* more removal of trustnode flag

* add todo

* fix lint

* remove file

* remove viper and add link to issue

* remve mention of trustnode
  • Loading branch information
tac0turtle authored Jul 23, 2020
1 parent e0a81d2 commit e6a5622
Show file tree
Hide file tree
Showing 24 changed files with 17 additions and 303 deletions.
5 changes: 0 additions & 5 deletions client/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,6 @@ func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Cont
clientCtx = clientCtx.WithChainID(chainID)
}

if flagSet.Changed(flags.FlagTrustNode) {
trustNode, _ := flagSet.GetBool(flags.FlagTrustNode)
clientCtx = clientCtx.WithTrustNode(trustNode)
}

if clientCtx.Keyring == nil || flagSet.Changed(flags.FlagKeyringBackend) {
keyringBackend, _ := flagSet.GetString(flags.FlagKeyringBackend)

Expand Down
15 changes: 0 additions & 15 deletions client/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"os"

"github.com/pkg/errors"
tmlite "github.com/tendermint/tendermint/lite"
rpcclient "github.com/tendermint/tendermint/rpc/client"
rpchttp "github.com/tendermint/tendermint/rpc/client/http"
yaml "gopkg.in/yaml.v2"
Expand Down Expand Up @@ -34,7 +33,6 @@ type Context struct {
From string
BroadcastMode string
FromName string
TrustNode bool
UseLedger bool
Simulate bool
GenerateOnly bool
Expand All @@ -43,7 +41,6 @@ type Context struct {
TxConfig TxConfig
AccountRetriever AccountRetriever
NodeURI string
Verifier tmlite.Verifier

// TODO: Deprecated (remove).
Codec *codec.Codec
Expand Down Expand Up @@ -86,12 +83,6 @@ func (ctx Context) WithFrom(from string) Context {
return ctx
}

// WithTrustNode returns a copy of the context with an updated TrustNode flag.
func (ctx Context) WithTrustNode(trustNode bool) Context {
ctx.TrustNode = trustNode
return ctx
}

// WithOutputFormat returns a copy of the context with an updated OutputFormat field.
func (ctx Context) WithOutputFormat(format string) Context {
ctx.OutputFormat = format
Expand Down Expand Up @@ -129,12 +120,6 @@ func (ctx Context) WithUseLedger(useLedger bool) Context {
return ctx
}

// WithVerifier returns a copy of the context with an updated Verifier.
func (ctx Context) WithVerifier(verifier tmlite.Verifier) Context {
ctx.Verifier = verifier
return ctx
}

// WithChainID returns a copy of the context with an updated chain ID.
func (ctx Context) WithChainID(chainID string) Context {
ctx.ChainID = chainID
Expand Down
3 changes: 0 additions & 3 deletions client/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const (
FlagNode = "node"
FlagHeight = "height"
FlagGasAdjustment = "gas-adjustment"
FlagTrustNode = "trust-node"
FlagFrom = "from"
FlagName = "name"
FlagAccountNumber = "account-number"
Expand Down Expand Up @@ -71,7 +70,6 @@ var LineBreak = &cobra.Command{Run: func(*cobra.Command, []string) {}}

// AddQueryFlagsToCmd adds common flags to a module query command.
func AddQueryFlagsToCmd(cmd *cobra.Command) {
cmd.Flags().Bool(FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
cmd.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device")
cmd.Flags().String(FlagNode, "tcp://localhost:26657", "<host>:<port> to Tendermint RPC interface for this chain")
cmd.Flags().Int64(FlagHeight, 0, "Use a specific height to query state at (this can error if the node is pruning state)")
Expand All @@ -96,7 +94,6 @@ func AddTxFlagsToCmd(cmd *cobra.Command) {
cmd.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device")
cmd.Flags().Float64(FlagGasAdjustment, DefaultGasAdjustment, "adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored ")
cmd.Flags().StringP(FlagBroadcastMode, "b", BroadcastSync, "Transaction broadcasting mode (sync|async|block)")
cmd.Flags().Bool(FlagTrustNode, true, "Trust connected full node (don't verify proofs for responses)")
cmd.Flags().Bool(FlagDryRun, false, "ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it")
cmd.Flags().Bool(FlagGenerateOnly, false, "Build an unsigned transaction and write it to STDOUT (when enabled, the local Keybase is not accessible)")
cmd.Flags().Bool(FlagOffline, false, "Offline mode (does not allow any online functionality")
Expand Down
92 changes: 2 additions & 90 deletions client/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,8 @@ import (
"github.com/pkg/errors"

abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/merkle"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
tmliteErr "github.com/tendermint/tendermint/lite/errors"
tmliteProxy "github.com/tendermint/tendermint/lite/proxy"
rpcclient "github.com/tendermint/tendermint/rpc/client"
tmtypes "github.com/tendermint/tendermint/types"

"github.com/cosmos/cosmos-sdk/store/rootmulti"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -86,7 +82,7 @@ func (ctx Context) queryABCI(req abci.RequestQuery) (abci.ResponseQuery, error)

opts := rpcclient.ABCIQueryOptions{
Height: ctx.Height,
Prove: req.Prove || !ctx.TrustNode,
Prove: req.Prove,
}

result, err := node.ABCIQueryWithOptions(req.Path, req.Data, opts)
Expand All @@ -103,18 +99,12 @@ func (ctx Context) queryABCI(req abci.RequestQuery) (abci.ResponseQuery, error)
return result.Response, nil
}

if err = ctx.verifyProof(req.Path, result.Response); err != nil {
return abci.ResponseQuery{}, err
}

return result.Response, nil
}

// query performs a query to a Tendermint node with the provided store name
// and path. It returns the result and height of the query upon success
// or an error if the query fails. In addition, it will verify the returned
// proof if TrustNode is disabled. If proof verification fails or the query
// height is invalid, an error will be returned.
// or an error if the query fails.
func (ctx Context) query(path string, key tmbytes.HexBytes) ([]byte, int64, error) {
resp, err := ctx.queryABCI(abci.RequestQuery{
Path: path,
Expand All @@ -127,64 +117,6 @@ func (ctx Context) query(path string, key tmbytes.HexBytes) ([]byte, int64, erro
return resp.Value, resp.Height, nil
}

// Verify verifies the consensus proof at given height.
func (ctx Context) Verify(height int64) (tmtypes.SignedHeader, error) {
if ctx.Verifier == nil {
return tmtypes.SignedHeader{}, fmt.Errorf("missing valid certifier to verify data from distrusted node")
}

check, err := tmliteProxy.GetCertifiedCommit(height, ctx.Client, ctx.Verifier)

switch {
case tmliteErr.IsErrCommitNotFound(err):
return tmtypes.SignedHeader{}, ErrVerifyCommit(height)
case err != nil:
return tmtypes.SignedHeader{}, err
}

return check, nil
}

// verifyProof perform response proof verification.
func (ctx Context) verifyProof(queryPath string, resp abci.ResponseQuery) error {
if ctx.Verifier == nil {
return fmt.Errorf("missing valid certifier to verify data from distrusted node")
}

// the AppHash for height H is in header H+1
commit, err := ctx.Verify(resp.Height + 1)
if err != nil {
return err
}

// TODO: Instead of reconstructing, stash on Context field?
prt := rootmulti.DefaultProofRuntime()

// TODO: Better convention for path?
storeName, err := parseQueryStorePath(queryPath)
if err != nil {
return err
}

kp := merkle.KeyPath{}
kp = kp.AppendKey([]byte(storeName), merkle.KeyEncodingURL)
kp = kp.AppendKey(resp.Key, merkle.KeyEncodingURL)

if resp.Value == nil {
err = prt.VerifyAbsence(resp.Proof, commit.Header.AppHash, kp.String())
if err != nil {
return errors.Wrap(err, "failed to prove merkle proof")
}
return nil
}

if err := prt.VerifyValue(resp.Proof, commit.Header.AppHash, kp.String(), resp.Value); err != nil {
return errors.Wrap(err, "failed to prove merkle proof")
}

return nil
}

// queryStore performs a query to a Tendermint node with the provided a store
// name and path. It returns the result and height of the query upon success
// or an error if the query fails.
Expand Down Expand Up @@ -213,23 +145,3 @@ func isQueryStoreWithProof(path string) bool {

return false
}

// parseQueryStorePath expects a format like /store/<storeName>/key.
func parseQueryStorePath(path string) (storeName string, err error) {
if !strings.HasPrefix(path, "/") {
return "", errors.New("expected path to start with /")
}

paths := strings.SplitN(path[1:], "/", 3)

switch {
case len(paths) != 3:
return "", errors.New("expected format like /store/<storeName>/key")
case paths[0] != "store":
return "", errors.New("expected format like /store/<storeName>/key")
case paths[2] != "key":
return "", errors.New("expected format like /store/<storeName>/key")
}

return paths[1], nil
}
18 changes: 0 additions & 18 deletions client/rpc/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/codec/legacy"
"github.com/cosmos/cosmos-sdk/types/rest"

tmliteProxy "github.com/tendermint/tendermint/lite/proxy"
)

//BlockCommand returns the verified block data for a given heights
Expand Down Expand Up @@ -50,7 +48,6 @@ func BlockCommand() *cobra.Command {
}

cmd.Flags().StringP(flags.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
cmd.Flags().Bool(flags.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")

return cmd
}
Expand All @@ -70,21 +67,6 @@ func getBlock(clientCtx client.Context, height *int64) ([]byte, error) {
return nil, err
}

if !clientCtx.TrustNode {
check, err := clientCtx.Verify(res.Block.Height)
if err != nil {
return nil, err
}

if err := tmliteProxy.ValidateHeader(&res.Block.Header, check); err != nil {
return nil, err
}

if err = tmliteProxy.ValidateBlock(res.Block, check); err != nil {
return nil, err
}
}

return legacy.Cdc.MarshalJSON(res)
}

Expand Down
13 changes: 0 additions & 13 deletions client/rpc/validators.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package rpc

import (
"bytes"
"fmt"
"net/http"
"strconv"
Expand Down Expand Up @@ -56,7 +55,6 @@ func ValidatorCommand() *cobra.Command {
}

cmd.Flags().StringP(flags.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
cmd.Flags().Bool(flags.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)")
cmd.Flags().Int(flags.FlagPage, 0, "Query a specific page of paginated results")
cmd.Flags().Int(flags.FlagLimit, 100, "Query number of results returned per page")
Expand Down Expand Up @@ -126,17 +124,6 @@ func GetValidators(clientCtx client.Context, height *int64, page, limit int) (Re
return ResultValidatorsOutput{}, err
}

if !clientCtx.TrustNode {
check, err := clientCtx.Verify(validatorsRes.BlockHeight)
if err != nil {
return ResultValidatorsOutput{}, err
}

if !bytes.Equal(check.ValidatorsHash, tmtypes.NewValidatorSet(validatorsRes.Validators).Hash()) {
return ResultValidatorsOutput{}, fmt.Errorf("received invalid validatorset")
}
}

outputValidatorsRes := ResultValidatorsOutput{
BlockHeight: validatorsRes.BlockHeight,
Validators: make([]ValidatorOutput, len(validatorsRes.Validators)),
Expand Down
56 changes: 0 additions & 56 deletions client/verifier.go

This file was deleted.

37 changes: 0 additions & 37 deletions client/verifier_test.go

This file was deleted.

2 changes: 1 addition & 1 deletion docs/building-modules/module-interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ This query returns the address that owns a particular name. The getter function
+ The function should first initialize a new [`Context`](../interfaces/query-lifecycle.md#context) with the application `codec`.
+ If applicable, the `Context` is used to retrieve any parameters (e.g. the query originator's address to be used in the query) and marshal them with the query parameter type, in preparation to be relayed to a node. There are no `Context` parameters in this case because the query does not involve any information about the user.
+ The `queryRoute` is used to construct a `path` [`baseapp`](../core/baseapp.md) will use to route the query to the appropriate [querier](./querier.md). The expected format for a query `path` is "queryCategory/queryRoute/queryType/arg1/arg2/...", where `queryCategory` can be `p2p`, `store`, `app`, or `custom`, `queryRoute` is the name of the module, and `queryType` is the name of the query type defined within the module. [`baseapp`](../core/baseapp.md) can handle each type of `queryCategory` by routing it to a module querier or retrieving results directly from stores and functions for querying peer nodes. Module queries are `custom` type queries (some SDK modules have exceptions, such as `auth` and `gov` module queries).
+ The `Context` `QueryWithData()` function is used to relay the query to a node and retrieve the response. It requires the `path`. It returns the result and height of the query upon success or an error if the query fails. In addition, it will verify the returned proof if `TrustNode` is disabled. If proof verification fails or the query height is invalid, an error will be returned.
+ The `Context` `QueryWithData()` function is used to relay the query to a node and retrieve the response. It requires the `path`. It returns the result and height of the query upon success or an error if the query fails.
+ The `codec` is used to nmarshal the response and the `Context` is used to print the output back to the user.
- **Flags.** Add any [flags](#flags) to the command.

Expand Down
Loading

0 comments on commit e6a5622

Please sign in to comment.