context: remove verifier & trust node (#6805)

* remove verifier

* more removal of trustnode flag

* add todo

* fix lint

* remove file

* remove viper and add link to issue

* remve mention of trustnode
This commit is contained in:
Marko
2020-07-23 06:44:18 +00:00
committed by GitHub
parent e0a81d2cca
commit e6a56226a8
24 changed files with 17 additions and 303 deletions
-5
View File
@@ -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)
-15
View File
@@ -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"
@@ -34,7 +33,6 @@ type Context struct {
From string
BroadcastMode string
FromName string
TrustNode bool
UseLedger bool
Simulate bool
GenerateOnly bool
@@ -43,7 +41,6 @@ type Context struct {
TxConfig TxConfig
AccountRetriever AccountRetriever
NodeURI string
Verifier tmlite.Verifier
// TODO: Deprecated (remove).
Codec *codec.Codec
@@ -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
@@ -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
-3
View File
@@ -40,7 +40,6 @@ const (
FlagNode = "node"
FlagHeight = "height"
FlagGasAdjustment = "gas-adjustment"
FlagTrustNode = "trust-node"
FlagFrom = "from"
FlagName = "name"
FlagAccountNumber = "account-number"
@@ -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)")
@@ -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")
+2 -90
View File
@@ -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"
@@ -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)
@@ -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,
@@ -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.
@@ -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
View File
@@ -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
@@ -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
}
@@ -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)
}
-13
View File
@@ -1,7 +1,6 @@
package rpc
import (
"bytes"
"fmt"
"net/http"
"strconv"
@@ -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")
@@ -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)),
-56
View File
@@ -1,56 +0,0 @@
package client
import (
"path/filepath"
"github.com/pkg/errors"
"github.com/tendermint/tendermint/libs/log"
tmlite "github.com/tendermint/tendermint/lite"
tmliteproxy "github.com/tendermint/tendermint/lite/proxy"
rpchttp "github.com/tendermint/tendermint/rpc/client/http"
)
const (
verifierDir = ".lite_verifier"
// DefaultVerifierCacheSize defines the default Tendermint cache size.
DefaultVerifierCacheSize = 10
)
// CreateVerifier returns a Tendermint verifier from a Context object and
// cache size. An error is returned if the Context is missing required values
// or if the verifier could not be created. A Context must at the very least
// have the chain ID and home directory set. If the Context has TrustNode
// enabled, no verifier will be created.
func CreateVerifier(ctx Context, cacheSize int) (tmlite.Verifier, error) {
if ctx.TrustNode {
return nil, nil
}
switch {
case ctx.ChainID == "":
return nil, errors.New("must provide a valid chain ID to create verifier")
case ctx.HomeDir == "":
return nil, errors.New("must provide a valid home directory to create verifier")
case ctx.Client == nil && ctx.NodeURI == "":
return nil, errors.New("must provide a valid RPC client or RPC URI to create verifier")
}
var err error
// create an RPC client based off of the RPC URI if no RPC client exists
client := ctx.Client
if client == nil {
client, err = rpchttp.New(ctx.NodeURI, "/websocket")
if err != nil {
return nil, err
}
}
return tmliteproxy.NewVerifier(
ctx.ChainID, filepath.Join(ctx.HomeDir, ctx.ChainID, verifierDir),
client, log.NewNopLogger(), cacheSize,
)
}
-37
View File
@@ -1,37 +0,0 @@
package client_test
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/testutil"
)
func TestCreateVerifier(t *testing.T) {
tmpDir, cleanup := testutil.NewTestCaseDir(t)
t.Cleanup(cleanup)
testCases := []struct {
name string
ctx client.Context
expectErr bool
}{
{"no chain ID", client.Context{}, true},
{"no home directory", client.Context{}.WithChainID("test"), true},
{"no client or RPC URI", client.Context{HomeDir: tmpDir}.WithChainID("test"), true},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
verifier, err := client.CreateVerifier(tc.ctx, client.DefaultVerifierCacheSize)
require.Equal(t, tc.expectErr, err != nil, err)
if !tc.expectErr {
require.NotNil(t, verifier)
}
})
}
}