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:
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user